• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"use strict";
2module.exports =
3function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
4         getDomain) {
5var util = require("./util");
6var canEvaluate = util.canEvaluate;
7var tryCatch = util.tryCatch;
8var errorObj = util.errorObj;
9var reject;
10
11if (!false) {
12if (canEvaluate) {
13    var thenCallback = function(i) {
14        return new Function("value", "holder", "                             \n\
15            'use strict';                                                    \n\
16            holder.pIndex = value;                                           \n\
17            holder.checkFulfillment(this);                                   \n\
18            ".replace(/Index/g, i));
19    };
20
21    var promiseSetter = function(i) {
22        return new Function("promise", "holder", "                           \n\
23            'use strict';                                                    \n\
24            holder.pIndex = promise;                                         \n\
25            ".replace(/Index/g, i));
26    };
27
28    var generateHolderClass = function(total) {
29        var props = new Array(total);
30        for (var i = 0; i < props.length; ++i) {
31            props[i] = "this.p" + (i+1);
32        }
33        var assignment = props.join(" = ") + " = null;";
34        var cancellationCode= "var promise;\n" + props.map(function(prop) {
35            return "                                                         \n\
36                promise = " + prop + ";                                      \n\
37                if (promise instanceof Promise) {                            \n\
38                    promise.cancel();                                        \n\
39                }                                                            \n\
40            ";
41        }).join("\n");
42        var passedArguments = props.join(", ");
43        var name = "Holder$" + total;
44
45
46        var code = "return function(tryCatch, errorObj, Promise, async) {    \n\
47            'use strict';                                                    \n\
48            function [TheName](fn) {                                         \n\
49                [TheProperties]                                              \n\
50                this.fn = fn;                                                \n\
51                this.asyncNeeded = true;                                     \n\
52                this.now = 0;                                                \n\
53            }                                                                \n\
54                                                                             \n\
55            [TheName].prototype._callFunction = function(promise) {          \n\
56                promise._pushContext();                                      \n\
57                var ret = tryCatch(this.fn)([ThePassedArguments]);           \n\
58                promise._popContext();                                       \n\
59                if (ret === errorObj) {                                      \n\
60                    promise._rejectCallback(ret.e, false);                   \n\
61                } else {                                                     \n\
62                    promise._resolveCallback(ret);                           \n\
63                }                                                            \n\
64            };                                                               \n\
65                                                                             \n\
66            [TheName].prototype.checkFulfillment = function(promise) {       \n\
67                var now = ++this.now;                                        \n\
68                if (now === [TheTotal]) {                                    \n\
69                    if (this.asyncNeeded) {                                  \n\
70                        async.invoke(this._callFunction, this, promise);     \n\
71                    } else {                                                 \n\
72                        this._callFunction(promise);                         \n\
73                    }                                                        \n\
74                                                                             \n\
75                }                                                            \n\
76            };                                                               \n\
77                                                                             \n\
78            [TheName].prototype._resultCancelled = function() {              \n\
79                [CancellationCode]                                           \n\
80            };                                                               \n\
81                                                                             \n\
82            return [TheName];                                                \n\
83        }(tryCatch, errorObj, Promise, async);                               \n\
84        ";
85
86        code = code.replace(/\[TheName\]/g, name)
87            .replace(/\[TheTotal\]/g, total)
88            .replace(/\[ThePassedArguments\]/g, passedArguments)
89            .replace(/\[TheProperties\]/g, assignment)
90            .replace(/\[CancellationCode\]/g, cancellationCode);
91
92        return new Function("tryCatch", "errorObj", "Promise", "async", code)
93                           (tryCatch, errorObj, Promise, async);
94    };
95
96    var holderClasses = [];
97    var thenCallbacks = [];
98    var promiseSetters = [];
99
100    for (var i = 0; i < 8; ++i) {
101        holderClasses.push(generateHolderClass(i + 1));
102        thenCallbacks.push(thenCallback(i + 1));
103        promiseSetters.push(promiseSetter(i + 1));
104    }
105
106    reject = function (reason) {
107        this._reject(reason);
108    };
109}}
110
111Promise.join = function () {
112    var last = arguments.length - 1;
113    var fn;
114    if (last > 0 && typeof arguments[last] === "function") {
115        fn = arguments[last];
116        if (!false) {
117            if (last <= 8 && canEvaluate) {
118                var ret = new Promise(INTERNAL);
119                ret._captureStackTrace();
120                var HolderClass = holderClasses[last - 1];
121                var holder = new HolderClass(fn);
122                var callbacks = thenCallbacks;
123
124                for (var i = 0; i < last; ++i) {
125                    var maybePromise = tryConvertToPromise(arguments[i], ret);
126                    if (maybePromise instanceof Promise) {
127                        maybePromise = maybePromise._target();
128                        var bitField = maybePromise._bitField;
129                        ;
130                        if (((bitField & 50397184) === 0)) {
131                            maybePromise._then(callbacks[i], reject,
132                                               undefined, ret, holder);
133                            promiseSetters[i](maybePromise, holder);
134                            holder.asyncNeeded = false;
135                        } else if (((bitField & 33554432) !== 0)) {
136                            callbacks[i].call(ret,
137                                              maybePromise._value(), holder);
138                        } else if (((bitField & 16777216) !== 0)) {
139                            ret._reject(maybePromise._reason());
140                        } else {
141                            ret._cancel();
142                        }
143                    } else {
144                        callbacks[i].call(ret, maybePromise, holder);
145                    }
146                }
147
148                if (!ret._isFateSealed()) {
149                    if (holder.asyncNeeded) {
150                        var domain = getDomain();
151                        if (domain !== null) {
152                            holder.fn = util.domainBind(domain, holder.fn);
153                        }
154                    }
155                    ret._setAsyncGuaranteed();
156                    ret._setOnCancel(holder);
157                }
158                return ret;
159            }
160        }
161    }
162    var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];};
163    if (fn) args.pop();
164    var ret = new PromiseArray(args).promise();
165    return fn !== undefined ? ret.spread(fn) : ret;
166};
167
168};
169