10 // 1 - fulfilled with _value
11 // 2 - rejected with _value
12 // 3 - adopted the state of another promise, _value
14 // once the state is no longer pending (0) it is immutable
16 // All `_` prefixed properties will be reduced to `_{random number}`
17 // at build time to obfuscate them and discourage their use.
18 // We don't use symbols or Object.defineProperty to fully hide them
19 // because the performance isn't good enough.
22 // to avoid using try/catch inside critical functions, we
23 // extract them to here.
24 var LAST_ERROR = null;
26 function getThen(obj) {
35 function tryCallOne(fn, a) {
43 function tryCallTwo(fn, a, b) {
52 module.exports = Promise;
54 function Promise(fn) {
55 if (typeof this !== 'object') {
56 throw new TypeError('Promises must be constructed via new');
58 if (typeof fn !== 'function') {
59 throw new TypeError('Promise constructor\'s argument is not a function');
65 if (fn === noop) return;
72 Promise.prototype.then = function(onFulfilled, onRejected) {
73 if (this.constructor !== Promise) {
74 return safeThen(this, onFulfilled, onRejected);
76 var res = new Promise(noop);
77 handle(this, new Handler(onFulfilled, onRejected, res));
81 function safeThen(self, onFulfilled, onRejected) {
82 return new self.constructor(function (resolve, reject) {
83 var res = new Promise(noop);
84 res.then(resolve, reject);
85 handle(self, new Handler(onFulfilled, onRejected, res));
88 function handle(self, deferred) {
89 while (self._65 === 3) {
101 if (self._40 === 1) {
103 self._72 = [self._72, deferred];
106 self._72.push(deferred);
109 handleResolved(self, deferred);
112 function handleResolved(self, deferred) {
113 setImmediate(function() {
114 var cb = self._65 === 1 ? deferred.onFulfilled : deferred.onRejected;
116 if (self._65 === 1) {
117 resolve(deferred.promise, self._55);
119 reject(deferred.promise, self._55);
123 var ret = tryCallOne(cb, self._55);
124 if (ret === IS_ERROR) {
125 reject(deferred.promise, LAST_ERROR);
127 resolve(deferred.promise, ret);
131 function resolve(self, newValue) {
132 // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
133 if (newValue === self) {
136 new TypeError('A promise cannot be resolved with itself.')
141 (typeof newValue === 'object' || typeof newValue === 'function')
143 var then = getThen(newValue);
144 if (then === IS_ERROR) {
145 return reject(self, LAST_ERROR);
148 then === self.then &&
149 newValue instanceof Promise
155 } else if (typeof then === 'function') {
156 doResolve(then.bind(newValue), self);
165 function reject(self, newValue) {
169 Promise._87(self, newValue);
173 function finale(self) {
174 if (self._40 === 1) {
175 handle(self, self._72);
178 if (self._40 === 2) {
179 for (var i = 0; i < self._72.length; i++) {
180 handle(self, self._72[i]);
186 function Handler(onFulfilled, onRejected, promise){
187 this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
188 this.onRejected = typeof onRejected === 'function' ? onRejected : null;
189 this.promise = promise;
193 * Take a potentially misbehaving resolver function and make sure
194 * onFulfilled and onRejected are only called once.
196 * Makes no guarantees about asynchrony.
198 function doResolve(fn, promise) {
200 var res = tryCallTwo(fn, function (value) {
203 resolve(promise, value);
204 }, function (reason) {
207 reject(promise, reason);
209 if (!done && res === IS_ERROR) {
211 reject(promise, LAST_ERROR);