Skip to content

Commit

Permalink
add a fix of V8 < 12.8 / NodeJS < 22.10 bug with handling infinite le…
Browse files Browse the repository at this point in the history
…ngth of set-like objects in `Set` methods

https://issues.chromium.org/issues/351332634
nodejs/node#54883
  • Loading branch information
zloirock committed Dec 30, 2024
1 parent 26b672c commit dd21b36
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 25 additions & 5 deletions packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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',
Expand Down
27 changes: 25 additions & 2 deletions packages/core-js/internals/set-method-accept-set-like.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion packages/core-js/modules/es.set.difference.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
4 changes: 3 additions & 1 deletion packages/core-js/modules/es.set.intersection.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
});
Expand Down
6 changes: 5 additions & 1 deletion packages/core-js/modules/es.set.is-disjoint-from.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
6 changes: 5 additions & 1 deletion packages/core-js/modules/es.set.is-subset-of.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
6 changes: 5 additions & 1 deletion packages/core-js/modules/es.set.is-superset-of.v2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
47 changes: 40 additions & 7 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;
Expand Down Expand Up @@ -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 () {
Expand Down

0 comments on commit dd21b36

Please sign in to comment.