Comparing version 3.2.3 to 3.3.0
@@ -19,3 +19,3 @@ !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){ | ||
},{"../lib/Promise":2,"../lib/decorators/unhandledRejection":5}],2:[function(require,module,exports){ | ||
},{"../lib/Promise":2,"../lib/decorators/unhandledRejection":6}],2:[function(require,module,exports){ | ||
/** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
@@ -29,3 +29,3 @@ /** @author Brian Cavalier */ | ||
var makePromise = require('./makePromise'); | ||
var Scheduler = require('./scheduler'); | ||
var Scheduler = require('./Scheduler'); | ||
var async = require('./async'); | ||
@@ -40,3 +40,3 @@ | ||
},{"./async":4,"./makePromise":6,"./scheduler":7}],3:[function(require,module,exports){ | ||
},{"./Scheduler":4,"./async":5,"./makePromise":7}],3:[function(require,module,exports){ | ||
/** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
@@ -121,2 +121,86 @@ /** @author Brian Cavalier */ | ||
var Queue = require('./Queue'); | ||
// 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._queue = new Queue(15); | ||
this._afterQueue = new Queue(5); | ||
this._running = false; | ||
var self = this; | ||
this.drain = function() { | ||
self._drain(); | ||
}; | ||
} | ||
/** | ||
* Enqueue a task | ||
* @param {{ run:function }} task | ||
*/ | ||
Scheduler.prototype.enqueue = function(task) { | ||
this._add(this._queue, task); | ||
}; | ||
/** | ||
* Enqueue a task to run after the main task queue | ||
* @param {{ run:function }} task | ||
*/ | ||
Scheduler.prototype.afterQueue = function(task) { | ||
this._add(this._afterQueue, task); | ||
}; | ||
/** | ||
* Drain the handler queue entirely, and then the after queue | ||
*/ | ||
Scheduler.prototype._drain = function() { | ||
runQueue(this._queue); | ||
this._running = false; | ||
runQueue(this._afterQueue); | ||
}; | ||
/** | ||
* Add a task to the q, and schedule drain if not already scheduled | ||
* @param {Queue} queue | ||
* @param {{run:function}} task | ||
* @private | ||
*/ | ||
Scheduler.prototype._add = function(queue, task) { | ||
queue.push(task); | ||
if(!this._running) { | ||
this._running = true; | ||
this._async(this.drain); | ||
} | ||
}; | ||
/** | ||
* Run all the tasks in the q | ||
* @param queue | ||
*/ | ||
function runQueue(queue) { | ||
while(queue.length > 0) { | ||
queue.shift().run(); | ||
} | ||
} | ||
return Scheduler; | ||
}); | ||
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); | ||
},{"./Queue":3}],5:[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) { | ||
// Sniff "best" async scheduling option | ||
@@ -177,3 +261,3 @@ // Prefer process.nextTick or MutationObserver, then check for | ||
},{}],5:[function(require,module,exports){ | ||
},{}],6:[function(require,module,exports){ | ||
/** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
@@ -282,3 +366,3 @@ /** @author Brian Cavalier */ | ||
},{"../timer":8}],6:[function(require,module,exports){ | ||
},{"../timer":8}],7:[function(require,module,exports){ | ||
/** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
@@ -315,6 +399,6 @@ /** @author Brian Cavalier */ | ||
* @param resolver | ||
* @returns {makePromise.DeferredHandler} | ||
* @returns {Pending} | ||
*/ | ||
function init(resolver) { | ||
var handler = new DeferredHandler(); | ||
var handler = new Pending(); | ||
@@ -362,2 +446,3 @@ try { | ||
Promise._defer = defer; | ||
Promise._handler = getHandler; | ||
@@ -372,3 +457,3 @@ /** | ||
return isPromise(x) ? x | ||
: new Promise(Handler, new AsyncHandler(getHandler(x))); | ||
: new Promise(Handler, new Async(getHandler(x))); | ||
} | ||
@@ -382,3 +467,3 @@ | ||
function reject(x) { | ||
return new Promise(Handler, new AsyncHandler(new RejectedHandler(x))); | ||
return new Promise(Handler, new Async(new Rejected(x))); | ||
} | ||
@@ -400,3 +485,3 @@ | ||
function defer() { | ||
return new Promise(Handler, new DeferredHandler()); | ||
return new Promise(Handler, new Pending()); | ||
} | ||
@@ -427,11 +512,4 @@ | ||
parent.when({ | ||
resolve: child.resolve, | ||
notify: child.notify, | ||
context: child, | ||
receiver: parent.receiver, | ||
fulfilled: onFulfilled, | ||
rejected: onRejected, | ||
progress: arguments.length > 2 ? arguments[2] : void 0 | ||
}); | ||
parent.chain(child, parent.receiver, onFulfilled, onRejected, | ||
arguments.length > 2 ? arguments[2] : void 0); | ||
@@ -459,3 +537,3 @@ return p; | ||
Promise.prototype._bindContext = function(thisArg) { | ||
return new Promise(Handler, new BoundHandler(this._handler, thisArg)); | ||
return new Promise(Handler, new Bound(this._handler, thisArg)); | ||
}; | ||
@@ -470,23 +548,6 @@ | ||
var parent = this._handler; | ||
var child = new DeferredHandler(parent.receiver, parent.join().context); | ||
var child = new Pending(parent.receiver, parent.join().context); | ||
return new this.constructor(Handler, child); | ||
}; | ||
/** | ||
* Check if x is a rejected promise, and if so, delegate to handler._fatal | ||
* @private | ||
* @param {*} x | ||
*/ | ||
Promise.prototype._maybeFatal = function(x) { | ||
if(!maybeThenable(x)) { | ||
return; | ||
} | ||
var handler = getHandler(x); | ||
var context = this._handler.context; | ||
handler.catchError(function() { | ||
this._fatal(context); | ||
}, handler); | ||
}; | ||
// Array combinators | ||
@@ -506,3 +567,3 @@ | ||
/*jshint maxcomplexity:8*/ | ||
var resolver = new DeferredHandler(); | ||
var resolver = new Pending(); | ||
var pending = promises.length >>> 0; | ||
@@ -527,3 +588,3 @@ var results = new Array(pending); | ||
if (s === 0) { | ||
resolveOne(resolver, results, h, i); | ||
h.fold(settleAt, i, results, resolver); | ||
} else if (s > 0) { | ||
@@ -544,13 +605,13 @@ results[i] = h.value; | ||
if(pending === 0) { | ||
resolver.become(new FulfilledHandler(results)); | ||
resolver.become(new Fulfilled(results)); | ||
} | ||
return new Promise(Handler, resolver); | ||
function resolveOne(resolver, results, handler, i) { | ||
handler.map(function(x) { | ||
results[i] = x; | ||
if(--pending === 0) { | ||
this.become(new FulfilledHandler(results)); | ||
} | ||
}, resolver); | ||
function settleAt(i, x, resolver) { | ||
/*jshint validthis:true*/ | ||
this[i] = x; | ||
if(--pending === 0) { | ||
resolver.become(new Fulfilled(this)); | ||
} | ||
} | ||
@@ -580,3 +641,3 @@ } | ||
var h = new DeferredHandler(); | ||
var h = new Pending(); | ||
var i, x; | ||
@@ -586,3 +647,3 @@ for(i=0; i<promises.length; ++i) { | ||
if (x !== void 0 && i in promises) { | ||
getHandler(x).chain(h, h.resolve, h.reject); | ||
getHandler(x).visit(h, h.resolve, h.reject); | ||
} | ||
@@ -594,6 +655,6 @@ } | ||
// Promise internals | ||
// Below this, everything is @private | ||
/** | ||
* Get an appropriate handler for x, without checking for cycles | ||
* @private | ||
* @param {*} x | ||
@@ -606,9 +667,5 @@ * @returns {object} handler | ||
} | ||
return maybeThenable(x) ? getHandlerUntrusted(x) : new FulfilledHandler(x); | ||
return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x); | ||
} | ||
function isPromise(x) { | ||
return x instanceof Promise; | ||
} | ||
/** | ||
@@ -623,6 +680,6 @@ * Get a handler for potentially untrusted thenable x | ||
return typeof untrustedThen === 'function' | ||
? new ThenableHandler(untrustedThen, x) | ||
: new FulfilledHandler(x); | ||
? new Thenable(untrustedThen, x) | ||
: new Fulfilled(x); | ||
} catch(e) { | ||
return new RejectedHandler(e); | ||
return new Rejected(e); | ||
} | ||
@@ -633,3 +690,2 @@ } | ||
* Handler for a promise that is pending forever | ||
* @private | ||
* @constructor | ||
@@ -640,6 +696,5 @@ */ | ||
Handler.prototype.when | ||
= Handler.prototype.resolve | ||
= Handler.prototype.reject | ||
= Handler.prototype.become | ||
= Handler.prototype.notify | ||
= Handler.prototype._fatal | ||
= Handler.prototype.fail | ||
= Handler.prototype._unreport | ||
@@ -670,8 +725,6 @@ = Handler.prototype._report | ||
Handler.prototype.chain = function(to, fulfilled, rejected, progress) { | ||
Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) { | ||
this.when({ | ||
resolve: noop, | ||
notify: noop, | ||
context: void 0, | ||
receiver: to, | ||
resolver: to, | ||
receiver: receiver, | ||
fulfilled: fulfilled, | ||
@@ -683,24 +736,31 @@ rejected: rejected, | ||
Handler.prototype.map = function(f, to) { | ||
this.chain(to, f, to.reject, to.notify); | ||
Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) { | ||
this.chain(failIfRejected, receiver, fulfilled, rejected, progress); | ||
}; | ||
Handler.prototype.catchError = function(f, to) { | ||
this.chain(to, to.resolve, f, to.notify); | ||
Handler.prototype.fold = function(f, z, c, to) { | ||
this.visit(to, function(x) { | ||
f.call(c, z, x, this); | ||
}, to.reject, to.notify); | ||
}; | ||
Handler.prototype.fold = function(to, f, z) { | ||
this.join().map(function(x) { | ||
getHandler(z).map(function(z) { | ||
this.resolve(tryCatchReject2(f, z, x, this.receiver)); | ||
}, this); | ||
}, 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 | ||
* @private | ||
* @constructor | ||
*/ | ||
function DeferredHandler(receiver, inheritedContext) { | ||
function Pending(receiver, inheritedContext) { | ||
Promise.createContext(this, inheritedContext); | ||
@@ -714,38 +774,40 @@ | ||
inherit(Handler, DeferredHandler); | ||
inherit(Handler, Pending); | ||
DeferredHandler.prototype._state = 0; | ||
Pending.prototype._state = 0; | ||
DeferredHandler.prototype.inspect = function() { | ||
Pending.prototype.inspect = function() { | ||
return this.resolved ? this.join().inspect() : toPendingState(); | ||
}; | ||
DeferredHandler.prototype.resolve = function(x) { | ||
if(!this.resolved) { | ||
this.become(getHandler(x)); | ||
} | ||
Pending.prototype.resolve = function(x) { | ||
this.become(getHandler(x)); | ||
}; | ||
DeferredHandler.prototype.reject = function(x) { | ||
if(!this.resolved) { | ||
this.become(new RejectedHandler(x)); | ||
Pending.prototype.reject = function(x) { | ||
if(this.resolved) { | ||
return; | ||
} | ||
this.become(new Rejected(x)); | ||
}; | ||
DeferredHandler.prototype.join = function() { | ||
if (this.resolved) { | ||
var h = this; | ||
while(h.handler !== void 0) { | ||
h = h.handler; | ||
if(h === this) { | ||
return this.handler = new Cycle(); | ||
} | ||
} | ||
return h; | ||
} else { | ||
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; | ||
}; | ||
DeferredHandler.prototype.run = function() { | ||
Pending.prototype.run = function() { | ||
var q = this.consumers; | ||
@@ -760,3 +822,7 @@ var handler = this.join(); | ||
DeferredHandler.prototype.become = function(handler) { | ||
Pending.prototype.become = function(handler) { | ||
if(this.resolved) { | ||
return; | ||
} | ||
this.resolved = true; | ||
@@ -773,3 +839,3 @@ this.handler = handler; | ||
DeferredHandler.prototype.when = function(continuation) { | ||
Pending.prototype.when = function(continuation) { | ||
if(this.resolved) { | ||
@@ -786,42 +852,41 @@ tasks.enqueue(new ContinuationTask(continuation, this.handler)); | ||
DeferredHandler.prototype.notify = function(x) { | ||
Pending.prototype.notify = function(x) { | ||
if(!this.resolved) { | ||
tasks.enqueue(new ProgressTask(this, x)); | ||
tasks.enqueue(new ProgressTask(x, this)); | ||
} | ||
}; | ||
DeferredHandler.prototype._report = function(context) { | ||
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); | ||
}; | ||
DeferredHandler.prototype._unreport = function() { | ||
Pending.prototype._unreport = function() { | ||
this.resolved && this.handler.join()._unreport(); | ||
}; | ||
DeferredHandler.prototype._fatal = function(context) { | ||
var c = typeof context === 'undefined' ? this.context : context; | ||
this.resolved && this.handler.join()._fatal(c); | ||
}; | ||
/** | ||
* Abstract base for handler that delegates to another handler | ||
* @private | ||
* @param {object} handler | ||
* @constructor | ||
*/ | ||
function DelegateHandler(handler) { | ||
function Delegating(handler) { | ||
this.handler = handler; | ||
} | ||
inherit(Handler, DelegateHandler); | ||
inherit(Handler, Delegating); | ||
DelegateHandler.prototype.inspect = function() { | ||
Delegating.prototype.inspect = function() { | ||
return this.join().inspect(); | ||
}; | ||
DelegateHandler.prototype._report = function(context) { | ||
Delegating.prototype._report = function(context) { | ||
this.join()._report(context); | ||
}; | ||
DelegateHandler.prototype._unreport = function() { | ||
Delegating.prototype._unreport = function() { | ||
this.join()._unreport(); | ||
@@ -832,14 +897,13 @@ }; | ||
* Wrap another handler and force it into a future stack | ||
* @private | ||
* @param {object} handler | ||
* @constructor | ||
*/ | ||
function AsyncHandler(handler) { | ||
DelegateHandler.call(this, handler); | ||
function Async(handler) { | ||
Delegating.call(this, handler); | ||
} | ||
inherit(DelegateHandler, AsyncHandler); | ||
inherit(Delegating, Async); | ||
AsyncHandler.prototype.when = function(continuation) { | ||
tasks.enqueue(new ContinuationTask(continuation, this.join())); | ||
Async.prototype.when = function(continuation) { | ||
tasks.enqueue(new ContinuationTask(continuation, this)); | ||
}; | ||
@@ -849,3 +913,2 @@ | ||
* Handler that follows another handler, injecting a receiver | ||
* @private | ||
* @param {object} handler another handler to follow | ||
@@ -855,10 +918,10 @@ * @param {object=undefined} receiver | ||
*/ | ||
function BoundHandler(handler, receiver) { | ||
DelegateHandler.call(this, handler); | ||
function Bound(handler, receiver) { | ||
Delegating.call(this, handler); | ||
this.receiver = receiver; | ||
} | ||
inherit(DelegateHandler, BoundHandler); | ||
inherit(Delegating, Bound); | ||
BoundHandler.prototype.when = function(continuation) { | ||
Bound.prototype.when = function(continuation) { | ||
// Because handlers are allowed to be shared among promises, | ||
@@ -876,3 +939,2 @@ // each of which possibly having a different receiver, we have | ||
* Handler that wraps an untrusted thenable and assimilates it in a future stack | ||
* @private | ||
* @param {function} then | ||
@@ -882,16 +944,15 @@ * @param {{then: function}} thenable | ||
*/ | ||
function ThenableHandler(then, thenable) { | ||
DeferredHandler.call(this); | ||
function Thenable(then, thenable) { | ||
Pending.call(this); | ||
tasks.enqueue(new AssimilateTask(then, thenable, this)); | ||
} | ||
inherit(DeferredHandler, ThenableHandler); | ||
inherit(Pending, Thenable); | ||
/** | ||
* Handler for a fulfilled promise | ||
* @private | ||
* @param {*} x fulfillment value | ||
* @constructor | ||
*/ | ||
function FulfilledHandler(x) { | ||
function Fulfilled(x) { | ||
Promise.createContext(this); | ||
@@ -901,35 +962,29 @@ this.value = x; | ||
inherit(Handler, FulfilledHandler); | ||
inherit(Handler, Fulfilled); | ||
FulfilledHandler.prototype._state = 1; | ||
Fulfilled.prototype._state = 1; | ||
FulfilledHandler.prototype.inspect = function() { | ||
Fulfilled.prototype.inspect = function() { | ||
return { state: 'fulfilled', value: this.value }; | ||
}; | ||
FulfilledHandler.prototype.when = function(cont) { | ||
var x; | ||
Fulfilled.prototype.fold = function(f, z, c, to) { | ||
runContinuation3(f, z, this, c, to); | ||
}; | ||
if (typeof cont.fulfilled === 'function') { | ||
Promise.enterContext(this); | ||
x = tryCatchReject(cont.fulfilled, this.value, cont.receiver); | ||
Promise.exitContext(); | ||
} else { | ||
x = this.value; | ||
} | ||
cont.resolve.call(cont.context, x); | ||
Fulfilled.prototype.when = function(cont) { | ||
runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver); | ||
}; | ||
var id = 0; | ||
var errorId = 0; | ||
/** | ||
* Handler for a rejected promise | ||
* @private | ||
* @param {*} x rejection reason | ||
* @constructor | ||
*/ | ||
function RejectedHandler(x) { | ||
function Rejected(x) { | ||
Promise.createContext(this); | ||
this.id = ++id; | ||
this.id = ++errorId; | ||
this.value = x; | ||
@@ -942,52 +997,55 @@ this.handled = false; | ||
inherit(Handler, RejectedHandler); | ||
inherit(Handler, Rejected); | ||
RejectedHandler.prototype._state = -1; | ||
Rejected.prototype._state = -1; | ||
RejectedHandler.prototype.inspect = function() { | ||
Rejected.prototype.inspect = function() { | ||
return { state: 'rejected', reason: this.value }; | ||
}; | ||
RejectedHandler.prototype.when = function(cont) { | ||
var x; | ||
Rejected.prototype.fold = function(f, z, c, to) { | ||
this._unreport(); | ||
to.become(this); | ||
}; | ||
if (typeof cont.rejected === 'function') { | ||
this._unreport(); | ||
Promise.enterContext(this); | ||
x = tryCatchReject(cont.rejected, this.value, cont.receiver); | ||
Promise.exitContext(); | ||
} else { | ||
x = new Promise(Handler, this); | ||
} | ||
cont.resolve.call(cont.context, x); | ||
Rejected.prototype.when = function(cont) { | ||
this._unreport(); | ||
runContinuation1(cont.rejected, this, cont.receiver, cont.resolver); | ||
}; | ||
RejectedHandler.prototype._report = function(context) { | ||
tasks.afterQueue(reportUnhandled, this, context); | ||
Rejected.prototype._report = function(context) { | ||
tasks.afterQueue(new ReportTask(this, context)); | ||
}; | ||
RejectedHandler.prototype._unreport = function() { | ||
Rejected.prototype._unreport = function() { | ||
this.handled = true; | ||
tasks.afterQueue(reportHandled, this); | ||
tasks.afterQueue(new UnreportTask(this)); | ||
}; | ||
RejectedHandler.prototype._fatal = function(context) { | ||
Promise.onFatalRejection(this, context); | ||
Rejected.prototype.fail = function(context) { | ||
Promise.onFatalRejection(this, context === void 0 ? this.context : context); | ||
}; | ||
function reportUnhandled(rejection, context) { | ||
if(!rejection.handled) { | ||
rejection.reported = true; | ||
Promise.onPotentiallyUnhandledRejection(rejection, context); | ||
} | ||
function ReportTask(rejection, context) { | ||
this.rejection = rejection; | ||
this.context = context; | ||
} | ||
function reportHandled(rejection) { | ||
if(rejection.reported) { | ||
Promise.onPotentiallyUnhandledRejectionHandled(rejection); | ||
ReportTask.prototype.run = function() { | ||
if(!this.rejection.handled) { | ||
this.rejection.reported = true; | ||
Promise.onPotentiallyUnhandledRejection(this.rejection, this.context); | ||
} | ||
}; | ||
function UnreportTask(rejection) { | ||
this.rejection = rejection; | ||
} | ||
UnreportTask.prototype.run = function() { | ||
if(this.rejection.reported) { | ||
Promise.onPotentiallyUnhandledRejectionHandled(this.rejection); | ||
} | ||
}; | ||
// Unhandled rejection hooks | ||
@@ -1010,8 +1068,6 @@ // By default, everything is a noop | ||
function Cycle() { | ||
RejectedHandler.call(this, new TypeError('Promise cycle')); | ||
function cycle() { | ||
return new Rejected(new TypeError('Promise cycle')); | ||
} | ||
inherit(RejectedHandler, Cycle); | ||
// Snapshot states | ||
@@ -1021,3 +1077,2 @@ | ||
* Creates a pending state snapshot | ||
* @private | ||
* @returns {{state:'pending'}} | ||
@@ -1033,3 +1088,2 @@ */ | ||
* Run a single consumer | ||
* @private | ||
* @constructor | ||
@@ -1048,6 +1102,5 @@ */ | ||
* Run a queue of progress handlers | ||
* @private | ||
* @constructor | ||
*/ | ||
function ProgressTask(handler, value) { | ||
function ProgressTask(value, handler) { | ||
this.handler = handler; | ||
@@ -1062,19 +1115,11 @@ this.value = value; | ||
} | ||
// First progress handler is at index 1 | ||
for (var i = 0; i < q.length; ++i) { | ||
this._notify(q[i]); | ||
for (var c, i = 0; i < q.length; ++i) { | ||
c = q[i]; | ||
runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver); | ||
} | ||
}; | ||
ProgressTask.prototype._notify = function(continuation) { | ||
var x = typeof continuation.progress === 'function' | ||
? tryCatchReturn(continuation.progress, this.value, continuation.receiver) | ||
: this.value; | ||
continuation.notify.call(continuation.context, x); | ||
}; | ||
/** | ||
* Assimilate a thenable, sending it's value to resolver | ||
* @private | ||
* @param {function} then | ||
@@ -1112,4 +1157,14 @@ * @param {object|function} thenable | ||
* @param {*} x | ||
* @returns {boolean} false iff x is guaranteed not to be a thenable | ||
* @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) { | ||
@@ -1119,12 +1174,41 @@ 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(); | ||
} | ||
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(); | ||
} | ||
/** | ||
* Return f.call(thisArg, x), or if it throws return a rejected promise for | ||
* the thrown exception | ||
* @private | ||
*/ | ||
function tryCatchReject(f, x, thisArg) { | ||
function tryCatchReject(f, x, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x); | ||
next.become(getHandler(f.call(thisArg, x))); | ||
} catch(e) { | ||
return reject(e); | ||
next.become(new Rejected(e)); | ||
} | ||
@@ -1135,9 +1219,8 @@ } | ||
* Same as above, but includes the extra argument parameter. | ||
* @private | ||
*/ | ||
function tryCatchReject2(f, x, y, thisArg) { | ||
function tryCatchReject3(f, x, y, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x, y); | ||
f.call(thisArg, x, y, next); | ||
} catch(e) { | ||
return reject(e); | ||
next.become(new Rejected(e)); | ||
} | ||
@@ -1148,9 +1231,8 @@ } | ||
* Return f.call(thisArg, x), or if it throws, *return* the exception | ||
* @private | ||
*/ | ||
function tryCatchReturn(f, x, thisArg) { | ||
function tryCatchReturn(f, x, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x); | ||
next.notify(f.call(thisArg, x)); | ||
} catch(e) { | ||
return e; | ||
next.notify(e); | ||
} | ||
@@ -1171,3 +1253,3 @@ } | ||
},{}],7:[function(require,module,exports){ | ||
},{}],8:[function(require,module,exports){ | ||
/** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
@@ -1179,74 +1261,2 @@ /** @author Brian Cavalier */ | ||
define(function(require) { | ||
var Queue = require('./Queue'); | ||
// Credit to Twisol (https://github.com/Twisol) for suggesting | ||
// this type of extensible queue + trampoline approach for next-tick conflation. | ||
function Scheduler(enqueue) { | ||
this._enqueue = enqueue; | ||
this._handlerQueue = new Queue(15); | ||
this._afterQueue = new Queue(5); | ||
this._running = false; | ||
var self = this; | ||
this.drain = function() { | ||
self._drain(); | ||
}; | ||
} | ||
/** | ||
* Enqueue a task. If the queue is not currently scheduled to be | ||
* drained, schedule it. | ||
* @param {function} task | ||
*/ | ||
Scheduler.prototype.enqueue = function(task) { | ||
this._handlerQueue.push(task); | ||
if(!this._running) { | ||
this._running = true; | ||
this._enqueue(this.drain); | ||
} | ||
}; | ||
Scheduler.prototype.afterQueue = function(f, x, y) { | ||
this._afterQueue.push(f); | ||
this._afterQueue.push(x); | ||
this._afterQueue.push(y); | ||
if(!this._running) { | ||
this._running = true; | ||
this._enqueue(this.drain); | ||
} | ||
}; | ||
/** | ||
* Drain the handler queue entirely, being careful to allow the | ||
* queue to be extended while it is being processed, and to continue | ||
* processing until it is truly empty. | ||
*/ | ||
Scheduler.prototype._drain = function() { | ||
var q = this._handlerQueue; | ||
while(q.length > 0) { | ||
q.shift().run(); | ||
} | ||
this._running = false; | ||
q = this._afterQueue; | ||
while(q.length > 0) { | ||
q.shift()(q.shift(), q.shift()); | ||
} | ||
}; | ||
return Scheduler; | ||
}); | ||
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(require); })); | ||
},{"./Queue":3}],8:[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) { | ||
/*global setTimeout,clearTimeout*/ | ||
@@ -1253,0 +1263,0 @@ var cjsRequire, vertx, setTimer, clearTimer; |
@@ -31,3 +31,3 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
* onFulfilled.apply(void 0, array) | ||
* @param (function) onFulfilled function to apply | ||
* @param {function} onFulfilled function to apply | ||
* @returns {Promise} promise for the result of applying onFulfilled | ||
@@ -53,12 +53,7 @@ */ | ||
return new Promise(function(resolve, reject) { | ||
var pending = 0; | ||
var errors = []; | ||
var pending = initRace(promises, resolve, handleReject); | ||
arrayForEach.call(promises, function(p) { | ||
++pending; | ||
toPromise(p).then(resolve, handleReject); | ||
}); | ||
if(pending === 0) { | ||
resolve(); | ||
reject(new RangeError('any() input must not be empty')); | ||
} | ||
@@ -89,12 +84,7 @@ | ||
return new Promise(function(resolve, reject, notify) { | ||
var nFulfill = 0; | ||
var nReject; | ||
var results = []; | ||
var errors = []; | ||
var nReject; | ||
var nFulfill = initRace(promises, handleResolve, handleReject, notify); | ||
arrayForEach.call(promises, function(p) { | ||
++nFulfill; | ||
toPromise(p).then(handleResolve, handleReject, notify); | ||
}); | ||
n = Math.max(n, 0); | ||
@@ -104,5 +94,7 @@ nReject = (nFulfill - n + 1); | ||
if(nFulfill === 0) { | ||
if(n > nFulfill) { | ||
reject(new RangeError('some() input must contain at least ' | ||
+ n + ' element(s), but had ' + nFulfill)); | ||
} else if(nFulfill === 0) { | ||
resolve(results); | ||
return; | ||
} | ||
@@ -134,2 +126,13 @@ | ||
function initRace(promises, resolve, reject, notify) { | ||
var pending = 0; | ||
arrayForEach.call(promises, function(p) { | ||
++pending; | ||
toPromise(p).then(resolve, reject, notify); | ||
}); | ||
return pending; | ||
} | ||
/** | ||
@@ -168,21 +171,17 @@ * Apply f to the value of each promise in a list of promises | ||
function reduce(promises, f) { | ||
var reducer = makeReducer(f); | ||
return arguments.length > 2 | ||
? arrayReduce.call(promises, reducer, arguments[2]) | ||
: arrayReduce.call(promises, reducer); | ||
function reducer(result, x, i) { | ||
return toPromise(result).then(function(r) { | ||
return toPromise(x).then(function(x) { | ||
return f(r, x, i); | ||
}); | ||
}); | ||
} | ||
} | ||
function reduceRight(promises, f) { | ||
var reducer = makeReducer(f); | ||
return arguments.length > 2 | ||
? arrayReduceRight.call(promises, reducer, arguments[2]) | ||
: arrayReduceRight.call(promises, reducer); | ||
} | ||
function reducer(result, x, i) { | ||
function makeReducer(f) { | ||
return function reducer(result, x, i) { | ||
return toPromise(result).then(function(r) { | ||
@@ -193,3 +192,3 @@ return toPromise(x).then(function(x) { | ||
}); | ||
} | ||
}; | ||
} | ||
@@ -199,3 +198,4 @@ }; | ||
}); | ||
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); |
@@ -23,6 +23,3 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
Promise.prototype.done = function(onResult, onError) { | ||
var h = this._handler; | ||
h.when({ resolve: this._maybeFatal, notify: noop, context: this, | ||
receiver: h.receiver, fulfilled: onResult, rejected: onError, | ||
progress: void 0 }); | ||
this._handler.visit(this._handler.receiver, onResult, onError); | ||
}; | ||
@@ -147,5 +144,5 @@ | ||
function noop() {} | ||
// function noop() {} | ||
}); | ||
}(typeof define === 'function' && define.amd ? define : function(factory) { module.exports = factory(); })); |
@@ -11,5 +11,11 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
Promise.prototype.fold = function(fn, arg) { | ||
Promise.prototype.fold = function(f, z) { | ||
var promise = this._beget(); | ||
this._handler.fold(promise._handler, fn, arg); | ||
this._handler.fold(function(z, x, to) { | ||
Promise._handler(z).fold(function(x, z, to) { | ||
to.resolve(f.call(this, z, x)); | ||
}, x, this, to); | ||
}, z, promise._handler.receiver, promise._handler); | ||
return promise; | ||
@@ -16,0 +22,0 @@ }; |
@@ -11,2 +11,8 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
function setTimeout(f, ms, x, y) { | ||
return timer.set(function() { | ||
f(x, y, ms); | ||
}, ms); | ||
} | ||
return function timed(Promise) { | ||
@@ -21,11 +27,14 @@ /** | ||
var p = this._beget(); | ||
var h = p._handler; | ||
this._handler.map(function delay(x) { | ||
timer.set(function() { h.resolve(x); }, ms); | ||
}, h); | ||
this._handler.fold(handleDelay, ms, void 0, p._handler); | ||
return p; | ||
}; | ||
function handleDelay(ms, x, h) { | ||
setTimeout(resolveDelay, ms, x, h); | ||
} | ||
function resolveDelay(x, h) { | ||
h.resolve(x); | ||
} | ||
/** | ||
@@ -37,20 +46,19 @@ * Return a new promise that rejects after ms milliseconds unless | ||
* @param {Error|*=} reason optional rejection reason to use, defaults | ||
* to an Error if not provided | ||
* to a TimeoutError if not provided | ||
* @returns {Promise} | ||
*/ | ||
Promise.prototype.timeout = function(ms, reason) { | ||
var hasReason = arguments.length > 1; | ||
var p = this._beget(); | ||
var h = p._handler; | ||
var t = timer.set(onTimeout, ms); | ||
var t = setTimeout(onTimeout, ms, reason, p._handler); | ||
this._handler.chain(h, | ||
this._handler.visit(h, | ||
function onFulfill(x) { | ||
timer.clear(t); | ||
this.resolve(x); // this = p._handler | ||
this.resolve(x); // this = h | ||
}, | ||
function onReject(x) { | ||
timer.clear(t); | ||
this.reject(x); // this = p._handler | ||
this.reject(x); // this = h | ||
}, | ||
@@ -60,9 +68,11 @@ h.notify); | ||
return p; | ||
function onTimeout() { | ||
h.reject(hasReason | ||
? reason : new TimeoutError('timed out after ' + ms + 'ms')); | ||
} | ||
}; | ||
function onTimeout(reason, h, ms) { | ||
var e = typeof reason === 'undefined' | ||
? new TimeoutError('timed out after ' + ms + 'ms') | ||
: reason; | ||
h.reject(e); | ||
} | ||
return Promise; | ||
@@ -69,0 +79,0 @@ }; |
@@ -32,6 +32,6 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
* @param resolver | ||
* @returns {makePromise.DeferredHandler} | ||
* @returns {Pending} | ||
*/ | ||
function init(resolver) { | ||
var handler = new DeferredHandler(); | ||
var handler = new Pending(); | ||
@@ -79,2 +79,3 @@ try { | ||
Promise._defer = defer; | ||
Promise._handler = getHandler; | ||
@@ -89,3 +90,3 @@ /** | ||
return isPromise(x) ? x | ||
: new Promise(Handler, new AsyncHandler(getHandler(x))); | ||
: new Promise(Handler, new Async(getHandler(x))); | ||
} | ||
@@ -99,3 +100,3 @@ | ||
function reject(x) { | ||
return new Promise(Handler, new AsyncHandler(new RejectedHandler(x))); | ||
return new Promise(Handler, new Async(new Rejected(x))); | ||
} | ||
@@ -117,3 +118,3 @@ | ||
function defer() { | ||
return new Promise(Handler, new DeferredHandler()); | ||
return new Promise(Handler, new Pending()); | ||
} | ||
@@ -144,11 +145,4 @@ | ||
parent.when({ | ||
resolve: child.resolve, | ||
notify: child.notify, | ||
context: child, | ||
receiver: parent.receiver, | ||
fulfilled: onFulfilled, | ||
rejected: onRejected, | ||
progress: arguments.length > 2 ? arguments[2] : void 0 | ||
}); | ||
parent.chain(child, parent.receiver, onFulfilled, onRejected, | ||
arguments.length > 2 ? arguments[2] : void 0); | ||
@@ -176,3 +170,3 @@ return p; | ||
Promise.prototype._bindContext = function(thisArg) { | ||
return new Promise(Handler, new BoundHandler(this._handler, thisArg)); | ||
return new Promise(Handler, new Bound(this._handler, thisArg)); | ||
}; | ||
@@ -187,23 +181,6 @@ | ||
var parent = this._handler; | ||
var child = new DeferredHandler(parent.receiver, parent.join().context); | ||
var child = new Pending(parent.receiver, parent.join().context); | ||
return new this.constructor(Handler, child); | ||
}; | ||
/** | ||
* Check if x is a rejected promise, and if so, delegate to handler._fatal | ||
* @private | ||
* @param {*} x | ||
*/ | ||
Promise.prototype._maybeFatal = function(x) { | ||
if(!maybeThenable(x)) { | ||
return; | ||
} | ||
var handler = getHandler(x); | ||
var context = this._handler.context; | ||
handler.catchError(function() { | ||
this._fatal(context); | ||
}, handler); | ||
}; | ||
// Array combinators | ||
@@ -223,3 +200,3 @@ | ||
/*jshint maxcomplexity:8*/ | ||
var resolver = new DeferredHandler(); | ||
var resolver = new Pending(); | ||
var pending = promises.length >>> 0; | ||
@@ -244,3 +221,3 @@ var results = new Array(pending); | ||
if (s === 0) { | ||
resolveOne(resolver, results, h, i); | ||
h.fold(settleAt, i, results, resolver); | ||
} else if (s > 0) { | ||
@@ -261,13 +238,13 @@ results[i] = h.value; | ||
if(pending === 0) { | ||
resolver.become(new FulfilledHandler(results)); | ||
resolver.become(new Fulfilled(results)); | ||
} | ||
return new Promise(Handler, resolver); | ||
function resolveOne(resolver, results, handler, i) { | ||
handler.map(function(x) { | ||
results[i] = x; | ||
if(--pending === 0) { | ||
this.become(new FulfilledHandler(results)); | ||
} | ||
}, resolver); | ||
function settleAt(i, x, resolver) { | ||
/*jshint validthis:true*/ | ||
this[i] = x; | ||
if(--pending === 0) { | ||
resolver.become(new Fulfilled(this)); | ||
} | ||
} | ||
@@ -297,3 +274,3 @@ } | ||
var h = new DeferredHandler(); | ||
var h = new Pending(); | ||
var i, x; | ||
@@ -303,3 +280,3 @@ for(i=0; i<promises.length; ++i) { | ||
if (x !== void 0 && i in promises) { | ||
getHandler(x).chain(h, h.resolve, h.reject); | ||
getHandler(x).visit(h, h.resolve, h.reject); | ||
} | ||
@@ -311,6 +288,6 @@ } | ||
// Promise internals | ||
// Below this, everything is @private | ||
/** | ||
* Get an appropriate handler for x, without checking for cycles | ||
* @private | ||
* @param {*} x | ||
@@ -323,9 +300,5 @@ * @returns {object} handler | ||
} | ||
return maybeThenable(x) ? getHandlerUntrusted(x) : new FulfilledHandler(x); | ||
return maybeThenable(x) ? getHandlerUntrusted(x) : new Fulfilled(x); | ||
} | ||
function isPromise(x) { | ||
return x instanceof Promise; | ||
} | ||
/** | ||
@@ -340,6 +313,6 @@ * Get a handler for potentially untrusted thenable x | ||
return typeof untrustedThen === 'function' | ||
? new ThenableHandler(untrustedThen, x) | ||
: new FulfilledHandler(x); | ||
? new Thenable(untrustedThen, x) | ||
: new Fulfilled(x); | ||
} catch(e) { | ||
return new RejectedHandler(e); | ||
return new Rejected(e); | ||
} | ||
@@ -350,3 +323,2 @@ } | ||
* Handler for a promise that is pending forever | ||
* @private | ||
* @constructor | ||
@@ -357,6 +329,5 @@ */ | ||
Handler.prototype.when | ||
= Handler.prototype.resolve | ||
= Handler.prototype.reject | ||
= Handler.prototype.become | ||
= Handler.prototype.notify | ||
= Handler.prototype._fatal | ||
= Handler.prototype.fail | ||
= Handler.prototype._unreport | ||
@@ -387,8 +358,6 @@ = Handler.prototype._report | ||
Handler.prototype.chain = function(to, fulfilled, rejected, progress) { | ||
Handler.prototype.chain = function(to, receiver, fulfilled, rejected, progress) { | ||
this.when({ | ||
resolve: noop, | ||
notify: noop, | ||
context: void 0, | ||
receiver: to, | ||
resolver: to, | ||
receiver: receiver, | ||
fulfilled: fulfilled, | ||
@@ -400,24 +369,31 @@ rejected: rejected, | ||
Handler.prototype.map = function(f, to) { | ||
this.chain(to, f, to.reject, to.notify); | ||
Handler.prototype.visit = function(receiver, fulfilled, rejected, progress) { | ||
this.chain(failIfRejected, receiver, fulfilled, rejected, progress); | ||
}; | ||
Handler.prototype.catchError = function(f, to) { | ||
this.chain(to, to.resolve, f, to.notify); | ||
Handler.prototype.fold = function(f, z, c, to) { | ||
this.visit(to, function(x) { | ||
f.call(c, z, x, this); | ||
}, to.reject, to.notify); | ||
}; | ||
Handler.prototype.fold = function(to, f, z) { | ||
this.join().map(function(x) { | ||
getHandler(z).map(function(z) { | ||
this.resolve(tryCatchReject2(f, z, x, this.receiver)); | ||
}, this); | ||
}, 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 | ||
* @private | ||
* @constructor | ||
*/ | ||
function DeferredHandler(receiver, inheritedContext) { | ||
function Pending(receiver, inheritedContext) { | ||
Promise.createContext(this, inheritedContext); | ||
@@ -431,38 +407,40 @@ | ||
inherit(Handler, DeferredHandler); | ||
inherit(Handler, Pending); | ||
DeferredHandler.prototype._state = 0; | ||
Pending.prototype._state = 0; | ||
DeferredHandler.prototype.inspect = function() { | ||
Pending.prototype.inspect = function() { | ||
return this.resolved ? this.join().inspect() : toPendingState(); | ||
}; | ||
DeferredHandler.prototype.resolve = function(x) { | ||
if(!this.resolved) { | ||
this.become(getHandler(x)); | ||
} | ||
Pending.prototype.resolve = function(x) { | ||
this.become(getHandler(x)); | ||
}; | ||
DeferredHandler.prototype.reject = function(x) { | ||
if(!this.resolved) { | ||
this.become(new RejectedHandler(x)); | ||
Pending.prototype.reject = function(x) { | ||
if(this.resolved) { | ||
return; | ||
} | ||
this.become(new Rejected(x)); | ||
}; | ||
DeferredHandler.prototype.join = function() { | ||
if (this.resolved) { | ||
var h = this; | ||
while(h.handler !== void 0) { | ||
h = h.handler; | ||
if(h === this) { | ||
return this.handler = new Cycle(); | ||
} | ||
} | ||
return h; | ||
} else { | ||
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; | ||
}; | ||
DeferredHandler.prototype.run = function() { | ||
Pending.prototype.run = function() { | ||
var q = this.consumers; | ||
@@ -477,3 +455,7 @@ var handler = this.join(); | ||
DeferredHandler.prototype.become = function(handler) { | ||
Pending.prototype.become = function(handler) { | ||
if(this.resolved) { | ||
return; | ||
} | ||
this.resolved = true; | ||
@@ -490,3 +472,3 @@ this.handler = handler; | ||
DeferredHandler.prototype.when = function(continuation) { | ||
Pending.prototype.when = function(continuation) { | ||
if(this.resolved) { | ||
@@ -503,42 +485,41 @@ tasks.enqueue(new ContinuationTask(continuation, this.handler)); | ||
DeferredHandler.prototype.notify = function(x) { | ||
Pending.prototype.notify = function(x) { | ||
if(!this.resolved) { | ||
tasks.enqueue(new ProgressTask(this, x)); | ||
tasks.enqueue(new ProgressTask(x, this)); | ||
} | ||
}; | ||
DeferredHandler.prototype._report = function(context) { | ||
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); | ||
}; | ||
DeferredHandler.prototype._unreport = function() { | ||
Pending.prototype._unreport = function() { | ||
this.resolved && this.handler.join()._unreport(); | ||
}; | ||
DeferredHandler.prototype._fatal = function(context) { | ||
var c = typeof context === 'undefined' ? this.context : context; | ||
this.resolved && this.handler.join()._fatal(c); | ||
}; | ||
/** | ||
* Abstract base for handler that delegates to another handler | ||
* @private | ||
* @param {object} handler | ||
* @constructor | ||
*/ | ||
function DelegateHandler(handler) { | ||
function Delegating(handler) { | ||
this.handler = handler; | ||
} | ||
inherit(Handler, DelegateHandler); | ||
inherit(Handler, Delegating); | ||
DelegateHandler.prototype.inspect = function() { | ||
Delegating.prototype.inspect = function() { | ||
return this.join().inspect(); | ||
}; | ||
DelegateHandler.prototype._report = function(context) { | ||
Delegating.prototype._report = function(context) { | ||
this.join()._report(context); | ||
}; | ||
DelegateHandler.prototype._unreport = function() { | ||
Delegating.prototype._unreport = function() { | ||
this.join()._unreport(); | ||
@@ -549,14 +530,13 @@ }; | ||
* Wrap another handler and force it into a future stack | ||
* @private | ||
* @param {object} handler | ||
* @constructor | ||
*/ | ||
function AsyncHandler(handler) { | ||
DelegateHandler.call(this, handler); | ||
function Async(handler) { | ||
Delegating.call(this, handler); | ||
} | ||
inherit(DelegateHandler, AsyncHandler); | ||
inherit(Delegating, Async); | ||
AsyncHandler.prototype.when = function(continuation) { | ||
tasks.enqueue(new ContinuationTask(continuation, this.join())); | ||
Async.prototype.when = function(continuation) { | ||
tasks.enqueue(new ContinuationTask(continuation, this)); | ||
}; | ||
@@ -566,3 +546,2 @@ | ||
* Handler that follows another handler, injecting a receiver | ||
* @private | ||
* @param {object} handler another handler to follow | ||
@@ -572,10 +551,10 @@ * @param {object=undefined} receiver | ||
*/ | ||
function BoundHandler(handler, receiver) { | ||
DelegateHandler.call(this, handler); | ||
function Bound(handler, receiver) { | ||
Delegating.call(this, handler); | ||
this.receiver = receiver; | ||
} | ||
inherit(DelegateHandler, BoundHandler); | ||
inherit(Delegating, Bound); | ||
BoundHandler.prototype.when = function(continuation) { | ||
Bound.prototype.when = function(continuation) { | ||
// Because handlers are allowed to be shared among promises, | ||
@@ -593,3 +572,2 @@ // each of which possibly having a different receiver, we have | ||
* Handler that wraps an untrusted thenable and assimilates it in a future stack | ||
* @private | ||
* @param {function} then | ||
@@ -599,16 +577,15 @@ * @param {{then: function}} thenable | ||
*/ | ||
function ThenableHandler(then, thenable) { | ||
DeferredHandler.call(this); | ||
function Thenable(then, thenable) { | ||
Pending.call(this); | ||
tasks.enqueue(new AssimilateTask(then, thenable, this)); | ||
} | ||
inherit(DeferredHandler, ThenableHandler); | ||
inherit(Pending, Thenable); | ||
/** | ||
* Handler for a fulfilled promise | ||
* @private | ||
* @param {*} x fulfillment value | ||
* @constructor | ||
*/ | ||
function FulfilledHandler(x) { | ||
function Fulfilled(x) { | ||
Promise.createContext(this); | ||
@@ -618,35 +595,29 @@ this.value = x; | ||
inherit(Handler, FulfilledHandler); | ||
inherit(Handler, Fulfilled); | ||
FulfilledHandler.prototype._state = 1; | ||
Fulfilled.prototype._state = 1; | ||
FulfilledHandler.prototype.inspect = function() { | ||
Fulfilled.prototype.inspect = function() { | ||
return { state: 'fulfilled', value: this.value }; | ||
}; | ||
FulfilledHandler.prototype.when = function(cont) { | ||
var x; | ||
Fulfilled.prototype.fold = function(f, z, c, to) { | ||
runContinuation3(f, z, this, c, to); | ||
}; | ||
if (typeof cont.fulfilled === 'function') { | ||
Promise.enterContext(this); | ||
x = tryCatchReject(cont.fulfilled, this.value, cont.receiver); | ||
Promise.exitContext(); | ||
} else { | ||
x = this.value; | ||
} | ||
cont.resolve.call(cont.context, x); | ||
Fulfilled.prototype.when = function(cont) { | ||
runContinuation1(cont.fulfilled, this, cont.receiver, cont.resolver); | ||
}; | ||
var id = 0; | ||
var errorId = 0; | ||
/** | ||
* Handler for a rejected promise | ||
* @private | ||
* @param {*} x rejection reason | ||
* @constructor | ||
*/ | ||
function RejectedHandler(x) { | ||
function Rejected(x) { | ||
Promise.createContext(this); | ||
this.id = ++id; | ||
this.id = ++errorId; | ||
this.value = x; | ||
@@ -659,52 +630,55 @@ this.handled = false; | ||
inherit(Handler, RejectedHandler); | ||
inherit(Handler, Rejected); | ||
RejectedHandler.prototype._state = -1; | ||
Rejected.prototype._state = -1; | ||
RejectedHandler.prototype.inspect = function() { | ||
Rejected.prototype.inspect = function() { | ||
return { state: 'rejected', reason: this.value }; | ||
}; | ||
RejectedHandler.prototype.when = function(cont) { | ||
var x; | ||
Rejected.prototype.fold = function(f, z, c, to) { | ||
this._unreport(); | ||
to.become(this); | ||
}; | ||
if (typeof cont.rejected === 'function') { | ||
this._unreport(); | ||
Promise.enterContext(this); | ||
x = tryCatchReject(cont.rejected, this.value, cont.receiver); | ||
Promise.exitContext(); | ||
} else { | ||
x = new Promise(Handler, this); | ||
} | ||
cont.resolve.call(cont.context, x); | ||
Rejected.prototype.when = function(cont) { | ||
this._unreport(); | ||
runContinuation1(cont.rejected, this, cont.receiver, cont.resolver); | ||
}; | ||
RejectedHandler.prototype._report = function(context) { | ||
tasks.afterQueue(reportUnhandled, this, context); | ||
Rejected.prototype._report = function(context) { | ||
tasks.afterQueue(new ReportTask(this, context)); | ||
}; | ||
RejectedHandler.prototype._unreport = function() { | ||
Rejected.prototype._unreport = function() { | ||
this.handled = true; | ||
tasks.afterQueue(reportHandled, this); | ||
tasks.afterQueue(new UnreportTask(this)); | ||
}; | ||
RejectedHandler.prototype._fatal = function(context) { | ||
Promise.onFatalRejection(this, context); | ||
Rejected.prototype.fail = function(context) { | ||
Promise.onFatalRejection(this, context === void 0 ? this.context : context); | ||
}; | ||
function reportUnhandled(rejection, context) { | ||
if(!rejection.handled) { | ||
rejection.reported = true; | ||
Promise.onPotentiallyUnhandledRejection(rejection, context); | ||
} | ||
function ReportTask(rejection, context) { | ||
this.rejection = rejection; | ||
this.context = context; | ||
} | ||
function reportHandled(rejection) { | ||
if(rejection.reported) { | ||
Promise.onPotentiallyUnhandledRejectionHandled(rejection); | ||
ReportTask.prototype.run = function() { | ||
if(!this.rejection.handled) { | ||
this.rejection.reported = true; | ||
Promise.onPotentiallyUnhandledRejection(this.rejection, this.context); | ||
} | ||
}; | ||
function UnreportTask(rejection) { | ||
this.rejection = rejection; | ||
} | ||
UnreportTask.prototype.run = function() { | ||
if(this.rejection.reported) { | ||
Promise.onPotentiallyUnhandledRejectionHandled(this.rejection); | ||
} | ||
}; | ||
// Unhandled rejection hooks | ||
@@ -727,8 +701,6 @@ // By default, everything is a noop | ||
function Cycle() { | ||
RejectedHandler.call(this, new TypeError('Promise cycle')); | ||
function cycle() { | ||
return new Rejected(new TypeError('Promise cycle')); | ||
} | ||
inherit(RejectedHandler, Cycle); | ||
// Snapshot states | ||
@@ -738,3 +710,2 @@ | ||
* Creates a pending state snapshot | ||
* @private | ||
* @returns {{state:'pending'}} | ||
@@ -750,3 +721,2 @@ */ | ||
* Run a single consumer | ||
* @private | ||
* @constructor | ||
@@ -765,6 +735,5 @@ */ | ||
* Run a queue of progress handlers | ||
* @private | ||
* @constructor | ||
*/ | ||
function ProgressTask(handler, value) { | ||
function ProgressTask(value, handler) { | ||
this.handler = handler; | ||
@@ -779,19 +748,11 @@ this.value = value; | ||
} | ||
// First progress handler is at index 1 | ||
for (var i = 0; i < q.length; ++i) { | ||
this._notify(q[i]); | ||
for (var c, i = 0; i < q.length; ++i) { | ||
c = q[i]; | ||
runNotify(c.progress, this.value, this.handler, c.receiver, c.resolver); | ||
} | ||
}; | ||
ProgressTask.prototype._notify = function(continuation) { | ||
var x = typeof continuation.progress === 'function' | ||
? tryCatchReturn(continuation.progress, this.value, continuation.receiver) | ||
: this.value; | ||
continuation.notify.call(continuation.context, x); | ||
}; | ||
/** | ||
* Assimilate a thenable, sending it's value to resolver | ||
* @private | ||
* @param {function} then | ||
@@ -829,4 +790,14 @@ * @param {object|function} thenable | ||
* @param {*} x | ||
* @returns {boolean} false iff x is guaranteed not to be a thenable | ||
* @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) { | ||
@@ -836,12 +807,41 @@ 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(); | ||
} | ||
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(); | ||
} | ||
/** | ||
* Return f.call(thisArg, x), or if it throws return a rejected promise for | ||
* the thrown exception | ||
* @private | ||
*/ | ||
function tryCatchReject(f, x, thisArg) { | ||
function tryCatchReject(f, x, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x); | ||
next.become(getHandler(f.call(thisArg, x))); | ||
} catch(e) { | ||
return reject(e); | ||
next.become(new Rejected(e)); | ||
} | ||
@@ -852,9 +852,8 @@ } | ||
* Same as above, but includes the extra argument parameter. | ||
* @private | ||
*/ | ||
function tryCatchReject2(f, x, y, thisArg) { | ||
function tryCatchReject3(f, x, y, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x, y); | ||
f.call(thisArg, x, y, next); | ||
} catch(e) { | ||
return reject(e); | ||
next.become(new Rejected(e)); | ||
} | ||
@@ -865,9 +864,8 @@ } | ||
* Return f.call(thisArg, x), or if it throws, *return* the exception | ||
* @private | ||
*/ | ||
function tryCatchReturn(f, x, thisArg) { | ||
function tryCatchReturn(f, x, thisArg, next) { | ||
try { | ||
return f.call(thisArg, x); | ||
next.notify(f.call(thisArg, x)); | ||
} catch(e) { | ||
return e; | ||
next.notify(e); | ||
} | ||
@@ -874,0 +872,0 @@ } |
@@ -9,3 +9,3 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
var makePromise = require('./makePromise'); | ||
var Scheduler = require('./scheduler'); | ||
var Scheduler = require('./Scheduler'); | ||
var async = require('./async'); | ||
@@ -12,0 +12,0 @@ |
49
node.js
@@ -71,5 +71,5 @@ /** @license MIT License (c) copyright 2013 original author or authors */ | ||
switch(args.length) { | ||
case 2: apply2(p, f, thisArg, args); break; | ||
case 1: apply1(p, f, thisArg, args); break; | ||
default: applyN(p, f, thisArg, args); | ||
case 2: apply2(p._handler, f, thisArg, args); break; | ||
case 1: apply1(p._handler, f, thisArg, args); break; | ||
default: applyN(p._handler, f, thisArg, args); | ||
} | ||
@@ -80,21 +80,21 @@ | ||
function applyN(p, f, thisArg, args) { | ||
Promise.all(args)._handler.chain(thisArg, function(args) { | ||
args.push(createCallback(p._handler)); | ||
function applyN(resolver, f, thisArg, args) { | ||
Promise.all(args)._handler.fold(function(f, args, resolver) { | ||
args.push(createCallback(resolver)); | ||
f.apply(this, args); | ||
}); | ||
}, f, thisArg, resolver); | ||
} | ||
function apply2(p, f, thisArg, args) { | ||
Promise.resolve(args[0]).then(function(x) { | ||
Promise.resolve(args[1])._handler.chain(thisArg, function(y) { | ||
f.call(this, x, y, createCallback(p._handler)); | ||
}); | ||
}); | ||
function apply2(resolver, f, thisArg, args) { | ||
Promise._handler(args[0]).fold(function(y, x, resolver) { | ||
Promise._handler(x).fold(function(x, y, resolver) { | ||
f.call(this, x, y, createCallback(resolver)); | ||
}, y, this, resolver); | ||
}, args[1], thisArg, resolver); | ||
} | ||
function apply1(p, f, thisArg, args) { | ||
Promise.resolve(args[0])._handler.chain(thisArg, function(x) { | ||
f.call(this, x, createCallback(p._handler)); | ||
}); | ||
function apply1(resolver, f, thisArg, args) { | ||
Promise._handler(args[0]).fold(function(f, x, resolver) { | ||
f.call(this, x, createCallback(resolver)); | ||
}, f, thisArg, resolver); | ||
} | ||
@@ -162,5 +162,16 @@ | ||
function lift(f /*, args... */) { | ||
var args = arguments.length > 1 ? slice.call(arguments, 1) : []; | ||
var args1 = arguments.length > 1 ? slice.call(arguments, 1) : []; | ||
return function() { | ||
return run(f, this, args.concat(slice.call(arguments))); | ||
// TODO: Simplify once partialing has been removed | ||
var l = args1.length; | ||
var al = arguments.length; | ||
var args = new Array(al + l); | ||
var i; | ||
for(i=0; i<l; ++i) { | ||
args[i] = args1[i]; | ||
} | ||
for(i=0; i<al; ++i) { | ||
args[i+l] = arguments[i]; | ||
} | ||
return run(f, this, args); | ||
}; | ||
@@ -167,0 +178,0 @@ } |
{ | ||
"name": "when", | ||
"version": "3.2.3", | ||
"version": "3.3.0", | ||
"description": "A lightweight Promises/A+ and when() implementation, plus other async goodies.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -8,3 +8,3 @@ /** @license MIT License (c) copyright 2010-2014 original author or authors */ | ||
* @author John Hann | ||
* @version 3.2.3 | ||
* @version 3.3.0 | ||
*/ | ||
@@ -53,2 +53,3 @@ (function(define) { 'use strict'; | ||
when.some = lift(Promise.some); // Multi-winner race | ||
when.race = lift(Promise.race); // First-to-settle race | ||
@@ -77,4 +78,4 @@ when.map = map; // Array.map() for promises | ||
* rejected. | ||
* @deprecated @param {function?} onProgress callback to be called when progress updates | ||
* are issued for x. | ||
* @param {function?} onProgress callback to be called when progress updates | ||
* are issued for x. @deprecated | ||
* @returns {Promise} a new promise that will fulfill with the return | ||
@@ -81,0 +82,0 @@ * value of callback or errback or the completion value of promiseOrValue if |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
143610
4285