9fd7f5ca31b139fa028ce337b43abd1c4539809a
[pwl6.git] / src / yuu / pre.js
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.
4 */
5
6 (function () {
7 "use strict";
8
9 /** Polyfills and cross-browser fixes */
10
11 if (!Math.sign)
12 Math.sign = function (a) { return a && (a > 0) - (a < 0); };
13
14 if (!String.prototype.repeat)
15 Object.defineProperty(String.prototype, "repeat", {
16 value: function (count) {
17 var string = this.toString();
18 var result = '';
19 var n = count | 0;
20 while (n) {
21 if (n % 2 === 1)
22 result += string;
23 if (n > 1)
24 string += string;
25 n >>= 1;
26 }
27 return result;
28 }
29 });
30
31 if (!String.prototype.startsWith)
32 Object.defineProperty(String.prototype, "startsWith", {
33 value: function (sub) {
34 return this.lastIndexOf(sub, 0) !== -1;
35 }
36 });
37
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;
42 }
43 });
44
45 function toObject (o) {
46 if (o === null || o === undefined)
47 throw new TypeError("invalid ToObject cast");
48 return Object(o);
49 }
50
51 if (!Object.assign)
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]];
60 }
61 }
62 });
63
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)
72 this[i] = value;
73 return this;
74 }
75 });
76
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);
86
87 if (!window.AudioContext)
88 window.AudioContext = (
89 window.webkitAudioContext
90 || window.mozAudioContext);
91
92 if (window.AudioContext && !window.AudioContext.prototype.createGain)
93 window.AudioContext.prototype.createGain =
94 window.AudioContext.prototype.createGainNode;
95
96 /** Canonicalize fullscreen function names if available.
97
98 Based on http://fullscreen.spec.whatwg.org/, June 7th 2013.
99 */
100
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
107 || function () {});
108 if (!document.exitFullscreen)
109 document.exitFullscreen = (
110 document.webkitExitFullscreen
111 || document.webkitCancelFullScreen
112 || document.mozCancelFullScreen
113 || function () {});
114 if (!document.hasOwnProperty("fullscreenEnabled"))
115 Object.defineProperty(document, "fullscreenEnabled", {
116 enumerable: true,
117 get: function () {
118 return (this.webkitFullscreenEnabled
119 || this.mozFullScreenEnabled
120 || false);
121 }
122 });
123 if (!document.hasOwnProperty("fullscreenElement"))
124 Object.defineProperty(document, "fullscreenElement", {
125 enumerable: true,
126 get: function () {
127 return (this.webkitFullscreenElement
128 || this.webkitCurrentFullScreenElement
129 || this.mozFullScreenEleement
130 || null);
131 }
132 });
133 }
134
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
137 // that one.
138 if (typeof Promise === "undefined" || !Promise.all) (function () {
139 /* Polyfill based heavily on Christoph Burgmer's ayepromise
140
141 https://github.com/cburgmer/ayepromise/blob/master/ayepromise.js
142 */
143 /* Wrap an arbitrary number of functions and allow only one of
144 them to be executed and only once */
145 function once () {
146 var wasCalled = false;
147
148 return function (wrappedFunction) {
149 return function () {
150 if (wasCalled) {
151 return;
152 }
153 wasCalled = true;
154 wrappedFunction.apply(null, arguments);
155 };
156 };
157 }
158
159 function getThenableIfExists (obj) {
160 // Make sure we only access the accessor once as required by the spec
161 var then = obj && obj.then;
162
163 if (typeof obj === "object" && typeof then === "function")
164 return then.bind(obj);
165 }
166
167 function aThenHandler (onFulfilled, onRejected) {
168 var deferred = defer();
169
170 function doHandlerCall (func, value) {
171 setTimeout(function () {
172 var returnValue;
173 try {
174 returnValue = func(value);
175 } catch (e) {
176 deferred.reject(e);
177 return;
178 }
179
180 if (returnValue === deferred.promise) {
181 deferred.reject(new TypeError());
182 } else {
183 deferred.resolve(returnValue);
184 }
185 }, 0);
186 }
187
188 return {
189 promise: deferred.promise,
190 callFulfilled: function (value) {
191 if (onFulfilled && onFulfilled.call) {
192 doHandlerCall(onFulfilled, value);
193 } else {
194 deferred.resolve(value);
195 }
196 },
197 callRejected: function (value) {
198 if (onRejected && onRejected.call) {
199 doHandlerCall(onRejected, value);
200 } else {
201 deferred.reject(value);
202 }
203 }
204 };
205 }
206
207 function defer () {
208 // States
209 var PENDING = 0,
210 FULFILLED = 1,
211 REJECTED = 2;
212
213 var state = PENDING,
214 outcome,
215 thenHandlers = [];
216
217 function doFulfill (value) {
218 state = FULFILLED;
219 outcome = value;
220
221 thenHandlers.forEach(function (then) {
222 then.callFulfilled(outcome);
223 });
224 thenHandlers = null;
225 }
226
227 function doReject (error) {
228 state = REJECTED;
229 outcome = error;
230
231 thenHandlers.forEach(function (then) {
232 then.callRejected(outcome);
233 });
234 thenHandlers = null;
235 }
236
237 function registerThenHandler (onFulfilled, onRejected) {
238 var thenHandler = aThenHandler(onFulfilled, onRejected);
239
240 if (state === FULFILLED) {
241 thenHandler.callFulfilled(outcome);
242 } else if (state === REJECTED) {
243 thenHandler.callRejected(outcome);
244 } else {
245 thenHandlers.push(thenHandler);
246 }
247
248 return thenHandler.promise;
249 }
250
251 function safelyResolveThenable (thenable) {
252 // Either fulfill, reject or reject with error
253 var onceWrapper = once();
254 try {
255 thenable(
256 onceWrapper(transparentlyResolveThenablesAndFulfill),
257 onceWrapper(doReject)
258 );
259 } catch (e) {
260 onceWrapper(doReject)(e);
261 }
262 }
263
264 function transparentlyResolveThenablesAndFulfill (value) {
265 var thenable;
266
267 try {
268 thenable = getThenableIfExists(value);
269 } catch (e) {
270 doReject(e);
271 return;
272 }
273
274 if (thenable) {
275 safelyResolveThenable(thenable);
276 } else {
277 doFulfill(value);
278 }
279 }
280
281 var onceWrapper = once();
282 return {
283 resolve: onceWrapper(transparentlyResolveThenablesAndFulfill),
284 reject: onceWrapper(doReject),
285 promise: {
286 then: registerThenHandler,
287 "catch": function (onRejected) {
288 return registerThenHandler(null, onRejected);
289 }
290 }
291 };
292 }
293
294 function Promise (callback) {
295 var deferred = defer();
296 try {
297 callback(deferred.resolve, deferred.reject);
298 } catch (exc) {
299 deferred.reject(exc);
300 }
301 return deferred.promise;
302 }
303
304 Promise.resolve = function (v) {
305 return new Promise(function (resolve) { resolve(v); });
306 };
307
308 Promise.reject = function (error) {
309 return new Promise(function (_, reject) { reject(error); });
310 };
311
312 Promise.all = function (promises) {
313 return new Promise(function (resolve, reject) {
314 var results = [];
315 var remaining = promises.length;
316 if (remaining === 0)
317 return resolve([]);
318
319 promises.forEach(function (promise, i) {
320 var then = getThenableIfExists(promise);
321 function resolve1 (value) {
322 results[i] = value;
323 if (--remaining === 0)
324 resolve(results);
325 }
326 if (then) {
327 then.call(promise, resolve1, reject);
328 } else {
329 --remaining;
330 results[i] = promise;
331 }
332 });
333 });
334 };
335
336 this.Promise = Promise;
337 }).call(this);
338 }).call(this);