A static array passed where a dynamically typed array is expected (for
example a `number[]` given to an `(object | undefined)[]` or `any[]`
parameter) travels as a live typed reference. Every operation on that
reference refreshed its dyn view by rebuilding the entire array, so
`xs[i]`, `xs.length`, `xs[i] = v`, `i in xs`, `Object.hasOwn`, each
`for...of` step, each `for...in` key probe, and `push`/`pop`/`at` all
cost O(n), and any loop over the array was quadratic: 10k elements took
12 s and 20k took 53 s on Linux. Writes also re-converted and swapped the
whole native storage on every store.
The native array is already the source of truth: each refresh rebuilds
the view from it and keeps only the prototype and symbol properties. Live
array capsules now carry per-element hooks (ScrDynTypedArrayOps), emitted
per array type next to the existing snapshot adapter and bound when the
capsule is built. The runtime answers length and presence from the native
array and converts exactly one element per read, writes an in-range or
appended element in place, and steps array iterators without a refresh.
Holes and out-of-range reads, which can reach the prototype chain, keep
using the view. A value the element type rejects, a write that would
grow the array by more than one element, a multi-value push, and `at`
with a coercible argument also keep the snapshot path, so their
diagnostics and atomicity are unchanged.
The capsule payload stays 80 bytes: the key length and the two flags now
share one 32-bit word, which frees the slot for the hooks pointer on both
64- and 32-bit targets.
Linux, 100k elements: the index loop went from beyond a 120 s timeout to
7 ms; Node takes 0.5 ms.
Test: test_json.c live_array_ref_tests. Corpus:
4598-live-array-ref-element-access.