makePromise.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. /** @license MIT License (c) copyright 2010-2014 original author or authors */
  2. /** @author Brian Cavalier */
  3. /** @author John Hann */
  4. (function(define) { 'use strict';
  5. define(function() {
  6. return function makePromise(environment) {
  7. var tasks = environment.scheduler;
  8. var emitRejection = initEmitRejection();
  9. var objectCreate = Object.create ||
  10. function(proto) {
  11. function Child() {}
  12. Child.prototype = proto;
  13. return new Child();
  14. };
  15. /**
  16. * Create a promise whose fate is determined by resolver
  17. * @constructor
  18. * @returns {Promise} promise
  19. * @name Promise
  20. */
  21. function Promise(resolver, handler) {
  22. this._handler = resolver === Handler ? handler : init(resolver);
  23. }
  24. /**
  25. * Run the supplied resolver
  26. * @param resolver
  27. * @returns {Pending}
  28. */
  29. function init(resolver) {
  30. var handler = new Pending();
  31. try {
  32. resolver(promiseResolve, promiseReject, promiseNotify);
  33. } catch (e) {
  34. promiseReject(e);
  35. }
  36. return handler;
  37. /**
  38. * Transition from pre-resolution state to post-resolution state, notifying
  39. * all listeners of the ultimate fulfillment or rejection
  40. * @param {*} x resolution value
  41. */
  42. function promiseResolve (x) {
  43. handler.resolve(x);
  44. }
  45. /**
  46. * Reject this promise with reason, which will be used verbatim
  47. * @param {Error|*} reason rejection reason, strongly suggested
  48. * to be an Error type
  49. */
  50. function promiseReject (reason) {
  51. handler.reject(reason);
  52. }
  53. /**
  54. * @deprecated
  55. * Issue a progress event, notifying all progress listeners
  56. * @param {*} x progress event payload to pass to all listeners
  57. */
  58. function promiseNotify (x) {
  59. handler.notify(x);
  60. }
  61. }
  62. // Creation
  63. Promise.resolve = resolve;
  64. Promise.reject = reject;
  65. Promise.never = never;
  66. Promise._defer = defer;
  67. Promise._handler = getHandler;
  68. /**
  69. * Returns a trusted promise. If x is already a trusted promise, it is
  70. * returned, otherwise returns a new trusted Promise which follows x.
  71. * @param {*} x
  72. * @return {Promise} promise
  73. */
  74. function resolve(x) {
  75. return isPromise(x) ? x
  76. : new Promise(Handler, new Async(getHandler(x)));
  77. }
  78. /**
  79. * Return a reject promise with x as its reason (x is used verbatim)
  80. * @param {*} x
  81. * @returns {Promise} rejected promise
  82. */
  83. function reject(x) {
  84. return new Promise(Handler, new Async(new Rejected(x)));
  85. }
  86. /**
  87. * Return a promise that remains pending forever
  88. * @returns {Promise} forever-pending promise.
  89. */
  90. function never() {
  91. return foreverPendingPromise; // Should be frozen
  92. }
  93. /**
  94. * Creates an internal {promise, resolver} pair
  95. * @private
  96. * @returns {Promise}
  97. */
  98. function defer() {
  99. return new Promise(Handler, new Pending());
  100. }
  101. // Transformation and flow control
  102. /**
  103. * Transform this promise's fulfillment value, returning a new Promise
  104. * for the transformed result. If the promise cannot be fulfilled, onRejected
  105. * is called with the reason. onProgress *may* be called with updates toward
  106. * this promise's fulfillment.
  107. * @param {function=} onFulfilled fulfillment handler
  108. * @param {function=} onRejected rejection handler
  109. * @param {function=} onProgress @deprecated progress handler
  110. * @return {Promise} new promise
  111. */
  112. Promise.prototype.then = function(onFulfilled, onRejected, onProgress) {
  113. var parent = this._handler;
  114. var state = parent.join().state();
  115. if ((typeof onFulfilled !== 'function' && state > 0) ||
  116. (typeof onRejected !== 'function' && state < 0)) {
  117. // Short circuit: value will not change, simply share handler
  118. return new this.constructor(Handler, parent);
  119. }
  120. var p = this._beget();
  121. var child = p._handler;
  122. parent.chain(child, parent.receiver, onFulfilled, onRejected, onProgress);
  123. return p;
  124. };
  125. /**
  126. * If this promise cannot be fulfilled due to an error, call onRejected to
  127. * handle the error. Shortcut for .then(undefined, onRejected)
  128. * @param {function?} onRejected
  129. * @return {Promise}
  130. */
  131. Promise.prototype['catch'] = function(onRejected) {
  132. return this.then(void 0, onRejected);
  133. };
  134. /**
  135. * Creates a new, pending promise of the same type as this promise
  136. * @private
  137. * @returns {Promise}
  138. */
  139. Promise.prototype._beget = function() {
  140. return begetFrom(this._handler, this.constructor);
  141. };
  142. function begetFrom(parent, Promise) {
  143. var child = new Pending(parent.receiver, parent.join().context);
  144. return new Promise(Handler, child);
  145. }
  146. // Array combinators
  147. Promise.all = all;
  148. Promise.race = race;
  149. Promise._traverse = traverse;
  150. /**
  151. * Return a promise that will fulfill when all promises in the
  152. * input array have fulfilled, or will reject when one of the
  153. * promises rejects.
  154. * @param {array} promises array of promises
  155. * @returns {Promise} promise for array of fulfillment values
  156. */
  157. function all(promises) {
  158. return traverseWith(snd, null, promises);
  159. }
  160. /**
  161. * Array<Promise<X>> -> Promise<Array<f(X)>>
  162. * @private
  163. * @param {function} f function to apply to each promise's value
  164. * @param {Array} promises array of promises
  165. * @returns {Promise} promise for transformed values
  166. */
  167. function traverse(f, promises) {
  168. return traverseWith(tryCatch2, f, promises);
  169. }
  170. function traverseWith(tryMap, f, promises) {
  171. var handler = typeof f === 'function' ? mapAt : settleAt;
  172. var resolver = new Pending();
  173. var pending = promises.length >>> 0;
  174. var results = new Array(pending);
  175. for (var i = 0, x; i < promises.length && !resolver.resolved; ++i) {
  176. x = promises[i];
  177. if (x === void 0 && !(i in promises)) {
  178. --pending;
  179. continue;
  180. }
  181. traverseAt(promises, handler, i, x, resolver);
  182. }
  183. if(pending === 0) {
  184. resolver.become(new Fulfilled(results));
  185. }
  186. return new Promise(Handler, resolver);
  187. function mapAt(i, x, resolver) {
  188. if(!resolver.resolved) {
  189. traverseAt(promises, settleAt, i, tryMap(f, x, i), resolver);
  190. }
  191. }
  192. function settleAt(i, x, resolver) {
  193. results[i] = x;
  194. if(--pending === 0) {
  195. resolver.become(new Fulfilled(results));
  196. }
  197. }
  198. }
  199. function traverseAt(promises, handler, i, x, resolver) {
  200. if (maybeThenable(x)) {
  201. var h = getHandlerMaybeThenable(x);
  202. var s = h.state();
  203. if (s === 0) {
  204. h.fold(handler, i, void 0, resolver);
  205. } else if (s > 0) {
  206. handler(i, h.value, resolver);
  207. } else {
  208. resolver.become(h);
  209. visitRemaining(promises, i+1, h);
  210. }
  211. } else {
  212. handler(i, x, resolver);
  213. }
  214. }
  215. Promise._visitRemaining = visitRemaining;
  216. function visitRemaining(promises, start, handler) {
  217. for(var i=start; i<promises.length; ++i) {
  218. markAsHandled(getHandler(promises[i]), handler);
  219. }
  220. }
  221. function markAsHandled(h, handler) {
  222. if(h === handler) {
  223. return;
  224. }
  225. var s = h.state();
  226. if(s === 0) {
  227. h.visit(h, void 0, h._unreport);
  228. } else if(s < 0) {
  229. h._unreport();
  230. }
  231. }
  232. /**
  233. * Fulfill-reject competitive race. Return a promise that will settle
  234. * to the same state as the earliest input promise to settle.
  235. *
  236. * WARNING: The ES6 Promise spec requires that race()ing an empty array
  237. * must return a promise that is pending forever. This implementation
  238. * returns a singleton forever-pending promise, the same singleton that is
  239. * returned by Promise.never(), thus can be checked with ===
  240. *
  241. * @param {array} promises array of promises to race
  242. * @returns {Promise} if input is non-empty, a promise that will settle
  243. * to the same outcome as the earliest input promise to settle. if empty
  244. * is empty, returns a promise that will never settle.
  245. */
  246. function race(promises) {
  247. if(typeof promises !== 'object' || promises === null) {
  248. return reject(new TypeError('non-iterable passed to race()'));
  249. }
  250. // Sigh, race([]) is untestable unless we return *something*
  251. // that is recognizable without calling .then() on it.
  252. return promises.length === 0 ? never()
  253. : promises.length === 1 ? resolve(promises[0])
  254. : runRace(promises);
  255. }
  256. function runRace(promises) {
  257. var resolver = new Pending();
  258. var i, x, h;
  259. for(i=0; i<promises.length; ++i) {
  260. x = promises[i];
  261. if (x === void 0 && !(i in promises)) {
  262. continue;
  263. }
  264. h = getHandler(x);
  265. if(h.state() !== 0) {
  266. resolver.become(h);
  267. visitRemaining(promises, i+1, h);
  268. break;
  269. } else {
  270. h.visit(resolver, resolver.resolve, resolver.reject);
  271. }
  272. }
  273. return new Promise(Handler, resolver);
  274. }
  275. // Promise internals
  276. // Below this, everything is @private
  277. /**
  278. * Get an appropriate handler for x, without checking for cycles
  279. * @param {*} x
  280. * @returns {object} handler
  281. */
  282. function getHandler(x) {
  283. if(isPromise(x)) {
  284. return x._handler.join();
  285. }
  286. return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
  287. }
  288. /**
  289. * Get a handler for thenable x.
  290. * NOTE: You must only call this if maybeThenable(x) == true
  291. * @param {object|function|Promise} x
  292. * @returns {object} handler
  293. */
  294. function getHandlerMaybeThenable(x) {
  295. return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x);
  296. }
  297. /**
  298. * Get a handler for potentially untrusted thenable x
  299. * @param {*} x
  300. * @returns {object} handler
  301. */
  302. function getHandlerUntrusted(x) {
  303. try {
  304. var untrustedThen = x.then;
  305. return typeof untrustedThen === 'function'
  306. ? new Thenable(untrustedThen, x)
  307. : new Fulfilled(x);
  308. } catch(e) {
  309. return new Rejected(e);
  310. }
  311. }
  312. /**
  313. * Handler for a promise that is pending forever
  314. * @constructor
  315. */
  316. function Handler() {}
  317. Handler.prototype.when
  318. = Handler.prototype.become
  319. = Handler.prototype.notify // deprecated
  320. = Handler.prototype.fail
  321. = Handler.prototype._unreport
  322. = Handler.prototype._report
  323. = noop;
  324. Handler.prototype._state = 0;
  325. Handler.prototype.state = function() {
  326. return this._state;
  327. };
  328. /**
  329. * Recursively collapse handler chain to find the handler
  330. * nearest to the fully resolved value.
  331. * @returns {object} handler nearest the fully resolved value
  332. */
  333. Handler.prototype.join = function() {
  334. var h = this;
  335. while(h.handler !== void 0) {
  336. h = h.handler;
  337. }
  338. return h;
  339. };
  340. Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
  341. this.when({
  342. resolver: to,
  343. receiver: receiver,
  344. fulfilled: fulfilled,
  345. rejected: rejected,
  346. progress: progress
  347. });
  348. };
  349. Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
  350. this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
  351. };
  352. Handler.prototype.fold = function(f, z, c, to) {
  353. this.when(new Fold(f, z, c, to));
  354. };
  355. /**
  356. * Handler that invokes fail() on any handler it becomes
  357. * @constructor
  358. */
  359. function FailIfRejected() {}
  360. inherit(Handler, FailIfRejected);
  361. FailIfRejected.prototype.become = function(h) {
  362. h.fail();
  363. };
  364. var failIfRejected = new FailIfRejected();
  365. /**
  366. * Handler that manages a queue of consumers waiting on a pending promise
  367. * @constructor
  368. */
  369. function Pending(receiver, inheritedContext) {
  370. Promise.createContext(this, inheritedContext);
  371. this.consumers = void 0;
  372. this.receiver = receiver;
  373. this.handler = void 0;
  374. this.resolved = false;
  375. }
  376. inherit(Handler, Pending);
  377. Pending.prototype._state = 0;
  378. Pending.prototype.resolve = function(x) {
  379. this.become(getHandler(x));
  380. };
  381. Pending.prototype.reject = function(x) {
  382. if(this.resolved) {
  383. return;
  384. }
  385. this.become(new Rejected(x));
  386. };
  387. Pending.prototype.join = function() {
  388. if (!this.resolved) {
  389. return this;
  390. }
  391. var h = this;
  392. while (h.handler !== void 0) {
  393. h = h.handler;
  394. if (h === this) {
  395. return this.handler = cycle();
  396. }
  397. }
  398. return h;
  399. };
  400. Pending.prototype.run = function() {
  401. var q = this.consumers;
  402. var handler = this.handler;
  403. this.handler = this.handler.join();
  404. this.consumers = void 0;
  405. for (var i = 0; i < q.length; ++i) {
  406. handler.when(q[i]);
  407. }
  408. };
  409. Pending.prototype.become = function(handler) {
  410. if(this.resolved) {
  411. return;
  412. }
  413. this.resolved = true;
  414. this.handler = handler;
  415. if(this.consumers !== void 0) {
  416. tasks.enqueue(this);
  417. }
  418. if(this.context !== void 0) {
  419. handler._report(this.context);
  420. }
  421. };
  422. Pending.prototype.when = function(continuation) {
  423. if(this.resolved) {
  424. tasks.enqueue(new ContinuationTask(continuation, this.handler));
  425. } else {
  426. if(this.consumers === void 0) {
  427. this.consumers = [continuation];
  428. } else {
  429. this.consumers.push(continuation);
  430. }
  431. }
  432. };
  433. /**
  434. * @deprecated
  435. */
  436. Pending.prototype.notify = function(x) {
  437. if(!this.resolved) {
  438. tasks.enqueue(new ProgressTask(x, this));
  439. }
  440. };
  441. Pending.prototype.fail = function(context) {
  442. var c = typeof context === 'undefined' ? this.context : context;
  443. this.resolved && this.handler.join().fail(c);
  444. };
  445. Pending.prototype._report = function(context) {
  446. this.resolved && this.handler.join()._report(context);
  447. };
  448. Pending.prototype._unreport = function() {
  449. this.resolved && this.handler.join()._unreport();
  450. };
  451. /**
  452. * Wrap another handler and force it into a future stack
  453. * @param {object} handler
  454. * @constructor
  455. */
  456. function Async(handler) {
  457. this.handler = handler;
  458. }
  459. inherit(Handler, Async);
  460. Async.prototype.when = function(continuation) {
  461. tasks.enqueue(new ContinuationTask(continuation, this));
  462. };
  463. Async.prototype._report = function(context) {
  464. this.join()._report(context);
  465. };
  466. Async.prototype._unreport = function() {
  467. this.join()._unreport();
  468. };
  469. /**
  470. * Handler that wraps an untrusted thenable and assimilates it in a future stack
  471. * @param {function} then
  472. * @param {{then: function}} thenable
  473. * @constructor
  474. */
  475. function Thenable(then, thenable) {
  476. Pending.call(this);
  477. tasks.enqueue(new AssimilateTask(then, thenable, this));
  478. }
  479. inherit(Pending, Thenable);
  480. /**
  481. * Handler for a fulfilled promise
  482. * @param {*} x fulfillment value
  483. * @constructor
  484. */
  485. function Fulfilled(x) {
  486. Promise.createContext(this);
  487. this.value = x;
  488. }
  489. inherit(Handler, Fulfilled);
  490. Fulfilled.prototype._state = 1;
  491. Fulfilled.prototype.fold = function(f, z, c, to) {
  492. runContinuation3(f, z, this, c, to);
  493. };
  494. Fulfilled.prototype.when = function(cont) {
  495. runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
  496. };
  497. var errorId = 0;
  498. /**
  499. * Handler for a rejected promise
  500. * @param {*} x rejection reason
  501. * @constructor
  502. */
  503. function Rejected(x) {
  504. Promise.createContext(this);
  505. this.id = ++errorId;
  506. this.value = x;
  507. this.handled = false;
  508. this.reported = false;
  509. this._report();
  510. }
  511. inherit(Handler, Rejected);
  512. Rejected.prototype._state = -1;
  513. Rejected.prototype.fold = function(f, z, c, to) {
  514. to.become(this);
  515. };
  516. Rejected.prototype.when = function(cont) {
  517. if(typeof cont.rejected === 'function') {
  518. this._unreport();
  519. }
  520. runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
  521. };
  522. Rejected.prototype._report = function(context) {
  523. tasks.afterQueue(new ReportTask(this, context));
  524. };
  525. Rejected.prototype._unreport = function() {
  526. if(this.handled) {
  527. return;
  528. }
  529. this.handled = true;
  530. tasks.afterQueue(new UnreportTask(this));
  531. };
  532. Rejected.prototype.fail = function(context) {
  533. this.reported = true;
  534. emitRejection('unhandledRejection', this);
  535. Promise.onFatalRejection(this, context === void 0 ? this.context : context);
  536. };
  537. function ReportTask(rejection, context) {
  538. this.rejection = rejection;
  539. this.context = context;
  540. }
  541. ReportTask.prototype.run = function() {
  542. if(!this.rejection.handled && !this.rejection.reported) {
  543. this.rejection.reported = true;
  544. emitRejection('unhandledRejection', this.rejection) ||
  545. Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
  546. }
  547. };
  548. function UnreportTask(rejection) {
  549. this.rejection = rejection;
  550. }
  551. UnreportTask.prototype.run = function() {
  552. if(this.rejection.reported) {
  553. emitRejection('rejectionHandled', this.rejection) ||
  554. Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
  555. }
  556. };
  557. // Unhandled rejection hooks
  558. // By default, everything is a noop
  559. Promise.createContext
  560. = Promise.enterContext
  561. = Promise.exitContext
  562. = Promise.onPotentiallyUnhandledRejection
  563. = Promise.onPotentiallyUnhandledRejectionHandled
  564. = Promise.onFatalRejection
  565. = noop;
  566. // Errors and singletons
  567. var foreverPendingHandler = new Handler();
  568. var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
  569. function cycle() {
  570. return new Rejected(new TypeError('Promise cycle'));
  571. }
  572. // Task runners
  573. /**
  574. * Run a single consumer
  575. * @constructor
  576. */
  577. function ContinuationTask(continuation, handler) {
  578. this.continuation = continuation;
  579. this.handler = handler;
  580. }
  581. ContinuationTask.prototype.run = function() {
  582. this.handler.join().when(this.continuation);
  583. };
  584. /**
  585. * Run a queue of progress handlers
  586. * @constructor
  587. */
  588. function ProgressTask(value, handler) {
  589. this.handler = handler;
  590. this.value = value;
  591. }
  592. ProgressTask.prototype.run = function() {
  593. var q = this.handler.consumers;
  594. if(q === void 0) {
  595. return;
  596. }
  597. for (var c, i = 0; i < q.length; ++i) {
  598. c = q[i];
  599. runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
  600. }
  601. };
  602. /**
  603. * Assimilate a thenable, sending it's value to resolver
  604. * @param {function} then
  605. * @param {object|function} thenable
  606. * @param {object} resolver
  607. * @constructor
  608. */
  609. function AssimilateTask(then, thenable, resolver) {
  610. this._then = then;
  611. this.thenable = thenable;
  612. this.resolver = resolver;
  613. }
  614. AssimilateTask.prototype.run = function() {
  615. var h = this.resolver;
  616. tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
  617. function _resolve(x) { h.resolve(x); }
  618. function _reject(x) { h.reject(x); }
  619. function _notify(x) { h.notify(x); }
  620. };
  621. function tryAssimilate(then, thenable, resolve, reject, notify) {
  622. try {
  623. then.call(thenable, resolve, reject, notify);
  624. } catch (e) {
  625. reject(e);
  626. }
  627. }
  628. /**
  629. * Fold a handler value with z
  630. * @constructor
  631. */
  632. function Fold(f, z, c, to) {
  633. this.f = f; this.z = z; this.c = c; this.to = to;
  634. this.resolver = failIfRejected;
  635. this.receiver = this;
  636. }
  637. Fold.prototype.fulfilled = function(x) {
  638. this.f.call(this.c, this.z, x, this.to);
  639. };
  640. Fold.prototype.rejected = function(x) {
  641. this.to.reject(x);
  642. };
  643. Fold.prototype.progress = function(x) {
  644. this.to.notify(x);
  645. };
  646. // Other helpers
  647. /**
  648. * @param {*} x
  649. * @returns {boolean} true iff x is a trusted Promise
  650. */
  651. function isPromise(x) {
  652. return x instanceof Promise;
  653. }
  654. /**
  655. * Test just enough to rule out primitives, in order to take faster
  656. * paths in some code
  657. * @param {*} x
  658. * @returns {boolean} false iff x is guaranteed *not* to be a thenable
  659. */
  660. function maybeThenable(x) {
  661. return (typeof x === 'object' || typeof x === 'function') && x !== null;
  662. }
  663. function runContinuation1(f, h, receiver, next) {
  664. if(typeof f !== 'function') {
  665. return next.become(h);
  666. }
  667. Promise.enterContext(h);
  668. tryCatchReject(f, h.value, receiver, next);
  669. Promise.exitContext();
  670. }
  671. function runContinuation3(f, x, h, receiver, next) {
  672. if(typeof f !== 'function') {
  673. return next.become(h);
  674. }
  675. Promise.enterContext(h);
  676. tryCatchReject3(f, x, h.value, receiver, next);
  677. Promise.exitContext();
  678. }
  679. /**
  680. * @deprecated
  681. */
  682. function runNotify(f, x, h, receiver, next) {
  683. if(typeof f !== 'function') {
  684. return next.notify(x);
  685. }
  686. Promise.enterContext(h);
  687. tryCatchReturn(f, x, receiver, next);
  688. Promise.exitContext();
  689. }
  690. function tryCatch2(f, a, b) {
  691. try {
  692. return f(a, b);
  693. } catch(e) {
  694. return reject(e);
  695. }
  696. }
  697. /**
  698. * Return f.call(thisArg, x), or if it throws return a rejected promise for
  699. * the thrown exception
  700. */
  701. function tryCatchReject(f, x, thisArg, next) {
  702. try {
  703. next.become(getHandler(f.call(thisArg, x)));
  704. } catch(e) {
  705. next.become(new Rejected(e));
  706. }
  707. }
  708. /**
  709. * Same as above, but includes the extra argument parameter.
  710. */
  711. function tryCatchReject3(f, x, y, thisArg, next) {
  712. try {
  713. f.call(thisArg, x, y, next);
  714. } catch(e) {
  715. next.become(new Rejected(e));
  716. }
  717. }
  718. /**
  719. * @deprecated
  720. * Return f.call(thisArg, x), or if it throws, *return* the exception
  721. */
  722. function tryCatchReturn(f, x, thisArg, next) {
  723. try {
  724. next.notify(f.call(thisArg, x));
  725. } catch(e) {
  726. next.notify(e);
  727. }
  728. }
  729. function inherit(Parent, Child) {
  730. Child.prototype = objectCreate(Parent.prototype);
  731. Child.prototype.constructor = Child;
  732. }
  733. function snd(x, y) {
  734. return y;
  735. }
  736. function noop() {}
  737. function hasCustomEvent() {
  738. if(typeof CustomEvent === 'function') {
  739. try {
  740. var ev = new CustomEvent('unhandledRejection');
  741. return ev instanceof CustomEvent;
  742. } catch (ignoredException) {}
  743. }
  744. return false;
  745. }
  746. function hasInternetExplorerCustomEvent() {
  747. if(typeof document !== 'undefined' && typeof document.createEvent === 'function') {
  748. try {
  749. // Try to create one event to make sure it's supported
  750. var ev = document.createEvent('CustomEvent');
  751. ev.initCustomEvent('eventType', false, true, {});
  752. return true;
  753. } catch (ignoredException) {}
  754. }
  755. return false;
  756. }
  757. function initEmitRejection() {
  758. /*global process, self, CustomEvent*/
  759. if(typeof process !== 'undefined' && process !== null
  760. && typeof process.emit === 'function') {
  761. // Returning falsy here means to call the default
  762. // onPotentiallyUnhandledRejection API. This is safe even in
  763. // browserify since process.emit always returns falsy in browserify:
  764. // https://github.com/defunctzombie/node-process/blob/master/browser.js#L40-L46
  765. return function(type, rejection) {
  766. return type === 'unhandledRejection'
  767. ? process.emit(type, rejection.value, rejection)
  768. : process.emit(type, rejection);
  769. };
  770. } else if(typeof self !== 'undefined' && hasCustomEvent()) {
  771. return (function (self, CustomEvent) {
  772. return function (type, rejection) {
  773. var ev = new CustomEvent(type, {
  774. detail: {
  775. reason: rejection.value,
  776. key: rejection
  777. },
  778. bubbles: false,
  779. cancelable: true
  780. });
  781. return !self.dispatchEvent(ev);
  782. };
  783. }(self, CustomEvent));
  784. } else if(typeof self !== 'undefined' && hasInternetExplorerCustomEvent()) {
  785. return (function(self, document) {
  786. return function(type, rejection) {
  787. var ev = document.createEvent('CustomEvent');
  788. ev.initCustomEvent(type, false, true, {
  789. reason: rejection.value,
  790. key: rejection
  791. });
  792. return !self.dispatchEvent(ev);
  793. };
  794. }(self, document));
  795. }
  796. return noop;
  797. }
  798. return Promise;
  799. };
  800. });
  801. }(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));