when-e6985d2a.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['exports'], function (exports) { 'use strict';
  3. /**
  4. * @function
  5. *
  6. * @param {*} value The object.
  7. * @returns {Boolean} Returns true if the object is defined, returns false otherwise.
  8. *
  9. * @example
  10. * if (Cesium.defined(positions)) {
  11. * doSomething();
  12. * } else {
  13. * doSomethingElse();
  14. * }
  15. */
  16. function defined(value) {
  17. return value !== undefined && value !== null;
  18. }
  19. /**
  20. * Returns the first parameter if not undefined, otherwise the second parameter.
  21. * Useful for setting a default value for a parameter.
  22. *
  23. * @function
  24. *
  25. * @param {*} a
  26. * @param {*} b
  27. * @returns {*} Returns the first parameter if not undefined, otherwise the second parameter.
  28. *
  29. * @example
  30. * param = Cesium.defaultValue(param, 'default');
  31. */
  32. function defaultValue(a, b) {
  33. if (a !== undefined && a !== null) {
  34. return a;
  35. }
  36. return b;
  37. }
  38. /**
  39. * A frozen empty object that can be used as the default value for options passed as
  40. * an object literal.
  41. * @type {Object}
  42. * @memberof defaultValue
  43. */
  44. defaultValue.EMPTY_OBJECT = Object.freeze({});
  45. /**
  46. @license
  47. when.js - https://github.com/cujojs/when
  48. MIT License (c) copyright B Cavalier & J Hann
  49. * A lightweight CommonJS Promises/A and when() implementation
  50. * when is part of the cujo.js family of libraries (http://cujojs.com/)
  51. *
  52. * Licensed under the MIT License at:
  53. * http://www.opensource.org/licenses/mit-license.php
  54. *
  55. * @version 1.7.1
  56. */
  57. var reduceArray, slice, undef;
  58. //
  59. // Public API
  60. //
  61. when.defer = defer; // Create a deferred
  62. when.resolve = resolve; // Create a resolved promise
  63. when.reject = reject; // Create a rejected promise
  64. when.join = join; // Join 2 or more promises
  65. when.all = all; // Resolve a list of promises
  66. when.map = map; // Array.map() for promises
  67. when.reduce = reduce; // Array.reduce() for promises
  68. when.any = any; // One-winner race
  69. when.some = some; // Multi-winner race
  70. when.chain = chain; // Make a promise trigger another resolver
  71. when.isPromise = isPromise; // Determine if a thing is a promise
  72. /**
  73. * Register an observer for a promise or immediate value.
  74. *
  75. * @param {*} promiseOrValue
  76. * @param {function?} [onFulfilled] callback to be called when promiseOrValue is
  77. * successfully fulfilled. If promiseOrValue is an immediate value, callback
  78. * will be invoked immediately.
  79. * @param {function?} [onRejected] callback to be called when promiseOrValue is
  80. * rejected.
  81. * @param {function?} [onProgress] callback to be called when progress updates
  82. * are issued for promiseOrValue.
  83. * @returns {Promise} a new {@link Promise} that will complete with the return
  84. * value of callback or errback or the completion value of promiseOrValue if
  85. * callback and/or errback is not supplied.
  86. */
  87. function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
  88. // Get a trusted promise for the input promiseOrValue, and then
  89. // register promise handlers
  90. return resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);
  91. }
  92. /**
  93. * Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if
  94. * promiseOrValue is a foreign promise, or a new, already-fulfilled {@link Promise}
  95. * whose value is promiseOrValue if promiseOrValue is an immediate value.
  96. *
  97. * @param {*} promiseOrValue
  98. * @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise}
  99. * returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise}
  100. * whose resolution value is:
  101. * * the resolution value of promiseOrValue if it's a foreign promise, or
  102. * * promiseOrValue if it's a value
  103. */
  104. function resolve(promiseOrValue) {
  105. var promise, deferred;
  106. if(promiseOrValue instanceof Promise) {
  107. // It's a when.js promise, so we trust it
  108. promise = promiseOrValue;
  109. } else {
  110. // It's not a when.js promise. See if it's a foreign promise or a value.
  111. if(isPromise(promiseOrValue)) {
  112. // It's a thenable, but we don't know where it came from, so don't trust
  113. // its implementation entirely. Introduce a trusted middleman when.js promise
  114. deferred = defer();
  115. // IMPORTANT: This is the only place when.js should ever call .then() on an
  116. // untrusted promise. Don't expose the return value to the untrusted promise
  117. promiseOrValue.then(
  118. function(value) { deferred.resolve(value); },
  119. function(reason) { deferred.reject(reason); },
  120. function(update) { deferred.progress(update); }
  121. );
  122. promise = deferred.promise;
  123. } else {
  124. // It's a value, not a promise. Create a resolved promise for it.
  125. promise = fulfilled(promiseOrValue);
  126. }
  127. }
  128. return promise;
  129. }
  130. /**
  131. * Returns a rejected promise for the supplied promiseOrValue. The returned
  132. * promise will be rejected with:
  133. * - promiseOrValue, if it is a value, or
  134. * - if promiseOrValue is a promise
  135. * - promiseOrValue's value after it is fulfilled
  136. * - promiseOrValue's reason after it is rejected
  137. * @param {*} promiseOrValue the rejected value of the returned {@link Promise}
  138. * @returns {Promise} rejected {@link Promise}
  139. */
  140. function reject(promiseOrValue) {
  141. return when(promiseOrValue, rejected);
  142. }
  143. /**
  144. * Trusted Promise constructor. A Promise created from this constructor is
  145. * a trusted when.js promise. Any other duck-typed promise is considered
  146. * untrusted.
  147. * @constructor
  148. * @name Promise
  149. */
  150. function Promise(then) {
  151. this.then = then;
  152. }
  153. Promise.prototype = {
  154. /**
  155. * Register a callback that will be called when a promise is
  156. * fulfilled or rejected. Optionally also register a progress handler.
  157. * Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress)
  158. * @param {function?} [onFulfilledOrRejected]
  159. * @param {function?} [onProgress]
  160. * @returns {Promise}
  161. */
  162. always: function(onFulfilledOrRejected, onProgress) {
  163. return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
  164. },
  165. /**
  166. * Register a rejection handler. Shortcut for .then(undefined, onRejected)
  167. * @param {function?} onRejected
  168. * @returns {Promise}
  169. */
  170. otherwise: function(onRejected) {
  171. return this.then(undef, onRejected);
  172. },
  173. /**
  174. * Shortcut for .then(function() { return value; })
  175. * @param {*} value
  176. * @returns {Promise} a promise that:
  177. * - is fulfilled if value is not a promise, or
  178. * - if value is a promise, will fulfill with its value, or reject
  179. * with its reason.
  180. */
  181. yield: function(value) {
  182. return this.then(function() {
  183. return value;
  184. });
  185. },
  186. /**
  187. * Assumes that this promise will fulfill with an array, and arranges
  188. * for the onFulfilled to be called with the array as its argument list
  189. * i.e. onFulfilled.spread(undefined, array).
  190. * @param {function} onFulfilled function to receive spread arguments
  191. * @returns {Promise}
  192. */
  193. spread: function(onFulfilled) {
  194. return this.then(function(array) {
  195. // array may contain promises, so resolve its contents.
  196. return all(array, function(array) {
  197. return onFulfilled.apply(undef, array);
  198. });
  199. });
  200. }
  201. };
  202. /**
  203. * Create an already-resolved promise for the supplied value
  204. * @private
  205. *
  206. * @param {*} value
  207. * @returns {Promise} fulfilled promise
  208. */
  209. function fulfilled(value) {
  210. var p = new Promise(function(onFulfilled) {
  211. // TODO: Promises/A+ check typeof onFulfilled
  212. try {
  213. return resolve(onFulfilled ? onFulfilled(value) : value);
  214. } catch(e) {
  215. return rejected(e);
  216. }
  217. });
  218. return p;
  219. }
  220. /**
  221. * Create an already-rejected {@link Promise} with the supplied
  222. * rejection reason.
  223. * @private
  224. *
  225. * @param {*} reason
  226. * @returns {Promise} rejected promise
  227. */
  228. function rejected(reason) {
  229. var p = new Promise(function(_, onRejected) {
  230. // TODO: Promises/A+ check typeof onRejected
  231. try {
  232. return onRejected ? resolve(onRejected(reason)) : rejected(reason);
  233. } catch(e) {
  234. return rejected(e);
  235. }
  236. });
  237. return p;
  238. }
  239. /**
  240. * Creates a new, Deferred with fully isolated resolver and promise parts,
  241. * either or both of which may be given out safely to consumers.
  242. * The Deferred itself has the full API: resolve, reject, progress, and
  243. * then. The resolver has resolve, reject, and progress. The promise
  244. * only has then.
  245. *
  246. * @returns {Deferred}
  247. */
  248. function defer() {
  249. var deferred, promise, handlers, progressHandlers,
  250. _then, _progress, _resolve;
  251. /**
  252. * The promise for the new deferred
  253. * @type {Promise}
  254. */
  255. promise = new Promise(then);
  256. /**
  257. * The full Deferred object, with {@link Promise} and {@link Resolver} parts
  258. * @class Deferred
  259. * @name Deferred
  260. */
  261. deferred = {
  262. then: then, // DEPRECATED: use deferred.promise.then
  263. resolve: promiseResolve,
  264. reject: promiseReject,
  265. // TODO: Consider renaming progress() to notify()
  266. progress: promiseProgress,
  267. promise: promise,
  268. resolver: {
  269. resolve: promiseResolve,
  270. reject: promiseReject,
  271. progress: promiseProgress
  272. }
  273. };
  274. handlers = [];
  275. progressHandlers = [];
  276. /**
  277. * Pre-resolution then() that adds the supplied callback, errback, and progback
  278. * functions to the registered listeners
  279. * @private
  280. *
  281. * @param {function?} [onFulfilled] resolution handler
  282. * @param {function?} [onRejected] rejection handler
  283. * @param {function?} [onProgress] progress handler
  284. */
  285. _then = function(onFulfilled, onRejected, onProgress) {
  286. // TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
  287. var deferred, progressHandler;
  288. deferred = defer();
  289. progressHandler = typeof onProgress === 'function'
  290. ? function(update) {
  291. try {
  292. // Allow progress handler to transform progress event
  293. deferred.progress(onProgress(update));
  294. } catch(e) {
  295. // Use caught value as progress
  296. deferred.progress(e);
  297. }
  298. }
  299. : function(update) { deferred.progress(update); };
  300. handlers.push(function(promise) {
  301. promise.then(onFulfilled, onRejected)
  302. .then(deferred.resolve, deferred.reject, progressHandler);
  303. });
  304. progressHandlers.push(progressHandler);
  305. return deferred.promise;
  306. };
  307. /**
  308. * Issue a progress event, notifying all progress listeners
  309. * @private
  310. * @param {*} update progress event payload to pass to all listeners
  311. */
  312. _progress = function(update) {
  313. processQueue(progressHandlers, update);
  314. return update;
  315. };
  316. /**
  317. * Transition from pre-resolution state to post-resolution state, notifying
  318. * all listeners of the resolution or rejection
  319. * @private
  320. * @param {*} value the value of this deferred
  321. */
  322. _resolve = function(value) {
  323. value = resolve(value);
  324. // Replace _then with one that directly notifies with the result.
  325. _then = value.then;
  326. // Replace _resolve so that this Deferred can only be resolved once
  327. _resolve = resolve;
  328. // Make _progress a noop, to disallow progress for the resolved promise.
  329. _progress = noop;
  330. // Notify handlers
  331. processQueue(handlers, value);
  332. // Free progressHandlers array since we'll never issue progress events
  333. progressHandlers = handlers = undef;
  334. return value;
  335. };
  336. return deferred;
  337. /**
  338. * Wrapper to allow _then to be replaced safely
  339. * @param {function?} [onFulfilled] resolution handler
  340. * @param {function?} [onRejected] rejection handler
  341. * @param {function?} [onProgress] progress handler
  342. * @returns {Promise} new promise
  343. */
  344. function then(onFulfilled, onRejected, onProgress) {
  345. // TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
  346. return _then(onFulfilled, onRejected, onProgress);
  347. }
  348. /**
  349. * Wrapper to allow _resolve to be replaced
  350. */
  351. function promiseResolve(val) {
  352. return _resolve(val);
  353. }
  354. /**
  355. * Wrapper to allow _reject to be replaced
  356. */
  357. function promiseReject(err) {
  358. return _resolve(rejected(err));
  359. }
  360. /**
  361. * Wrapper to allow _progress to be replaced
  362. */
  363. function promiseProgress(update) {
  364. return _progress(update);
  365. }
  366. }
  367. /**
  368. * Determines if promiseOrValue is a promise or not. Uses the feature
  369. * test from http://wiki.commonjs.org/wiki/Promises/A to determine if
  370. * promiseOrValue is a promise.
  371. *
  372. * @param {*} promiseOrValue anything
  373. * @returns {boolean} true if promiseOrValue is a {@link Promise}
  374. */
  375. function isPromise(promiseOrValue) {
  376. return promiseOrValue && typeof promiseOrValue.then === 'function';
  377. }
  378. /**
  379. * Initiates a competitive race, returning a promise that will resolve when
  380. * howMany of the supplied promisesOrValues have resolved, or will reject when
  381. * it becomes impossible for howMany to resolve, for example, when
  382. * (promisesOrValues.length - howMany) + 1 input promises reject.
  383. *
  384. * @param {Array} promisesOrValues array of anything, may contain a mix
  385. * of promises and values
  386. * @param howMany {number} number of promisesOrValues to resolve
  387. * @param {function?} [onFulfilled] resolution handler
  388. * @param {function?} [onRejected] rejection handler
  389. * @param {function?} [onProgress] progress handler
  390. * @returns {Promise} promise that will resolve to an array of howMany values that
  391. * resolved first, or will reject with an array of (promisesOrValues.length - howMany) + 1
  392. * rejection reasons.
  393. */
  394. function some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {
  395. checkCallbacks(2, arguments);
  396. return when(promisesOrValues, function(promisesOrValues) {
  397. var toResolve, toReject, values, reasons, deferred, fulfillOne, rejectOne, progress, len, i;
  398. len = promisesOrValues.length >>> 0;
  399. toResolve = Math.max(0, Math.min(howMany, len));
  400. values = [];
  401. toReject = (len - toResolve) + 1;
  402. reasons = [];
  403. deferred = defer();
  404. // No items in the input, resolve immediately
  405. if (!toResolve) {
  406. deferred.resolve(values);
  407. } else {
  408. progress = deferred.progress;
  409. rejectOne = function(reason) {
  410. reasons.push(reason);
  411. if(!--toReject) {
  412. fulfillOne = rejectOne = noop;
  413. deferred.reject(reasons);
  414. }
  415. };
  416. fulfillOne = function(val) {
  417. // This orders the values based on promise resolution order
  418. // Another strategy would be to use the original position of
  419. // the corresponding promise.
  420. values.push(val);
  421. if (!--toResolve) {
  422. fulfillOne = rejectOne = noop;
  423. deferred.resolve(values);
  424. }
  425. };
  426. for(i = 0; i < len; ++i) {
  427. if(i in promisesOrValues) {
  428. when(promisesOrValues[i], fulfiller, rejecter, progress);
  429. }
  430. }
  431. }
  432. return deferred.then(onFulfilled, onRejected, onProgress);
  433. function rejecter(reason) {
  434. rejectOne(reason);
  435. }
  436. function fulfiller(val) {
  437. fulfillOne(val);
  438. }
  439. });
  440. }
  441. /**
  442. * Initiates a competitive race, returning a promise that will resolve when
  443. * any one of the supplied promisesOrValues has resolved or will reject when
  444. * *all* promisesOrValues have rejected.
  445. *
  446. * @param {Array|Promise} promisesOrValues array of anything, may contain a mix
  447. * of {@link Promise}s and values
  448. * @param {function?} [onFulfilled] resolution handler
  449. * @param {function?} [onRejected] rejection handler
  450. * @param {function?} [onProgress] progress handler
  451. * @returns {Promise} promise that will resolve to the value that resolved first, or
  452. * will reject with an array of all rejected inputs.
  453. */
  454. function any(promisesOrValues, onFulfilled, onRejected, onProgress) {
  455. function unwrapSingleResult(val) {
  456. return onFulfilled ? onFulfilled(val[0]) : val[0];
  457. }
  458. return some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);
  459. }
  460. /**
  461. * Return a promise that will resolve only once all the supplied promisesOrValues
  462. * have resolved. The resolution value of the returned promise will be an array
  463. * containing the resolution values of each of the promisesOrValues.
  464. * @memberOf when
  465. *
  466. * @param {Array|Promise} promisesOrValues array of anything, may contain a mix
  467. * of {@link Promise}s and values
  468. * @param {function?} [onFulfilled] resolution handler
  469. * @param {function?} [onRejected] rejection handler
  470. * @param {function?} [onProgress] progress handler
  471. * @returns {Promise}
  472. */
  473. function all(promisesOrValues, onFulfilled, onRejected, onProgress) {
  474. checkCallbacks(1, arguments);
  475. return map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);
  476. }
  477. /**
  478. * Joins multiple promises into a single returned promise.
  479. * @returns {Promise} a promise that will fulfill when *all* the input promises
  480. * have fulfilled, or will reject when *any one* of the input promises rejects.
  481. */
  482. function join(/* ...promises */) {
  483. return map(arguments, identity);
  484. }
  485. /**
  486. * Traditional map function, similar to `Array.prototype.map()`, but allows
  487. * input to contain {@link Promise}s and/or values, and mapFunc may return
  488. * either a value or a {@link Promise}
  489. *
  490. * @param {Array|Promise} promise array of anything, may contain a mix
  491. * of {@link Promise}s and values
  492. * @param {function} mapFunc mapping function mapFunc(value) which may return
  493. * either a {@link Promise} or value
  494. * @returns {Promise} a {@link Promise} that will resolve to an array containing
  495. * the mapped output values.
  496. */
  497. function map(promise, mapFunc) {
  498. return when(promise, function(array) {
  499. var results, len, toResolve, resolve, i, d;
  500. // Since we know the resulting length, we can preallocate the results
  501. // array to avoid array expansions.
  502. toResolve = len = array.length >>> 0;
  503. results = [];
  504. d = defer();
  505. if(!toResolve) {
  506. d.resolve(results);
  507. } else {
  508. resolve = function resolveOne(item, i) {
  509. when(item, mapFunc).then(function(mapped) {
  510. results[i] = mapped;
  511. if(!--toResolve) {
  512. d.resolve(results);
  513. }
  514. }, d.reject);
  515. };
  516. // Since mapFunc may be async, get all invocations of it into flight
  517. for(i = 0; i < len; i++) {
  518. if(i in array) {
  519. resolve(array[i], i);
  520. } else {
  521. --toResolve;
  522. }
  523. }
  524. }
  525. return d.promise;
  526. });
  527. }
  528. /**
  529. * Traditional reduce function, similar to `Array.prototype.reduce()`, but
  530. * input may contain promises and/or values, and reduceFunc
  531. * may return either a value or a promise, *and* initialValue may
  532. * be a promise for the starting value.
  533. *
  534. * @param {Array|Promise} promise array or promise for an array of anything,
  535. * may contain a mix of promises and values.
  536. * @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),
  537. * where total is the total number of items being reduced, and will be the same
  538. * in each call to reduceFunc.
  539. * @returns {Promise} that will resolve to the final reduced value
  540. */
  541. function reduce(promise, reduceFunc /*, initialValue */) {
  542. var args = slice.call(arguments, 1);
  543. return when(promise, function(array) {
  544. var total;
  545. total = array.length;
  546. // Wrap the supplied reduceFunc with one that handles promises and then
  547. // delegates to the supplied.
  548. args[0] = function (current, val, i) {
  549. return when(current, function (c) {
  550. return when(val, function (value) {
  551. return reduceFunc(c, value, i, total);
  552. });
  553. });
  554. };
  555. return reduceArray.apply(array, args);
  556. });
  557. }
  558. /**
  559. * Ensure that resolution of promiseOrValue will trigger resolver with the
  560. * value or reason of promiseOrValue, or instead with resolveValue if it is provided.
  561. *
  562. * @param promiseOrValue
  563. * @param {Object} resolver
  564. * @param {function} resolver.resolve
  565. * @param {function} resolver.reject
  566. * @param {*} [resolveValue]
  567. * @returns {Promise}
  568. */
  569. function chain(promiseOrValue, resolver, resolveValue) {
  570. var useResolveValue = arguments.length > 2;
  571. return when(promiseOrValue,
  572. function(val) {
  573. val = useResolveValue ? resolveValue : val;
  574. resolver.resolve(val);
  575. return val;
  576. },
  577. function(reason) {
  578. resolver.reject(reason);
  579. return rejected(reason);
  580. },
  581. resolver.progress
  582. );
  583. }
  584. //
  585. // Utility functions
  586. //
  587. /**
  588. * Apply all functions in queue to value
  589. * @param {Array} queue array of functions to execute
  590. * @param {*} value argument passed to each function
  591. */
  592. function processQueue(queue, value) {
  593. var handler, i = 0;
  594. while (handler = queue[i++]) {
  595. handler(value);
  596. }
  597. }
  598. /**
  599. * Helper that checks arrayOfCallbacks to ensure that each element is either
  600. * a function, or null or undefined.
  601. * @private
  602. * @param {number} start index at which to start checking items in arrayOfCallbacks
  603. * @param {Array} arrayOfCallbacks array to check
  604. * @throws {Error} if any element of arrayOfCallbacks is something other than
  605. * a functions, null, or undefined.
  606. */
  607. function checkCallbacks(start, arrayOfCallbacks) {
  608. // TODO: Promises/A+ update type checking and docs
  609. var arg, i = arrayOfCallbacks.length;
  610. while(i > start) {
  611. arg = arrayOfCallbacks[--i];
  612. if (arg != null && typeof arg != 'function') {
  613. throw new Error('arg '+i+' must be a function');
  614. }
  615. }
  616. }
  617. /**
  618. * No-Op function used in method replacement
  619. * @private
  620. */
  621. function noop() {}
  622. slice = [].slice;
  623. // ES5 reduce implementation if native not available
  624. // See: http://es5.github.com/#x15.4.4.21 as there are many
  625. // specifics and edge cases.
  626. reduceArray = [].reduce ||
  627. function(reduceFunc /*, initialValue */) {
  628. /*jshint maxcomplexity: 7*/
  629. // ES5 dictates that reduce.length === 1
  630. // This implementation deviates from ES5 spec in the following ways:
  631. // 1. It does not check if reduceFunc is a Callable
  632. var arr, args, reduced, len, i;
  633. i = 0;
  634. // This generates a jshint warning, despite being valid
  635. // "Missing 'new' prefix when invoking a constructor."
  636. // See https://github.com/jshint/jshint/issues/392
  637. arr = Object(this);
  638. len = arr.length >>> 0;
  639. args = arguments;
  640. // If no initialValue, use first item of array (we know length !== 0 here)
  641. // and adjust i to start at second item
  642. if(args.length <= 1) {
  643. // Skip to the first real element in the array
  644. for(;;) {
  645. if(i in arr) {
  646. reduced = arr[i++];
  647. break;
  648. }
  649. // If we reached the end of the array without finding any real
  650. // elements, it's a TypeError
  651. if(++i >= len) {
  652. throw new TypeError();
  653. }
  654. }
  655. } else {
  656. // If initialValue provided, use it
  657. reduced = args[1];
  658. }
  659. // Do the actual reduce
  660. for(;i < len; ++i) {
  661. // Skip holes
  662. if(i in arr) {
  663. reduced = reduceFunc(reduced, arr[i], i, arr);
  664. }
  665. }
  666. return reduced;
  667. };
  668. function identity(x) {
  669. return x;
  670. }
  671. exports.defaultValue = defaultValue;
  672. exports.defined = defined;
  673. exports.when = when;
  674. });