2 var $ = require('../internals/export');
3 var IS_PURE = require('../internals/is-pure');
4 var global = require('../internals/global');
5 var getBuiltIn = require('../internals/get-built-in');
6 var NativePromise = require('../internals/native-promise-constructor');
7 var redefine = require('../internals/redefine');
8 var redefineAll = require('../internals/redefine-all');
9 var setToStringTag = require('../internals/set-to-string-tag');
10 var setSpecies = require('../internals/set-species');
11 var isObject = require('../internals/is-object');
12 var aFunction = require('../internals/a-function');
13 var anInstance = require('../internals/an-instance');
14 var classof = require('../internals/classof-raw');
15 var inspectSource = require('../internals/inspect-source');
16 var iterate = require('../internals/iterate');
17 var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
18 var speciesConstructor = require('../internals/species-constructor');
19 var task = require('../internals/task').set;
20 var microtask = require('../internals/microtask');
21 var promiseResolve = require('../internals/promise-resolve');
22 var hostReportErrors = require('../internals/host-report-errors');
23 var newPromiseCapabilityModule = require('../internals/new-promise-capability');
24 var perform = require('../internals/perform');
25 var InternalStateModule = require('../internals/internal-state');
26 var isForced = require('../internals/is-forced');
27 var wellKnownSymbol = require('../internals/well-known-symbol');
28 var V8_VERSION = require('../internals/engine-v8-version');
30 var SPECIES = wellKnownSymbol('species');
31 var PROMISE = 'Promise';
32 var getInternalState = InternalStateModule.get;
33 var setInternalState = InternalStateModule.set;
34 var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
35 var PromiseConstructor = NativePromise;
36 var TypeError = global.TypeError;
37 var document = global.document;
38 var process = global.process;
39 var $fetch = getBuiltIn('fetch');
40 var newPromiseCapability = newPromiseCapabilityModule.f;
41 var newGenericPromiseCapability = newPromiseCapability;
42 var IS_NODE = classof(process) == 'process';
43 var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
44 var UNHANDLED_REJECTION = 'unhandledrejection';
45 var REJECTION_HANDLED = 'rejectionhandled';
51 var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
53 var FORCED = isForced(PROMISE, function () {
54 var GLOBAL_CORE_JS_PROMISE = inspectSource(PromiseConstructor) !== String(PromiseConstructor);
55 if (!GLOBAL_CORE_JS_PROMISE) {
56 // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
57 // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
58 // We can't detect it synchronously, so just check versions
59 if (V8_VERSION === 66) return true;
60 // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
61 if (!IS_NODE && typeof PromiseRejectionEvent != 'function') return true;
63 // We need Promise#finally in the pure version for preventing prototype pollution
64 if (IS_PURE && !PromiseConstructor.prototype['finally']) return true;
65 // We can't use @@species feature detection in V8 since it causes
66 // deoptimization and performance degradation
67 // https://github.com/zloirock/core-js/issues/679
68 if (V8_VERSION >= 51 && /native code/.test(PromiseConstructor)) return false;
69 // Detect correctness of subclassing with @@species support
70 var promise = PromiseConstructor.resolve(1);
71 var FakePromise = function (exec) {
72 exec(function () { /* empty */ }, function () { /* empty */ });
74 var constructor = promise.constructor = {};
75 constructor[SPECIES] = FakePromise;
76 return !(promise.then(function () { /* empty */ }) instanceof FakePromise);
79 var INCORRECT_ITERATION = FORCED || !checkCorrectnessOfIteration(function (iterable) {
80 PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
84 var isThenable = function (it) {
86 return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
89 var notify = function (promise, state, isReject) {
90 if (state.notified) return;
91 state.notified = true;
92 var chain = state.reactions;
93 microtask(function () {
94 var value = state.value;
95 var ok = state.state == FULFILLED;
97 // variable length - can't use forEach
98 while (chain.length > index) {
99 var reaction = chain[index++];
100 var handler = ok ? reaction.ok : reaction.fail;
101 var resolve = reaction.resolve;
102 var reject = reaction.reject;
103 var domain = reaction.domain;
104 var result, then, exited;
108 if (state.rejection === UNHANDLED) onHandleUnhandled(promise, state);
109 state.rejection = HANDLED;
111 if (handler === true) result = value;
113 if (domain) domain.enter();
114 result = handler(value); // can throw
120 if (result === reaction.promise) {
121 reject(TypeError('Promise-chain cycle'));
122 } else if (then = isThenable(result)) {
123 then.call(result, resolve, reject);
124 } else resolve(result);
125 } else reject(value);
127 if (domain && !exited) domain.exit();
131 state.reactions = [];
132 state.notified = false;
133 if (isReject && !state.rejection) onUnhandled(promise, state);
137 var dispatchEvent = function (name, promise, reason) {
139 if (DISPATCH_EVENT) {
140 event = document.createEvent('Event');
141 event.promise = promise;
142 event.reason = reason;
143 event.initEvent(name, false, true);
144 global.dispatchEvent(event);
145 } else event = { promise: promise, reason: reason };
146 if (handler = global['on' + name]) handler(event);
147 else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
150 var onUnhandled = function (promise, state) {
151 task.call(global, function () {
152 var value = state.value;
153 var IS_UNHANDLED = isUnhandled(state);
156 result = perform(function () {
158 process.emit('unhandledRejection', value, promise);
159 } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
161 // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
162 state.rejection = IS_NODE || isUnhandled(state) ? UNHANDLED : HANDLED;
163 if (result.error) throw result.value;
168 var isUnhandled = function (state) {
169 return state.rejection !== HANDLED && !state.parent;
172 var onHandleUnhandled = function (promise, state) {
173 task.call(global, function () {
175 process.emit('rejectionHandled', promise);
176 } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
180 var bind = function (fn, promise, state, unwrap) {
181 return function (value) {
182 fn(promise, state, value, unwrap);
186 var internalReject = function (promise, state, value, unwrap) {
187 if (state.done) return;
189 if (unwrap) state = unwrap;
191 state.state = REJECTED;
192 notify(promise, state, true);
195 var internalResolve = function (promise, state, value, unwrap) {
196 if (state.done) return;
198 if (unwrap) state = unwrap;
200 if (promise === value) throw TypeError("Promise can't be resolved itself");
201 var then = isThenable(value);
203 microtask(function () {
204 var wrapper = { done: false };
207 bind(internalResolve, promise, wrapper, state),
208 bind(internalReject, promise, wrapper, state)
211 internalReject(promise, wrapper, error, state);
216 state.state = FULFILLED;
217 notify(promise, state, false);
220 internalReject(promise, { done: false }, error, state);
224 // constructor polyfill
226 // 25.4.3.1 Promise(executor)
227 PromiseConstructor = function Promise(executor) {
228 anInstance(this, PromiseConstructor, PROMISE);
231 var state = getInternalState(this);
233 executor(bind(internalResolve, this, state), bind(internalReject, this, state));
235 internalReject(this, state, error);
238 // eslint-disable-next-line no-unused-vars
239 Internal = function Promise(executor) {
240 setInternalState(this, {
251 Internal.prototype = redefineAll(PromiseConstructor.prototype, {
252 // `Promise.prototype.then` method
253 // https://tc39.github.io/ecma262/#sec-promise.prototype.then
254 then: function then(onFulfilled, onRejected) {
255 var state = getInternalPromiseState(this);
256 var reaction = newPromiseCapability(speciesConstructor(this, PromiseConstructor));
257 reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
258 reaction.fail = typeof onRejected == 'function' && onRejected;
259 reaction.domain = IS_NODE ? process.domain : undefined;
261 state.reactions.push(reaction);
262 if (state.state != PENDING) notify(this, state, false);
263 return reaction.promise;
265 // `Promise.prototype.catch` method
266 // https://tc39.github.io/ecma262/#sec-promise.prototype.catch
267 'catch': function (onRejected) {
268 return this.then(undefined, onRejected);
271 OwnPromiseCapability = function () {
272 var promise = new Internal();
273 var state = getInternalState(promise);
274 this.promise = promise;
275 this.resolve = bind(internalResolve, promise, state);
276 this.reject = bind(internalReject, promise, state);
278 newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
279 return C === PromiseConstructor || C === PromiseWrapper
280 ? new OwnPromiseCapability(C)
281 : newGenericPromiseCapability(C);
284 if (!IS_PURE && typeof NativePromise == 'function') {
285 nativeThen = NativePromise.prototype.then;
287 // wrap native Promise#then for native async functions
288 redefine(NativePromise.prototype, 'then', function then(onFulfilled, onRejected) {
290 return new PromiseConstructor(function (resolve, reject) {
291 nativeThen.call(that, resolve, reject);
292 }).then(onFulfilled, onRejected);
293 // https://github.com/zloirock/core-js/issues/640
294 }, { unsafe: true });
297 if (typeof $fetch == 'function') $({ global: true, enumerable: true, forced: true }, {
298 // eslint-disable-next-line no-unused-vars
299 fetch: function fetch(input /* , init */) {
300 return promiseResolve(PromiseConstructor, $fetch.apply(global, arguments));
306 $({ global: true, wrap: true, forced: FORCED }, {
307 Promise: PromiseConstructor
310 setToStringTag(PromiseConstructor, PROMISE, false, true);
313 PromiseWrapper = getBuiltIn(PROMISE);
316 $({ target: PROMISE, stat: true, forced: FORCED }, {
317 // `Promise.reject` method
318 // https://tc39.github.io/ecma262/#sec-promise.reject
319 reject: function reject(r) {
320 var capability = newPromiseCapability(this);
321 capability.reject.call(undefined, r);
322 return capability.promise;
326 $({ target: PROMISE, stat: true, forced: IS_PURE || FORCED }, {
327 // `Promise.resolve` method
328 // https://tc39.github.io/ecma262/#sec-promise.resolve
329 resolve: function resolve(x) {
330 return promiseResolve(IS_PURE && this === PromiseWrapper ? PromiseConstructor : this, x);
334 $({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION }, {
335 // `Promise.all` method
336 // https://tc39.github.io/ecma262/#sec-promise.all
337 all: function all(iterable) {
339 var capability = newPromiseCapability(C);
340 var resolve = capability.resolve;
341 var reject = capability.reject;
342 var result = perform(function () {
343 var $promiseResolve = aFunction(C.resolve);
347 iterate(iterable, function (promise) {
348 var index = counter++;
349 var alreadyCalled = false;
350 values.push(undefined);
352 $promiseResolve.call(C, promise).then(function (value) {
353 if (alreadyCalled) return;
354 alreadyCalled = true;
355 values[index] = value;
356 --remaining || resolve(values);
359 --remaining || resolve(values);
361 if (result.error) reject(result.value);
362 return capability.promise;
364 // `Promise.race` method
365 // https://tc39.github.io/ecma262/#sec-promise.race
366 race: function race(iterable) {
368 var capability = newPromiseCapability(C);
369 var reject = capability.reject;
370 var result = perform(function () {
371 var $promiseResolve = aFunction(C.resolve);
372 iterate(iterable, function (promise) {
373 $promiseResolve.call(C, promise).then(capability.resolve, reject);
376 if (result.error) reject(result.value);
377 return capability.promise;