Skip to content

runtime: computed object-key write on a class prototype is invisible to instances and to the computed read #6945

Description

@proggeramlug

Found while writing the #6941 regression suite (an assertion had to be dropped because of it). Not a GC bug — reproduces with zero allocation pressure.

A computed object key write onto a class prototype lands somewhere that instance lookup and the computed read cannot see. A plain string key works.

class C { m(): number { return 1; } }
const k: any = { toString(): string { return "protoKey"; } };
(C.prototype as any)[k] = { tag: 6 };
console.log("computed via instance:", JSON.stringify((new C() as any).protoKey));
console.log("computed direct:",       JSON.stringify((C.prototype as any).protoKey));
console.log("computed via key obj:",  JSON.stringify((C.prototype as any)[k]));

const plain: any = {};
plain[k] = { tag: 7 };
console.log("plain:", JSON.stringify(plain.protoKey));

Node 26.5.0 (the pinned oracle):

computed via instance: {"tag":6}
computed direct: {"tag":6}
computed via key obj: {"tag":6}
plain: {"tag":7}

Perry (main @ 0bb03e8):

computed via instance: undefined     <-- wrong
computed direct: {"tag":6}
computed via key obj: undefined      <-- wrong
plain: {"tag":7}

So the write does land somewhere the static C.prototype.protoKey read finds, but neither the instance prototype-chain lookup nor the computed read (C.prototype)[k] resolves it. Replacing k with the literal "protoKey" makes all three correct, so the difference is purely the computed/object-key path.

A closely related miss on the class-constructor (static) side, same file:

class C { static s(): number { return 1; } }
const k: any = { toString(): string { return "statKey"; } };
(C as any)[k] = { tag: 6 };
console.log("static via name:",    JSON.stringify((C as any).statKey));  // {"tag":6}  ok
console.log("static via key obj:", JSON.stringify((C as any)[k]));       // undefined  wrong (node: {"tag":6})

Likely area: the class-ref (INT32 tag 0x7FFE) arms. The write side (js_object_set_property_key / js_dyn_index_set) routes class refs into the by-name setter and the static/CLASS_DYNAMIC_PROPS tables, but the computed read arm in js_dyn_index_get and the instance prototype-chain lookup do not appear to consult the same place for a coerced object key.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions