You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					287 lines
				
				9.6 KiB
			
		
		
			
		
	
	
					287 lines
				
				9.6 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | var LIBRARY = require('./_library'); | ||
|  | var global = require('./_global'); | ||
|  | var ctx = require('./_ctx'); | ||
|  | var classof = require('./_classof'); | ||
|  | var $export = require('./_export'); | ||
|  | var isObject = require('./_is-object'); | ||
|  | var aFunction = require('./_a-function'); | ||
|  | var anInstance = require('./_an-instance'); | ||
|  | var forOf = require('./_for-of'); | ||
|  | var speciesConstructor = require('./_species-constructor'); | ||
|  | var task = require('./_task').set; | ||
|  | var microtask = require('./_microtask')(); | ||
|  | var newPromiseCapabilityModule = require('./_new-promise-capability'); | ||
|  | var perform = require('./_perform'); | ||
|  | var userAgent = require('./_user-agent'); | ||
|  | var promiseResolve = require('./_promise-resolve'); | ||
|  | var PROMISE = 'Promise'; | ||
|  | var TypeError = global.TypeError; | ||
|  | var process = global.process; | ||
|  | var versions = process && process.versions; | ||
|  | var v8 = versions && versions.v8 || ''; | ||
|  | var $Promise = global[PROMISE]; | ||
|  | var isNode = classof(process) == 'process'; | ||
|  | var empty = function () { /* empty */ }; | ||
|  | var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper; | ||
|  | var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f; | ||
|  | 
 | ||
|  | var USE_NATIVE = !!function () { | ||
|  |   try { | ||
|  |     // correct subclassing with @@species support
 | ||
|  |     var promise = $Promise.resolve(1); | ||
|  |     var FakePromise = (promise.constructor = {})[require('./_wks')('species')] = function (exec) { | ||
|  |       exec(empty, empty); | ||
|  |     }; | ||
|  |     // unhandled rejections tracking support, NodeJS Promise without it fails @@species test
 | ||
|  |     return (isNode || typeof PromiseRejectionEvent == 'function') | ||
|  |       && promise.then(empty) instanceof FakePromise | ||
|  |       // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
 | ||
|  |       // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
 | ||
|  |       // we can't detect it synchronously, so just check versions
 | ||
|  |       && v8.indexOf('6.6') !== 0 | ||
|  |       && userAgent.indexOf('Chrome/66') === -1; | ||
|  |   } catch (e) { /* empty */ } | ||
|  | }(); | ||
|  | 
 | ||
|  | // helpers
 | ||
