You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Array.prototype.{join,indexOf,map,forEach}.call(arr) does not fill holes through a custom prototype #9221
The generic array-like engine behind Array.prototype.<method>.call(...) reads elements on a path that bypasses array_spec_get, so a hole filled by the array's prototype is seen as a hole rather than as the inherited value.
constproto={1: "holeFill"};constk=[0,,2];// hole at index 1Object.setPrototypeOf(k,proto);k[1]// "holeFill" (correct after #9219)Array.prototype.join.call(k)// node: "0,holeFill,2" perry: "0,,2"Array.prototype.indexOf.call(k,"holeFill")// node: 1 perry: -1
map and forEach diverge the same way — ES defines their hole check as HasProperty, which is a full prototype-chain walk, not an own-element test.
Not the setPrototypeOf bug
Pre-existing and independent of #9192. Found while fixing it; the control that establishes this is that the divergence reproduces identically when the prototype is itself an array — the long-supported shape. #9219 fixes direct indexed and named reads; these generic-engine element reads are a separate path it does not touch.
Impact
Silent wrong values from the most generic, most-copied array idiom in JS. Anything using Array.prototype.<m>.call on an array-like with an inherited fill — a common polyfill and arguments-handling shape — gets a hole where a value belongs.
Fix direction
Route the generic engine's element reads through array_spec_get (or the same ArrayCustomProto classification #9219 introduced in crates/perry-runtime/src/array/indexing.rs), and make the hole test a HasProperty walk rather than an own-element check when the receiver has a recorded prototype. Arrays with the default chain should keep the current fast read, gated on the existing per-array recorded-prototype check, so this costs nothing for the overwhelmingly common case.
Checks 106–110 of the differential harness in the #9219 branch already cover this.
Activity
refactor(runtime): split the spec prototype-chain block out of indexi…
refactor(runtime): split the spec prototype-chain block out of indexi…
fix(runtime): indexed writes honour a custom array prototype (from #9297
proggeramlug commentedon Sep 2, 2026
Closing: fixed alongside #9220 in #9370 (shared fixture test_gap_9220_9221_array_proto_paths).