join.js 6.9 KB

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