Skip to content

Commit dd21b36

Browse files
committed
add a fix of V8 < 12.8 / NodeJS < 22.10 bug with handling infinite length of set-like objects in Set methods
https://issues.chromium.org/issues/351332634 nodejs/node#54883
1 parent 26b672c commit dd21b36

9 files changed

+114
-19
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- 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`
77
- [`Iterator` sequencing stage 2.7 proposal](https://github.com/tc39/proposal-iterator-sequencing):
88
- 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
9+
- 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
910
- Optimized `DataView.prototype.{ getFloat16, setFloat16 }` performance, [#1379](https://github.com/zloirock/core-js/pull/1379), thanks [**@LeviPesin**](https://github.com/LeviPesin)
1011
- Dropped unneeded feature detection of non-standard `%TypedArray%.prototype.toSpliced`
1112
- Dropped possible re-usage of some non-standard / early stage features (like `Math.scale`) available on global

packages/core-js-compat/src/data.mjs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1464,8 +1464,12 @@ export const data = {
14641464
bun: '1.1.1',
14651465
// v8 ~ Chrome 122 does not properly work with set-like objects
14661466
// https://bugs.chromium.org/p/v8/issues/detail?id=14559
1467-
chrome: '123',
1467+
// v8 < Chrome 128 does not properly convert set-like objects Infinty size
1468+
// https://issues.chromium.org/issues/351332634
1469+
chrome: '128', // '122',
14681470
firefox: '127',
1471+
// https://github.com/nodejs/node/pull/54883
1472+
node: '22.10',
14691473
// safari 17 does not properly work with set-like objects
14701474
// https://bugs.webkit.org/show_bug.cgi?id=267494
14711475
safari: '18.0', // '17.0',
@@ -1474,8 +1478,12 @@ export const data = {
14741478
bun: '1.1.1',
14751479
// v8 ~ Chrome 122 does not properly work with set-like objects
14761480
// https://bugs.chromium.org/p/v8/issues/detail?id=14559
1477-
chrome: '123',
1481+
// v8 < Chrome 128 does not properly convert set-like objects Infinty size
1482+
// https://issues.chromium.org/issues/351332634
1483+
chrome: '128', // '122',
14781484
firefox: '127',
1485+
// https://github.com/nodejs/node/pull/54883
1486+
node: '22.10',
14791487
// safari 17 does not properly work with set-like objects
14801488
// https://bugs.webkit.org/show_bug.cgi?id=267494
14811489
safari: '18.0', // '17.0',
@@ -1484,8 +1492,12 @@ export const data = {
14841492
bun: '1.1.1',
14851493
// v8 ~ Chrome 122 does not properly work with set-like objects
14861494
// https://bugs.chromium.org/p/v8/issues/detail?id=14559
1487-
chrome: '123',
1495+
// v8 < Chrome 128 does not properly convert set-like objects Infinty size
1496+
// https://issues.chromium.org/issues/351332634
1497+
chrome: '128', // '122',
14881498
firefox: '127',
1499+
// https://github.com/nodejs/node/pull/54883
1500+
node: '22.10',
14891501
// safari 17 does not properly work with set-like objects
14901502
// https://bugs.webkit.org/show_bug.cgi?id=267494
14911503
safari: '18.0', // '17.0',
@@ -1494,8 +1506,12 @@ export const data = {
14941506
bun: '1.1.1',
14951507
// v8 ~ Chrome 122 does not properly work with set-like objects
14961508
// https://bugs.chromium.org/p/v8/issues/detail?id=14559
1497-
chrome: '123',
1509+
// v8 < Chrome 128 does not properly convert set-like objects Infinty size
1510+
// https://issues.chromium.org/issues/351332634
1511+
chrome: '128', // '122',
14981512
firefox: '127',
1513+
// https://github.com/nodejs/node/pull/54883
1514+
node: '22.10',
14991515
// safari 17 does not properly work with set-like objects
15001516
// https://bugs.webkit.org/show_bug.cgi?id=267494
15011517
safari: '18.0', // '17.0',
@@ -1504,8 +1520,12 @@ export const data = {
15041520
bun: '1.1.1',
15051521
// v8 ~ Chrome 122 does not properly work with set-like objects
15061522
// https://bugs.chromium.org/p/v8/issues/detail?id=14559
1507-
chrome: '123',
1523+
// v8 < Chrome 128 does not properly convert set-like objects Infinty size
1524+
// https://issues.chromium.org/issues/351332634
1525+
chrome: '128', // '122',
15081526
firefox: '127',
1527+
// https://github.com/nodejs/node/pull/54883
1528+
node: '22.10',
15091529
// safari 17 does not properly work with set-like objects
15101530
// https://bugs.webkit.org/show_bug.cgi?id=267494
15111531
safari: '18.0', // '17.0',

packages/core-js/internals/set-method-accept-set-like.js

+25-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,19 @@ var createSetLike = function (size) {
1717
};
1818
};
1919

20-
module.exports = function (name) {
20+
var createSetLikeWithInfinitySize = function (size) {
21+
return {
22+
size: size,
23+
has: function () {
24+
return true;
25+
},
26+
keys: function () {
27+
throw new Error('e');
28+
}
29+
};
30+
};
31+
32+
module.exports = function (name, callback) {
2133
var Set = getBuiltIn('Set');
2234
try {
2335
new Set()[name](createSetLike(0));
@@ -27,7 +39,18 @@ module.exports = function (name) {
2739
new Set()[name](createSetLike(-1));
2840
return false;
2941
} catch (error2) {
30-
return true;
42+
if (!callback) return true;
43+
// early V8 implementation bug
44+
// https://issues.chromium.org/issues/351332634
45+
try {
46+
new Set()[name](createSetLikeWithInfinitySize(-Infinity));
47+
return false;
48+
} catch (error) {
49+
var set = new Set();
50+
set.add(1);
51+
set.add(2);
52+
return callback(set[name](createSetLikeWithInfinitySize(Infinity)));
53+
}
3154
}
3255
} catch (error) {
3356
return false;

packages/core-js/modules/es.set.difference.v2.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ var $ = require('../internals/export');
33
var difference = require('../internals/set-difference');
44
var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');
55

6+
var INCORRECT = !setMethodAcceptSetLike('difference', function (result) {
7+
return result.size === 0;
8+
});
9+
610
// `Set.prototype.difference` method
711
// https://tc39.es/ecma262/#sec-set.prototype.difference
8-
$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('difference') }, {
12+
$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
913
difference: difference
1014
});

packages/core-js/modules/es.set.intersection.v2.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ var fails = require('../internals/fails');
44
var intersection = require('../internals/set-intersection');
55
var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');
66

7-
var INCORRECT = !setMethodAcceptSetLike('intersection') || fails(function () {
7+
var INCORRECT = !setMethodAcceptSetLike('intersection', function (result) {
8+
return result.size === 2 && result.has(1) && result.has(2);
9+
}) || fails(function () {
810
// eslint-disable-next-line es/no-array-from, es/no-set, es/no-set-prototype-intersection -- testing
911
return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) !== '3,2';
1012
});

packages/core-js/modules/es.set.is-disjoint-from.v2.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ var $ = require('../internals/export');
33
var isDisjointFrom = require('../internals/set-is-disjoint-from');
44
var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');
55

6+
var INCORRECT = !setMethodAcceptSetLike('isDisjointFrom', function (result) {
7+
return !result;
8+
});
9+
610
// `Set.prototype.isDisjointFrom` method
711
// https://tc39.es/ecma262/#sec-set.prototype.isdisjointfrom
8-
$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isDisjointFrom') }, {
12+
$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
913
isDisjointFrom: isDisjointFrom
1014
});

packages/core-js/modules/es.set.is-subset-of.v2.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ var $ = require('../internals/export');
33
var isSubsetOf = require('../internals/set-is-subset-of');
44
var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');
55

6+
var INCORRECT = !setMethodAcceptSetLike('isSubsetOf', function (result) {
7+
return result;
8+
});
9+
610
// `Set.prototype.isSubsetOf` method
711
// https://tc39.es/ecma262/#sec-set.prototype.issubsetof
8-
$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSubsetOf') }, {
12+
$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
913
isSubsetOf: isSubsetOf
1014
});

packages/core-js/modules/es.set.is-superset-of.v2.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ var $ = require('../internals/export');
33
var isSupersetOf = require('../internals/set-is-superset-of');
44
var setMethodAcceptSetLike = require('../internals/set-method-accept-set-like');
55

6+
var INCORRECT = !setMethodAcceptSetLike('isSupersetOf', function (result) {
7+
return !result;
8+
});
9+
610
// `Set.prototype.isSupersetOf` method
711
// https://tc39.es/ecma262/#sec-set.prototype.issupersetof
8-
$({ target: 'Set', proto: true, real: true, forced: !setMethodAcceptSetLike('isSupersetOf') }, {
12+
$({ target: 'Set', proto: true, real: true, forced: INCORRECT }, {
913
isSupersetOf: isSupersetOf
1014
});

tests/compat/tests.js

+40-7
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,19 @@ function createSetLike(size) {
243243
};
244244
}
245245

246-
function createSetMethodTest(METHOD_NAME) {
246+
function createSetLikeWithInfinitySize(size) {
247+
return {
248+
size: size,
249+
has: function () {
250+
return true;
251+
},
252+
keys: function () {
253+
throw new Error('e');
254+
}
255+
};
256+
}
257+
258+
function createSetMethodTest(METHOD_NAME, callback) {
247259
return function () {
248260
try {
249261
new Set()[METHOD_NAME](createSetLike(0));
@@ -253,7 +265,18 @@ function createSetMethodTest(METHOD_NAME) {
253265
new Set()[METHOD_NAME](createSetLike(-1));
254266
return false;
255267
} catch (error2) {
256-
return true;
268+
if (!callback) return true;
269+
// early V8 implementation bug
270+
// https://issues.chromium.org/issues/351332634
271+
try {
272+
new Set()[METHOD_NAME](createSetLikeWithInfinitySize(-Infinity));
273+
return false;
274+
} catch (error) {
275+
var set = new Set();
276+
set.add(1);
277+
set.add(2);
278+
return callback(set[METHOD_NAME](createSetLikeWithInfinitySize(Infinity)));
279+
}
257280
}
258281
} catch (error) {
259282
return false;
@@ -1200,13 +1223,23 @@ GLOBAL.tests = {
12001223
&& set.has(0)
12011224
&& set[Symbol.toStringTag];
12021225
}],
1203-
'es.set.difference.v2': createSetMethodTest('difference'),
1204-
'es.set.intersection.v2': [createSetMethodTest('intersection'), function () {
1226+
'es.set.difference.v2': createSetMethodTest('difference', function (result) {
1227+
return result.size === 0;
1228+
}),
1229+
'es.set.intersection.v2': [createSetMethodTest('intersection', function (result) {
1230+
return result.size === 2 && result.has(1) && result.has(2);
1231+
}), function () {
12051232
return String(Array.from(new Set([1, 2, 3]).intersection(new Set([3, 2])))) === '3,2';
12061233
}],
1207-
'es.set.is-disjoint-from.v2': createSetMethodTest('isDisjointFrom'),
1208-
'es.set.is-subset-of.v2': createSetMethodTest('isSubsetOf'),
1209-
'es.set.is-superset-of.v2': createSetMethodTest('isSupersetOf'),
1234+
'es.set.is-disjoint-from.v2': createSetMethodTest('isDisjointFrom', function (result) {
1235+
return !result;
1236+
}),
1237+
'es.set.is-subset-of.v2': createSetMethodTest('isSubsetOf', function (result) {
1238+
return result;
1239+
}),
1240+
'es.set.is-superset-of.v2': createSetMethodTest('isSupersetOf', function (result) {
1241+
return !result;
1242+
}),
12101243
'es.set.symmetric-difference.v2': createSetMethodTest('symmetricDifference'),
12111244
'es.set.union.v2': createSetMethodTest('union'),
12121245
'es.string.at-alternative': function () {

0 commit comments

Comments
 (0)