|  | var isThenable = function (it) { | ||
|  |   var then; | ||
|  |   return isObject(it) && typeof (then = it.then) == 'function' ? then : false; | ||
|  | }; | ||
|  | var notify = function (promise, isReject) { | ||
|  |   if (promise._n) return; | ||
|  |   promise._n = true; | ||
|  |   var chain = promise._c; | ||
|  |   microtask(function () { | ||
|  |     var value = promise._v; | ||
|  |     var ok = promise._s == 1; | ||
|  |     var i = 0; | ||
|  |     var run = function (reaction) { | ||
|  |       var handler = ok ? reaction.ok : reaction.fail; | ||
|  |       var resolve = reaction.resolve; | ||
|  |       var reject = reaction.reject; | ||
|  |       var domain = reaction.domain; | ||
|  |       var result, then, exited; | ||
|  |       try { | ||
|  |         if (handler) { | ||
|  |           if (!ok) { | ||
|  |             if (promise._h == 2) onHandleUnhandled(promise); | ||
|  |             promise._h = 1; | ||
|  |           } | ||
|  |           if (handler === true) result = value; | ||
|  |           else { | ||
|  |             if (domain) domain.enter(); | ||
|  |             result = handler(value); // may throw
 | ||
|  |             if (domain) { | ||
|  |               domain.exit(); | ||
|  |               exited = true; | ||
|  |             } | ||
|  |           } | ||
|  |           if (result === reaction.promise) { | ||
|  |             reject(TypeError('Promise-chain cycle')); | ||
|  |           } else if (then = isThenable(result)) { | ||
|  |             then.call(result, resolve, reject); | ||
|  |           } else resolve(result); | ||
|  |         } else reject(value); | ||
|  |       } catch (e) { | ||
|  |         if (domain && !exited) domain.exit(); | ||
|  |         reject(e); | ||
|  |       } | ||
|  |     }; | ||
|  |     while (chain.length > i) run(chain[i++]); // variable length - can't use forEach
 | ||
|  |     promise._c = []; | ||
|  |     promise._n = false; | ||
|  |     if (isReject && !promise._h) onUnhandled(promise); | ||
|  |   }); | ||
|  | }; | ||
|  | var onUnhandled = function (promise) { | ||
|  |   task.call(global, function () { | ||
|  |     var value = promise._v; | ||
|  |     var unhandled = isUnhandled(promise); | ||
|  |     var result, handler, console; | ||
|  |     if (unhandled) { | ||
|  |       result = perform(function () { | ||
|  |         if (isNode) { | ||
|  |           process.emit('unhandledRejection', value, promise); | ||
|  |         } else if (handler = global.onunhandledrejection) { | ||
|  |           handler({ promise: promise, reason: value }); | ||
|  |         } else if ((console = global.console) && console.error) { | ||
|  |           console.error('Unhandled promise rejection', value); | ||
|  |         } | ||
|  |       }); | ||
|  |       // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
 | ||
|  |       promise._h = isNode || isUnhandled(promise) ? 2 : 1; | ||
|  |     } promise._a = undefined; | ||
|  |     if (unhandled && result.e) throw result.v; | ||
|  |   }); | ||
|  | }; | ||
|  | var isUnhandled = function (promise) { | ||
|  |   return promise._h !== 1 && (promise._a || promise._c).length === 0; | ||
|  | }; | ||
|  | var onHandleUnhandled = function (promise) { | ||
|  |   task.call(global, function () { | ||
|  |     var handler; | ||
|  |     if (isNode) { | ||
|  |       process.emit('rejectionHandled', promise); | ||
|  |     } else if (handler = global.onrejectionhandled) { | ||
|  |       handler({ promise: promise, reason: promise._v }); | ||
|  |     } | ||
|  |   }); | ||
|  | }; | ||
|  | var $reject = function (value) { | ||
|  |   var promise = this; | ||
|  |   if (promise._d) return; | ||
|  |   promise._d = true; | ||
|  |   promise = promise._w || promise; // unwrap
 | ||
|  |   promise._v = value; | ||
|  |   promise._s = 2; | ||
|  |   if (!promise._a) promise._a = promise._c.slice(); | ||
|  |   notify(promise, true); | ||
|  | }; | ||
|  | var $resolve = function (value) { | ||
|  |   var promise = this; | ||
|  |   var then; | ||
|  |   if (promise._d) return; | ||
|  |   promise._d = true; | ||
|  |   promise = promise._w || promise; // unwrap
 | ||
|  |   try { | ||
|  |     if (promise === value) throw TypeError("Promise can't be resolved itself"); | ||
|  |     if (then = isThenable(value)) { | ||
|  |       microtask(function () { | ||
|  |         var wrapper = { _w: promise, _d: false }; // wrap
 | ||
|  |         try { | ||
|  |           then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); | ||
|  |         } catch (e) { | ||
|  |           $reject.call(wrapper, e); | ||
|  |         } | ||
|  |       }); | ||
|  |     } else { | ||
|  |       promise._v = value; | ||
|  |       promise._s = 1; | ||
|  |       notify(promise, false); | ||
|  |     } | ||
|  |   } catch (e) { | ||
|  |     $reject.call({ _w: promise, _d: false }, e); // wrap
 | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | // constructor polyfill
 | ||
|  | if (!USE_NATIVE) { | ||
|  |   // 25.4.3.1 Promise(executor)
 | ||
|  |   $Promise = function Promise(executor) { | ||
|  |     anInstance(this, $Promise, PROMISE, '_h'); | ||
|  |     aFunction(executor); | ||
|  |     Internal.call(this); | ||
|  |     try { | ||
|  |       executor(ctx($resolve, this, 1), ctx($reject, this, 1)); | ||
|  |     } catch (err) { | ||
|  |       $reject.call(this, err); | ||
|  |     } | ||
|  |   }; | ||
|  |   // eslint-disable-next-line no-unused-vars
 | ||
|  |   Internal = function Promise(executor) { | ||
|  |     this._c = [];             // <- awaiting reactions
 | ||
|  |     this._a = undefined;      // <- checked in isUnhandled reactions
 | ||
|  |     this._s = 0;              // <- state
 | ||
|  |     this._d = false;          // <- done
 | ||
|  |     this._v = undefined;      // <- value
 | ||
|  |     this._h = 0;              // <- rejection state, 0 - default, 1 - handled, 2 - unhandled
 | ||
|  |     this._n = false;          // <- notify
 | ||
|  |   }; | ||
|  |   Internal.prototype = require('./_redefine-all')($Promise.prototype, { | ||
|  |     // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
 | ||
|  |     then: function then(onFulfilled, onRejected) { | ||
|  |       var reaction = newPromiseCapability(speciesConstructor(this, $Promise)); | ||
|  |       reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; | ||
|  |       reaction.fail = typeof onRejected == 'function' && onRejected; | ||
|  |       reaction.domain = isNode ? process.domain : undefined; | ||
|  |       this._c.push(reaction); | ||
|  |       if (this._a) this._a.push(reaction); | ||
|  |       if (this._s) notify(this, false); | ||
|  |       return reaction.promise; | ||
|  |     }, | ||
|  |     // 25.4.5.1 Promise.prototype.catch(onRejected)
 | ||
|  |     'catch': function (onRejected) { | ||
|  |       return this.then(undefined, onRejected); | ||
|  |     } | ||
|  |   }); | ||
|  |   OwnPromiseCapability = function () { | ||
|  |     var promise = new Internal(); | ||
|  |     this.promise = promise; | ||
|  |     this.resolve = ctx($resolve, promise, 1); | ||
|  |     this.reject = ctx($reject, promise, 1); | ||
|  |   }; | ||
|  |   newPromiseCapabilityModule.f = newPromiseCapability = function (C) { | ||
|  |     return C === $Promise || C === Wrapper | ||
|  |       ? new OwnPromiseCapability(C) | ||
|  |       : newGenericPromiseCapability(C); | ||
|  |   }; | ||
|  | } | ||
|  | 
 | ||
|  | $export($export.G + $export.W + $export.F * !USE_NATIVE, { Promise: $Promise }); | ||
|  | require('./_set-to-string-tag')($Promise, PROMISE); | ||
|  | require('./_set-species')(PROMISE); | ||
|  | Wrapper = require('./_core')[PROMISE]; | ||
|  | 
 | ||
|  | // statics
 | ||
|  | $export($export.S + $export.F * !USE_NATIVE, PROMISE, { | ||
|  |   // 25.4.4.5 Promise.reject(r)
 | ||
|  |   reject: function reject(r) { | ||
|  |     var capability = newPromiseCapability(this); | ||
|  |     var $$reject = capability.reject; | ||
|  |     $$reject(r); | ||
|  |     return capability.promise; | ||
|  |   } | ||
|  | }); | ||
|  | $export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, { | ||
|  |   // 25.4.4.6 Promise.resolve(x)
 | ||
|  |   resolve: function resolve(x) { | ||
|  |     return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x); | ||
|  |   } | ||
|  | }); | ||
|  | $export($export.S + $export.F * !(USE_NATIVE && require('./_iter-detect')(function (iter) { | ||
|  |   $Promise.all(iter)['catch'](empty); | ||
|  | })), PROMISE, { | ||
|  |   // 25.4.4.1 Promise.all(iterable)
 | ||
|  |   all: function all(iterable) { | ||
|  |     var C = this; | ||
|  |     var capability = newPromiseCapability(C); | ||
|  |     var resolve = capability.resolve; | ||
|  |     var reject = capability.reject; | ||
|  |     var result = perform(function () { | ||
|  |       var values = []; | ||
|  |       var index = 0; | ||
|  |       var remaining = 1; | ||
|  |       forOf(iterable, false, function (promise) { | ||
|  |         var $index = index++; | ||
|  |         var alreadyCalled = false; | ||
|  |         values.push(undefined); | ||
|  |         remaining++; | ||
|  |         C.resolve(promise).then(function (value) { | ||
|  |           if (alreadyCalled) return; | ||
|  |           alreadyCalled = true; | ||
|  |           values[$index] = value; | ||
|  |           --remaining || resolve(values); | ||
|  |         }, reject); | ||
|  |       }); | ||
|  |       --remaining || resolve(values); | ||
|  |     }); | ||
|  |     if (result.e) reject(result.v); | ||
|  |     return capability.promise; | ||
|  |   }, | ||
|  |   // 25.4.4.4 Promise.race(iterable)
 | ||
|  |   race: function race(iterable) { | ||
|  |     var C = this; | ||
|  |     var capability = newPromiseCapability(C); | ||
|  |     var reject = capability.reject; | ||
|  |     var result = perform(function () { | ||
|  |       forOf(iterable, false, function (promise) { | ||
|  |         C.resolve(promise).then(capability.resolve, reject); | ||
|  |       }); | ||
|  |     }); | ||
|  |     if (result.e) reject(result.v); | ||
|  |     return capability.promise; | ||
|  |   } | ||
|  | }); |