mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
Every ScrArr carried sixteen words, seven of them (sparse slots, their length and capacity, noncanonical numeric properties with length and capacity, and match-result metadata) used only by sparse arrays, arrays with numeric non-index properties and regex match results. They now live in a ScrArrExt the array points at, allocated on first use: a dense array shrinks from 128 to 80 bytes, and a cycle-capable one (with its 16-byte collector header) from 144 to 96. Runtime readers go through a shared empty ext; writers allocate it. The backend mirror loses the seven fields, tagged-template arrays are emitted with a NULL ext, live stream commits swap the ext pointer (which swapped all seven fields before), and the cached typed-view refresh swaps sparse slots and properties through scr_arr_swap_indexed_ext, keeping each array's metadata as before. The program-object ABI marker moves to scr_runtime_abi_v11. A corpus program (4610-array-ext-dyn-refresh.ts, with its order baseline) pins numeric non-index properties of a dynamically typed array through its refreshed typed view, sparse slots written directly and through a live reference, truncation, and regex match metadata read directly, through `any` and after a copy.
45 lines
1.7 KiB
TypeScript
45 lines
1.7 KiB
TypeScript
// Sparse slots, noncanonical numeric properties and regex match metadata
|
|
// live in an array's out-of-line storage: they keep their values through
|
|
// typed views of dynamically typed arrays, writes through live references,
|
|
// truncation and copies.
|
|
|
|
function asNumbers(value: any): number[] {
|
|
return value as number[];
|
|
}
|
|
|
|
const parsed: any = JSON.parse("[1, 2, 3]");
|
|
const first = asNumbers(parsed);
|
|
console.log("first", first.length, first[0], first[2]);
|
|
|
|
parsed[-1] = 9;
|
|
parsed["1.5"] = 11;
|
|
parsed.push(4);
|
|
const second = asNumbers(parsed);
|
|
console.log("properties", second.length, second[3], parsed[-1], parsed["1.5"], "-1" in parsed, Object.keys(parsed).length);
|
|
|
|
delete parsed[-1];
|
|
parsed.push(5);
|
|
const third = asNumbers(parsed);
|
|
console.log("third", third.length, third[4], parsed[-1], "-1" in parsed, "1.5" in parsed);
|
|
|
|
const sparse: number[] = [1, 2, 3];
|
|
sparse[4_000_000] = 7;
|
|
console.log("sparse", sparse.length, sparse[4_000_000], 3_999_999 in sparse, 4_000_000 in sparse);
|
|
sparse.length = 3;
|
|
console.log("sparse truncated", sparse.length, sparse[4_000_000], 4_000_000 in sparse);
|
|
|
|
const typed: number[] = [5, 6];
|
|
typed[3_000_000] = 1;
|
|
const viaAny: any = typed;
|
|
viaAny[3_000_001] = 2;
|
|
console.log("typed", typed.length, typed[3_000_000], typed[3_000_001], 3_000_001 in typed);
|
|
typed.length = 2;
|
|
console.log("typed truncated", typed.length, typed[3_000_000], viaAny.length);
|
|
|
|
const match = /(b)(c)?/.exec("abd")!;
|
|
console.log("match", match.index, match.input, match.length, match[1], match[2]);
|
|
const loose: any = match;
|
|
console.log("match via any", loose.index, loose.input, loose[1], loose.length);
|
|
const copy = match.slice();
|
|
console.log("copy", copy.length, copy[0], copy[1]);
|