UNPKG

jsdoc-75lb

Version:

An API documentation generator for JavaScript.

149 lines (135 loc) 5.02 kB
"use strict"; module.exports = function(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL) { var getDomain = Promise._getDomain; var async = require("./async.js"); var util = require("./util.js"); var tryCatch = util.tryCatch; var errorObj = util.errorObj; function ReductionPromiseArray(promises, fn, accum, _each) { this.constructor$(promises); this._promise._captureStackTrace(); this._preservedValues = _each === INTERNAL ? [] : null; this._zerothIsAccum = (accum === undefined); this._gotAccum = false; this._reducingIndex = (this._zerothIsAccum ? 1 : 0); this._valuesPhase = undefined; var maybePromise = tryConvertToPromise(accum, this._promise); var rejected = false; var isPromise = maybePromise instanceof Promise; if (isPromise) { maybePromise = maybePromise._target(); if (maybePromise._isPending()) { maybePromise._proxyPromiseArray(this, -1); } else if (maybePromise._isFulfilled()) { accum = maybePromise._value(); this._gotAccum = true; } else { this._reject(maybePromise._reason()); rejected = true; } } if (!(isPromise || this._zerothIsAccum)) this._gotAccum = true; var domain = getDomain(); this._callback = domain === null ? fn : domain.bind(fn); this._accum = accum; if (!rejected) async.invoke(init, this, undefined); } function init() { this._init$(undefined, -5); } util.inherits(ReductionPromiseArray, PromiseArray); ReductionPromiseArray.prototype._init = function () {}; ReductionPromiseArray.prototype._resolveEmptyArray = function () { if (this._gotAccum || this._zerothIsAccum) { this._resolve(this._preservedValues !== null ? [] : this._accum); } }; ReductionPromiseArray.prototype._promiseFulfilled = function (value, index) { var values = this._values; values[index] = value; var length = this.length(); var preservedValues = this._preservedValues; var isEach = preservedValues !== null; var gotAccum = this._gotAccum; var valuesPhase = this._valuesPhase; var valuesPhaseIndex; if (!valuesPhase) { valuesPhase = this._valuesPhase = new Array(length); for (valuesPhaseIndex=0; valuesPhaseIndex<length; ++valuesPhaseIndex) { valuesPhase[valuesPhaseIndex] = 0; } } valuesPhaseIndex = valuesPhase[index]; if (index === 0 && this._zerothIsAccum) { this._accum = value; this._gotAccum = gotAccum = true; valuesPhase[index] = ((valuesPhaseIndex === 0) ? 1 : 2); } else if (index === -1) { this._accum = value; this._gotAccum = gotAccum = true; } else { if (valuesPhaseIndex === 0) { valuesPhase[index] = 1; } else { valuesPhase[index] = 2; this._accum = value; } } if (!gotAccum) return; var callback = this._callback; var receiver = this._promise._boundValue(); var ret; for (var i = this._reducingIndex; i < length; ++i) { valuesPhaseIndex = valuesPhase[i]; if (valuesPhaseIndex === 2) { this._reducingIndex = i + 1; continue; } if (valuesPhaseIndex !== 1) return; value = values[i]; this._promise._pushContext(); if (isEach) { preservedValues.push(value); ret = tryCatch(callback).call(receiver, value, i, length); } else { ret = tryCatch(callback) .call(receiver, this._accum, value, i, length); } this._promise._popContext(); if (ret === errorObj) return this._reject(ret.e); var maybePromise = tryConvertToPromise(ret, this._promise); if (maybePromise instanceof Promise) { maybePromise = maybePromise._target(); if (maybePromise._isPending()) { valuesPhase[i] = 4; return maybePromise._proxyPromiseArray(this, i); } else if (maybePromise._isFulfilled()) { ret = maybePromise._value(); } else { return this._reject(maybePromise._reason()); } } this._reducingIndex = i + 1; this._accum = ret; } this._resolve(isEach ? preservedValues : this._accum); }; function reduce(promises, fn, initialValue, _each) { if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); var array = new ReductionPromiseArray(promises, fn, initialValue, _each); return array.promise(); } Promise.prototype.reduce = function (fn, initialValue) { return reduce(this, fn, initialValue, null); }; Promise.reduce = function (promises, fn, initialValue, _each) { return reduce(promises, fn, initialValue, _each); }; };