mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
`JSON.stringify(new Url(...))` was refused (SC1090) for every program class, although JSON.stringify of a class with a toJSON hook serializes whatever toJSON(key) returns. A class whose chain declares toJSON now crosses into the runtime JSON walker through its checked-dynamic class view, which calls the hook with the root key "" and handles nested hooks; an undefined hook result keeps the dyn-root undefined rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
// JSON.stringify of a class instance whose class (or a base) declares
|
|
// toJSON serializes what toJSON(key) returns: the root key is "", nested
|
|
// hooks run through the same walker, and a toJSON answering undefined
|
|
// makes the whole result undefined.
|
|
class Url {
|
|
href: string;
|
|
constructor(href: string) {
|
|
this.href = href;
|
|
}
|
|
toJSON(): string {
|
|
return this.href;
|
|
}
|
|
}
|
|
class NextUrl extends Url {
|
|
base = "ignored";
|
|
}
|
|
class Keyed {
|
|
toJSON(key: string): { key: string; at: Url[] } {
|
|
return { key, at: [new Url("n")] };
|
|
}
|
|
}
|
|
class Missing {
|
|
toJSON(): undefined {
|
|
return undefined;
|
|
}
|
|
}
|
|
console.log(JSON.stringify(new Url("http://x/")));
|
|
console.log(JSON.stringify(new NextUrl("http://y/")));
|
|
console.log(JSON.stringify(new Keyed()));
|
|
console.log(JSON.stringify(new Keyed(), null, 2));
|
|
function serialize(value: Missing): string {
|
|
const text = JSON.stringify(value);
|
|
return text === undefined ? "undefined result" : `text ${text}`;
|
|
}
|
|
console.log(serialize(new Missing()), JSON.stringify(new Missing()) === undefined);
|
|
let calls = 0;
|
|
class Counted {
|
|
toJSON(): number {
|
|
calls++;
|
|
return calls;
|
|
}
|
|
}
|
|
const c = new Counted();
|
|
console.log(JSON.stringify(c), JSON.stringify(c), calls);
|