82f2b76e25
We now use webpack instead of SystemJS, effectively bundling modules into one file (plus commons chunks) for every entry point. This results in a much smaller extension size (almost half). Furthermore we use yarn/npm even for extension run-time dependencies. This relieves us from manually vendoring and building dependencies. It's also easier to understand for new developers familiar with node.
1299 lines
32 KiB
JavaScript
1299 lines
32 KiB
JavaScript
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.Promise=e():"undefined"!=typeof global?global.Promise=e():"undefined"!=typeof self&&(self.Promise=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
/**
|
|
* ES6 global Promise shim
|
|
*/
|
|
var unhandledRejections = require('../lib/decorators/unhandledRejection');
|
|
var PromiseConstructor = unhandledRejections(require('../lib/Promise'));
|
|
|
|
module.exports = typeof global != 'undefined' ? (global.Promise = PromiseConstructor)
|
|
: typeof self != 'undefined' ? (self.Promise = PromiseConstructor)
|
|
: PromiseConstructor;
|
|
|
|
},{"../lib/Promise":2,"../lib/decorators/unhandledRejection":4}],2:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
(function(define) { 'use strict';
|
|
define(function (require) {
|
|
|
|
var makePromise = require('./makePromise');
|
|
var Scheduler = require('./Scheduler');
|
|
var async = require('./env').asap;
|
|
|
|
return makePromise({
|
|
scheduler: new Scheduler(async)
|
|
});
|
|
|
|
});
|
|
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
|
|
|
|
},{"./Scheduler":3,"./env":5,"./makePromise":7}],3:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
(function(define) { 'use strict';
|
|
define(function() {
|
|
|
|
// Credit to Twisol (https://github.com/Twisol) for suggesting
|
|
// this type of extensible queue + trampoline approach for next-tick conflation.
|
|
|
|
/**
|
|
* Async task scheduler
|
|
* @param {function} async function to schedule a single async function
|
|
* @constructor
|
|
*/
|
|
function Scheduler(async) {
|
|
this._async = async;
|
|
this._running = false;
|
|
|
|
this._queue = this;
|
|
this._queueLen = 0;
|
|
this._afterQueue = {};
|
|
this._afterQueueLen = 0;
|
|
|
|
var self = this;
|
|
this.drain = function() {
|
|
self._drain();
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Enqueue a task
|
|
* @param {{ run:function }} task
|
|
*/
|
|
Scheduler.prototype.enqueue = function(task) {
|
|
this._queue[this._queueLen++] = task;
|
|
this.run();
|
|
};
|
|
|
|
/**
|
|
* Enqueue a task to run after the main task queue
|
|
* @param {{ run:function }} task
|
|
*/
|
|
Scheduler.prototype.afterQueue = function(task) {
|
|
this._afterQueue[this._afterQueueLen++] = task;
|
|
this.run();
|
|
};
|
|
|
|
Scheduler.prototype.run = function() {
|
|
if (!this._running) {
|
|
this._running = true;
|
|
this._async(this.drain);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Drain the handler queue entirely, and then the after queue
|
|
*/
|
|
Scheduler.prototype._drain = function() {
|
|
var i = 0;
|
|
for (; i < this._queueLen; ++i) {
|
|
this._queue[i].run();
|
|
this._queue[i] = void 0;
|
|
}
|
|
|
|
this._queueLen = 0;
|
|
this._running = false;
|
|
|
|
for (i = 0; i < this._afterQueueLen; ++i) {
|
|
this._afterQueue[i].run();
|
|
this._afterQueue[i] = void 0;
|
|
}
|
|
|
|
this._afterQueueLen = 0;
|
|
};
|
|
|
|
return Scheduler;
|
|
|
|
});
|
|
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
|
|
|
|
},{}],4:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
(function(define) { 'use strict';
|
|
define(function(require) {
|
|
|
|
var setTimer = require('../env').setTimer;
|
|
var format = require('../format');
|
|
|
|
return function unhandledRejection(Promise) {
|
|
|
|
var logError = noop;
|
|
var logInfo = noop;
|
|
var localConsole;
|
|
|
|
if(typeof console !== 'undefined') {
|
|
// Alias console to prevent things like uglify's drop_console option from
|
|
// removing console.log/error. Unhandled rejections fall into the same
|
|
// category as uncaught exceptions, and build tools shouldn't silence them.
|
|
localConsole = console;
|
|
logError = typeof localConsole.error !== 'undefined'
|
|
? function (e) { localConsole.error(e); }
|
|
: function (e) { localConsole.log(e); };
|
|
|
|
logInfo = typeof localConsole.info !== 'undefined'
|
|
? function (e) { localConsole.info(e); }
|
|
: function (e) { localConsole.log(e); };
|
|
}
|
|
|
|
Promise.onPotentiallyUnhandledRejection = function(rejection) {
|
|
enqueue(report, rejection);
|
|
};
|
|
|
|
Promise.onPotentiallyUnhandledRejectionHandled = function(rejection) {
|
|
enqueue(unreport, rejection);
|
|
};
|
|
|
|
Promise.onFatalRejection = function(rejection) {
|
|
enqueue(throwit, rejection.value);
|
|
};
|
|
|
|
var tasks = [];
|
|
var reported = [];
|
|
var running = null;
|
|
|
|
function report(r) {
|
|
if(!r.handled) {
|
|
reported.push(r);
|
|
logError('Potentially unhandled rejection [' + r.id + '] ' + format.formatError(r.value));
|
|
}
|
|
}
|
|
|
|
function unreport(r) {
|
|
var i = reported.indexOf(r);
|
|
if(i >= 0) {
|
|
reported.splice(i, 1);
|
|
logInfo('Handled previous rejection [' + r.id + '] ' + format.formatObject(r.value));
|
|
}
|
|
}
|
|
|
|
function enqueue(f, x) {
|
|
tasks.push(f, x);
|
|
if(running === null) {
|
|
running = setTimer(flush, 0);
|
|
}
|
|
}
|
|
|
|
function flush() {
|
|
running = null;
|
|
while(tasks.length > 0) {
|
|
tasks.shift()(tasks.shift());
|
|
}
|
|
}
|
|
|
|
return Promise;
|
|
};
|
|
|
|
function throwit(e) {
|
|
throw e;
|
|
}
|
|
|
|
function noop() {}
|
|
|
|
});
|
|
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
|
|
|
|
},{"../env":5,"../format":6}],5:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
/*global process,document,setTimeout,clearTimeout,MutationObserver,WebKitMutationObserver*/
|
|
(function(define) { 'use strict';
|
|
define(function(require) {
|
|
/*jshint maxcomplexity:6*/
|
|
|
|
// Sniff "best" async scheduling option
|
|
// Prefer process.nextTick or MutationObserver, then check for
|
|
// setTimeout, and finally vertx, since its the only env that doesn't
|
|
// have setTimeout
|
|
|
|
var MutationObs;
|
|
var capturedSetTimeout = typeof setTimeout !== 'undefined' && setTimeout;
|
|
|
|
// Default env
|
|
var setTimer = function(f, ms) { return setTimeout(f, ms); };
|
|
var clearTimer = function(t) { return clearTimeout(t); };
|
|
var asap = function (f) { return capturedSetTimeout(f, 0); };
|
|
|
|
// Detect specific env
|
|
if (isNode()) { // Node
|
|
asap = function (f) { return process.nextTick(f); };
|
|
|
|
} else if (MutationObs = hasMutationObserver()) { // Modern browser
|
|
asap = initMutationObserver(MutationObs);
|
|
|
|
} else if (!capturedSetTimeout) { // vert.x
|
|
var vertxRequire = require;
|
|
var vertx = vertxRequire('vertx');
|
|
setTimer = function (f, ms) { return vertx.setTimer(ms, f); };
|
|
clearTimer = vertx.cancelTimer;
|
|
asap = vertx.runOnLoop || vertx.runOnContext;
|
|
}
|
|
|
|
return {
|
|
setTimer: setTimer,
|
|
clearTimer: clearTimer,
|
|
asap: asap
|
|
};
|
|
|
|
function isNode () {
|
|
return typeof process !== 'undefined' &&
|
|
Object.prototype.toString.call(process) === '[object process]';
|
|
}
|
|
|
|
function hasMutationObserver () {
|
|
return (typeof MutationObserver !== 'undefined' && MutationObserver) ||
|
|
(typeof WebKitMutationObserver !== 'undefined' && WebKitMutationObserver);
|
|
}
|
|
|
|
function initMutationObserver(MutationObserver) {
|
|
var scheduled;
|
|
var node = document.createTextNode('');
|
|
var o = new MutationObserver(run);
|
|
o.observe(node, { characterData: true });
|
|
|
|
function run() {
|
|
var f = scheduled;
|
|
scheduled = void 0;
|
|
f();
|
|
}
|
|
|
|
var i = 0;
|
|
return function (f) {
|
|
scheduled = f;
|
|
node.data = (i ^= 1);
|
|
};
|
|
}
|
|
});
|
|
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); }));
|
|
|
|
},{}],6:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
(function(define) { 'use strict';
|
|
define(function() {
|
|
|
|
return {
|
|
formatError: formatError,
|
|
formatObject: formatObject,
|
|
tryStringify: tryStringify
|
|
};
|
|
|
|
/**
|
|
* Format an error into a string. If e is an Error and has a stack property,
|
|
* it's returned. Otherwise, e is formatted using formatObject, with a
|
|
* warning added about e not being a proper Error.
|
|
* @param {*} e
|
|
* @returns {String} formatted string, suitable for output to developers
|
|
*/
|
|
function formatError(e) {
|
|
var s = typeof e === 'object' && e !== null && (e.stack || e.message) ? e.stack || e.message : formatObject(e);
|
|
return e instanceof Error ? s : s + ' (WARNING: non-Error used)';
|
|
}
|
|
|
|
/**
|
|
* Format an object, detecting "plain" objects and running them through
|
|
* JSON.stringify if possible.
|
|
* @param {Object} o
|
|
* @returns {string}
|
|
*/
|
|
function formatObject(o) {
|
|
var s = String(o);
|
|
if(s === '[object Object]' && typeof JSON !== 'undefined') {
|
|
s = tryStringify(o, s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
/**
|
|
* Try to return the result of JSON.stringify(x). If that fails, return
|
|
* defaultValue
|
|
* @param {*} x
|
|
* @param {*} defaultValue
|
|
* @returns {String|*} JSON.stringify(x) or defaultValue
|
|
*/
|
|
function tryStringify(x, defaultValue) {
|
|
try {
|
|
return JSON.stringify(x);
|
|
} catch(e) {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
});
|
|
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
|
|
|
|
},{}],7:[function(require,module,exports){
|
|
/** @license MIT License (c) copyright 2010-2014 original author or authors */
|
|
/** @author Brian Cavalier */
|
|
/** @author John Hann */
|
|
|
|
(function(define) { 'use strict';
|
|
define(function() {
|
|
|
|
return function makePromise(environment) {
|
|
|
|
var tasks = environment.scheduler;
|
|
var emitRejection = initEmitRejection();
|
|
|
|
var objectCreate = Object.create ||
|
|
function(proto) {
|
|
function Child() {}
|
|
Child.prototype = proto;
|
|
return new Child();
|
|
};
|
|
|
|
/**
|
|
* Create a promise whose fate is determined by resolver
|
|
* @constructor
|
|
* @returns {Promise} promise
|
|
* @name Promise
|
|
*/
|
|
function Promise(resolver, handler) {
|
|
this._handler = resolver === Handler ? handler : init(resolver);
|
|
}
|
|
|
|
/**
|
|
* Run the supplied resolver
|
|
* @param resolver
|
|
* @returns {Pending}
|
|
*/
|
|
function init(resolver) {
|
|
var handler = new Pending();
|
|
|
|
try {
|
|
resolver(promiseResolve, promiseReject, promiseNotify);
|
|
} catch (e) {
|
|
promiseReject(e);
|
|
}
|
|
|
|
return handler;
|
|
|
|
/**
|
|
* Transition from pre-resolution state to post-resolution state, notifying
|
|
* all listeners of the ultimate fulfillment or rejection
|
|
* @param {*} x resolution value
|
|
*/
|
|
function promiseResolve (x) {
|
|
handler.resolve(x);
|
|
}
|
|
/**
|
|
* Reject this promise with reason, which will be used verbatim
|
|
* @param {Error|*} reason rejection reason, strongly suggested
|
|
* to be an Error type
|
|
*/
|
|
function promiseReject (reason) {
|
|
handler.reject(reason);
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
* Issue a progress event, notifying all progress listeners
|
|
* @param {*} x progress event payload to pass to all listeners
|
|
*/
|
|
function promiseNotify (x) {
|
|
handler.notify(x);
|
|
}
|
|
}
|
|
|
|
// Creation
|
|
|
|
Promise.resolve = resolve;
|
|
Promise.reject = reject;
|
|
Promise.never = never;
|
|
|
|
Promise._defer = defer;
|
|
Promise._handler = getHandler;
|
|
|
|
/**
|
|
* Returns a trusted promise. If x is already a trusted promise, it is
|
|
* returned, otherwise returns a new trusted Promise which follows x.
|
|
* @param {*} x
|
|
* @return {Promise} promise
|
|
*/
|
|
function resolve(x) {
|
|
return isPromise(x) ? x
|
|
: new Promise(Handler, new Async(getHandler(x)));
|
|
}
|
|
|
|
/**
|
|
* Return a reject promise with x as its reason (x is used verbatim)
|
|
* @param {*} x
|
|
* @returns {Promise} rejected promise
|
|
*/
|
|
function reject(x) {
|
|
return new Promise(Handler, new Async(new Rejected(x)));
|
|
}
|
|
|
|
/**
|
|
* Return a promise that remains pending forever
|
|
* @returns {Promise} forever-pending promise.
|
|
*/
|
|
function never() {
|
|
return foreverPendingPromise; // Should be frozen
|
|
}
|
|
|
|
/**
|
|
* Creates an internal {promise, resolver} pair
|
|
* @private
|
|
* @returns {Promise}
|
|
*/
|
|
function defer() {
|
|
return new Promise(Handler, new Pending());
|
|
}
|
|
|
|
// Transformation and flow control
|
|
|
|
/**
|
|
* Transform this promise's fulfillment value, returning a new Promise
|
|
* for the transformed result. If the promise cannot be fulfilled, onRejected
|
|
* is called with the reason. onProgress *may* be called with updates toward
|
|
* this promise's fulfillment.
|
|
* @param {function=} onFulfilled fulfillment handler
|
|
* @param {function=} onRejected rejection handler
|
|
* @param {function=} onProgress @deprecated progress handler
|
|
* @return {Promise} new promise
|
|
*/
|
|
Promise.prototype.then = function(onFulfilled, onRejected, onProgress) {
|
|
var parent = this._handler;
|
|
var state = parent.join().state();
|
|
|
|
if ((typeof onFulfilled !== 'function' && state > 0) ||
|
|
(typeof onRejected !== 'function' && state < 0)) {
|
|
// Short circuit: value will not change, simply share handler
|
|
return new this.constructor(Handler, parent);
|
|
}
|
|
|
|
var p = this._beget();
|
|
var child = p._handler;
|
|
|
|
parent.chain(child, parent.receiver, onFulfilled, onRejected, onProgress);
|
|
|
|
return p;
|
|
};
|
|
|
|
/**
|
|
* If this promise cannot be fulfilled due to an error, call onRejected to
|
|
* handle the error. Shortcut for .then(undefined, onRejected)
|
|
* @param {function?} onRejected
|
|
* @return {Promise}
|
|
*/
|
|
Promise.prototype['catch'] = function(onRejected) {
|
|
return this.then(void 0, onRejected);
|
|
};
|
|
|
|
/**
|
|
* Creates a new, pending promise of the same type as this promise
|
|
* @private
|
|
* @returns {Promise}
|
|
*/
|
|
Promise.prototype._beget = function() {
|
|
return begetFrom(this._handler, this.constructor);
|
|
};
|
|
|
|
function begetFrom(parent, Promise) {
|
|
var child = new Pending(parent.receiver, parent.join().context);
|
|
return new Promise(Handler, child);
|
|
}
|
|
|
|
// Array combinators
|
|
|
|
Promise.all = all;
|
|
Promise.race = race;
|
|
Promise._traverse = traverse;
|
|
|
|
/**
|
|
* Return a promise that will fulfill when all promises in the
|
|
* input array have fulfilled, or will reject when one of the
|
|
* promises rejects.
|
|
* @param {array} promises array of promises
|
|
* @returns {Promise} promise for array of fulfillment values
|
|
*/
|
|
function all(promises) {
|
|
return traverseWith(snd, null, promises);
|
|
}
|
|
|
|
/**
|
|
* Array<Promise<X>> -> Promise<Array<f(X)>>
|
|
* @private
|
|
* @param {function} f function to apply to each promise's value
|
|
* @param {Array} promises array of promises
|
|
* @returns {Promise} promise for transformed values
|
|
*/
|
|
function traverse(f, promises) {
|
|
return traverseWith(tryCatch2, f, promises);
|
|
}
|
|
|
|
function traverseWith(tryMap, f, promises) {
|
|
var handler = typeof f === 'function' ? mapAt : settleAt;
|
|
|
|
var resolver = new Pending();
|
|
var pending = promises.length >>> 0;
|
|
var results = new Array(pending);
|
|
|
|
for (var i = 0, x; i < promises.length && !resolver.resolved; ++i) {
|
|
x = promises[i];
|
|
|
|
if (x === void 0 && !(i in promises)) {
|
|
--pending;
|
|
continue;
|
|
}
|
|
|
|
traverseAt(promises, handler, i, x, resolver);
|
|
}
|
|
|
|
if(pending === 0) {
|
|
resolver.become(new Fulfilled(results));
|
|
}
|
|
|
|
return new Promise(Handler, resolver);
|
|
|
|
function mapAt(i, x, resolver) {
|
|
if(!resolver.resolved) {
|
|
traverseAt(promises, settleAt, i, tryMap(f, x, i), resolver);
|
|
}
|
|
}
|
|
|
|
function settleAt(i, x, resolver) {
|
|
results[i] = x;
|
|
if(--pending === 0) {
|
|
resolver.become(new Fulfilled(results));
|
|
}
|
|
}
|
|
}
|
|
|
|
function traverseAt(promises, handler, i, x, resolver) {
|
|
if (maybeThenable(x)) {
|
|
var h = getHandlerMaybeThenable(x);
|
|
var s = h.state();
|
|
|
|
if (s === 0) {
|
|
h.fold(handler, i, void 0, resolver);
|
|
} else if (s > 0) {
|
|
handler(i, h.value, resolver);
|
|
} else {
|
|
resolver.become(h);
|
|
visitRemaining(promises, i+1, h);
|
|
}
|
|
} else {
|
|
handler(i, x, resolver);
|
|
}
|
|
}
|
|
|
|
Promise._visitRemaining = visitRemaining;
|
|
function visitRemaining(promises, start, handler) {
|
|
for(var i=start; i<promises.length; ++i) {
|
|
markAsHandled(getHandler(promises[i]), handler);
|
|
}
|
|
}
|
|
|
|
function markAsHandled(h, handler) {
|
|
if(h === handler) {
|
|
return;
|
|
}
|
|
|
|
var s = h.state();
|
|
if(s === 0) {
|
|
h.visit(h, void 0, h._unreport);
|
|
} else if(s < 0) {
|
|
h._unreport();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fulfill-reject competitive race. Return a promise that will settle
|
|
* to the same state as the earliest input promise to settle.
|
|
*
|
|
* WARNING: The ES6 Promise spec requires that race()ing an empty array
|
|
* must return a promise that is pending forever. This implementation
|
|
* returns a singleton forever-pending promise, the same singleton that is
|
|
* returned by Promise.never(), thus can be checked with ===
|
|
*
|
|
* @param {array} promises array of promises to race
|
|
* @returns {Promise} if input is non-empty, a promise that will settle
|
|
* to the same outcome as the earliest input promise to settle. if empty
|
|
* is empty, returns a promise that will never settle.
|
|
*/
|
|
function race(promises) {
|
|
if(typeof promises !== 'object' || promises === null) {
|
|
return reject(new TypeError('non-iterable passed to race()'));
|
|
}
|
|
|
|
// Sigh, race([]) is untestable unless we return *something*
|
|
// that is recognizable without calling .then() on it.
|
|
return promises.length === 0 ? never()
|
|
: promises.length === 1 ? resolve(promises[0])
|
|
: runRace(promises);
|
|
}
|
|
|
|
function runRace(promises) {
|
|
var resolver = new Pending();
|
|
var i, x, h;
|
|
for(i=0; i<promises.length; ++i) {
|
|
x = promises[i];
|
|
if (x === void 0 && !(i in promises)) {
|
|
continue;
|
|
}
|
|
|
|
h = getHandler(x);
|
|
if(h.state() !== 0) {
|
|
resolver.become(h);
|
|
visitRemaining(promises, i+1, h);
|
|
break;
|
|
} else {
|
|
h.visit(resolver, resolver.resolve, resolver.reject);
|
|
}
|
|
}
|
|
return new Promise(Handler, resolver);
|
|
}
|
|
|
|
// Promise internals
|
|
// Below this, everything is @private
|
|
|
|
/**
|
|
* Get an appropriate handler for x, without checking for cycles
|
|
* @param {*} x
|
|
* @returns {object} handler
|
|
*/
|
|
function getHandler(x) {
|
|
if(isPromise(x)) {
|
|
return x._handler.join();
|
|
}
|
|
return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x);
|
|
}
|
|
|
|
/**
|
|
* Get a handler for thenable x.
|
|
* NOTE: You must only call this if maybeThenable(x) == true
|
|
* @param {object|function|Promise} x
|
|
* @returns {object} handler
|
|
*/
|
|
function getHandlerMaybeThenable(x) {
|
|
return isPromise(x) ? x._handler.join() : getHandlerUntrusted(x);
|
|
}
|
|
|
|
/**
|
|
* Get a handler for potentially untrusted thenable x
|
|
* @param {*} x
|
|
* @returns {object} handler
|
|
*/
|
|
function getHandlerUntrusted(x) {
|
|
try {
|
|
var untrustedThen = x.then;
|
|
return typeof untrustedThen === 'function'
|
|
? new Thenable(untrustedThen, x)
|
|
: new Fulfilled(x);
|
|
} catch(e) {
|
|
return new Rejected(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handler for a promise that is pending forever
|
|
* @constructor
|
|
*/
|
|
function Handler() {}
|
|
|
|
Handler.prototype.when
|
|
= Handler.prototype.become
|
|
= Handler.prototype.notify // deprecated
|
|
= Handler.prototype.fail
|
|
= Handler.prototype._unreport
|
|
= Handler.prototype._report
|
|
= noop;
|
|
|
|
Handler.prototype._state = 0;
|
|
|
|
Handler.prototype.state = function() {
|
|
return this._state;
|
|
};
|
|
|
|
/**
|
|
* Recursively collapse handler chain to find the handler
|
|
* nearest to the fully resolved value.
|
|
* @returns {object} handler nearest the fully resolved value
|
|
*/
|
|
Handler.prototype.join = function() {
|
|
var h = this;
|
|
while(h.handler !== void 0) {
|
|
h = h.handler;
|
|
}
|
|
return h;
|
|
};
|
|
|
|
Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) {
|
|
this.when({
|
|
resolver: to,
|
|
receiver: receiver,
|
|
fulfilled: fulfilled,
|
|
rejected: rejected,
|
|
progress: progress
|
|
});
|
|
};
|
|
|
|
Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) {
|
|
this.chain(failIfRejected, receiver, fulfilled, rejected, progress);
|
|
};
|
|
|
|
Handler.prototype.fold = function(f, z, c, to) {
|
|
this.when(new Fold(f, z, c, to));
|
|
};
|
|
|
|
/**
|
|
* Handler that invokes fail() on any handler it becomes
|
|
* @constructor
|
|
*/
|
|
function FailIfRejected() {}
|
|
|
|
inherit(Handler, FailIfRejected);
|
|
|
|
FailIfRejected.prototype.become = function(h) {
|
|
h.fail();
|
|
};
|
|
|
|
var failIfRejected = new FailIfRejected();
|
|
|
|
/**
|
|
* Handler that manages a queue of consumers waiting on a pending promise
|
|
* @constructor
|
|
*/
|
|
function Pending(receiver, inheritedContext) {
|
|
Promise.createContext(this, inheritedContext);
|
|
|
|
this.consumers = void 0;
|
|
this.receiver = receiver;
|
|
this.handler = void 0;
|
|
this.resolved = false;
|
|
}
|
|
|
|
inherit(Handler, Pending);
|
|
|
|
Pending.prototype._state = 0;
|
|
|
|
Pending.prototype.resolve = function(x) {
|
|
this.become(getHandler(x));
|
|
};
|
|
|
|
Pending.prototype.reject = function(x) {
|
|
if(this.resolved) {
|
|
return;
|
|
}
|
|
|
|
this.become(new Rejected(x));
|
|
};
|
|
|
|
Pending.prototype.join = function() {
|
|
if (!this.resolved) {
|
|
return this;
|
|
}
|
|
|
|
var h = this;
|
|
|
|
while (h.handler !== void 0) {
|
|
h = h.handler;
|
|
if (h === this) {
|
|
return this.handler = cycle();
|
|
}
|
|
}
|
|
|
|
return h;
|
|
};
|
|
|
|
Pending.prototype.run = function() {
|
|
var q = this.consumers;
|
|
var handler = this.handler;
|
|
this.handler = this.handler.join();
|
|
this.consumers = void 0;
|
|
|
|
for (var i = 0; i < q.length; ++i) {
|
|
handler.when(q[i]);
|
|
}
|
|
};
|
|
|
|
Pending.prototype.become = function(handler) {
|
|
if(this.resolved) {
|
|
return;
|
|
}
|
|
|
|
this.resolved = true;
|
|
this.handler = handler;
|
|
if(this.consumers !== void 0) {
|
|
tasks.enqueue(this);
|
|
}
|
|
|
|
if(this.context !== void 0) {
|
|
handler._report(this.context);
|
|
}
|
|
};
|
|
|
|
Pending.prototype.when = function(continuation) {
|
|
if(this.resolved) {
|
|
tasks.enqueue(new ContinuationTask(continuation, this.handler));
|
|
} else {
|
|
if(this.consumers === void 0) {
|
|
this.consumers = [continuation];
|
|
} else {
|
|
this.consumers.push(continuation);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
Pending.prototype.notify = function(x) {
|
|
if(!this.resolved) {
|
|
tasks.enqueue(new ProgressTask(x, this));
|
|
}
|
|
};
|
|
|
|
Pending.prototype.fail = function(context) {
|
|
var c = typeof context === 'undefined' ? this.context : context;
|
|
this.resolved && this.handler.join().fail(c);
|
|
};
|
|
|
|
Pending.prototype._report = function(context) {
|
|
this.resolved && this.handler.join()._report(context);
|
|
};
|
|
|
|
Pending.prototype._unreport = function() {
|
|
this.resolved && this.handler.join()._unreport();
|
|
};
|
|
|
|
/**
|
|
* Wrap another handler and force it into a future stack
|
|
* @param {object} handler
|
|
* @constructor
|
|
*/
|
|
function Async(handler) {
|
|
this.handler = handler;
|
|
}
|
|
|
|
inherit(Handler, Async);
|
|
|
|
Async.prototype.when = function(continuation) {
|
|
tasks.enqueue(new ContinuationTask(continuation, this));
|
|
};
|
|
|
|
Async.prototype._report = function(context) {
|
|
this.join()._report(context);
|
|
};
|
|
|
|
Async.prototype._unreport = function() {
|
|
this.join()._unreport();
|
|
};
|
|
|
|
/**
|
|
* Handler that wraps an untrusted thenable and assimilates it in a future stack
|
|
* @param {function} then
|
|
* @param {{then: function}} thenable
|
|
* @constructor
|
|
*/
|
|
function Thenable(then, thenable) {
|
|
Pending.call(this);
|
|
tasks.enqueue(new AssimilateTask(then, thenable, this));
|
|
}
|
|
|
|
inherit(Pending, Thenable);
|
|
|
|
/**
|
|
* Handler for a fulfilled promise
|
|
* @param {*} x fulfillment value
|
|
* @constructor
|
|
*/
|
|
function Fulfilled(x) {
|
|
Promise.createContext(this);
|
|
this.value = x;
|
|
}
|
|
|
|
inherit(Handler, Fulfilled);
|
|
|
|
Fulfilled.prototype._state = 1;
|
|
|
|
Fulfilled.prototype.fold = function(f, z, c, to) {
|
|
runContinuation3(f, z, this, c, to);
|
|
};
|
|
|
|
Fulfilled.prototype.when = function(cont) {
|
|
runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver);
|
|
};
|
|
|
|
var errorId = 0;
|
|
|
|
/**
|
|
* Handler for a rejected promise
|
|
* @param {*} x rejection reason
|
|
* @constructor
|
|
*/
|
|
function Rejected(x) {
|
|
Promise.createContext(this);
|
|
|
|
this.id = ++errorId;
|
|
this.value = x;
|
|
this.handled = false;
|
|
this.reported = false;
|
|
|
|
this._report();
|
|
}
|
|
|
|
inherit(Handler, Rejected);
|
|
|
|
Rejected.prototype._state = -1;
|
|
|
|
Rejected.prototype.fold = function(f, z, c, to) {
|
|
to.become(this);
|
|
};
|
|
|
|
Rejected.prototype.when = function(cont) {
|
|
if(typeof cont.rejected === 'function') {
|
|
this._unreport();
|
|
}
|
|
runContinuation1(cont.rejected, this, cont.receiver, cont.resolver);
|
|
};
|
|
|
|
Rejected.prototype._report = function(context) {
|
|
tasks.afterQueue(new ReportTask(this, context));
|
|
};
|
|
|
|
Rejected.prototype._unreport = function() {
|
|
if(this.handled) {
|
|
return;
|
|
}
|
|
this.handled = true;
|
|
tasks.afterQueue(new UnreportTask(this));
|
|
};
|
|
|
|
Rejected.prototype.fail = function(context) {
|
|
this.reported = true;
|
|
emitRejection('unhandledRejection', this);
|
|
Promise.onFatalRejection(this, context === void 0 ? this.context : context);
|
|
};
|
|
|
|
function ReportTask(rejection, context) {
|
|
this.rejection = rejection;
|
|
this.context = context;
|
|
}
|
|
|
|
ReportTask.prototype.run = function() {
|
|
if(!this.rejection.handled && !this.rejection.reported) {
|
|
this.rejection.reported = true;
|
|
emitRejection('unhandledRejection', this.rejection) ||
|
|
Promise.onPotentiallyUnhandledRejection(this.rejection, this.context);
|
|
}
|
|
};
|
|
|
|
function UnreportTask(rejection) {
|
|
this.rejection = rejection;
|
|
}
|
|
|
|
UnreportTask.prototype.run = function() {
|
|
if(this.rejection.reported) {
|
|
emitRejection('rejectionHandled', this.rejection) ||
|
|
Promise.onPotentiallyUnhandledRejectionHandled(this.rejection);
|
|
}
|
|
};
|
|
|
|
// Unhandled rejection hooks
|
|
// By default, everything is a noop
|
|
|
|
Promise.createContext
|
|
= Promise.enterContext
|
|
= Promise.exitContext
|
|
= Promise.onPotentiallyUnhandledRejection
|
|
= Promise.onPotentiallyUnhandledRejectionHandled
|
|
= Promise.onFatalRejection
|
|
= noop;
|
|
|
|
// Errors and singletons
|
|
|
|
var foreverPendingHandler = new Handler();
|
|
var foreverPendingPromise = new Promise(Handler, foreverPendingHandler);
|
|
|
|
function cycle() {
|
|
return new Rejected(new TypeError('Promise cycle'));
|
|
}
|
|
|
|
// Task runners
|
|
|
|
/**
|
|
* Run a single consumer
|
|
* @constructor
|
|
*/
|
|
function ContinuationTask(continuation, handler) {
|
|
this.continuation = continuation;
|
|
this.handler = handler;
|
|
}
|
|
|
|
ContinuationTask.prototype.run = function() {
|
|
this.handler.join().when(this.continuation);
|
|
};
|
|
|
|
/**
|
|
* Run a queue of progress handlers
|
|
* @constructor
|
|
*/
|
|
function ProgressTask(value, handler) {
|
|
this.handler = handler;
|
|
this.value = value;
|
|
}
|
|
|
|
ProgressTask.prototype.run = function() {
|
|
var q = this.handler.consumers;
|
|
if(q === void 0) {
|
|
return;
|
|
}
|
|
|
|
for (var c, i = 0; i < q.length; ++i) {
|
|
c = q[i];
|
|
runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Assimilate a thenable, sending it's value to resolver
|
|
* @param {function} then
|
|
* @param {object|function} thenable
|
|
* @param {object} resolver
|
|
* @constructor
|
|
*/
|
|
function AssimilateTask(then, thenable, resolver) {
|
|
this._then = then;
|
|
this.thenable = thenable;
|
|
this.resolver = resolver;
|
|
}
|
|
|
|
AssimilateTask.prototype.run = function() {
|
|
var h = this.resolver;
|
|
tryAssimilate(this._then, this.thenable, _resolve, _reject, _notify);
|
|
|
|
function _resolve(x) { h.resolve(x); }
|
|
function _reject(x) { h.reject(x); }
|
|
function _notify(x) { h.notify(x); }
|
|
};
|
|
|
|
function tryAssimilate(then, thenable, resolve, reject, notify) {
|
|
try {
|
|
then.call(thenable, resolve, reject, notify);
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fold a handler value with z
|
|
* @constructor
|
|
*/
|
|
function Fold(f, z, c, to) {
|
|
this.f = f; this.z = z; this.c = c; this.to = to;
|
|
this.resolver = failIfRejected;
|
|
this.receiver = this;
|
|
}
|
|
|
|
Fold.prototype.fulfilled = function(x) {
|
|
this.f.call(this.c, this.z, x, this.to);
|
|
};
|
|
|
|
Fold.prototype.rejected = function(x) {
|
|
this.to.reject(x);
|
|
};
|
|
|
|
Fold.prototype.progress = function(x) {
|
|
this.to.notify(x);
|
|
};
|
|
|
|
// Other helpers
|
|
|
|
/**
|
|
* @param {*} x
|
|
* @returns {boolean} true iff x is a trusted Promise
|
|
*/
|
|
function isPromise(x) {
|
|
return x instanceof Promise;
|
|
}
|
|
|
|
/**
|
|
* Test just enough to rule out primitives, in order to take faster
|
|
* paths in some code
|
|
* @param {*} x
|
|
* @returns {boolean} false iff x is guaranteed *not* to be a thenable
|
|
*/
|
|
function maybeThenable(x) {
|
|
return (typeof x === 'object' || typeof x === 'function') && x !== null;
|
|
}
|
|
|
|
function runContinuation1(f, h, receiver, next) {
|
|
if(typeof f !== 'function') {
|
|
return next.become(h);
|
|
}
|
|
|
|
Promise.enterContext(h);
|
|
tryCatchReject(f, h.value, receiver, next);
|
|
Promise.exitContext();
|
|
}
|
|
|
|
function runContinuation3(f, x, h, receiver, next) {
|
|
if(typeof f !== 'function') {
|
|
return next.become(h);
|
|
}
|
|
|
|
Promise.enterContext(h);
|
|
tryCatchReject3(f, x, h.value, receiver, next);
|
|
Promise.exitContext();
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
*/
|
|
function runNotify(f, x, h, receiver, next) {
|
|
if(typeof f !== 'function') {
|
|
return next.notify(x);
|
|
}
|
|
|
|
Promise.enterContext(h);
|
|
tryCatchReturn(f, x, receiver, next);
|
|
Promise.exitContext();
|
|
}
|
|
|
|
function tryCatch2(f, a, b) {
|
|
try {
|
|
return f(a, b);
|
|
} catch(e) {
|
|
return reject(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return f.call(thisArg, x), or if it throws return a rejected promise for
|
|
* the thrown exception
|
|
*/
|
|
function tryCatchReject(f, x, thisArg, next) {
|
|
try {
|
|
next.become(getHandler(f.call(thisArg, x)));
|
|
} catch(e) {
|
|
next.become(new Rejected(e));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Same as above, but includes the extra argument parameter.
|
|
*/
|
|
function tryCatchReject3(f, x, y, thisArg, next) {
|
|
try {
|
|
f.call(thisArg, x, y, next);
|
|
} catch(e) {
|
|
next.become(new Rejected(e));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @deprecated
|
|
* Return f.call(thisArg, x), or if it throws, *return* the exception
|
|
*/
|
|
function tryCatchReturn(f, x, thisArg, next) {
|
|
try {
|
|
next.notify(f.call(thisArg, x));
|
|
} catch(e) {
|
|
next.notify(e);
|
|
}
|
|
}
|
|
|
|
function inherit(Parent, Child) {
|
|
Child.prototype = objectCreate(Parent.prototype);
|
|
Child.prototype.constructor = Child;
|
|
}
|
|
|
|
function snd(x, y) {
|
|
return y;
|
|
}
|
|
|
|
function noop() {}
|
|
|
|
function hasCustomEvent() {
|
|
if(typeof CustomEvent === 'function') {
|
|
try {
|
|
var ev = new CustomEvent('unhandledRejection');
|
|
return ev instanceof CustomEvent;
|
|
} catch (ignoredException) {}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function hasInternetExplorerCustomEvent() {
|
|
if(typeof document !== 'undefined' && typeof document.createEvent === 'function') {
|
|
try {
|
|
// Try to create one event to make sure it's supported
|
|
var ev = document.createEvent('CustomEvent');
|
|
ev.initCustomEvent('eventType', false, true, {});
|
|
return true;
|
|
} catch (ignoredException) {}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function initEmitRejection() {
|
|
/*global process, self, CustomEvent*/
|
|
if(typeof process !== 'undefined' && process !== null
|
|
&& typeof process.emit === 'function') {
|
|
// Returning falsy here means to call the default
|
|
// onPotentiallyUnhandledRejection API. This is safe even in
|
|
// browserify since process.emit always returns falsy in browserify:
|
|
// https://github.com/defunctzombie/node-process/blob/master/browser.js#L40-L46
|
|
return function(type, rejection) {
|
|
return type === 'unhandledRejection'
|
|
? process.emit(type, rejection.value, rejection)
|
|
: process.emit(type, rejection);
|
|
};
|
|
} else if(typeof self !== 'undefined' && hasCustomEvent()) {
|
|
return (function (self, CustomEvent) {
|
|
return function (type, rejection) {
|
|
var ev = new CustomEvent(type, {
|
|
detail: {
|
|
reason: rejection.value,
|
|
key: rejection
|
|
},
|
|
bubbles: false,
|
|
cancelable: true
|
|
});
|
|
|
|
return !self.dispatchEvent(ev);
|
|
};
|
|
}(self, CustomEvent));
|
|
} else if(typeof self !== 'undefined' && hasInternetExplorerCustomEvent()) {
|
|
return (function(self, document) {
|
|
return function(type, rejection) {
|
|
var ev = document.createEvent('CustomEvent');
|
|
ev.initCustomEvent(type, false, true, {
|
|
reason: rejection.value,
|
|
key: rejection
|
|
});
|
|
|
|
return !self.dispatchEvent(ev);
|
|
};
|
|
}(self, document));
|
|
}
|
|
|
|
return noop;
|
|
}
|
|
|
|
return Promise;
|
|
};
|
|
});
|
|
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); }));
|
|
|
|
},{}]},{},[1])
|
|
//# sourceMappingURL=Promise.js.map
|
|
(1)
|
|
});
|
|
; |