mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-02 07:43:42 +08:00
zod 4 builds every schema through `$constructor`, a factory of JavaScript
patterns the dynamic tier refused or answered wrongly. Each is fixed
generally:
- `"key" in BuiltinCtor` (`"captureStackTrace" in Error`) folds to Node's
answer from a table of the builtin constructor globals' keys.
- A class whose heritage evaluates to Object or Error at runtime
(`class D extends (params?.Parent ?? Object)`): Object means no
heritage; Error links Error.prototype and super() installs message,
cause and stack.
- `Object.defineProperty` on a class value boxes to its constructor, and
a JavaScript class targeted by defineProperty gets a live static table.
- A Symbol.hasInstance defined on a function's own table answers
untyped `instanceof`; an error constructor held as a value answers by
error kind.
- A builtin error constructor stored in a slot of its class value type
(`{ Parent: Error }`) is the class value, not a checked cast that fails.
- A function hoisted above a local class it references captures the
class binding as a TDZ box the class statement initializes.
- Names a program stores on the global object read back from it instead
of folding to undefined.
- A module namespace whose exports never change converts to an untyped
object (`{ ...ns }`).
- An untyped call of a String-only method name (`x.trim()`) dispatches on
the receiver's runtime kind, so objects defining that member work.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
36 lines
1.2 KiB
JavaScript
36 lines
1.2 KiB
JavaScript
const desc = { value: undefined, enumerable: false };
|
|
function factory(name) {
|
|
class Definition {}
|
|
Object.defineProperty(Definition, "name", { value: name });
|
|
function init(inst, def) {
|
|
if (!inst._meta) {
|
|
desc.value = { def, traits: new Set() };
|
|
try {
|
|
Object.defineProperty(inst, "_meta", desc);
|
|
} finally {
|
|
desc.value = undefined;
|
|
}
|
|
}
|
|
inst._meta.traits.add(name);
|
|
}
|
|
function _(def) {
|
|
const inst = this;
|
|
init(inst, def);
|
|
return inst;
|
|
}
|
|
Object.defineProperty(_, "init", { value: init });
|
|
Object.defineProperty(_, Symbol.hasInstance, {
|
|
value: (inst) => !!(inst && inst._meta && inst._meta.traits.has(name)),
|
|
});
|
|
Object.defineProperty(_, "name", { value: name });
|
|
return { ctor: _, Definition };
|
|
}
|
|
const { ctor: Thing, Definition } = factory("Thing");
|
|
console.log(Definition.name, Thing.name, typeof Thing.init);
|
|
const t = new Thing({ a: 1 });
|
|
console.log(Object.keys(t), JSON.stringify(t), t._meta.def.a, [...t._meta.traits]);
|
|
console.log(t instanceof Thing, {} instanceof Thing);
|
|
const plain = {};
|
|
Thing.init(plain, { b: 2 });
|
|
console.log(plain instanceof Thing, Object.keys(plain), plain._meta.def.b);
|