diff --git a/CHANGELOG.md b/CHANGELOG.md index 3da0871d9fac..204b325edff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - We have no bulletproof way to polyfill this method / check if the object is an error, so it's an enough naive implementation that is marked as `.sham` - [`Iterator` sequencing stage 2.7 proposal](https://github.com/tc39/proposal-iterator-sequencing): - Reuse `IteratorResult` objects when possible, [tc39/proposal-iterator-sequencing/17](https://github.com/tc39/proposal-iterator-sequencing/issues/17), [tc39/proposal-iterator-sequencing/18](https://github.com/tc39/proposal-iterator-sequencing/pull/18), December 2024 TC39 meeting +- Added a fix of [V8 < 12.8](https://issues.chromium.org/issues/351332634) / [NodeJS < 22.10](https://github.com/nodejs/node/pull/54883) bug with handling infinite length of set-like objects in `Set` methods - Optimized `DataView.prototype.{ getFloat16, setFloat16 }` performance, [#1379](https://github.com/zloirock/core-js/pull/1379), thanks [**@LeviPesin**](https://github.com/LeviPesin) - Dropped unneeded feature detection of non-standard `%TypedArray%.prototype.toSpliced` - Dropped possible re-usage of some non-standard / early stage features (like `Math.scale`) available on global diff --git a/packages/core-js-compat/src/data.mjs b/packages/core-js-compat/src/data.mjs index 7316e854e830..44d548236510 100644 --- a/packages/core-js-compat/src/data.mjs +++ b/packages/core-js-compat/src/data.mjs @@ -1464,8 +1464,12 @@ export const data = { bun: '1.1.1', // v8 ~ Chrome 122 does not properly work with set-like objects // https://bugs.chromium.org/p/v8/issues/detail?id=14559 - chrome: '123', + // v8 < Chrome 128 does not properly convert set-like objects Infinty size + // https://issues.chromium.org/issues/351332634 + chrome: '128', // '122', firefox: '127', + // https://github.com/nodejs/node/pull/54883 + node: '22.10', // safari 17 does not properly work with set-like objects // https://bugs.webkit.org/show_bug.cgi?id=267494 safari: '18.0', // '17.0', @@ -1474,8 +1478,12 @@ export const data = { bun: '1.1.1', // v8 ~ Chrome 122 does not properly work with set-like objects // https://bugs.chromium.org/p/v8/issues/detail?id=14559 - chrome: '123', + // v8 < Chrome 128 does not properly convert set-like objects Infinty size + // https://issues.chromium.org/issues/351332634 + chrome: '128', // '122', firefox: '127', + // https://github.com/nodejs/node/pull/54883 + node: '22.10', // safari 17 does not properly work with set-like objects // https://bugs.webkit.org/show_bug.cgi?id=267494 safari: '18.0', // '17.0', @@ -1484,8 +1492,12 @@ export const data = { bun: '1.1.1', // v8 ~ Chrome 122 does not properly work with set-like objects // https://bugs.chromium.org/p/v8/issues/detail?id=14559 - chrome: '123', + // v8 < Chrome 128 does not properly convert set-like objects Infinty size + // https://issues.chromium.org/issues/351332634 + chrome: '128', // '122', firefox: '127', + // https://github.com/nodejs/node/pull/54883 + node: '22.10', // safari 17 does not properly work with set-like objects // https://bugs.webkit.org/show_bug.cgi?id=267494 safari: '18.0', // '17.0', @@ -1494,8 +1506,12 @@ export const data = { bun: '1.1.1', // v8 ~ Chrome 122 does not properly work with set-like objects // https://bugs.chromium.org/p/v8/issues/detail?id=14559 - chrome: '123', + // v8 < Chrome 128 does not properly convert set-like objects Infinty size + // https://issues.chromium.org/issues/351332634 + chrome: '128', // '122', firefox: '127', + // https://github.com/nodejs/node/pull/54883 + node: '22.10', // safari 17 does not properly work with set-like objects // https://bugs.webkit.org/show_bug.cgi?id=267494 safari: '18.0', // '17.0', @@ -1504,8 +1520,12 @@ export const data = { bun: '1.1.1', // v8 ~ Chrome 122 does not properly work with set-like objects // https://bugs.chromium.org/p/v8/issues/detail?id=14559 - chrome: '123', + // v8 < Chrome 128 does not properly convert set-like objects Infinty size + // https://issues.chromium.org/issues/351332634 + chrome: '128', // '122', firefox: '127', + // https://github.com/nodejs/node/pull/54883 + node: '22.10', // safari 17 does not properly work with set-like objects // https://bugs.webkit.org/show_bug.cgi?id=267494 safari: '18.0', // '17.0', diff --git a/packages/core-js/internals/set-method-accept-set-like.js b/packages/core-js/internals/set-method-accept-set-like.js index 679087970658..94faa0853446 100644 --- a/packages/core-js/internals/set-method-accept-set-like.js +++ b/packages/core-js/internals/set-method-accept-set-like.js @@ -17,7 +17,19 @@ var createSetLike = function (size) { }; }; -module.exports = function (name) { +var createSetLikeWithInfinitySize = function (size) { + return { + size: size, + has: function () { + return true; + }, + keys: function () { + throw new Error('e'); + } + }; +}; + +module.exports = function (name, callback) { var Set = getBuiltIn('Set'); try { new Set()[name](createSetLike(0)); @@ -27,7 +39,18 @@ module.exports = function (name) { new Set()[name](createSetLike(-1)); return false; } catch (error2) { - return true; + if (!callback) return true; + // early V8 implementation bug + // https://issues.chromium.org/issues/351332634 + try { + new Set()[name](createSetLikeWithInfinitySize(-Infinity)); + return false; + } catch (error) { + var set = new Set(); + set.add(1); + set.add(2); + return callback(set[name](createSetLikeWithInfinitySize(Infinity))); + } } } catch (error) { return false; diff --git a/packages/core-js/modules/es.set.difference.v2.js b/packages/core-js/modules/es.set.difference.v2.js index b3d832492d6c..1316eb408122 100644 --- a/packages/core-js/modules/es.set.difference.v2.js +++ b/packages/core-js/modules/es.set.difference.v2.js @@ -3,8 +3,12 @@ var $ = require('../internals/export'); var difference = require('../internals/set-difference'); var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like'); +var INCORRECT = !setMethodAcceptSetLike('difference', function (result) { + return result.size === 0; +}); + // `Set.prototype.difference` method // https://tc39.es/ecma262/#sec-set.prototype.difference -$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('difference') }, { +$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, { difference: difference }); diff --git a/packages/core-js/modules/es.set.intersection.v2.js b/packages/core-js/modules/es.set.intersection.v2.js index 4f6b01322d9b..e79f1c7a38b6 100644 --- a/packages/core-js/modules/es.set.intersection.v2.js +++ b/packages/core-js/modules/es.set.intersection.v2.js @@ -4,7 +4,9 @@ var fails = require('../internals/fails'); var intersection = require('../internals/set-intersection'); var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like'); -var INCORRECT = !setMethodAcceptSetLike('intersection') || fails(function () { +var INCORRECT = !setMethodAcceptSetLike('intersection', function (result) { + return result.size === 2 && result.has(1) && result.has(2); +}) || fails(function () { // eslint-disable-next-line es/no-array-from, es/no-set, es/no-set-prototype-intersection -- testing return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) !== '3,2'; }); diff --git a/packages/core-js/modules/es.set.is-disjoint-from.v2.js b/packages/core-js/modules/es.set.is-disjoint-from.v2.js index a194823a57fb..b68fe55f106d 100644 --- a/packages/core-js/modules/es.set.is-disjoint-from.v2.js +++ b/packages/core-js/modules/es.set.is-disjoint-from.v2.js @@ -3,8 +3,12 @@ var $ = require('../internals/export'); var isDisjointFrom = require('../internals/set-is-disjoint-from'); var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like'); +var INCORRECT = !setMethodAcceptSetLike('isDisjointFrom', function (result) { + return !result; +}); + // `Set.prototype.isDisjointFrom` method // https://tc39.es/ecma262/#sec-set.prototype.isdisjointfrom -$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isDisjointFrom') }, { +$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, { isDisjointFrom: isDisjointFrom }); diff --git a/packages/core-js/modules/es.set.is-subset-of.v2.js b/packages/core-js/modules/es.set.is-subset-of.v2.js index 6487067720d3..3117f01c118a 100644 --- a/packages/core-js/modules/es.set.is-subset-of.v2.js +++ b/packages/core-js/modules/es.set.is-subset-of.v2.js @@ -3,8 +3,12 @@ var $ = require('../internals/export'); var isSubsetOf = require('../internals/set-is-subset-of'); var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like'); +var INCORRECT = !setMethodAcceptSetLike('isSubsetOf', function (result) { + return result; +}); + // `Set.prototype.isSubsetOf` method // https://tc39.es/ecma262/#sec-set.prototype.issubsetof -$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSubsetOf') }, { +$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, { isSubsetOf: isSubsetOf }); diff --git a/packages/core-js/modules/es.set.is-superset-of.v2.js b/packages/core-js/modules/es.set.is-superset-of.v2.js index 5d1ae8377cc4..2d47461cf9bc 100644 --- a/packages/core-js/modules/es.set.is-superset-of.v2.js +++ b/packages/core-js/modules/es.set.is-superset-of.v2.js @@ -3,8 +3,12 @@ var $ = require('../internals/export'); var isSupersetOf = require('../internals/set-is-superset-of'); var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like'); +var INCORRECT = !setMethodAcceptSetLike('isSupersetOf', function (result) { + return !result; +}); + // `Set.prototype.isSupersetOf` method // https://tc39.es/ecma262/#sec-set.prototype.issupersetof -$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSupersetOf') }, { +$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, { isSupersetOf: isSupersetOf }); diff --git a/tests/compat/tests.js b/tests/compat/tests.js index ba2e7fac5ae7..cf5885e8fec2 100644 --- a/tests/compat/tests.js +++ b/tests/compat/tests.js @@ -243,7 +243,19 @@ function createSetLike(size) { }; } -function createSetMethodTest(METHOD_NAME) { +function createSetLikeWithInfinitySize(size) { + return { + size: size, + has: function () { + return true; + }, + keys: function () { + throw new Error('e'); + } + }; +} + +function createSetMethodTest(METHOD_NAME, callback) { return function () { try { new Set()[METHOD_NAME](createSetLike(0)); @@ -253,7 +265,18 @@ function createSetMethodTest(METHOD_NAME) { new Set()[METHOD_NAME](createSetLike(-1)); return false; } catch (error2) { - return true; + if (!callback) return true; + // early V8 implementation bug + // https://issues.chromium.org/issues/351332634 + try { + new Set()[METHOD_NAME](createSetLikeWithInfinitySize(-Infinity)); + return false; + } catch (error) { + var set = new Set(); + set.add(1); + set.add(2); + return callback(set[METHOD_NAME](createSetLikeWithInfinitySize(Infinity))); + } } } catch (error) { return false; @@ -1200,13 +1223,23 @@ GLOBAL.tests = { && set.has(0) && set[Symbol.toStringTag]; }], - 'es.set.difference.v2': createSetMethodTest('difference'), - 'es.set.intersection.v2': [createSetMethodTest('intersection'), function () { + 'es.set.difference.v2': createSetMethodTest('difference', function (result) { + return result.size === 0; + }), + 'es.set.intersection.v2': [createSetMethodTest('intersection', function (result) { + return result.size === 2 && result.has(1) && result.has(2); + }), function () { return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) === '3,2'; }], - 'es.set.is-disjoint-from.v2': createSetMethodTest('isDisjointFrom'), - 'es.set.is-subset-of.v2': createSetMethodTest('isSubsetOf'), - 'es.set.is-superset-of.v2': createSetMethodTest('isSupersetOf'), + 'es.set.is-disjoint-from.v2': createSetMethodTest('isDisjointFrom', function (result) { + return !result; + }), + 'es.set.is-subset-of.v2': createSetMethodTest('isSubsetOf', function (result) { + return result; + }), + 'es.set.is-superset-of.v2': createSetMethodTest('isSupersetOf', function (result) { + return !result; + }), 'es.set.symmetric-difference.v2': createSetMethodTest('symmetricDifference'), 'es.set.union.v2': createSetMethodTest('union'), 'es.string.at-alternative': function () {