You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.1 KiB

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