Skip to content

Commit

Permalink
native promise-based APIs Promise#{ catch, finally } returns polyfi…
Browse files Browse the repository at this point in the history
…lled `Promise` instances when it's required
  • Loading branch information
zloirock committed May 5, 2021
1 parent e9d9f68 commit f26cd0b
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 15 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Changelog
##### Unreleased
- Nothing
- Native promise-based APIs `Promise#{ catch, finally }` returns polyfilled `Promise` instances when it's required

##### 3.11.2 - 2021.05.03
- Added a workaround of WebKit ~ iOS 10.3 Safari `Promise` bug, [#932](https://github.com/zloirock/core-js/issues/932)
Expand Down
9 changes: 6 additions & 3 deletions packages/core-js/modules/es.promise.finally.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ $({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
}
});

// patch native Promise.prototype for native async functions
if (!IS_PURE && typeof NativePromise == 'function' && !NativePromise.prototype['finally']) {
redefine(NativePromise.prototype, 'finally', getBuiltIn('Promise').prototype['finally']);
// makes sure that native promise-based APIs `Promise#finally` properly works with patched `Promise#then`
if (!IS_PURE && typeof NativePromise == 'function') {
var method = getBuiltIn('Promise').prototype['finally'];
if (NativePromise.prototype['finally'] !== method) {
redefine(NativePromise.prototype, 'finally', method, { unsafe: true });
}
}
29 changes: 18 additions & 11 deletions packages/core-js/modules/es.promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var setInternalState = InternalStateModule.set;
var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
var NativePromisePrototype = NativePromise && NativePromise.prototype;
var PromiseConstructor = NativePromise;
var PromiseConstructorPrototype = NativePromisePrototype;
var TypeError = global.TypeError;
var document = global.document;
var process = global.process;
Expand All @@ -60,7 +61,7 @@ var FORCED = isForced(PROMISE, function () {
// 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 && !PromiseConstructorPrototype['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
Expand Down Expand Up @@ -239,6 +240,7 @@ if (FORCED) {
internalReject(state, error);
}
};
PromiseConstructorPrototype = PromiseConstructor.prototype;
// eslint-disable-next-line no-unused-vars -- required for `.length`
Internal = function Promise(executor) {
setInternalState(this, {
Expand All @@ -252,7 +254,7 @@ if (FORCED) {
value: undefined
});
};
Internal.prototype = redefineAll(PromiseConstructor.prototype, {
Internal.prototype = redefineAll(PromiseConstructorPrototype, {
// `Promise.prototype.then` method
// https://tc39.es/ecma262/#sec-promise.prototype.then
then: function then(onFulfilled, onRejected) {
Expand Down Expand Up @@ -288,14 +290,19 @@ if (FORCED) {
if (!IS_PURE && typeof NativePromise == 'function' && NativePromisePrototype !== Object.prototype) {
nativeThen = NativePromisePrototype.then;

// make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
if (!SUBCLASSING) redefine(NativePromisePrototype, '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) {
nativeThen.call(that, resolve, reject);
}).then(onFulfilled, onRejected);
// https://github.com/zloirock/core-js/issues/640
}, { unsafe: true });

// makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
redefine(NativePromisePrototype, 'catch', PromiseConstructorPrototype['catch'], { unsafe: true });
}

// make `.constructor === Promise` work for native promise-based APIs
try {
Expand All @@ -304,7 +311,7 @@ if (FORCED) {

// make `instanceof Promise` work for native promise-based APIs
if (setPrototypeOf) {
setPrototypeOf(NativePromisePrototype, PromiseConstructor.prototype);
setPrototypeOf(NativePromisePrototype, PromiseConstructorPrototype);
}
}
}
Expand Down

0 comments on commit f26cd0b

Please sign in to comment.