From 5b908c249493702e32050240c3d483de98a7f747 Mon Sep 17 00:00:00 2001 From: Denis Pushkarev Date: Thu, 11 Apr 2024 22:31:47 +0700 Subject: [PATCH] add a fix of Safari bug with double call of constructor in `Array.fromAsync` https://bugs.webkit.org/show_bug.cgi?id=271703 --- CHANGELOG.md | 2 ++ packages/core-js-compat/src/data.mjs | 6 ++++-- .../core-js/modules/esnext.array.from-async.js | 14 +++++++++++++- tests/compat/tests.js | 8 +++++++- tests/unit-global/esnext.array.from-async.js | 9 +++++++++ tests/unit-pure/esnext.array.from-async.js | 9 +++++++++ 6 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a2b5b19d12..73e3be69310e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ - Added [`URL.parse`](https://url.spec.whatwg.org/#dom-url-parse), [url/825](https://github.com/whatwg/url/pull/825) - [`RegExp.escape`](https://github.com/tc39/proposal-regex-escaping) [moved to hex-escape semantics](https://github.com/tc39/proposal-regex-escaping/pull/67) - Some minor updates of [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) Stage 3 proposal like [explicit-resource-management/217](https://github.com/tc39/proposal-explicit-resource-management/pull/217) +- Engines bugs fixes: + - Added a fix of [Safari bug with double call of constructor in `Array.fromAsync`](https://bugs.webkit.org/show_bug.cgi?id=271703) - Compat data improvements: - [`URL.parse`](https://url.spec.whatwg.org/#dom-url-parse) added and marked as supported [from FF 126](https://bugzilla.mozilla.org/show_bug.cgi?id=1887611) - `URL.canParse` fixed and marked as supported [from Bun 1.1.0](https://github.com/oven-sh/bun/pull/9710) diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index e66d381d56f0..1d6a3e56fa47 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -1982,11 +1982,13 @@ export const data = { // bun: '1.0.23', }, 'esnext.array.from-async': { - bun: '0.3.0', + // https://bugs.webkit.org/show_bug.cgi?id=271703 + bun: '1.1.2', // bun: '0.3.0', chrome: '121', deno: '1.38', firefox: '115', - safari: '16.4', + // https://bugs.webkit.org/show_bug.cgi?id=271703 + // safari: '16.4', }, // TODO: Remove from `core-js@4` 'esnext.array.at': null, diff --git a/packages/core-js/modules/esnext.array.from-async.js b/packages/core-js/modules/esnext.array.from-async.js index 10c22e720d03..3d483137aa0e 100644 --- a/packages/core-js/modules/esnext.array.from-async.js +++ b/packages/core-js/modules/esnext.array.from-async.js @@ -1,9 +1,21 @@ 'use strict'; var $ = require('../internals/export'); var fromAsync = require('../internals/array-from-async'); +var fails = require('../internals/fails'); + +var nativeFromAsync = Array.fromAsync; +// https://bugs.webkit.org/show_bug.cgi?id=271703 +var INCORRECT_CONSTRUCTURING = !nativeFromAsync || fails(function () { + var counter = 0; + nativeFromAsync.call(function () { + counter++; + return []; + }, { length: 0 }); + return counter !== 1; +}); // `Array.fromAsync` method // https://github.com/tc39/proposal-array-from-async -$({ target: 'Array', stat: true }, { +$({ target: 'Array', stat: true, forced: INCORRECT_CONSTRUCTURING }, { fromAsync: fromAsync }); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index e7e215b06a0f..b7d5c2b19a9f 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -1525,7 +1525,13 @@ GLOBAL.tests = { && SuppressedError(1, 2, 3, { cause: 4 }).cause !== 4; }, 'esnext.array.from-async': function () { - return Array.fromAsync; + // https://bugs.webkit.org/show_bug.cgi?id=271703 + var counter = 0; + Array.fromAsync.call(function () { + counter++; + return []; + }, { length: 0 }); + return counter === 1; }, 'esnext.array.filter-reject': function () { return [].filterReject; diff --git a/tests/unit-global/esnext.array.from-async.js b/tests/unit-global/esnext.array.from-async.js index f5e52a689065..05c28f9ee225 100644 --- a/tests/unit-global/esnext.array.from-async.js +++ b/tests/unit-global/esnext.array.from-async.js @@ -10,6 +10,15 @@ QUnit.test('Array.fromAsync', assert => { assert.looksNative(fromAsync); assert.nonEnumerable(Array, 'fromAsync'); + let counter = 0; + // eslint-disable-next-line prefer-arrow-callback -- constructor + fromAsync.call(function () { + counter++; + return []; + }, { length: 0 }); + + assert.same(counter, 1, 'proper number of constructor calling'); + function C() { /* empty */ } return fromAsync(createAsyncIterable([1, 2, 3]), it => it ** 2).then(it => { diff --git a/tests/unit-pure/esnext.array.from-async.js b/tests/unit-pure/esnext.array.from-async.js index 8cebe376bb76..d9b49ab50777 100644 --- a/tests/unit-pure/esnext.array.from-async.js +++ b/tests/unit-pure/esnext.array.from-async.js @@ -9,6 +9,15 @@ QUnit.test('Array.fromAsync', assert => { assert.arity(fromAsync, 1); assert.name(fromAsync, 'fromAsync'); + let counter = 0; + // eslint-disable-next-line prefer-arrow-callback -- constructor + fromAsync.call(function () { + counter++; + return []; + }, { length: 0 }); + + assert.same(counter, 1, 'proper number of constructor calling'); + function C() { /* empty */ } return fromAsync(createAsyncIterable([1, 2, 3]), it => it ** 2).then(it => {