169 lines
8 KiB
JavaScript
169 lines
8 KiB
JavaScript
|
"use strict";
|
||
|
module.exports =
|
||
|
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
|
||
|
getDomain) {
|
||
|
var util = require("./util");
|
||
|
var canEvaluate = util.canEvaluate;
|
||
|
var tryCatch = util.tryCatch;
|
||
|
var errorObj = util.errorObj;
|
||
|
var reject;
|
||
|
|
||
|
if (!false) {
|
||
|
if (canEvaluate) {
|
||
|
var thenCallback = function(i) {
|
||
|
return new Function("value", "holder", " \n\
|
||
|
'use strict'; \n\
|
||
|
holder.pIndex = value; \n\
|
||
|
holder.checkFulfillment(this); \n\
|
||
|
".replace(/Index/g, i));
|
||
|
};
|
||
|
|
||
|
var promiseSetter = function(i) {
|
||
|
return new Function("promise", "holder", " \n\
|
||
|
'use strict'; \n\
|
||
|
holder.pIndex = promise; \n\
|
||
|
".replace(/Index/g, i));
|
||
|
};
|
||
|
|
||
|
var generateHolderClass = function(total) {
|
||
|
var props = new Array(total);
|
||
|
for (var i = 0; i < props.length; ++i) {
|
||
|
props[i] = "this.p" + (i+1);
|
||
|
}
|
||
|
var assignment = props.join(" = ") + " = null;";
|
||
|
var cancellationCode= "var promise;\n" + props.map(function(prop) {
|
||
|
return " \n\
|
||
|
promise = " + prop + "; \n\
|
||
|
if (promise instanceof Promise) { \n\
|
||
|
promise.cancel(); \n\
|
||
|
} \n\
|
||
|
";
|
||
|
}).join("\n");
|
||
|
var passedArguments = props.join(", ");
|
||
|
var name = "Holder$" + total;
|
||
|
|
||
|
|
||
|
var code = "return function(tryCatch, errorObj, Promise, async) { \n\
|
||
|
'use strict'; \n\
|
||
|
function [TheName](fn) { \n\
|
||
|
[TheProperties] \n\
|
||
|
this.fn = fn; \n\
|
||
|
this.asyncNeeded = true; \n\
|
||
|
this.now = 0; \n\
|
||
|
} \n\
|
||
|
\n\
|
||
|
[TheName].prototype._callFunction = function(promise) { \n\
|
||
|
promise._pushContext(); \n\
|
||
|
var ret = tryCatch(this.fn)([ThePassedArguments]); \n\
|
||
|
promise._popContext(); \n\
|
||
|
if (ret === errorObj) { \n\
|
||
|
promise._rejectCallback(ret.e, false); \n\
|
||
|
} else { \n\
|
||
|
promise._resolveCallback(ret); \n\
|
||
|
} \n\
|
||
|
}; \n\
|
||
|
\n\
|
||
|
[TheName].prototype.checkFulfillment = function(promise) { \n\
|
||
|
var now = ++this.now; \n\
|
||
|
if (now === [TheTotal]) { \n\
|
||
|
if (this.asyncNeeded) { \n\
|
||
|
async.invoke(this._callFunction, this, promise); \n\
|
||
|
} else { \n\
|
||
|
this._callFunction(promise); \n\
|
||
|
} \n\
|
||
|
\n\
|
||
|
} \n\
|
||
|
}; \n\
|
||
|
\n\
|
||
|
[TheName].prototype._resultCancelled = function() { \n\
|
||
|
[CancellationCode] \n\
|
||
|
}; \n\
|
||
|
\n\
|
||
|
return [TheName]; \n\
|
||
|
}(tryCatch, errorObj, Promise, async); \n\
|
||
|
";
|
||
|
|
||
|
code = code.replace(/\[TheName\]/g, name)
|
||
|
.replace(/\[TheTotal\]/g, total)
|
||
|
.replace(/\[ThePassedArguments\]/g, passedArguments)
|
||
|
.replace(/\[TheProperties\]/g, assignment)
|
||
|
.replace(/\[CancellationCode\]/g, cancellationCode);
|
||
|
|
||
|
return new Function("tryCatch", "errorObj", "Promise", "async", code)
|
||
|
(tryCatch, errorObj, Promise, async);
|
||
|
};
|
||
|
|
||
|
var holderClasses = [];
|
||
|
var thenCallbacks = [];
|
||
|
var promiseSetters = [];
|
||
|
|
||
|
for (var i = 0; i < 8; ++i) {
|
||
|
holderClasses.push(generateHolderClass(i + 1));
|
||
|
thenCallbacks.push(thenCallback(i + 1));
|
||
|
promiseSetters.push(promiseSetter(i + 1));
|
||
|
}
|
||
|
|
||
|
reject = function (reason) {
|
||
|
this._reject(reason);
|
||
|
};
|
||
|
}}
|
||
|
|
||
|
Promise.join = function () {
|
||
|
var last = arguments.length - 1;
|
||
|
var fn;
|
||
|
if (last > 0 && typeof arguments[last] === "function") {
|
||
|
fn = arguments[last];
|
||
|
if (!false) {
|
||
|
if (last <= 8 && canEvaluate) {
|
||
|
var ret = new Promise(INTERNAL);
|
||
|
ret._captureStackTrace();
|
||
|
var HolderClass = holderClasses[last - 1];
|
||
|
var holder = new HolderClass(fn);
|
||
|
var callbacks = thenCallbacks;
|
||
|
|
||
|
for (var i = 0; i < last; ++i) {
|
||
|
var maybePromise = tryConvertToPromise(arguments[i], ret);
|
||
|
if (maybePromise instanceof Promise) {
|
||
|
maybePromise = maybePromise._target();
|
||
|
var bitField = maybePromise._bitField;
|
||
|
;
|
||
|
if (((bitField & 50397184) === 0)) {
|
||
|
maybePromise._then(callbacks[i], reject,
|
||
|
undefined, ret, holder);
|
||
|
promiseSetters[i](maybePromise, holder);
|
||
|
holder.asyncNeeded = false;
|
||
|
} else if (((bitField & 33554432) !== 0)) {
|
||
|
callbacks[i].call(ret,
|
||
|
maybePromise._value(), holder);
|
||
|
} else if (((bitField & 16777216) !== 0)) {
|
||
|
ret._reject(maybePromise._reason());
|
||
|
} else {
|
||
|
ret._cancel();
|
||
|
}
|
||
|
} else {
|
||
|
callbacks[i].call(ret, maybePromise, holder);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!ret._isFateSealed()) {
|
||
|
if (holder.asyncNeeded) {
|
||
|
var domain = getDomain();
|
||
|
if (domain !== null) {
|
||
|
holder.fn = util.domainBind(domain, holder.fn);
|
||
|
}
|
||
|
}
|
||
|
ret._setAsyncGuaranteed();
|
||
|
ret._setOnCancel(holder);
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];};
|
||
|
if (fn) args.pop();
|
||
|
var ret = new PromiseArray(args).promise();
|
||
|
return fn !== undefined ? ret.spread(fn) : ret;
|
||
|
};
|
||
|
|
||
|
};
|