fix a modern Safari bug in Array.prototype.includes with sparse arrays and fromIndex

https://bugs.webkit.org/show_bug.cgi?id=309342
This commit is contained in:
Denis Pushkarev
2026-03-15 17:31:01 +02:00
parent 258e81e398
commit aa7dec080c
6 changed files with 22 additions and 3 deletions
+2
View File
@@ -9,6 +9,7 @@
- Minor performance optimization polyfills of methods from [`Map` upsert proposal](https://github.com/tc39/proposal-upsert)
- Polyfills of methods from [`Map` upsert proposal](https://github.com/tc39/proposal-upsert) from the pure version made generic to make it work with polyfilled and native collections
- Wrap `Symbol.for` in `Symbol.prototype.description` polyfill for correct handling of empty string descriptions
- Fixed [a modern Safari bug](https://bugs.webkit.org/show_bug.cgi?id=309342) in `Array.prototype.includes` with sparse arrays and `fromIndex`
- Fixed one more case (`Iterator.prototype.take`) of a V8 ~ Chromium < 126 [bug](https://issues.chromium.org/issues/336839115)
- Forced replacement of `Iterator.{ concat, zip, zipKeyed }` in the pure version for ensuring proper wrapped `Iterator` instances as the result
- Fixed proxying `.return()` on exhausted iterator from some methods of iterator helpers polyfill to the underlying iterator
@@ -97,6 +98,7 @@
- [`Math.sumPrecise`](https://github.com/tc39/proposal-math-sum) marked as [shipped in V8 ~ Chrome 147](https://issues.chromium.org/issues/374310075#comment16)
- [`Iterator.concat`](https://github.com/tc39/proposal-iterator-sequencing) marked as [shipped in V8 ~ Chrome 146](https://issues.chromium.org/issues/434977727#comment7)
- [`Iterator.concat`](https://github.com/tc39/proposal-iterator-sequencing) marked as shipped in Safari 26.4
- Because of [a bug](https://bugs.webkit.org/show_bug.cgi?id=309342), `Array.prototype.includes` marked as not supported in modern Safari
- Fixed compat data for `parseInt` and `parseFloat`
- Added Deno [2.6.7](https://github.com/denoland/deno/releases/tag/v2.6.7), [2.7.0](https://github.com/denoland/deno/releases/tag/v2.7.0) and [2.7.2](https://github.com/denoland/deno/releases/tag/v2.7.2) compat data mapping
- Added Electron 42 compat data mapping
+3 -1
View File
@@ -314,7 +314,9 @@ export const data = {
// FF99-101 broken on sparse arrays
firefox: '102', // '48',
rhino: '1.8.0',
safari: '10.0',
// Safari broken on sparse arrays with fromIndex
// https://bugs.webkit.org/show_bug.cgi?id=309342
// safari: '10.0',
},
'es.array.index-of': {
chrome: '51',
@@ -10,9 +10,15 @@ var BROKEN_ON_SPARSE = fails(function () {
return !Array(1).includes();
});
// Safari 26.4- bug
var BROKEN_ON_SPARSE_WITH_FROM_INDEX = fails(function () {
// eslint-disable-next-line no-sparse-arrays, es/no-array-prototype-includes -- detection
return [, 1].includes(undefined, 1);
});
// `Array.prototype.includes` method
// https://tc39.es/ecma262/#sec-array.prototype.includes
$({ target: 'Array', proto: true, forced: BROKEN_ON_SPARSE }, {
$({ target: 'Array', proto: true, forced: BROKEN_ON_SPARSE || BROKEN_ON_SPARSE_WITH_FROM_INDEX }, {
includes: function includes(el /* , fromIndex = 0 */) {
return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
}
+4 -1
View File
@@ -526,7 +526,10 @@ GLOBAL.tests = {
'es.array.from': SAFE_ITERATION_CLOSING_SUPPORT,
'es.array.includes': function () {
return Array(1).includes()
&& Array.prototype[Symbol.unscopables].includes;
&& Array.prototype[Symbol.unscopables].includes
// https://bugs.webkit.org/show_bug.cgi?id=309342
// eslint-disable-next-line no-sparse-arrays -- testing
&& ![, 1].includes(undefined, 1);
},
'es.array.index-of': function () {
try {
+3
View File
@@ -18,6 +18,9 @@ QUnit.test('Array#includes', assert => {
assert.false(array.includes({}));
assert.true(Array(1).includes(undefined));
assert.true([NaN].includes(NaN));
// https://bugs.webkit.org/show_bug.cgi?id=309342
// eslint-disable-next-line no-sparse-arrays -- testing
assert.false([, 1].includes(undefined, 1), '`Array#includes(undefined, fromIndex)` should not find holes before fromIndex');
if (STRICT) {
assert.throws(() => includes.call(null, 0), TypeError);
assert.throws(() => includes.call(undefined, 0), TypeError);
+3
View File
@@ -15,6 +15,9 @@ QUnit.test('Array#includes', assert => {
assert.false(includes(array, {}));
assert.true(includes(Array(1), undefined));
assert.true(includes([NaN], NaN));
// https://bugs.webkit.org/show_bug.cgi?id=309342
// eslint-disable-next-line no-sparse-arrays -- testing
assert.false(includes([, 1], undefined, 1), '`Array#includes(undefined, fromIndex)` should not find holes before fromIndex');
if (STRICT) {
assert.throws(() => includes(null, 0), TypeError);
assert.throws(() => includes(undefined, 0), TypeError);