mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-03 07:54:40 +08:00
A checked conversion of a capsule of record A into record type B, when A has all of B's fields with the same types in any order, now answers a view: a B object whose two trailing words hold A and A's offsets for B's fields. Every field address of a B value tests the first word (recordViewFieldPtr, the record clone and the JSON walker), so reads and writes through either name reach the same storage. The view's record-source entry owns A's capsule: boxing the view answers that capsule, so identity holds, B's reflective surfaces and spreads see the whole object, and the entry dies with the view, which releases A's capsule. The capsule finds its views again through borrowed cast-list entries. Only the target types of such conversions carry the words and the test. They are planned from the IR before emission (record-views.ts): record types a checked conversion can produce for which another record type in the module has all their fields. Programs without checked conversions are unchanged. This replaces the prefix pointer pass, whose narrower release could not free the source's extra fields. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
1.0 KiB
TypeScript
27 lines
1.0 KiB
TypeScript
// A native record converted from an untyped value into another record type
|
|
// that names some of its fields, in any order, is the same object: writes
|
|
// through either name show through the other, identity holds, and the
|
|
// untyped views, JSON and spreads of the narrower name see every field.
|
|
type Wide = { a: number; b: string; c: boolean; d: number[] };
|
|
type AC = { a: number; c: boolean };
|
|
type DB = { d: number[]; b: string };
|
|
const wide: Wide = { a: 1, b: "x", c: true, d: [1] };
|
|
const o: unknown = wide;
|
|
const v = o as AC;
|
|
v.c = false;
|
|
console.log((o as Wide).c, wide.c, o === v, (v as unknown) === o);
|
|
wide.a = 5;
|
|
console.log(v.a, JSON.stringify(v), Object.keys(v).join(","));
|
|
const w = o as DB;
|
|
w.d.push(2);
|
|
w.b = "y";
|
|
w.d = [7, 8];
|
|
console.log(wide.b, wide.d.length, JSON.stringify(o), w === (o as DB), v === (o as AC));
|
|
const v2 = { ...v };
|
|
console.log(JSON.stringify(v2));
|
|
function bump(x: AC): void { x.a += 1; }
|
|
bump(v);
|
|
console.log(wide.a, v.a);
|
|
const list: AC[] = [v, { a: 9, c: true }];
|
|
console.log(list.map((x) => x.a).join(","), JSON.stringify(list));
|