b6d07de69e3735522319b32d091528497485c511
[yaffs-website] / node_modules / es6-promise / lib / es6-promise / -internal.js
1 import {
2   objectOrFunction,
3   isFunction
4 } from './utils';
5
6 import {
7   asap
8 } from './asap';
9
10 import originalThen from './then';
11 import originalResolve from './promise/resolve';
12
13 export const PROMISE_ID = Math.random().toString(36).substring(16);
14
15 function noop() {}
16
17 const PENDING   = void 0;
18 const FULFILLED = 1;
19 const REJECTED  = 2;
20
21 const GET_THEN_ERROR = new ErrorObject();
22
23 function selfFulfillment() {
24   return new TypeError("You cannot resolve a promise with itself");
25 }
26
27 function cannotReturnOwn() {
28   return new TypeError('A promises callback cannot return that same promise.');
29 }
30
31 function getThen(promise) {
32   try {
33     return promise.then;
34   } catch(error) {
35     GET_THEN_ERROR.error = error;
36     return GET_THEN_ERROR;
37   }
38 }
39
40 function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
41   try {
42     then.call(value, fulfillmentHandler, rejectionHandler);
43   } catch(e) {
44     return e;
45   }
46 }
47
48 function handleForeignThenable(promise, thenable, then) {
49    asap(promise => {
50     var sealed = false;
51     var error = tryThen(then, thenable, value => {
52       if (sealed) { return; }
53       sealed = true;
54       if (thenable !== value) {
55         resolve(promise, value);
56       } else {
57         fulfill(promise, value);
58       }
59     }, reason => {
60       if (sealed) { return; }
61       sealed = true;
62
63       reject(promise, reason);
64     }, 'Settle: ' + (promise._label || ' unknown promise'));
65
66     if (!sealed && error) {
67       sealed = true;
68       reject(promise, error);
69     }
70   }, promise);
71 }
72
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);
78   } else {
79     subscribe(thenable, undefined, value  => resolve(promise, value),
80                                    reason => reject(promise, reason))
81   }
82 }
83
84 function handleMaybeThenable(promise, maybeThenable, then) {
85   if (maybeThenable.constructor === promise.constructor &&
86       then === originalThen &&
87       maybeThenable.constructor.resolve === originalResolve) {
88     handleOwnThenable(promise, maybeThenable);
89   } else {
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);
96     } else {
97       fulfill(promise, maybeThenable);
98     }
99   }
100 }
101
102 function resolve(promise, value) {
103   if (promise === value) {
104     reject(promise, selfFulfillment());
105   } else if (objectOrFunction(value)) {
106     handleMaybeThenable(promise, value, getThen(value));
107   } else {
108     fulfill(promise, value);
109   }
110 }
111
112 function publishRejection(promise) {
113   if (promise._onerror) {
114     promise._onerror(promise._result);
115   }
116
117   publish(promise);
118 }
119
120 function fulfill(promise, value) {
121   if (promise._state !== PENDING) { return; }
122
123   promise._result = value;
124   promise._state = FULFILLED;
125
126   if (promise._subscribers.length !== 0) {
127     asap(publish, promise);
128   }
129 }
130
131 function reject(promise, reason) {
132   if (promise._state !== PENDING) { return; }
133   promise._state = REJECTED;
134   promise._result = reason;
135
136   asap(publishRejection, promise);
137 }
138
139 function subscribe(parent, child, onFulfillment, onRejection) {
140   let { _subscribers } = parent;
141   let { length } = _subscribers;
142
143   parent._onerror = null;
144
145   _subscribers[length] = child;
146   _subscribers[length + FULFILLED] = onFulfillment;
147   _subscribers[length + REJECTED]  = onRejection;
148
149   if (length === 0 && parent._state) {
150     asap(publish, parent);
151   }
152 }
153
154 function publish(promise) {
155   let subscribers = promise._subscribers;
156   let settled = promise._state;
157
158   if (subscribers.length === 0) { return; }
159
160   let child, callback, detail = promise._result;
161
162   for (let i = 0; i < subscribers.length; i += 3) {
163     child = subscribers[i];
164     callback = subscribers[i + settled];
165
166     if (child) {
167       invokeCallback(settled, child, callback, detail);
168     } else {
169       callback(detail);
170     }
171   }
172
173   promise._subscribers.length = 0;
174 }
175
176 function ErrorObject() {
177   this.error = null;
178 }
179
180 const TRY_CATCH_ERROR = new ErrorObject();
181
182 function tryCatch(callback, detail) {
183   try {
184     return callback(detail);
185   } catch(e) {
186     TRY_CATCH_ERROR.error = e;
187     return TRY_CATCH_ERROR;
188   }
189 }
190
191 function invokeCallback(settled, promise, callback, detail) {
192   let hasCallback = isFunction(callback),
193       value, error, succeeded, failed;
194
195   if (hasCallback) {
196     value = tryCatch(callback, detail);
197
198     if (value === TRY_CATCH_ERROR) {
199       failed = true;
200       error = value.error;
201       value = null;
202     } else {
203       succeeded = true;
204     }
205
206     if (promise === value) {
207       reject(promise, cannotReturnOwn());
208       return;
209     }
210
211   } else {
212     value = detail;
213     succeeded = true;
214   }
215
216   if (promise._state !== PENDING) {
217     // noop
218   } else if (hasCallback && succeeded) {
219     resolve(promise, value);
220   } else if (failed) {
221     reject(promise, error);
222   } else if (settled === FULFILLED) {
223     fulfill(promise, value);
224   } else if (settled === REJECTED) {
225     reject(promise, value);
226   }
227 }
228
229 function initializePromise(promise, resolver) {
230   try {
231     resolver(function resolvePromise(value){
232       resolve(promise, value);
233     }, function rejectPromise(reason) {
234       reject(promise, reason);
235     });
236   } catch(e) {
237     reject(promise, e);
238   }
239 }
240
241 let id = 0;
242 function nextId() {
243   return id++;
244 }
245
246 function makePromise(promise) {
247   promise[PROMISE_ID] = id++;
248   promise._state = undefined;
249   promise._result = undefined;
250   promise._subscribers = [];
251 }
252
253 export {
254   nextId,
255   makePromise,
256   getThen,
257   noop,
258   resolve,
259   reject,
260   fulfill,
261   subscribe,
262   publish,
263   publishRejection,
264   initializePromise,
265   invokeCallback,
266   FULFILLED,
267   REJECTED,
268   PENDING,
269   handleMaybeThenable
270 };