var IS_PURE = require('../internals/is-pure');
var global = require('../internals/global');
var getBuiltIn = require('../internals/get-built-in');
+var call = require('../internals/function-call');
var NativePromise = require('../internals/native-promise-constructor');
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 aFunction = require('../internals/a-function');
var anInstance = require('../internals/an-instance');
var inspectSource = require('../internals/inspect-source');
var iterate = require('../internals/iterate');
var InternalStateModule = require('../internals/internal-state');
var isForced = require('../internals/is-forced');
var wellKnownSymbol = require('../internals/well-known-symbol');
+var IS_BROWSER = require('../internals/engine-is-browser');
var IS_NODE = require('../internals/engine-is-node');
var V8_VERSION = require('../internals/engine-v8-version');
var SPECIES = wellKnownSymbol('species');
var PROMISE = 'Promise';
+
var getInternalState = InternalStateModule.get;
var setInternalState = InternalStateModule.set;
var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
+var NativePromisePrototype = NativePromise && NativePromise.prototype;
var PromiseConstructor = NativePromise;
+var PromisePrototype = NativePromisePrototype;
var TypeError = global.TypeError;
var document = global.document;
var process = global.process;
-var $fetch = getBuiltIn('fetch');
var newPromiseCapability = newPromiseCapabilityModule.f;
var newGenericPromiseCapability = newPromiseCapability;
+
var DISPATCH_EVENT = !!(document && document.createEvent && global.dispatchEvent);
-var NATIVE_REJECTION_EVENT = typeof PromiseRejectionEvent == 'function';
+var NATIVE_REJECTION_EVENT = isCallable(global.PromiseRejectionEvent);
var UNHANDLED_REJECTION = 'unhandledrejection';
var REJECTION_HANDLED = 'rejectionhandled';
var PENDING = 0;
var REJECTED = 2;
var HANDLED = 1;
var UNHANDLED = 2;
+var SUBCLASSING = false;
+
var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
var FORCED = isForced(PROMISE, function () {
- var GLOBAL_CORE_JS_PROMISE = inspectSource(PromiseConstructor) !== String(PromiseConstructor);
- if (!GLOBAL_CORE_JS_PROMISE) {
- // 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
- if (V8_VERSION === 66) return true;
- // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
- if (!IS_NODE && !NATIVE_REJECTION_EVENT) return true;
- }
+ var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(PromiseConstructor);
+ var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(PromiseConstructor);
+ // 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
+ if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION === 66) return true;
// We need Promise#finally in the pure version for preventing prototype pollution
- if (IS_PURE && !PromiseConstructor.prototype['finally']) return true;
+ if (IS_PURE && !PromisePrototype['finally']) return true;
// We can't use @@species feature detection in V8 since it causes
// deoptimization and performance degradation
// https://github.com/zloirock/core-js/issues/679
- if (V8_VERSION >= 51 && /native code/.test(PromiseConstructor)) return false;
+ if (V8_VERSION >= 51 && /native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) return false;
// Detect correctness of subclassing with @@species support
- var promise = PromiseConstructor.resolve(1);
+ var promise = new PromiseConstructor(function (resolve) { resolve(1); });
var FakePromise = function (exec) {
exec(function () { /* empty */ }, function () { /* empty */ });
};
var constructor = promise.constructor = {};
constructor[SPECIES] = FakePromise;
- return !(promise.then(function () { /* empty */ }) instanceof FakePromise);
+ SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
+ if (!SUBCLASSING) return true;
+ // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
+ return !GLOBAL_CORE_JS_PROMISE && IS_BROWSER && !NATIVE_REJECTION_EVENT;
});
var INCORRECT_ITERATION = FORCED || !checkCorrectnessOfIteration(function (iterable) {
// helpers
var isThenable = function (it) {
var then;
- return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
+ return isObject(it) && isCallable(then = it.then) ? then : false;
};
var notify = function (state, isReject) {
if (result === reaction.promise) {
reject(TypeError('Promise-chain cycle'));
} else if (then = isThenable(result)) {
- then.call(result, resolve, reject);
+ call(then, result, resolve, reject);
} else resolve(result);
} else reject(value);
} catch (error) {
};
var onUnhandled = function (state) {
- task.call(global, function () {
+ call(task, global, function () {
var promise = state.facade;
var value = state.value;
var IS_UNHANDLED = isUnhandled(state);
};
var onHandleUnhandled = function (state) {
- task.call(global, function () {
+ call(task, global, function () {
var promise = state.facade;
if (IS_NODE) {
process.emit('rejectionHandled', promise);
microtask(function () {
var wrapper = { done: false };
try {
- then.call(value,
+ call(then, value,
bind(internalResolve, wrapper, state),
bind(internalReject, wrapper, state)
);
if (FORCED) {
// 25.4.3.1 Promise(executor)
PromiseConstructor = function Promise(executor) {
- anInstance(this, PromiseConstructor, PROMISE);
- aFunction(executor);
- Internal.call(this);
+ anInstance(this, PromisePrototype);
+ aCallable(executor);
+ call(Internal, this);
var state = getInternalState(this);
try {
executor(bind(internalResolve, state), bind(internalReject, state));
internalReject(state, error);
}
};
+ PromisePrototype = PromiseConstructor.prototype;
// eslint-disable-next-line no-unused-vars -- required for `.length`
Internal = function Promise(executor) {
setInternalState(this, {
value: undefined
});
};
- Internal.prototype = redefineAll(PromiseConstructor.prototype, {
+ Internal.prototype = redefineAll(PromisePrototype, {
// `Promise.prototype.then` method
// https://tc39.es/ecma262/#sec-promise.prototype.then
then: function then(onFulfilled, onRejected) {
var state = getInternalPromiseState(this);
+ var reactions = state.reactions;
var reaction = newPromiseCapability(speciesConstructor(this, PromiseConstructor));
- reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
- reaction.fail = typeof onRejected == 'function' && onRejected;
+ reaction.ok = isCallable(onFulfilled) ? onFulfilled : true;
+ reaction.fail = isCallable(onRejected) && onRejected;
reaction.domain = IS_NODE ? process.domain : undefined;
state.parent = true;
- state.reactions.push(reaction);
+ reactions[reactions.length] = reaction;
if (state.state != PENDING) notify(state, false);
return reaction.promise;
},
: newGenericPromiseCapability(C);
};
- if (!IS_PURE && typeof NativePromise == 'function') {
- nativeThen = NativePromise.prototype.then;
+ if (!IS_PURE && isCallable(NativePromise) && NativePromisePrototype !== Object.prototype) {
+ nativeThen = NativePromisePrototype.then;
- // wrap native Promise#then for native async functions
- redefine(NativePromise.prototype, 'then', function then(onFulfilled, onRejected) {
- var that = this;
- return new PromiseConstructor(function (resolve, reject) {
- nativeThen.call(that, resolve, reject);
- }).then(onFulfilled, onRejected);
- // https://github.com/zloirock/core-js/issues/640
- }, { unsafe: true });
+ if (!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 });
- // wrap fetch result
- if (typeof $fetch == 'function') $({ global: true, enumerable: true, forced: true }, {
- // eslint-disable-next-line no-unused-vars -- required for `.length`
- fetch: function fetch(input /* , init */) {
- return promiseResolve(PromiseConstructor, $fetch.apply(global, arguments));
- }
- });
+ // makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
+ redefine(NativePromisePrototype, 'catch', PromisePrototype['catch'], { 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);
+ }
}
}
// https://tc39.es/ecma262/#sec-promise.reject
reject: function reject(r) {
var capability = newPromiseCapability(this);
- capability.reject.call(undefined, r);
+ call(capability.reject, undefined, r);
return capability.promise;
}
});
var resolve = capability.resolve;
var reject = capability.reject;
var result = perform(function () {
- var $promiseResolve = aFunction(C.resolve);
+ var $promiseResolve = aCallable(C.resolve);
var values = [];
var counter = 0;
var remaining = 1;
iterate(iterable, function (promise) {
var index = counter++;
var alreadyCalled = false;
- values.push(undefined);
remaining++;
- $promiseResolve.call(C, promise).then(function (value) {
+ call($promiseResolve, C, promise).then(function (value) {
if (alreadyCalled) return;
alreadyCalled = true;
values[index] = value;
var capability = newPromiseCapability(C);
var reject = capability.reject;
var result = perform(function () {
- var $promiseResolve = aFunction(C.resolve);
+ var $promiseResolve = aCallable(C.resolve);
iterate(iterable, function (promise) {
- $promiseResolve.call(C, promise).then(capability.resolve, reject);
+ call($promiseResolve, C, promise).then(capability.resolve, reject);
});
});
if (result.error) reject(result.value);