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 inspectSource = require('../internals/inspect-source');
15 var iterate = require('../internals/iterate');
16 var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
17 var speciesConstructor = require('../internals/species-constructor');
18 var task = require('../internals/task').set;
19 var microtask = require('../internals/microtask');
20 var promiseResolve = require('../internals/promise-resolve');
21 var hostReportErrors = require('../internals/host-report-errors');
22 var newPromiseCapabilityModule = require('../internals/new-promise-capability');
23 var perform = require('../internals/perform');
24 var InternalStateModule = require('../internals/internal-state');
25 var isForced = require('../internals/is-forced');
26 var wellKnownSymbol = require('../internals/well-known-symbol');
27 var IS_NODE = require('../internals/engine-is-node');
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 DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
43 var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
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 && !NATIVE_REJECTION_EVENT) 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 (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(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(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 (!NATIVE_REJECTION_EVENT && (handler = global['on' + name])) handler(event);
147 else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
150 var onUnhandled = function (state) {
151 task.call(global, function () {
152 var promise = state.facade;
153 var value = state.value;
154 var IS_UNHANDLED = isUnhandled(state);
157 result = perform(function () {
159 process.emit('unhandledRejection', value, promise);
160 } else dispatchEvent(UNHANDLED_REJECTION, promise, value);
162 // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
163 state.rejection = IS_NODE || isUnhandled(state) ? UNHANDLED : HANDLED;
164 if (result.error) throw result.value;
169 var isUnhandled = function (state) {
170 return state.rejection !== HANDLED && !state.parent;
173 var onHandleUnhandled = function (state) {
174 task.call(global, function () {
175 var promise = state.facade;
177 process.emit('rejectionHandled', promise);
178 } else dispatchEvent(REJECTION_HANDLED, promise, state.value);
182 var bind = function (fn, state, unwrap) {
183 return function (value) {
184 fn(state, value, unwrap);
188 var internalReject = function (state, value, unwrap) {
189 if (state.done) return;
191 if (unwrap) state = unwrap;
193 state.state = REJECTED;
197 var internalResolve = function (state, value, unwrap) {
198 if (state.done) return;
200 if (unwrap) state = unwrap;
202 if (state.facade === value) throw TypeError("Promise can't be resolved itself");
203 var then = isThenable(value);
205 microtask(function () {
206 var wrapper = { done: false };
209 bind(internalResolve, wrapper, state),
210 bind(internalReject, wrapper, state)
213 internalReject(wrapper, error, state);
218 state.state = FULFILLED;
219 notify(state, false);
222 internalReject({ done: false }, error, state);
226 // constructor polyfill
228 // 25.4.3.1 Promise(executor)
229 PromiseConstructor = function Promise(executor) {
230 anInstance(this, PromiseConstructor, PROMISE);
233 var state = getInternalState(this);
235 executor(bind(internalResolve, state), bind(internalReject, state));
237 internalReject(state, error);
240 // eslint-disable-next-line no-unused-vars
241 Internal = function Promise(executor) {
242 setInternalState(this, {
253 Internal.prototype = redefineAll(PromiseConstructor.prototype, {
254 // `Promise.prototype.then` method
255 // https://tc39.github.io/ecma262/#sec-promise.prototype.then
256 then: function then(onFulfilled, onRejected) {
257 var state = getInternalPromiseState(this);
258 var reaction = newPromiseCapability(speciesConstructor(this, PromiseConstructor));
259 reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
260 reaction.fail = typeof onRejected == 'function' && onRejected;
261 reaction.domain = IS_NODE ? process.domain : undefined;
263 state.reactions.push(reaction);
264 if (state.state != PENDING) notify(state, false);
265 return reaction.promise;
267 // `Promise.prototype.catch` method
268 // https://tc39.github.io/ecma262/#sec-promise.prototype.catch
269 'catch': function (onRejected) {
270 return this.then(undefined, onRejected);
273 OwnPromiseCapability = function () {
274 var promise = new Internal();
275 var state = getInternalState(promise);
276 this.promise = promise;
277 this.resolve = bind(internalResolve, state);
278 this.reject = bind(internalReject, state);
280 newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
281 return C === PromiseConstructor || C === PromiseWrapper
282 ? new OwnPromiseCapability(C)
283 : newGenericPromiseCapability(C);
286 if (!IS_PURE && typeof NativePromise == 'function') {
287 nativeThen = NativePromise.prototype.then;
289 // wrap native Promise#then for native async functions
290 redefine(NativePromise.prototype, 'then', function then(onFulfilled, onRejected) {
292 return new PromiseConstructor(function (resolve, reject) {
293 nativeThen.call(that, resolve, reject);
294 }).then(onFulfilled, onRejected);
295 // https://github.com/zloirock/core-js/issues/640
296 }, { unsafe: true });
299 if (typeof $fetch == 'function') $({ global: true, enumerable: true, forced: true }, {
300 // eslint-disable-next-line no-unused-vars
301 fetch: function fetch(input /* , init */) {
302 return promiseResolve(PromiseConstructor, $fetch.apply(global, arguments));
308 $({ global: true, wrap: true, forced: FORCED }, {
309 Promise: PromiseConstructor
312 setToStringTag(PromiseConstructor, PROMISE, false, true);
315 PromiseWrapper = getBuiltIn(PROMISE);
318 $({ target: PROMISE, stat: true, forced: FORCED }, {
319 // `Promise.reject` method
320 // https://tc39.github.io/ecma262/#sec-promise.reject
321 reject: function reject(r) {
322 var capability = newPromiseCapability(this);
323 capability.reject.call(undefined, r);
324 return capability.promise;
328 $({ target: PROMISE, stat: true, forced: IS_PURE || FORCED }, {
329 // `Promise.resolve` method
330 // https://tc39.github.io/ecma262/#sec-promise.resolve
331 resolve: function resolve(x) {
332 return promiseResolve(IS_PURE && this === PromiseWrapper ? PromiseConstructor : this, x);
336 $({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION }, {
337 // `Promise.all` method
338 // https://tc39.github.io/ecma262/#sec-promise.all
339 all: function all(iterable) {
341 var capability = newPromiseCapability(C);
342 var resolve = capability.resolve;
343 var reject = capability.reject;
344 var result = perform(function () {
345 var $promiseResolve = aFunction(C.resolve);
349 iterate(iterable, function (promise) {
350 var index = counter++;
351 var alreadyCalled = false;
352 values.push(undefined);
354 $promiseResolve.call(C, promise).then(function (value) {
355 if (alreadyCalled) return;
356 alreadyCalled = true;
357 values[index] = value;
358 --remaining || resolve(values);
361 --remaining || resolve(values);
363 if (result.error) reject(result.value);
364 return capability.promise;
366 // `Promise.race` method
367 // https://tc39.github.io/ecma262/#sec-promise.race
368 race: function race(iterable) {
370 var capability = newPromiseCapability(C);
371 var reject = capability.reject;
372 var result = perform(function () {
373 var $promiseResolve = aFunction(C.resolve);
374 iterate(iterable, function (promise) {
375 $promiseResolve.call(C, promise).then(capability.resolve, reject);
378 if (result.error) reject(result.value);
379 return capability.promise;