Keine Beschreibung

-internal.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import {
  2. objectOrFunction,
  3. isFunction
  4. } from './utils';
  5. import {
  6. asap
  7. } from './asap';
  8. function noop() {}
  9. var PENDING = void 0;
  10. var FULFILLED = 1;
  11. var REJECTED = 2;
  12. var GET_THEN_ERROR = new ErrorObject();
  13. function selfFullfillment() {
  14. return new TypeError("You cannot resolve a promise with itself");
  15. }
  16. function cannotReturnOwn() {
  17. return new TypeError('A promises callback cannot return that same promise.');
  18. }
  19. function getThen(promise) {
  20. try {
  21. return promise.then;
  22. } catch(error) {
  23. GET_THEN_ERROR.error = error;
  24. return GET_THEN_ERROR;
  25. }
  26. }
  27. function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
  28. try {
  29. then.call(value, fulfillmentHandler, rejectionHandler);
  30. } catch(e) {
  31. return e;
  32. }
  33. }
  34. function handleForeignThenable(promise, thenable, then) {
  35. asap(function(promise) {
  36. var sealed = false;
  37. var error = tryThen(then, thenable, function(value) {
  38. if (sealed) { return; }
  39. sealed = true;
  40. if (thenable !== value) {
  41. resolve(promise, value);
  42. } else {
  43. fulfill(promise, value);
  44. }
  45. }, function(reason) {
  46. if (sealed) { return; }
  47. sealed = true;
  48. reject(promise, reason);
  49. }, 'Settle: ' + (promise._label || ' unknown promise'));
  50. if (!sealed && error) {
  51. sealed = true;
  52. reject(promise, error);
  53. }
  54. }, promise);
  55. }
  56. function handleOwnThenable(promise, thenable) {
  57. if (thenable._state === FULFILLED) {
  58. fulfill(promise, thenable._result);
  59. } else if (thenable._state === REJECTED) {
  60. reject(promise, thenable._result);
  61. } else {
  62. subscribe(thenable, undefined, function(value) {
  63. resolve(promise, value);
  64. }, function(reason) {
  65. reject(promise, reason);
  66. });
  67. }
  68. }
  69. function handleMaybeThenable(promise, maybeThenable) {
  70. if (maybeThenable.constructor === promise.constructor) {
  71. handleOwnThenable(promise, maybeThenable);
  72. } else {
  73. var then = getThen(maybeThenable);
  74. if (then === GET_THEN_ERROR) {
  75. reject(promise, GET_THEN_ERROR.error);
  76. } else if (then === undefined) {
  77. fulfill(promise, maybeThenable);
  78. } else if (isFunction(then)) {
  79. handleForeignThenable(promise, maybeThenable, then);
  80. } else {
  81. fulfill(promise, maybeThenable);
  82. }
  83. }
  84. }
  85. function resolve(promise, value) {
  86. if (promise === value) {
  87. reject(promise, selfFullfillment());
  88. } else if (objectOrFunction(value)) {
  89. handleMaybeThenable(promise, value);
  90. } else {
  91. fulfill(promise, value);
  92. }
  93. }
  94. function publishRejection(promise) {
  95. if (promise._onerror) {
  96. promise._onerror(promise._result);
  97. }
  98. publish(promise);
  99. }
  100. function fulfill(promise, value) {
  101. if (promise._state !== PENDING) { return; }
  102. promise._result = value;
  103. promise._state = FULFILLED;
  104. if (promise._subscribers.length !== 0) {
  105. asap(publish, promise);
  106. }
  107. }
  108. function reject(promise, reason) {
  109. if (promise._state !== PENDING) { return; }
  110. promise._state = REJECTED;
  111. promise._result = reason;
  112. asap(publishRejection, promise);
  113. }
  114. function subscribe(parent, child, onFulfillment, onRejection) {
  115. var subscribers = parent._subscribers;
  116. var length = subscribers.length;
  117. parent._onerror = null;
  118. subscribers[length] = child;
  119. subscribers[length + FULFILLED] = onFulfillment;
  120. subscribers[length + REJECTED] = onRejection;
  121. if (length === 0 && parent._state) {
  122. asap(publish, parent);
  123. }
  124. }
  125. function publish(promise) {
  126. var subscribers = promise._subscribers;
  127. var settled = promise._state;
  128. if (subscribers.length === 0) { return; }
  129. var child, callback, detail = promise._result;
  130. for (var i = 0; i < subscribers.length; i += 3) {
  131. child = subscribers[i];
  132. callback = subscribers[i + settled];
  133. if (child) {
  134. invokeCallback(settled, child, callback, detail);
  135. } else {
  136. callback(detail);
  137. }
  138. }
  139. promise._subscribers.length = 0;
  140. }
  141. function ErrorObject() {
  142. this.error = null;
  143. }
  144. var TRY_CATCH_ERROR = new ErrorObject();
  145. function tryCatch(callback, detail) {
  146. try {
  147. return callback(detail);
  148. } catch(e) {
  149. TRY_CATCH_ERROR.error = e;
  150. return TRY_CATCH_ERROR;
  151. }
  152. }
  153. function invokeCallback(settled, promise, callback, detail) {
  154. var hasCallback = isFunction(callback),
  155. value, error, succeeded, failed;
  156. if (hasCallback) {
  157. value = tryCatch(callback, detail);
  158. if (value === TRY_CATCH_ERROR) {
  159. failed = true;
  160. error = value.error;
  161. value = null;
  162. } else {
  163. succeeded = true;
  164. }
  165. if (promise === value) {
  166. reject(promise, cannotReturnOwn());
  167. return;
  168. }
  169. } else {
  170. value = detail;
  171. succeeded = true;
  172. }
  173. if (promise._state !== PENDING) {
  174. // noop
  175. } else if (hasCallback && succeeded) {
  176. resolve(promise, value);
  177. } else if (failed) {
  178. reject(promise, error);
  179. } else if (settled === FULFILLED) {
  180. fulfill(promise, value);
  181. } else if (settled === REJECTED) {
  182. reject(promise, value);
  183. }
  184. }
  185. function initializePromise(promise, resolver) {
  186. try {
  187. resolver(function resolvePromise(value){
  188. resolve(promise, value);
  189. }, function rejectPromise(reason) {
  190. reject(promise, reason);
  191. });
  192. } catch(e) {
  193. reject(promise, e);
  194. }
  195. }
  196. export {
  197. noop,
  198. resolve,
  199. reject,
  200. fulfill,
  201. subscribe,
  202. publish,
  203. publishRejection,
  204. initializePromise,
  205. invokeCallback,
  206. FULFILLED,
  207. REJECTED,
  208. PENDING
  209. };