promise_array.js (5252B)
1 "use strict"; 2 module.exports = function(Promise, INTERNAL, tryConvertToPromise, 3 apiRejection, Proxyable) { 4 var util = require("./util"); 5 var isArray = util.isArray; 6 7 function toResolutionValue(val) { 8 switch(val) { 9 case -2: return []; 10 case -3: return {}; 11 case -6: return new Map(); 12 } 13 } 14 15 function PromiseArray(values) { 16 var promise = this._promise = new Promise(INTERNAL); 17 if (values instanceof Promise) { 18 promise._propagateFrom(values, 3); 19 values.suppressUnhandledRejections(); 20 } 21 promise._setOnCancel(this); 22 this._values = values; 23 this._length = 0; 24 this._totalResolved = 0; 25 this._init(undefined, -2); 26 } 27 util.inherits(PromiseArray, Proxyable); 28 29 PromiseArray.prototype.length = function () { 30 return this._length; 31 }; 32 33 PromiseArray.prototype.promise = function () { 34 return this._promise; 35 }; 36 37 PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { 38 var values = tryConvertToPromise(this._values, this._promise); 39 if (values instanceof Promise) { 40 values = values._target(); 41 var bitField = values._bitField; 42 ; 43 this._values = values; 44 45 if (((bitField & 50397184) === 0)) { 46 this._promise._setAsyncGuaranteed(); 47 return values._then( 48 init, 49 this._reject, 50 undefined, 51 this, 52 resolveValueIfEmpty 53 ); 54 } else if (((bitField & 33554432) !== 0)) { 55 values = values._value(); 56 } else if (((bitField & 16777216) !== 0)) { 57 return this._reject(values._reason()); 58 } else { 59 return this._cancel(); 60 } 61 } 62 values = util.asArray(values); 63 if (values === null) { 64 var err = apiRejection( 65 "expecting an array or an iterable object but got " + util.classString(values)).reason(); 66 this._promise._rejectCallback(err, false); 67 return; 68 } 69 70 if (values.length === 0) { 71 if (resolveValueIfEmpty === -5) { 72 this._resolveEmptyArray(); 73 } 74 else { 75 this._resolve(toResolutionValue(resolveValueIfEmpty)); 76 } 77 return; 78 } 79 this._iterate(values); 80 }; 81 82 PromiseArray.prototype._iterate = function(values) { 83 var len = this.getActualLength(values.length); 84 this._length = len; 85 this._values = this.shouldCopyValues() ? new Array(len) : this._values; 86 var result = this._promise; 87 var isResolved = false; 88 var bitField = null; 89 for (var i = 0; i < len; ++i) { 90 var maybePromise = tryConvertToPromise(values[i], result); 91 92 if (maybePromise instanceof Promise) { 93 maybePromise = maybePromise._target(); 94 bitField = maybePromise._bitField; 95 } else { 96 bitField = null; 97 } 98 99 if (isResolved) { 100 if (bitField !== null) { 101 maybePromise.suppressUnhandledRejections(); 102 } 103 } else if (bitField !== null) { 104 if (((bitField & 50397184) === 0)) { 105 maybePromise._proxy(this, i); 106 this._values[i] = maybePromise; 107 } else if (((bitField & 33554432) !== 0)) { 108 isResolved = this._promiseFulfilled(maybePromise._value(), i); 109 } else if (((bitField & 16777216) !== 0)) { 110 isResolved = this._promiseRejected(maybePromise._reason(), i); 111 } else { 112 isResolved = this._promiseCancelled(i); 113 } 114 } else { 115 isResolved = this._promiseFulfilled(maybePromise, i); 116 } 117 } 118 if (!isResolved) result._setAsyncGuaranteed(); 119 }; 120 121 PromiseArray.prototype._isResolved = function () { 122 return this._values === null; 123 }; 124 125 PromiseArray.prototype._resolve = function (value) { 126 this._values = null; 127 this._promise._fulfill(value); 128 }; 129 130 PromiseArray.prototype._cancel = function() { 131 if (this._isResolved() || !this._promise._isCancellable()) return; 132 this._values = null; 133 this._promise._cancel(); 134 }; 135 136 PromiseArray.prototype._reject = function (reason) { 137 this._values = null; 138 this._promise._rejectCallback(reason, false); 139 }; 140 141 PromiseArray.prototype._promiseFulfilled = function (value, index) { 142 this._values[index] = value; 143 var totalResolved = ++this._totalResolved; 144 if (totalResolved >= this._length) { 145 this._resolve(this._values); 146 return true; 147 } 148 return false; 149 }; 150 151 PromiseArray.prototype._promiseCancelled = function() { 152 this._cancel(); 153 return true; 154 }; 155 156 PromiseArray.prototype._promiseRejected = function (reason) { 157 this._totalResolved++; 158 this._reject(reason); 159 return true; 160 }; 161 162 PromiseArray.prototype._resultCancelled = function() { 163 if (this._isResolved()) return; 164 var values = this._values; 165 this._cancel(); 166 if (values instanceof Promise) { 167 values.cancel(); 168 } else { 169 for (var i = 0; i < values.length; ++i) { 170 if (values[i] instanceof Promise) { 171 values[i].cancel(); 172 } 173 } 174 } 175 }; 176 177 PromiseArray.prototype.shouldCopyValues = function () { 178 return true; 179 }; 180 181 PromiseArray.prototype.getActualLength = function (len) { 182 return len; 183 }; 184 185 return PromiseArray; 186 };