mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-25 06:24:27 +08:00
`const parsed: { score: number }[] = JSON.parse(doc)` printed a different
checksum from Node: the checked conversion (and the schema-directed
JSON.parse fast path) stored only the declared fields of each object in
its native record, so JSON.stringify(parsed) silently dropped `id`,
`name` and `active`, and every other reflective surface agreed.
A closed record converted from an ordinary object now keeps the source's
own properties beside it when the object has undeclared keys or holds the
declared ones out of declaration order. The runtime keeps a per-thread
table from the native record to a view of the source's own keys
(placeholders for declared keys, which the record still owns), released
through the native dispose hook when the record is freed:
- the checked record builder notes its source (scr_record_source_note);
- the schema parser parses undeclared members into the view instead of
declining, so typed parses keep their one-pass fast path;
- typed JSON.stringify writes such records in source key order, declared
fields through a generated per-shape field writer and the others through
the dyn writer;
- record capsules adopt the view and refresh it in place, so untyped reads
and writes see and persist undeclared properties;
- util.inspect and Object.keys/values/entries answer through the live view
(values/entries check the extra values into their static result type and
throw the checked-conversion TypeError when one does not fit).
Copies made by object spread, Object.assign, rest destructuring or
conversion to another record type still hold only the declared fields;
the limitations page documents this.