10 import originalThen from './then';
11 import originalResolve from './promise/resolve';
13 export const PROMISE_ID = Math.random().toString(36).substring(16);
17 const PENDING = void 0;
21 const GET_THEN_ERROR = new ErrorObject();
23 function selfFulfillment() {
24 return new TypeError("You cannot resolve a promise with itself");
27 function cannotReturnOwn() {
28 return new TypeError('A promises callback cannot return that same promise.');
31 function getThen(promise) {
35 GET_THEN_ERROR.error = error;
36 return GET_THEN_ERROR;
40 function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
42 then.call(value, fulfillmentHandler, rejectionHandler);
48 function handleForeignThenable(promise, thenable, then) {
51 var error = tryThen(then, thenable, value => {
52 if (sealed) { return; }
54 if (thenable !== value) {
55 resolve(promise, value);
57 fulfill(promise, value);
60 if (sealed) { return; }
63 reject(promise, reason);
64 }, 'Settle: ' + (promise._label || ' unknown promise'));
66 if (!sealed && error) {
68 reject(promise, error);
73 function handleOwnThenable(promise, thenable) {
74 if (thenable._state === FULFILLED) {
75 fulfill(promise, thenable._result);
76 } else if (thenable._state === REJECTED) {
77 reject(promise, thenable._result);
79 subscribe(thenable, undefined, value => resolve(promise, value),
80 reason => reject(promise, reason))
84 function handleMaybeThenable(promise, maybeThenable, then) {
85 if (maybeThenable.constructor === promise.constructor &&
86 then === originalThen &&
87 maybeThenable.constructor.resolve === originalResolve) {
88 handleOwnThenable(promise, maybeThenable);
90 if (then === GET_THEN_ERROR) {
91 reject(promise, GET_THEN_ERROR.error);
92 } else if (then === undefined) {
93 fulfill(promise, maybeThenable);
94 } else if (isFunction(then)) {
95 handleForeignThenable(promise, maybeThenable, then);
97 fulfill(promise, maybeThenable);
102 function resolve(promise, value) {
103 if (promise === value) {
104 reject(promise, selfFulfillment());
105 } else if (objectOrFunction(value)) {
106 handleMaybeThenable(promise, value, getThen(value));
108 fulfill(promise, value);
112 function publishRejection(promise) {
113 if (promise._onerror) {
114 promise._onerror(promise._result);
120 function fulfill(promise, value) {
121 if (promise._state !== PENDING) { return; }
123 promise._result = value;
124 promise._state = FULFILLED;
126 if (promise._subscribers.length !== 0) {
127 asap(publish, promise);
131 function reject(promise, reason) {
132 if (promise._state !== PENDING) { return; }
133 promise._state = REJECTED;
134 promise._result = reason;
136 asap(publishRejection, promise);
139 function subscribe(parent, child, onFulfillment, onRejection) {
140 let { _subscribers } = parent;
141 let { length } = _subscribers;
143 parent._onerror = null;
145 _subscribers[length] = child;
146 _subscribers[length + FULFILLED] = onFulfillment;
147 _subscribers[length + REJECTED] = onRejection;
149 if (length === 0 && parent._state) {
150 asap(publish, parent);
154 function publish(promise) {
155 let subscribers = promise._subscribers;
156 let settled = promise._state;
158 if (subscribers.length === 0) { return; }
160 let child, callback, detail = promise._result;
162 for (let i = 0; i < subscribers.length; i += 3) {
163 child = subscribers[i];
164 callback = subscribers[i + settled];
167 invokeCallback(settled, child, callback, detail);
173 promise._subscribers.length = 0;
176 function ErrorObject() {
180 const TRY_CATCH_ERROR = new ErrorObject();
182 function tryCatch(callback, detail) {
184 return callback(detail);
186 TRY_CATCH_ERROR.error = e;
187 return TRY_CATCH_ERROR;
191 function invokeCallback(settled, promise, callback, detail) {
192 let hasCallback = isFunction(callback),
193 value, error, succeeded, failed;
196 value = tryCatch(callback, detail);
198 if (value === TRY_CATCH_ERROR) {
206 if (promise === value) {
207 reject(promise, cannotReturnOwn());
216 if (promise._state !== PENDING) {
218 } else if (hasCallback && succeeded) {
219 resolve(promise, value);
221 reject(promise, error);
222 } else if (settled === FULFILLED) {
223 fulfill(promise, value);
224 } else if (settled === REJECTED) {
225 reject(promise, value);
229 function initializePromise(promise, resolver) {
231 resolver(function resolvePromise(value){
232 resolve(promise, value);
233 }, function rejectPromise(reason) {
234 reject(promise, reason);
246 function makePromise(promise) {
247 promise[PROMISE_ID] = id++;
248 promise._state = undefined;
249 promise._result = undefined;
250 promise._subscribers = [];