'use strict'; var $ = require('../internals/export'); var IS_PURE = require('../internals/is-pure'); var IS_NODE = require('../internals/engine-is-node'); var global = require('../internals/global'); var call = require('../internals/function-call'); var redefine = require('../internals/redefine'); var redefineAll = require('../internals/redefine-all'); var setPrototypeOf = require('../internals/object-set-prototype-of'); var setToStringTag = require('../internals/set-to-string-tag'); var setSpecies = require('../internals/set-species'); var aCallable = require('../internals/a-callable'); var isCallable = require('../internals/is-callable'); var isObject = require('../internals/is-object'); var anInstance = require('../internals/an-instance'); var speciesConstructor = require('../internals/species-constructor'); var task = require('../internals/task').set; var microtask = require('../internals/microtask'); var hostReportErrors = require('../internals/host-report-errors'); var perform = require('../internals/perform'); var Queue = require('../internals/queue'); var InternalStateModule = require('../internals/internal-state'); var NativePromiseConstructor = require('../internals/promise-native-constructor'); var PromiseConstructorDetection = require('../internals/promise-constructor-detection'); var newPromiseCapabilityModule = require('../internals/new-promise-capability'); var PROMISE = 'Promise'; var FORCED_PROMISE_CONSTRUCTOR = PromiseConstructorDetection.CONSTRUCTOR; var NATIVE_PROMISE_REJECTION_EVENT = PromiseConstructorDetection.REJECTION_EVENT; var NATIVE_PROMISE_SUBCLASSING = PromiseConstructorDetection.SUBCLASSING; var getInternalPromiseState = InternalStateModule.getterFor(PROMISE); var setInternalState = InternalStateModule.set; var NativePromisePrototype = NativePromiseConstructor && NativePromiseConstructor.prototype; var PromiseConstructor = NativePromiseConstructor; var PromisePrototype = NativePromisePrototype; var TypeError = global.TypeError; var document = global.document; var process = global.process; var newPromiseCapability = newPromiseCapabilityModule.f; var newGenericPromiseCapability = newPromiseCapability; var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent); var UNHANDLED_REJECTION = 'unhandledrejection'; var REJECTION_HANDLED = 'rejectionhandled'; var PENDING = 0; var FULFILLED = 1; var REJECTED = 2; var HANDLED = 1; var UNHANDLED = 2; var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen; // helpers var isThenable = function (it) { var then; return isObject(it) && isCallable(then = it.then) ? then : false; }; var callReaction = function (reaction, state) { var value = state.value; var ok = state.state == FULFILLED; 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 (state.rejection === UNHANDLED) onHandleUnhandled(state); state.rejection = HANDLED; } if (handler === true) result = value; else { if (domain) domain.enter(); result = handler(value); // can throw if (domain) { domain.exit(); exited = true; } } if (result === reaction.promise) { reject(TypeError('Promise-chain cycle')); } else if (then = isThenable(result)) { call(then, result, resolve, reject); } else resolve(result); } else reject(value); } catch (error) { if (domain && !exited) domain.exit(); reject(error); } }; var notify = function (state, isReject) { if (state.notified) return; state.notified = true; microtask(function () { var reactions = state.reactions; var reaction; while (reaction = reactions.get()) { callReaction(reaction, state); } state.notified = false; if (isReject && !state.rejection) onUnhandled(state); }); }; var dispatchEvent = function (name, promise, reason) { var event, handler; if (DISPATCH_EVENT) { event = document.createEvent('Event'); event.promise = promise; event.reason = reason; event.initEvent(name, false, true); global.dispatchEvent(event); } else event = { promise: promise, reason: reason }; if (!NATIVE_PROMISE_REJECTION_EVENT && (handler = global['on' + name])) handler(event); else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason); }; var onUnhandled = function (state) { call(task, global, function () { var promise = state.facade; var value = state.value; var IS_UNHANDLED = isUnhandled(state); var result; if (IS_UNHANDLED) { result = perform(function () { if (IS_NODE) { process.emit('unhandledRejection', value, promise); } else dispatchEvent(UNHANDLED_REJECTION, promise, value); }); // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should state.rejection = IS_NODE || isUnhandled(state) ? UNHANDLED : HANDLED; if (result.error) throw result.value; } }); }; var isUnhandled = function (state) { return state.rejection !== HANDLED && !state.parent; }; var onHandleUnhandled = function (state) { call(task, global, function () { var promise = state.facade; if (IS_NODE) { process.emit('rejectionHandled', promise); } else dispatchEvent(REJECTION_HANDLED, promise, state.value); }); }; var bind = function (fn, state, unwrap) { return function (value) { fn(state, value, unwrap); }; }; var internalReject = function (state, value, unwrap) { if (state.done) return; state.done = true; if (unwrap) state = unwrap; state.value = value; state.state = REJECTED; notify(state, true); }; var internalResolve = function (state, value, unwrap) { if (state.done) return; state.done = true; if (unwrap) state = unwrap; try { if (state.facade === value) throw TypeError("Promise can't be resolved itself"); var then = isThenable(value); if (then) { microtask(function () { var wrapper = { done: false }; try { call(then, value, bind(internalResolve, wrapper, state), bind(internalReject, wrapper, state) ); } catch (error) { internalReject(wrapper, error, state); } }); } else { state.value = value; state.state = FULFILLED; notify(state, false); } } catch (error) { internalReject({ done: false }, error, state); } }; // constructor polyfill if (FORCED_PROMISE_CONSTRUCTOR) { // 25.4.3.1 Promise(executor) PromiseConstructor = function Promise(executor) { anInstance(this, PromisePrototype); aCallable(executor); call(Internal, this); var state = getInternalPromiseState(this); try { executor(bind(internalResolve, state), bind(internalReject, state)); } catch (error) { internalReject(state, error); } }; PromisePrototype = PromiseConstructor.prototype; // eslint-disable-next-line no-unused-vars -- required for `.length` Internal = function Promise(executor) { setInternalState(this, { type: PROMISE, done: false, notified: false, parent: false, reactions: new Queue(), rejection: false, state: PENDING, value: undefined }); }; Internal.prototype = redefineAll(PromisePrototype, { // `Promise.prototype.then` method // https://tc39.es/ecma262/#sec-promise.prototype.then // eslint-disable-next-line unicorn/no-thenable -- safe then: function then(onFulfilled, onRejected) { var state = getInternalPromiseState(this); var reaction = newPromiseCapability(speciesConstructor(this, PromiseConstructor)); state.parent = true; reaction.ok = isCallable(onFulfilled) ? onFulfilled : true; reaction.fail = isCallable(onRejected) && onRejected; reaction.domain = IS_NODE ? process.domain : undefined; if (state.state == PENDING) state.reactions.add(reaction); else microtask(function () { callReaction(reaction, state); }); return reaction.promise; } }); OwnPromiseCapability = function () { var promise = new Internal(); var state = getInternalPromiseState(promise); this.promise = promise; this.resolve = bind(internalResolve, state); this.reject = bind(internalReject, state); }; newPromiseCapabilityModule.f = newPromiseCapability = function (C) { return C === PromiseConstructor || C === PromiseWrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C); }; if (!IS_PURE && isCallable(NativePromiseConstructor) && NativePromisePrototype !== Object.prototype) { nativeThen = NativePromisePrototype.then; if (!NATIVE_PROMISE_SUBCLASSING) { // make `Promise#then` return a polyfilled `Promise` for native promise-based APIs redefine(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) { var that = this; return new PromiseConstructor(function (resolve, reject) { call(nativeThen, that, resolve, reject); }).then(onFulfilled, onRejected); // https://github.com/zloirock/core-js/issues/640 }, { unsafe: true }); } // make `.constructor === Promise` work for native promise-based APIs try { delete NativePromisePrototype.constructor; } catch (error) { /* empty */ } // make `instanceof Promise` work for native promise-based APIs if (setPrototypeOf) { setPrototypeOf(NativePromisePrototype, PromisePrototype); } } } $({ global: true, wrap: true, forced: FORCED_PROMISE_CONSTRUCTOR }, { Promise: PromiseConstructor }); setToStringTag(PromiseConstructor, PROMISE, false, true); setSpecies(PROMISE);