Files
scriptc/tests/corpus/record-dynamic-writes.ts
T
Malte UblandClaude Opus 5.5 c2f9b49113 Write untyped stores into live records and pass prefix records by pointer
An untyped write of a present declared field of a live record capsule now
stores into the native record through a per-shape `set` hook (checked like
the commit, refusing to the snapshot path for values the field cannot hold),
so the capsule keeps answering from the record instead of turning into a
permanent snapshot. Object.assign from a plain object takes the same path,
and checked conversions and matches read a capsule through a fresh,
uncached snapshot.

A checked conversion of a record capsule into a record type whose storage
is a same-offset prefix of the capsule's record (and whose extra fields hold
no references) passes the pointer: both names keep one object, writes show
through either, and the record remembers its own capsule parameters, so
every later box of it and the narrower type's reflective surfaces answer
for the whole object (decision D3). Other cross-layout conversions keep the
refreshed copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 15:05:27 -07:00

63 lines
2.3 KiB
TypeScript

// Writes through an untyped view of a native record store into the record
// itself: typed reads see them, the view keeps answering from the record
// (no snapshot), and typed writes show through the view again.
type Point = { x: number; y: number; label: string; tag?: string };
const p: Point = { x: 1, y: 2, label: "a" };
const d = p as unknown as Record<string, unknown>;
d.x = 10;
d.label = "b";
console.log(p.x, p.label, JSON.stringify(d), Object.keys(d).join(","));
p.y = 7;
console.log(d.y, JSON.stringify(p), "y" in d);
d.tag = "t";
console.log(p.tag, JSON.stringify(d), Object.keys(p).join(","));
d.tag = "u";
console.log(p.tag, d.tag);
d.label = "c";
console.log(p.label, JSON.stringify(Object.entries(d)));
// Nested values written through the view are the record's own.
type Nested = { inner: { v: number }; list: number[]; flag: boolean };
const n: Nested = { inner: { v: 1 }, list: [1], flag: false };
const dn = n as unknown as { inner: unknown; list: unknown; flag: unknown };
const fresh = { v: 2 };
dn.inner = fresh;
fresh.v = 3;
console.log(n.inner.v, JSON.stringify(dn));
dn.list = [4, 5];
n.list.push(6);
console.log(n.list.length, n.list[1], JSON.stringify(dn.list));
dn.flag = true;
console.log(n.flag, dn.flag);
// A counter updated through the view in a loop.
const acc: { total: number; count: number } = { total: 0, count: 0 };
const da = acc as unknown as { total: number; count: number };
for (let i = 0; i < 100000; i++) {
da.total = da.total + i;
da.count += 1;
}
console.log(acc.total, acc.count);
// Object.assign onto the view.
type Cfg = { host: string; port: number; debug: boolean; tags?: string[] };
const c: Cfg = { host: "a", port: 1, debug: false, tags: ["x"] };
const dc = c as unknown as object;
Object.assign(dc, { port: 2, debug: true });
console.log(c.port, c.debug, JSON.stringify(dc));
Object.assign(dc, { host: "z", extra: 1 });
console.log(c.host, JSON.stringify(dc), Object.keys(dc).length);
c.port = 3;
console.log(JSON.stringify(dc));
// Writes through a function that takes the record as unknown.
function bump(value: unknown, key: string): void {
const object = value as Record<string, number>;
object[key] = object[key]! + 1;
}
const counts = { a: 1, b: 2 };
bump(counts, "a");
bump(counts, "b");
bump(counts, "b");
console.log(counts.a, counts.b, JSON.stringify(counts));