10 import originalThen from './then';
11 import originalResolve from './promise/resolve';
13 export const PROMISE_ID = Math.random().toString(36).substring(2);
17 const PENDING = void 0;
21 function selfFulfillment() {
22 return new TypeError("You cannot resolve a promise with itself");
25 function cannotReturnOwn() {
26 return new TypeError('A promises callback cannot return that same promise.');
29 function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
31 then.call(value, fulfillmentHandler, rejectionHandler);
37 function handleForeignThenable(promise, thenable, then) {
40 let error = tryThen(then, thenable, value => {
41 if (sealed) { return; }
43 if (thenable !== value) {
44 resolve(promise, value);
46 fulfill(promise, value);
49 if (sealed) { return; }
52 reject(promise, reason);
53 }, 'Settle: ' + (promise._label || ' unknown promise'));
55 if (!sealed && error) {
57 reject(promise, error);
62 function handleOwnThenable(promise, thenable) {
63 if (thenable._state === FULFILLED) {
64 fulfill(promise, thenable._result);
65 } else if (thenable._state === REJECTED) {
66 reject(promise, thenable._result);
68 subscribe(thenable, undefined, value => resolve(promise, value),
69 reason => reject(promise, reason))
73 function handleMaybeThenable(promise, maybeThenable, then) {
74 if (maybeThenable.constructor === promise.constructor &&
75 then === originalThen &&
76 maybeThenable.constructor.resolve === originalResolve) {
77 handleOwnThenable(promise, maybeThenable);
79 if (then === undefined) {
80 fulfill(promise, maybeThenable);
81 } else if (isFunction(then)) {
82 handleForeignThenable(promise, maybeThenable, then);
84 fulfill(promise, maybeThenable);
89 function resolve(promise, value) {
90 if (promise === value) {
91 reject(promise, selfFulfillment());
92 } else if (objectOrFunction(value)) {
97 reject(promise, error);
100 handleMaybeThenable(promise, value, then);
102 fulfill(promise, value);
106 function publishRejection(promise) {
107 if (promise._onerror) {
108 promise._onerror(promise._result);
114 function fulfill(promise, value) {
115 if (promise._state !== PENDING) { return; }
117 promise._result = value;
118 promise._state = FULFILLED;
120 if (promise._subscribers.length !== 0) {
121 asap(publish, promise);
125 function reject(promise, reason) {
126 if (promise._state !== PENDING) { return; }
127 promise._state = REJECTED;
128 promise._result = reason;
130 asap(publishRejection, promise);
133 function subscribe(parent, child, onFulfillment, onRejection) {
134 let { _subscribers } = parent;
135 let { length } = _subscribers;
137 parent._onerror = null;
139 _subscribers[length] = child;
140 _subscribers[length + FULFILLED] = onFulfillment;
141 _subscribers[length + REJECTED] = onRejection;
143 if (length === 0 && parent._state) {
144 asap(publish, parent);
148 function publish(promise) {
149 let subscribers = promise._subscribers;
150 let settled = promise._state;
152 if (subscribers.length === 0) { return; }
154 let child, callback, detail = promise._result;
156 for (let i = 0; i < subscribers.length; i += 3) {
157 child = subscribers[i];
158 callback = subscribers[i + settled];
161 invokeCallback(settled, child, callback, detail);
167 promise._subscribers.length = 0;
170 function invokeCallback(settled, promise, callback, detail) {
171 let hasCallback = isFunction(callback),
172 value, error, succeeded = true;
176 value = callback(detail);
182 if (promise === value) {
183 reject(promise, cannotReturnOwn());
190 if (promise._state !== PENDING) {
192 } else if (hasCallback && succeeded) {
193 resolve(promise, value);
194 } else if (succeeded === false) {
195 reject(promise, error);
196 } else if (settled === FULFILLED) {
197 fulfill(promise, value);
198 } else if (settled === REJECTED) {
199 reject(promise, value);
203 function initializePromise(promise, resolver) {
205 resolver(function resolvePromise(value){
206 resolve(promise, value);
207 }, function rejectPromise(reason) {
208 reject(promise, reason);
220 function makePromise(promise) {
221 promise[PROMISE_ID] = id++;
222 promise._state = undefined;
223 promise._result = undefined;
224 promise._subscribers = [];