Skip to content

An indexed write that grows an array discards an explicit null [[Prototype]] #9304

Description

@proggeramlug

An indexed write that grows an array silently restores Array.prototype, discarding an explicit null [[Prototype]].

const n: any = [4, 5];
Object.setPrototypeOf(n, null);
console.log(Object.getPrototypeOf(n), Object.getPrototypeOf(n) === null);  // null true
n[9] = 1;                                                                   // grows past length
console.log(Object.getPrototypeOf(n), Object.getPrototypeOf(n) === null);  // [] false   <-- node: null true
console.log(n.length, n[9]);                                                // 10 1  (correct)
before the write after the write
node 26.5.1 null, === null true null, === null true
perry null, === null true [], === null false

The element write itself is correct — length becomes 10 and n[9] reads back 1. It is the [[Prototype]] that is silently re-linked to Array.prototype.

Two things make this worth more than a formatting curiosity:

  • It is silent and it re-attaches a whole surface. After the write, the array inherits every Array.prototype method again — so a null-prototype array used deliberately as a bare index container (the array analogue of Object.create(null) for maps) stops being bare the moment it grows, and n.map/n.constructor/n[Symbol.iterator] reappear.
  • It is write-triggered, so it will not show up in a construction-time test. Object.getPrototypeOf immediately after setPrototypeOf is correct; only a subsequent growing write moves it.

I did not narrow which write path does it — a growing write (n[9] past length 2) reproduces; I have not checked whether an in-bounds write, push, or a non-array null-prototype object are affected.

Confirmed pre-existing, not from #9297: reverting that PR's seven runtime files and rebuilding gives the identical [] false. Found while auditing #9297, which fixes three other divergences on the same probe (inherited index reads, a proto setter on a growing write, and both after GC) and takes it from four divergences to this one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions