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.
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.
Node 26.5.0 (the pinned oracle):
Perry (
main@ 0bb03e8):So the write does land somewhere the static
C.prototype.protoKeyread finds, but neither the instance prototype-chain lookup nor the computed read(C.prototype)[k]resolves it. Replacingkwith 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:
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_PROPStables, but the computed read arm injs_dyn_index_getand the instance prototype-chain lookup do not appear to consult the same place for a coerced object key.