“use strict”; module.exports = function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async) { 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 context = Promise._getContext();
                    holder.fn = util.contextBind(context, 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;

};

};