Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81160 views
1
"use strict";
2
module.exports = function(Promise,
3
PromiseArray,
4
apiRejection,
5
tryConvertToPromise,
6
INTERNAL) {
7
var async = require("./async.js");
8
var util = require("./util.js");
9
var tryCatch = util.tryCatch;
10
var errorObj = util.errorObj;
11
function ReductionPromiseArray(promises, fn, accum, _each) {
12
this.constructor$(promises);
13
this._promise._captureStackTrace();
14
this._preservedValues = _each === INTERNAL ? [] : null;
15
this._zerothIsAccum = (accum === undefined);
16
this._gotAccum = false;
17
this._reducingIndex = (this._zerothIsAccum ? 1 : 0);
18
this._valuesPhase = undefined;
19
var maybePromise = tryConvertToPromise(accum, this._promise);
20
var rejected = false;
21
var isPromise = maybePromise instanceof Promise;
22
if (isPromise) {
23
maybePromise = maybePromise._target();
24
if (maybePromise._isPending()) {
25
maybePromise._proxyPromiseArray(this, -1);
26
} else if (maybePromise._isFulfilled()) {
27
accum = maybePromise._value();
28
this._gotAccum = true;
29
} else {
30
this._reject(maybePromise._reason());
31
rejected = true;
32
}
33
}
34
if (!(isPromise || this._zerothIsAccum)) this._gotAccum = true;
35
this._callback = fn;
36
this._accum = accum;
37
if (!rejected) async.invoke(init, this, undefined);
38
}
39
function init() {
40
this._init$(undefined, -5);
41
}
42
util.inherits(ReductionPromiseArray, PromiseArray);
43
44
ReductionPromiseArray.prototype._init = function () {};
45
46
ReductionPromiseArray.prototype._resolveEmptyArray = function () {
47
if (this._gotAccum || this._zerothIsAccum) {
48
this._resolve(this._preservedValues !== null
49
? [] : this._accum);
50
}
51
};
52
53
ReductionPromiseArray.prototype._promiseFulfilled = function (value, index) {
54
var values = this._values;
55
values[index] = value;
56
var length = this.length();
57
var preservedValues = this._preservedValues;
58
var isEach = preservedValues !== null;
59
var gotAccum = this._gotAccum;
60
var valuesPhase = this._valuesPhase;
61
var valuesPhaseIndex;
62
if (!valuesPhase) {
63
valuesPhase = this._valuesPhase = new Array(length);
64
for (valuesPhaseIndex=0; valuesPhaseIndex<length; ++valuesPhaseIndex) {
65
valuesPhase[valuesPhaseIndex] = 0;
66
}
67
}
68
valuesPhaseIndex = valuesPhase[index];
69
70
if (index === 0 && this._zerothIsAccum) {
71
this._accum = value;
72
this._gotAccum = gotAccum = true;
73
valuesPhase[index] = ((valuesPhaseIndex === 0)
74
? 1 : 2);
75
} else if (index === -1) {
76
this._accum = value;
77
this._gotAccum = gotAccum = true;
78
} else {
79
if (valuesPhaseIndex === 0) {
80
valuesPhase[index] = 1;
81
} else {
82
valuesPhase[index] = 2;
83
this._accum = value;
84
}
85
}
86
if (!gotAccum) return;
87
88
var callback = this._callback;
89
var receiver = this._promise._boundTo;
90
var ret;
91
92
for (var i = this._reducingIndex; i < length; ++i) {
93
valuesPhaseIndex = valuesPhase[i];
94
if (valuesPhaseIndex === 2) {
95
this._reducingIndex = i + 1;
96
continue;
97
}
98
if (valuesPhaseIndex !== 1) return;
99
value = values[i];
100
this._promise._pushContext();
101
if (isEach) {
102
preservedValues.push(value);
103
ret = tryCatch(callback).call(receiver, value, i, length);
104
}
105
else {
106
ret = tryCatch(callback)
107
.call(receiver, this._accum, value, i, length);
108
}
109
this._promise._popContext();
110
111
if (ret === errorObj) return this._reject(ret.e);
112
113
var maybePromise = tryConvertToPromise(ret, this._promise);
114
if (maybePromise instanceof Promise) {
115
maybePromise = maybePromise._target();
116
if (maybePromise._isPending()) {
117
valuesPhase[i] = 4;
118
return maybePromise._proxyPromiseArray(this, i);
119
} else if (maybePromise._isFulfilled()) {
120
ret = maybePromise._value();
121
} else {
122
return this._reject(maybePromise._reason());
123
}
124
}
125
126
this._reducingIndex = i + 1;
127
this._accum = ret;
128
}
129
130
this._resolve(isEach ? preservedValues : this._accum);
131
};
132
133
function reduce(promises, fn, initialValue, _each) {
134
if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a");
135
var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
136
return array.promise();
137
}
138
139
Promise.prototype.reduce = function (fn, initialValue) {
140
return reduce(this, fn, initialValue, null);
141
};
142
143
Promise.reduce = function (promises, fn, initialValue, _each) {
144
return reduce(promises, fn, initialValue, _each);
145
};
146
};
147
148