Files
scriptc/tests/corpus/set-checked-storage.ts
T
Chris Tate 3434aacec4 Pick the iteration step from the key kind for checked collections
A typed number-key Map or Set that is boxed and cast back to
Map<unknown, unknown> or Set<unknown> keeps its own storage, with
16-byte entries. Inline iteration over a checked collection used the
24-byte step, so it tested the wrong words for liveness and read past
the entry array: a Set skipped entries and a Map aborted with "map
iteration index out of range".

The iteration step for a collection with checked keys now reads the
map's key kind and takes the number-key step for SCR_MAP_KEY_F64 and the
24-byte step otherwise. Keys and values are at bytes 0 and 8 in both
layouts, so the slot reads are unchanged. Typed collections keep their
static step, and their IR is unchanged. scr_map.h asserts the key kind's
offset and SCR_MAP_KEY_F64's value.

set-checked-storage.ts iterates a number-key Set and a hashed number-key
Map through their checked views, with deleted entries.
2026-10-21 00:35:00 -05:00

34 lines
1.4 KiB
TypeScript

function opaque(value: unknown): unknown { return value; }
const source = new Set<unknown>([1, "one", 0n]);
const record = opaque({ values: source }) as { values: Set<unknown> };
console.log(record.values === source);
record.values.add(2);
const roundTrip = opaque(source) as Set<unknown>;
console.log(roundTrip === source, source.size, source.has(2), source.has(0n));
source.delete(1);
console.log(roundTrip.size, roundTrip.has(1));
console.log(String(opaque(source)), Object.prototype.toString.call(opaque(source)));
console.log("set");
// A typed number-key collection cast back to its checked form keeps its own
// storage; iteration visits its live entries in insertion order.
const numbers = new Set<number>([5, 6, 7.5, 8]);
numbers.delete(6);
const numberView = opaque(numbers) as Set<unknown>;
const seen: unknown[] = [];
for (const value of numberView) seen.push(value);
numberView.forEach((value) => seen.push(value));
console.log(numberView.size, seen.join(","), [...numberView].join(","));
const byId = new Map<number, string>();
for (let i = 0; i < 40; i++) byId.set(i * 1000 + 0.5, `v${i}`);
byId.delete(1000.5);
byId.delete(39000.5);
const mapView = opaque(byId) as Map<unknown, unknown>;
let keys = 0;
let last = "";
for (const [key, value] of mapView) {
keys += key as number;
last = value as string;
}
console.log(mapView.size, keys, last, [...mapView.keys()].length, [...mapView.values()][0]);