Assigning a named (non-index) property to an array is silently dropped: the write appears to succeed, the read returns undefined, and the key never shows up in Object.keys.
const arr: any[] = [1, 2, 3];
arr.foo = "bar";
arr[10] = "sparse";
console.log(arr.length, arr.foo, arr[10]);
console.log(Object.keys(arr).join(","));
|
output |
| node 26.5.1 |
11 bar sparse / 0,1,2,10,foo |
| perry |
11 undefined sparse / 0,1,2,10 |
Index writes are fine — arr[10] sets, reads back, extends length to 11, and JSON.stringify produces the identical sparse-with-null form node does. It is specifically the named key that vanishes. No error is raised, in strict mode or otherwise, which is what makes it costly: the failure is silent and the array otherwise behaves normally.
This pattern is common in real code — attaching metadata to an array (results.total, rows.hasMore), and several npm packages return arrays with named fields alongside the elements.
Confirmed pre-existing on main, not caused by #9190, by reverting that PR's four runtime files to main and rebuilding the runtime and stdlib static wrappers: output byte-identical to the PR build, and both differ from node in exactly these two lines. Found while auditing #9190.
Everything else in the same probe matches node byte-for-byte: 300+ named keys on a plain object, numeric-vs-string key aliasing (o[5] / o["5"]), negative and fractional keys, non-enumerable and accessor properties, symbol keys, getOwnPropertyNames, prototype shadowing with for…in order, Object.freeze, and a 400-key index-like receiver.
Assigning a named (non-index) property to an array is silently dropped: the write appears to succeed, the read returns
undefined, and the key never shows up inObject.keys.11 bar sparse/0,1,2,10,foo11 undefined sparse/0,1,2,10Index writes are fine —
arr[10]sets, reads back, extendslengthto 11, andJSON.stringifyproduces the identical sparse-with-nullform node does. It is specifically the named key that vanishes. No error is raised, in strict mode or otherwise, which is what makes it costly: the failure is silent and the array otherwise behaves normally.This pattern is common in real code — attaching metadata to an array (
results.total,rows.hasMore), and several npm packages return arrays with named fields alongside the elements.Confirmed pre-existing on
main, not caused by #9190, by reverting that PR's four runtime files tomainand rebuilding the runtime and stdlib static wrappers: output byte-identical to the PR build, and both differ from node in exactly these two lines. Found while auditing #9190.Everything else in the same probe matches node byte-for-byte: 300+ named keys on a plain object, numeric-vs-string key aliasing (
o[5]/o["5"]), negative and fractional keys, non-enumerable and accessor properties, symbol keys,getOwnPropertyNames, prototype shadowing withfor…inorder,Object.freeze, and a 400-key index-like receiver.