Skip to content

Fix for-in missing inherited enumerable index properties placed on Array.prototype#2655

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix-forin-inherited-array-prototype-index
Jul 13, 2026
Merged

Fix for-in missing inherited enumerable index properties placed on Array.prototype#2655
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix-forin-inherited-array-prototype-index

Conversation

@lahma

@lahma lahma commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Bug

Array.prototype[5] = "inherited";
for (var k in [10, 20]) print(k);
// actual:   0, 1
// expected: 0, 1, 5

Array.prototype is itself array-backed, so script-placed elements live in its dense element store. The for-in key-collection shortcut for builtin-shaped hosts (GetForInStringKeys) handed out the shared builtin name list, which only covers shape slots — own index keys on the prototype were invisible to enumeration. Verified against pristine main.

Fix

The shortcut steps aside when an array-backed host carries any own index-keyed element (new ArrayInstance.HasAnyOwnIndex(): a present dense element or a materialized per-index descriptor); the fallback path collects indices and builtin names correctly. For pristine prototypes — the overwhelmingly common case — the added cost is one type test plus a scan of an empty backing store, and the shared-name-list shortcut still applies.

Found by a new enumeration test written while working on the for-in array fast path (follow-up PR); regression test included.

Gate

Jint.Tests, PublicInterface, CommonScripts all green; Test262 full run green except the four known load-dependent annexB RegExp *-escape-BMP slow tests, which pass in 5s when run in isolation (they time out at 30s only under full-suite CPU starvation — flake hardening for those is coming separately).

🤖 Generated with Claude Code

@lahma
lahma enabled auto-merge (squash) July 13, 2026 07:47
…ray.prototype

Array.prototype is itself array-backed, so script-placed elements
(Array.prototype[5] = x) live in its dense element store. The for-in
key-collection shortcut for builtin-shaped hosts handed out the shared
builtin name list, which only covers shape slots - the own index keys
were invisible, so `for (var k in [1, 2])` never yielded the inherited
enumerable index.

The shortcut now steps aside when an array-backed host carries any own
index-keyed element (a present dense element or a materialized per-index
descriptor); the fallback path collects indices and builtin names
correctly. The extra cost for pristine prototypes is one type test plus
a scan of an empty backing store.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant