mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-20 05:40:17 +08:00
- The ratified rename rider (world-unification §7 lane 5): "DOM" collided with the browser DOM and, post-lane-1, the structure is no longer a document tree. Comments and doc prose now say "the checked-dynamic tree" for the noun and "dyn" adjectivally; runtime symbol names (scr_dyn_*), the error.domClone libCall, and the real web DOMException family are unchanged. - The few user-facing strings carrying the nickname move with it (the structuredClone cyclic message, the dc subscriber/publish fences, two emitter ICE texts); diagnostics snapshots regenerated (96 pass). One private compiler constant (DOM_PROTO_METHOD_NAMES -> DYN_PROTO_METHOD_NAMES) rides along. - Mechanical sweep, 142 files, comments/prose only — no behavior change.
149 lines
7.5 KiB
JavaScript
149 lines
7.5 KiB
JavaScript
// Generates util.inspect oracle cases with Node as the oracle.
|
||
// Each line: <op>\t<arg-hex>\t<expected-hex>
|
||
//
|
||
// node gen-inspect-cases.mjs > inspect-cases.txt
|
||
//
|
||
// Ops:
|
||
// f64 — arg is decimal number text; expected = util.inspect(Number)
|
||
// str — arg is raw string bytes (WTF-8 for lone surrogates);
|
||
// expected = util.inspect(string) at indentation 0
|
||
// json — arg is JSON text; expected = util.inspect(JSON.parse(arg)) —
|
||
// this drives the LAYOUT engine (frames, break-length,
|
||
// grid grouping, depth placeholders) through scr_insp_dyn
|
||
// buffer — arg is raw bytes; expected = util.inspect(Buffer.from(bytes))
|
||
//
|
||
// All fields are hex-encoded ("-" = empty) so the file is unambiguous.
|
||
// Node v24 is the oracle (breakLength 80, compact 3, maxArrayLength 100,
|
||
// maxStringLength 10000 defaults).
|
||
import { inspect } from "node:util";
|
||
|
||
const hex = (buf) => (buf.length ? Buffer.from(buf).toString("hex") : "-");
|
||
const lines = [];
|
||
const emit = (op, argBytes, result) => {
|
||
lines.push([op, hex(argBytes), hex(Buffer.from(result, "utf8"))].join("\t"));
|
||
};
|
||
|
||
// ── numbers ──────────────────────────────────────────────────────────
|
||
const numbers = [
|
||
0, -0, 1, -1, 0.5, -0.5, 1.5, 123456789, -123456789, 2 ** 53, -(2 ** 53),
|
||
1e21, -1e21, 1e-7, -1e-7, 5e-324, 1.7976931348623157e308, NaN, Infinity,
|
||
-Infinity, 3.141592653589793, 100, 1000000, 0.1, 0.30000000000000004,
|
||
1234567890123456789, 2 ** 31, -(2 ** 31), 1e15, 1e16, 123.456, 0.000001,
|
||
];
|
||
for (const n of numbers) {
|
||
emit("f64", Buffer.from(String(n) === "0" && Object.is(n, -0) ? "-0" : String(n), "utf8"), inspect(n));
|
||
}
|
||
|
||
// ── strings (quoting ladder, escapes, splitting) ─────────────────────
|
||
const strings = [
|
||
"", "a", "abc", "it's", 'say "hi"', `it's "quoted"`, "a`b", "`tick`",
|
||
`mix ' " \``, `dollar \${x} ' "`, "tab\there", "nl\nhere", "cr\rhere",
|
||
"\x00\x01\x1f", "\x7f", "", " ", "backslash\\here",
|
||
"\b\f\v", "unicode ✓ ok", "emoji 😀 wide", "日本語テキスト",
|
||
"x".repeat(75), "x".repeat(76), "y".repeat(200),
|
||
"line one\nline two\nline three",
|
||
("long line padding padding padding padding padding padding padding X\n").repeat(3),
|
||
"a\n", "a\n\nb", "\n", "short\nlines\nhere",
|
||
"z".repeat(9999), "z".repeat(10000), "z".repeat(10001), "z".repeat(10002),
|
||
"w".repeat(5000) + "\n" + "w".repeat(6000),
|
||
];
|
||
for (const s of strings) {
|
||
emit("str", Buffer.from(s, "utf8"), inspect(s));
|
||
}
|
||
// Lone surrogates: WTF-8 bytes hand-encoded (Buffer.from would replace
|
||
// them with U+FFFD). Node sees the real lone-surrogate string.
|
||
const wtf8 = (cp) =>
|
||
Buffer.from([0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f)]);
|
||
const loneHigh = String.fromCharCode(0xd800);
|
||
const loneLow = String.fromCharCode(0xdfff);
|
||
emit("str", Buffer.concat([Buffer.from("a", "utf8"), wtf8(0xd800), Buffer.from("b", "utf8")]), inspect(`a${loneHigh}b`));
|
||
emit("str", Buffer.concat([wtf8(0xdfff), Buffer.from("end", "utf8")]), inspect(`${loneLow}end`));
|
||
|
||
// ── json trees (the layout engine) ───────────────────────────────────
|
||
const jsonCases = [
|
||
// scalars through the dyn renderer
|
||
"1", "-0", '"s"', "true", "false", "null",
|
||
// flat arrays: single-line vs break vs grid grouping
|
||
"[]", "[1]", "[1,2,3]", "[1,2,3,4,5,6]", "[1,2,3,4,5,6,7]",
|
||
JSON.stringify(Array.from({ length: 26 }, (_, i) => i)),
|
||
JSON.stringify(Array.from({ length: 100 }, (_, i) => i)),
|
||
JSON.stringify(Array.from({ length: 101 }, (_, i) => i)),
|
||
JSON.stringify(Array.from({ length: 250 }, (_, i) => i * 1000)),
|
||
JSON.stringify(Array.from({ length: 30 }, (_, i) => `str-${i}`)),
|
||
JSON.stringify(Array.from({ length: 8 }, (_, i) => i % 2 ? i : `s${i}`)),
|
||
JSON.stringify(Array.from({ length: 12 }, () => "0123456789012345678901234567890123456789")),
|
||
// objects: keys, quoting, nesting, depth placeholders
|
||
"{}", '{"a":1}', '{"a":1,"b":"two","c":true}',
|
||
// NOTE: integer-like keys come FIRST so the checked-dynamic tree's insertion order and
|
||
// JS's integer-keys-first property order agree (the dyn keeps
|
||
// insertion order — the runtime's documented Object.keys stance).
|
||
'{"0":2,"a-b":1,"__proto__":3,"k l":4,"ok_1":5}',
|
||
'{"a":{"b":{"c":{}}}}', '{"a":{"b":{"c":{"d":1}}}}',
|
||
'{"a":{"b":{"c":[1,2]}}}', '{"a":[[1,[2,[3,[4]]]]]}',
|
||
'{"deep":{"deeper":{"deepest":[1,2,3,4,5,6,7,8,9,10]}}}',
|
||
// the 80-column break edges
|
||
JSON.stringify({ key: "v".repeat(60) }),
|
||
JSON.stringify({ key: "v".repeat(61) }),
|
||
JSON.stringify({ key: "v".repeat(62) }),
|
||
JSON.stringify({ key: "v".repeat(63) }),
|
||
JSON.stringify({ aaaa: 1, bbbb: 2, cccc: 3, dddd: 4, eeee: 5, ffff: 6, gggg: 7, hhhh: 8 }),
|
||
JSON.stringify({ nested: { one: "aaaaaaaaaaaaaaaaaaaa", two: "bbbbbbbbbbbbbbbbbbbb", three: "cccccccccccccccccccc" } }),
|
||
// long strings INSIDE composites (indentation-dependent splitting)
|
||
JSON.stringify({ s: "x".repeat(75) + "\ny" }),
|
||
JSON.stringify({ s: "line one padding padding padding\nline two padding padding padding padding\nline three" }),
|
||
JSON.stringify([("long ".repeat(20) + "\n").repeat(2)]),
|
||
// mixed nesting
|
||
'[{"a":1},{"b":2},{"c":3}]',
|
||
'[{"name":"first","values":[1,2,3]},{"name":"second","values":[4,5,6]}]',
|
||
JSON.stringify({ list: Array.from({ length: 40 }, (_, i) => i), tag: "end" }),
|
||
JSON.stringify(Array.from({ length: 9 }, (_, i) => ({ id: i }))),
|
||
];
|
||
// seeded pseudo-random trees (deterministic — no Math.random)
|
||
let seed = 42;
|
||
const rnd = () => (seed = (seed * 1103515245 + 12345) % 2 ** 31) / 2 ** 31;
|
||
const randVal = (d) => {
|
||
const r = rnd();
|
||
if (d <= 0 || r < 0.25) {
|
||
const r2 = rnd();
|
||
if (r2 < 0.3) return Math.floor(rnd() * 1000) - 500;
|
||
if (r2 < 0.5) return rnd() > 0.5;
|
||
if (r2 < 0.6) return null;
|
||
return "s".repeat(Math.floor(rnd() * 12)) + (rnd() > 0.7 ? "'q\"" : "");
|
||
}
|
||
if (r < 0.6) return Array.from({ length: Math.floor(rnd() * 9) }, () => randVal(d - 1));
|
||
const o = {};
|
||
const n = Math.floor(rnd() * 6);
|
||
for (let i = 0; i < n; i++) o[rnd() > 0.6 ? `key${i}` : `k-${i}`] = randVal(d - 1);
|
||
return o;
|
||
};
|
||
for (let i = 0; i < 120; i++) {
|
||
jsonCases.push(JSON.stringify(randVal(4)));
|
||
}
|
||
// deeper trees: depth placeholders ([Object]/[Array]) + currentDepth math
|
||
for (let i = 0; i < 80; i++) {
|
||
jsonCases.push(JSON.stringify(randVal(6)));
|
||
}
|
||
// unicode in composites: UTF-16 break-length counting + grid widths
|
||
jsonCases.push(
|
||
JSON.stringify(Array.from({ length: 12 }, (_, i) => "日本" + i)),
|
||
JSON.stringify(Array.from({ length: 20 }, (_, i) => (i % 3 ? "✓" : "😀").repeat(i % 5))),
|
||
JSON.stringify({ 名前: "テスト", emoji: "😀😀😀", mix: ["ascii", "日本語", 42] }),
|
||
JSON.stringify(Array.from({ length: 9 }, () => "0123456789".repeat(3))),
|
||
);
|
||
for (const text of jsonCases) {
|
||
emit("json", Buffer.from(text, "utf8"), inspect(JSON.parse(text)));
|
||
}
|
||
|
||
// ── Buffers ──────────────────────────────────────────────────────────
|
||
const buffers = [
|
||
[], [0], [0xab], Array.from({ length: 10 }, (_, i) => i),
|
||
Array.from({ length: 49 }, () => 0xff), Array.from({ length: 50 }, () => 0xff),
|
||
Array.from({ length: 51 }, () => 0xff), Array.from({ length: 52 }, () => 0xff),
|
||
Array.from({ length: 200 }, (_, i) => i % 256),
|
||
];
|
||
for (const b of buffers) {
|
||
emit("buffer", Buffer.from(b), inspect(Buffer.from(b)));
|
||
}
|
||
|
||
process.stdout.write(lines.join("\n") + "\n");
|