1 /* This is free and unencumbered software released into the public
2 domain. To the extent possible under law, the author of this file
3 waives all copyright and related or neighboring rights to it.
9 /** Polyfills and cross-browser fixes */
12 Math
.sign = function (a
) { return a
&& (a
> 0) - (a
< 0); };
14 if (!String
.prototype.repeat
)
15 Object
.defineProperty(String
.prototype, "repeat", {
16 value: function (count
) {
17 var string
= this.toString();
31 if (!String
.prototype.startsWith
)
32 Object
.defineProperty(String
.prototype, "startsWith", {
33 value: function (sub
) {
34 return this.lastIndexOf(sub
, 0) !== -1;
38 if (!String
.prototype.endsWith
)
39 Object
.defineProperty(String
.prototype, "endsWith", {
40 value: function (sub
) {
41 return this.indexOf(sub
, this.length
- sub
.length
) !== -1;
45 function toObject (o
) {
46 if (o
=== null || o
=== undefined)
47 throw new TypeError("invalid ToObject cast");
52 Object
.defineProperty(Object
, "assign", {
53 value: function (target
) {
54 target
= toObject(target
);
55 for (var i
= 1; i
< arguments
.length
; ++i
) {
56 var source
= toObject(arguments
[i
]);
57 var keys
= Object
.keys(source
);
58 for (var j
= 0; j
< keys
.length
; ++j
)
59 target
[keys
[j
]] = source
[keys
[j
]];
64 if (!Array
.prototype.fill
)
65 Object
.defineProperty(Array
.prototype, "fill", {
66 value: function (value
) {
67 var beg
= arguments
.length
> 1 ? +arguments
[1] : 0;
68 var end
= arguments
.length
> 2 ? +arguments
[2] : this.length
;
69 if (beg
< 0) beg
+= this.length
;
70 if (end
< 0) end
+= this.length
;
71 for (var i
= beg
; i
< end
; ++i
)
77 if (typeof window
!== "undefined") {
78 window
.requestAnimationFrame
= (
79 window
.requestAnimationFrame
80 || window
.mozRequestAnimationFrame
81 || window
.webkitRequestAnimationFrame
);
82 window
.cancelAnimationFrame
= (
83 window
.cancelAnimationFrame
84 || window
.mozCancelAnimationFrame
85 || window
.webkitCancelAnimationFrame
);
87 if (!window
.AudioContext
)
88 window
.AudioContext
= (
89 window
.webkitAudioContext
90 || window
.mozAudioContext
);
92 if (window
.AudioContext
&& !window
.AudioContext
.prototype.createGain
)
93 window
.AudioContext
.prototype.createGain
=
94 window
.AudioContext
.prototype.createGainNode
;
96 /** Canonicalize fullscreen function names if available.
98 Based on http://fullscreen.spec.whatwg.org/, June 7th 2013.
101 if (!Element
.prototype.requestFullscreen
)
102 Element
.prototype.requestFullscreen
= (
103 Element
.prototype.requestFullScreen
104 || Element
.prototype.webkitRequestFullscreen
105 || Element
.prototype.webkitRequestFullScreen
106 || Element
.prototype.mozRequestFullScreen
108 if (!document
.exitFullscreen
)
109 document
.exitFullscreen
= (
110 document
.webkitExitFullscreen
111 || document
.webkitCancelFullScreen
112 || document
.mozCancelFullScreen
114 if (!document
.hasOwnProperty("fullscreenEnabled"))
115 Object
.defineProperty(document
, "fullscreenEnabled", {
118 return (this.webkitFullscreenEnabled
119 || this.mozFullScreenEnabled
123 if (!document
.hasOwnProperty("fullscreenElement"))
124 Object
.defineProperty(document
, "fullscreenElement", {
127 return (this.webkitFullscreenElement
128 || this.webkitCurrentFullScreenElement
129 || this.mozFullScreenEleement
135 // Check for Promise.all as Chrome 30 shipped an implementation
136 // without it and with some other quirks and we don't want to use
138 if (typeof Promise
=== "undefined" || !Promise
.all
) (function () {
139 /* Polyfill based heavily on Christoph Burgmer's ayepromise
141 https://github.com/cburgmer/ayepromise/blob/master/ayepromise.js
143 /* Wrap an arbitrary number of functions and allow only one of
144 them to be executed and only once */
146 var wasCalled
= false;
148 return function (wrappedFunction
) {
154 wrappedFunction
.apply(null, arguments
);
159 function getThenableIfExists (obj
) {
160 // Make sure we only access the accessor once as required by the spec
161 var then
= obj
&& obj
.then
;
163 if (typeof obj
=== "object" && typeof then
=== "function")
164 return then
.bind(obj
);
167 function aThenHandler (onFulfilled
, onRejected
) {
168 var deferred
= defer();
170 function doHandlerCall (func
, value
) {
171 setTimeout(function () {
174 returnValue
= func(value
);
180 if (returnValue
=== deferred
.promise
) {
181 deferred
.reject(new TypeError());
183 deferred
.resolve(returnValue
);
189 promise
: deferred
.promise
,
190 callFulfilled: function (value
) {
191 if (onFulfilled
&& onFulfilled
.call
) {
192 doHandlerCall(onFulfilled
, value
);
194 deferred
.resolve(value
);
197 callRejected: function (value
) {
198 if (onRejected
&& onRejected
.call
) {
199 doHandlerCall(onRejected
, value
);
201 deferred
.reject(value
);
217 function doFulfill (value
) {
221 thenHandlers
.forEach(function (then
) {
222 then
.callFulfilled(outcome
);
227 function doReject (error
) {
231 thenHandlers
.forEach(function (then
) {
232 then
.callRejected(outcome
);
237 function registerThenHandler (onFulfilled
, onRejected
) {
238 var thenHandler
= aThenHandler(onFulfilled
, onRejected
);
240 if (state
=== FULFILLED
) {
241 thenHandler
.callFulfilled(outcome
);
242 } else if (state
=== REJECTED
) {
243 thenHandler
.callRejected(outcome
);
245 thenHandlers
.push(thenHandler
);
248 return thenHandler
.promise
;
251 function safelyResolveThenable (thenable
) {
252 // Either fulfill, reject or reject with error
253 var onceWrapper
= once();
256 onceWrapper(transparentlyResolveThenablesAndFulfill
),
257 onceWrapper(doReject
)
260 onceWrapper(doReject
)(e
);
264 function transparentlyResolveThenablesAndFulfill (value
) {
268 thenable
= getThenableIfExists(value
);
275 safelyResolveThenable(thenable
);
281 var onceWrapper
= once();
283 resolve
: onceWrapper(transparentlyResolveThenablesAndFulfill
),
284 reject
: onceWrapper(doReject
),
286 then
: registerThenHandler
,
287 "catch": function (onRejected
) {
288 return registerThenHandler(null, onRejected
);
294 function Promise (callback
) {
295 var deferred
= defer();
297 callback(deferred
.resolve
, deferred
.reject
);
299 deferred
.reject(exc
);
301 return deferred
.promise
;
304 Promise
.resolve = function (v
) {
305 return new Promise(function (resolve
) { resolve(v
); });
308 Promise
.reject = function (error
) {
309 return new Promise(function (_
, reject
) { reject(error
); });
312 Promise
.all = function (promises
) {
313 return new Promise(function (resolve
, reject
) {
315 var remaining
= promises
.length
;
319 promises
.forEach(function (promise
, i
) {
320 var then
= getThenableIfExists(promise
);
321 function resolve1 (value
) {
323 if (--remaining
=== 0)
327 then
.call(promise
, resolve1
, reject
);
330 results
[i
] = promise
;
336 this.Promise
= Promise
;