Skip to content

Commit f26cd0b

Browse files
committed
native promise-based APIs Promise#{ catch, finally } returns polyfilled Promise instances when it's required
1 parent e9d9f68 commit f26cd0b

File tree

3 files changed

+25
-15
lines changed

3 files changed

+25
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Changelog
22
##### Unreleased
3-
- Nothing
3+
- Native promise-based APIs `Promise#{ catch, finally }` returns polyfilled `Promise` instances when it's required
44

55
##### 3.11.2 - 2021.05.03
66
- Added a workaround of WebKit ~ iOS 10.3 Safari `Promise` bug, [#932](https://github.com/zloirock/core-js/issues/932)

packages/core-js/modules/es.promise.finally.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ $({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
3030
}
3131
});
3232

33-
// patch native Promise.prototype for native async functions
34-
if (!IS_PURE && typeof NativePromise == 'function' && !NativePromise.prototype['finally']) {
35-
redefine(NativePromise.prototype, 'finally', getBuiltIn('Promise').prototype['finally']);
33+
// makes sure that native promise-based APIs `Promise#finally` properly works with patched `Promise#then`
34+
if (!IS_PURE && typeof NativePromise == 'function') {
35+
var method = getBuiltIn('Promise').prototype['finally'];
36+
if (NativePromise.prototype['finally'] !== method) {
37+
redefine(NativePromise.prototype, 'finally', method, { unsafe: true });
38+
}
3639
}

packages/core-js/modules/es.promise.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var setInternalState = InternalStateModule.set;
3636
var getInternalPromiseState = InternalStateModule.getterFor(PROMISE);
3737
var NativePromisePrototype = NativePromise && NativePromise.prototype;
3838
var PromiseConstructor = NativePromise;
39+
var PromiseConstructorPrototype = NativePromisePrototype;
3940
var TypeError = global.TypeError;
4041
var document = global.document;
4142
var process = global.process;
@@ -60,7 +61,7 @@ var FORCED = isForced(PROMISE, function () {
6061
// We can't detect it synchronously, so just check versions
6162
if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION === 66) return true;
6263
// We need Promise#finally in the pure version for preventing prototype pollution
63-
if (IS_PURE && !PromiseConstructor.prototype['finally']) return true;
64+
if (IS_PURE && !PromiseConstructorPrototype['finally']) return true;
6465
// We can't use @@species feature detection in V8 since it causes
6566
// deoptimization and performance degradation
6667
// https://github.com/zloirock/core-js/issues/679
@@ -239,6 +240,7 @@ if (FORCED) {
239240
internalReject(state, error);
240241
}
241242
};
243+
PromiseConstructorPrototype = PromiseConstructor.prototype;
242244
// eslint-disable-next-line no-unused-vars -- required for `.length`
243245
Internal = function Promise(executor) {
244246
setInternalState(this, {
@@ -252,7 +254,7 @@ if (FORCED) {
252254
value: undefined
253255
});
254256
};
255-
Internal.prototype = redefineAll(PromiseConstructor.prototype, {
257+
Internal.prototype = redefineAll(PromiseConstructorPrototype, {
256258
// `Promise.prototype.then` method
257259
// https://tc39.es/ecma262/#sec-promise.prototype.then
258260
then: function then(onFulfilled, onRejected) {
@@ -288,14 +290,19 @@ if (FORCED) {
288290
if (!IS_PURE && typeof NativePromise == 'function' && NativePromisePrototype !== Object.prototype) {
289291
nativeThen = NativePromisePrototype.then;
290292

291-
// make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
292-
if (!SUBCLASSING) redefine(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) {
293-
var that = this;
294-
return new PromiseConstructor(function (resolve, reject) {
295-
nativeThen.call(that, resolve, reject);
296-
}).then(onFulfilled, onRejected);
297-
// https://github.com/zloirock/core-js/issues/640
298-
}, { unsafe: true });
293+
if (!SUBCLASSING) {
294+
// make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
295+
redefine(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) {
296+
var that = this;
297+
return new PromiseConstructor(function (resolve, reject) {
298+
nativeThen.call(that, resolve, reject);
299+
}).then(onFulfilled, onRejected);
300+
// https://github.com/zloirock/core-js/issues/640
301+
}, { unsafe: true });
302+
303+
// makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
304+
redefine(NativePromisePrototype, 'catch', PromiseConstructorPrototype['catch'], { unsafe: true });
305+
}
299306

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

305312
// make `instanceof Promise` work for native promise-based APIs
306313
if (setPrototypeOf) {
307-
setPrototypeOf(NativePromisePrototype, PromiseConstructor.prototype);
314+
setPrototypeOf(NativePromisePrototype, PromiseConstructorPrototype);
308315
}
309316
}
310317
}

0 commit comments

Comments
 (0)