10 import originalThen from './then';
11 import originalResolve from './promise/resolve';
13 export var PROMISE_ID = Math.random().toString(36).substring(16);
21 var 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) {
49 asap(function(promise) {
51 var error = tryThen(then, thenable, function(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, function(value) {
80 resolve(promise, value);
82 reject(promise, reason);
87 function handleMaybeThenable(promise, maybeThenable, then) {
88 if (maybeThenable.constructor === promise.constructor &&
89 then === originalThen &&
90 constructor.resolve === originalResolve) {
91 handleOwnThenable(promise, maybeThenable);
93 if (then === GET_THEN_ERROR) {
94 reject(promise, GET_THEN_ERROR.error);
95 } else if (then === undefined) {
96 fulfill(promise, maybeThenable);
97 } else if (isFunction(then)) {
98 handleForeignThenable(promise, maybeThenable, then);
100 fulfill(promise, maybeThenable);
105 function resolve(promise, value) {
106 if (promise === value) {
107 reject(promise, selfFulfillment());
108 } else if (objectOrFunction(value)) {
109 handleMaybeThenable(promise, value, getThen(value));
111 fulfill(promise, value);
115 function publishRejection(promise) {
116 if (promise._onerror) {
117 promise._onerror(promise._result);
123 function fulfill(promise, value) {
124 if (promise._state !== PENDING) { return; }
126 promise._result = value;
127 promise._state = FULFILLED;
129 if (promise._subscribers.length !== 0) {
130 asap(publish, promise);
134 function reject(promise, reason) {
135 if (promise._state !== PENDING) { return; }
136 promise._state = REJECTED;
137 promise._result = reason;
139 asap(publishRejection, promise);
142 function subscribe(parent, child, onFulfillment, onRejection) {
143 var subscribers = parent._subscribers;
144 var length = subscribers.length;
146 parent._onerror = null;
148 subscribers[length] = child;
149 subscribers[length + FULFILLED] = onFulfillment;
150 subscribers[length + REJECTED] = onRejection;
152 if (length === 0 && parent._state) {
153 asap(publish, parent);
157 function publish(promise) {
158 var subscribers = promise._subscribers;
159 var settled = promise._state;
161 if (subscribers.length === 0) { return; }
163 var child, callback, detail = promise._result;
165 for (var i = 0; i < subscribers.length; i += 3) {
166 child = subscribers[i];
167 callback = subscribers[i + settled];
170 invokeCallback(settled, child, callback, detail);
176 promise._subscribers.length = 0;
179 function ErrorObject() {
183 var TRY_CATCH_ERROR = new ErrorObject();
185 function tryCatch(callback, detail) {
187 return callback(detail);
189 TRY_CATCH_ERROR.error = e;
190 return TRY_CATCH_ERROR;
194 function invokeCallback(settled, promise, callback, detail) {
195 var hasCallback = isFunction(callback),
196 value, error, succeeded, failed;
199 value = tryCatch(callback, detail);
201 if (value === TRY_CATCH_ERROR) {
209 if (promise === value) {
210 reject(promise, cannotReturnOwn());
219 if (promise._state !== PENDING) {
221 } else if (hasCallback && succeeded) {
222 resolve(promise, value);
224 reject(promise, error);
225 } else if (settled === FULFILLED) {
226 fulfill(promise, value);
227 } else if (settled === REJECTED) {
228 reject(promise, value);
232 function initializePromise(promise, resolver) {
234 resolver(function resolvePromise(value){
235 resolve(promise, value);
236 }, function rejectPromise(reason) {
237 reject(promise, reason);
249 function makePromise(promise) {
250 promise[PROMISE_ID] = id++;
251 promise._state = undefined;
252 promise._result = undefined;
253 promise._subscribers = [];