mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-03 07:54:40 +08:00
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.