zod-compiler 2.0.5 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -118
- package/dist/core/codegen/build-path.d.ts.map +1 -1
- package/dist/core/codegen/build-path.js +16 -7
- package/dist/core/codegen/build-path.js.map +1 -1
- package/dist/core/codegen/context.d.ts +10 -7
- package/dist/core/codegen/context.d.ts.map +1 -1
- package/dist/core/codegen/context.js +10 -8
- package/dist/core/codegen/context.js.map +1 -1
- package/dist/core/codegen/index.js +3 -2
- package/dist/core/codegen/index.js.map +1 -1
- package/dist/core/codegen/issue-decls.d.ts +28 -1
- package/dist/core/codegen/issue-decls.d.ts.map +1 -1
- package/dist/core/codegen/issue-decls.js +30 -1
- package/dist/core/codegen/issue-decls.js.map +1 -1
- package/dist/core/codegen/schemas/array.js +2 -2
- package/dist/core/codegen/schemas/array.js.map +1 -1
- package/dist/core/codegen/schemas/custom.js +1 -1
- package/dist/core/codegen/schemas/discriminated-union.js +1 -1
- package/dist/core/codegen/schemas/discriminated-union.js.map +1 -1
- package/dist/core/codegen/schemas/effect.js +2 -2
- package/dist/core/codegen/schemas/effect.js.map +1 -1
- package/dist/core/codegen/schemas/fallback.js +1 -1
- package/dist/core/codegen/schemas/map.js +1 -1
- package/dist/core/codegen/schemas/number.js +1 -1
- package/dist/core/codegen/schemas/object.js +3 -3
- package/dist/core/codegen/schemas/object.js.map +1 -1
- package/dist/core/codegen/schemas/record.js +2 -2
- package/dist/core/codegen/schemas/record.js.map +1 -1
- package/dist/core/codegen/schemas/sizeable.js +1 -1
- package/dist/core/codegen/schemas/string.d.ts +15 -2
- package/dist/core/codegen/schemas/string.d.ts.map +1 -1
- package/dist/core/codegen/schemas/string.js +97 -35
- package/dist/core/codegen/schemas/string.js.map +1 -1
- package/dist/core/codegen/schemas/tuple.js +2 -2
- package/dist/core/codegen/schemas/tuple.js.map +1 -1
- package/dist/core/codegen/schemas/union.js +1 -1
- package/dist/core/iife.d.ts +11 -12
- package/dist/core/iife.d.ts.map +1 -1
- package/dist/core/iife.js +12 -13
- package/dist/core/iife.js.map +1 -1
- package/dist/runtime.d.ts +2 -0
- package/dist/runtime.js +3 -1
- package/dist/static-filter.d.ts +19 -1
- package/dist/static-filter.d.ts.map +1 -1
- package/dist/static-filter.js +27 -1
- package/dist/static-filter.js.map +1 -1
- package/dist/unplugin/virtual.js +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-decls.js","names":[],"sources":["../../../src/core/codegen/issue-decls.ts"],"sourcesContent":["/**\n * Issue factory function bodies (statement form).\n *\n * These functions produce the same `{code, ...}` shapes that lean-mode\n * generated code would otherwise inline at every check site.\n * Hosted in \"virtual:zod-compiler/runtime\" and called as `__zcTS(...)` etc.\n *\n * Argument convention (positional, kept short to minimize call-site bytes):\n * __zcTS(minimum, origin, inclusive, input, path, msg?) — too_small\n * __zcTSt(minimum, origin, input, path, msg?) — too_small, tuple key order\n * __zcTBt(maximum, origin, input, path, msg?) — too_big, tuple key order\n * __zcTB(maximum, origin, inclusive, input, path, msg?) — too_big\n * __zcIT(expected, input, path, msg?) — invalid_type\n * __zcITc(expected, input, path, msg?) — invalid_type, `code` first\n * __zcIF(origin, format, input, path, extra?, msg?) — invalid_format (extra merged into result)\n * __zcIV(values, input, path, extra?, msg?) — invalid_value (extra merged into result)\n * __zcUK(keys, input, path, msg?) — unrecognized_keys\n *\n * The trailing msg argument carries a static custom error message; when\n * absent, the __zcFin finalizer applies the configured locale default.\n *\n * KEY ORDER IS PART OF THE CONTRACT. `ZodError.message` is\n * `JSON.stringify(issues, …, 2)`, so the order these factories insert keys in is\n * printed verbatim in the message every consumer logs, snapshots or serializes.\n * Each literal below therefore reproduces the order of the corresponding\n * `payload.issues.push({…})` in zod, which is irregular by type — `too_small`\n * from a check leads with `origin` while the same code from a tuple's length\n * branch leads with `code` — and every factory writes `message` LAST, because\n * zod's `finalizeIssue` assigns it after the fact (`full.message = …`) even for\n * a custom message baked into the check's error map.\n */\n\nconst ZC_TS_DECL =\n 'function __zcTS(m,o,i,inp,p,msg){var r={origin:o,code:\"too_small\",minimum:m,inclusive:i,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * too_small in the TUPLE under-length key order. $ZodTuple pushes\n * `{ code, minimum, inclusive: true, input, inst, origin }`, so its `origin`\n * trails `inclusive` where every check-created size issue leads with it. Its\n * over-length sibling is __zcTBt.\n */\nconst ZC_TS_TUPLE_DECL =\n 'function __zcTSt(m,o,inp,p,msg){var r={code:\"too_small\",minimum:m,inclusive:true,origin:o,input:inp,path:p,continue:false};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TS_EXACT_DECL =\n 'function __zcTSx(m,o,inp,p,msg){var r={origin:o,code:\"too_small\",minimum:m,inclusive:true,exact:true,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TB_DECL =\n 'function __zcTB(m,o,i,inp,p,msg){var r={origin:o,code:\"too_big\",maximum:m,inclusive:i,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * too_big in the TUPLE over-length key order. $ZodTuple spreads\n * `{ code, maximum, inclusive }` and appends `origin` after `input`/`inst`, so\n * its `origin` trails `inclusive` where every check-created size issue leads\n * with it. Its under-length sibling is __zcTSt.\n */\nconst ZC_TB_TUPLE_DECL =\n 'function __zcTBt(m,o,inp,p,msg){var r={code:\"too_big\",maximum:m,inclusive:true,origin:o,input:inp,path:p,continue:false};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TB_EXACT_DECL =\n 'function __zcTBx(m,o,inp,p,msg){var r={origin:o,code:\"too_big\",maximum:m,inclusive:true,exact:true,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_IT_DECL =\n 'function __zcIT(e,inp,p,msg){var r={expected:e,code:\"invalid_type\",input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * invalid_type with `code` ahead of `expected`. Every schema in zod spells this\n * issue `{ expected, code }` — except `$ZodDiscriminatedUnion`, whose\n * non-object guard writes `{ code, expected }`. One literal, one key order, and\n * it shows up in `ZodError.message`.\n */\nconst ZC_IT_CODE_FIRST_DECL =\n 'function __zcITc(e,inp,p,msg){var r={code:\"invalid_type\",expected:e,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * `o` is the leading `origin`, present only for the formats whose issue carries\n * one: `$ZodCheckStringFormat`'s default pattern check and the regex /\n * includes / starts_with / ends_with checks all lead with `origin: \"string\"`,\n * while `z.url()`'s own pushes and every `$ZodCustomStringFormat` omit it\n * entirely. `extra` holds the per-format tail (`pattern`, `includes`, `prefix`,\n * `suffix`, `note`) and is merged BEFORE input/path so it lands where zod\n * writes it.\n */\nconst ZC_IF_DECL =\n 'function __zcIF(o,f,inp,p,extra,msg){var r=o===undefined?{code:\"invalid_format\",format:f}:{origin:o,code:\"invalid_format\",format:f};if(extra)Object.assign(r,extra);r.input=inp;r.path=p;if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * `extra` carries the per-producer fields: enum and literal push `values` only,\n * while z.stringbool()'s codec transform also pushes `expected: \"stringbool\"`.\n * Merged the same way __zcIF merges its own.\n */\nconst ZC_IV_DECL =\n 'function __zcIV(values,inp,p,extra,msg){var r={code:\"invalid_value\"};if(extra)Object.assign(r,extra);r.values=values;r.input=inp;r.path=p;if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_UK_DECL =\n 'function __zcUK(k,inp,p,msg){var r={code:\"unrecognized_keys\",keys:k,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/** All issue factory declarations indexed by helper name. */\nexport const ISSUE_DECLS: Readonly<Record<string, string>> = {\n __zcTS: ZC_TS_DECL,\n __zcTSt: ZC_TS_TUPLE_DECL,\n __zcTSx: ZC_TS_EXACT_DECL,\n __zcTB: ZC_TB_DECL,\n __zcTBt: ZC_TB_TUPLE_DECL,\n __zcTBx: ZC_TB_EXACT_DECL,\n __zcIT: ZC_IT_DECL,\n __zcITc: ZC_IT_CODE_FIRST_DECL,\n __zcIF: ZC_IF_DECL,\n __zcIV: ZC_IV_DECL,\n __zcUK: ZC_UK_DECL,\n};\n\n/**\n * Float-safe remainder — byte-for-byte port of zod's util.floatSafeRemainder.\n * Raw `%` mis-rejects valid multiples of decimal steps (0.3 % 0.1 !== 0).\n *\n * zod 4.5 REPLACED the decimal-scaling implementation this once mirrored with a\n * ratio-and-tolerance one, and the two disagree in both directions: the old form\n * accepted `1e-7` as a multiple of 3 (its `toFixed` scaling collapsed the value\n * to 0) and rejected `1e21` (where `toFixed` yields exponential notation and\n * `parseInt` then reads 1). The tolerance is 4x epsilon because `val` and `step`\n * each round to a double before the division rounds again, so a true decimal\n * multiple's quotient can sit up to 1.5 scaled epsilons from the integer.\n */\nexport const ZC_FSR_DECL =\n \"function __zcFsr(v,s){var r=v/s;var q=Math.round(r);\" +\n \"var t=4*Number.EPSILON*Math.max(Math.abs(r),1);\" +\n \"return Math.abs(r-q)<t?0:r-q;}\";\n\n/**\n * Hoisted `Object.prototype.hasOwnProperty` reference. Record fast/slow paths\n * iterate keys with `for(k in o)` (no `Object.keys` array allocation) and guard\n * each key with `__zcHop.call(o,k)` to skip inherited enumerable properties —\n * yielding the exact own-enumerable string-key set `Object.keys` would, so\n * fast/slow stay in agreement and parity with zod's own-key record semantics is\n * preserved. The hoisted reference inlines in V8; reading the prototype property\n * per call would not.\n */\nexport const ZC_HOP_DECL = \"const __zcHop=Object.prototype.hasOwnProperty;\";\n\n/**\n * Port of zod's `util.isPlainObject` — the guard `$ZodRecord` applies to its\n * input, and a STRICTLY narrower test than the `util.isObject` (`typeof\n * \"object\"`, not null, not an array) that `$ZodObject` uses.\n *\n * The distinction is load-bearing and was a validation hole while records shared\n * the object guard: `z.record(z.string(), z.string())` accepted a `Date`, a\n * `Map`, a `RegExp`, an `Error`, a `File` and any class instance — every one of\n * which zod rejects with `invalid_type`/`expected: \"record\"`, and none of which\n * has own enumerable string keys for the value schema to catch. Compiled output\n * therefore said \"valid\" to inputs zod refuses, which is the one direction a\n * validator must never diverge in.\n *\n * The algorithm is zod's, step for step, because the answer is observable and\n * the edge cases are deliberate:\n * - `constructor === undefined` (a null-prototype object) is PLAIN;\n * - a non-function own `constructor` (`{ constructor: 1 }`) is PLAIN;\n * - otherwise the constructor's `prototype` must be an object carrying its OWN\n * `isPrototypeOf` — which `Object.prototype` does and `Date.prototype`,\n * `Map.prototype` and every user class prototype do not. Testing that rather\n * than `Object.getPrototypeOf(o) === Object.prototype` is what lets a plain\n * object from another realm (a vm context, an iframe) still count as plain.\n *\n * `c===Object` is a short-cut, not a fourth rule: it is exactly the case where\n * zod's remaining steps are foregone — `Object.prototype` is an object and has\n * its own `isPrototypeOf` — so the answer is `true` either way. It is also the\n * case every ordinary record takes (an object literal, `JSON.parse` output, a\n * `Map`-free DTO), and taking it saves the `prototype` load and the\n * `hasOwnProperty` call: measured 9.6 → 5.7 ns on a monomorphic record and\n * 15.7 → 9.2 ns across 16 shapes, i.e. 22% of a five-key record's whole parse.\n * A plain object from another realm has a different `Object` and simply takes\n * the long road to the same verdict, as before.\n *\n * Self-contained (`Object.prototype.hasOwnProperty` spelled out rather than\n * reusing `__zcHop`) so inline mode can emit this decl alone: `emitRuntimeHelper`\n * pushes only the decl it is asked for, and a helper that closed over another\n * name would dangle wherever that one was not also emitted.\n */\nexport const ZC_PLAIN_DECL =\n 'function __zcPlain(o){if(typeof o!==\"object\"||o===null||Array.isArray(o))return false;' +\n 'var c=o.constructor;if(c===Object||c===undefined||typeof c!==\"function\")return true;' +\n 'var p=c.prototype;if(typeof p!==\"object\"||p===null||Array.isArray(p))return false;' +\n 'return Object.prototype.hasOwnProperty.call(p,\"isPrototypeOf\");}';\n\n/**\n * `z.email()`'s default validator, `regexes.email`, as a single linear scan.\n *\n * Zod's pattern is\n * `^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$`,\n * and even its lookahead-free rewrite (EMAIL_FAST_REGEX_SOURCE) backtracks at\n * every dot it fails to find: `(?:[X]+\\.)*` re-tries the run one character\n * shorter each time, and the domain's `(?:label\\.)+` does the same over the\n * TLD. Written as a scanner the language is:\n *\n * local — `[A-Za-z0-9_'+.-]+`, no leading `.`, no `..`, and the character\n * before `@` is neither `.` nor `'` (that last is the `[A-Za-z0-9_+-]`\n * the pattern demands there);\n * domain — one or more labels `[A-Za-z0-9][A-Za-z0-9-]*` each ending in `.`,\n * then a TLD of two or more letters running to the end.\n *\n * A trailing `\\n` is not accepted: the pattern has no `m` flag, so its `$`\n * matches only at the end of input, and the scan reads to `length`.\n *\n * Measured against the fast regex on V8: 32 → 16 ns for `alice@example.com`,\n * 48 → 40 for `bob_smith-99@mail-server.io`, 39 → 20 for a non-address, and a\n * tie from ~35 characters up (the regex's per-character work is cheaper than a\n * `charCodeAt` loop's; its fixed dispatch cost is what the scanner avoids). A\n * lookbehind rewrite runs about as fast but needs ES2018 regex support, which\n * the CLI's React Native / Hermes and older-Safari consumers cannot assume.\n *\n * Equivalence to zod's regex — every string, both verdicts — is pinned by\n * tests/core/codegen/email-scanner.test.ts. Reached only behind a `typeof`\n * string guard, like the `.test()` it replaces; issue sites keep reporting\n * zod's own pattern string (see `emitRegexSourceString`).\n */\nexport const ZC_EMAIL_DECL =\n \"function __zcEmail(s){var n=s.length,i=0,c,p=46;\" +\n // Local part. `p` starts as `.` so a leading dot trips the `..` rule.\n \"for(;;){if(i===n)return false;c=s.charCodeAt(i);if(c===64)break;\" +\n \"if(c===46){if(p===46)return false;}\" +\n \"else if(!((c>=97&&c<=122)||(c>=65&&c<=90)||(c>=48&&c<=57)||c===95||c===39||c===43||c===45))return false;\" +\n \"p=c;i++;}\" +\n \"if(p===46||p===39)return false;\" +\n // Domain. `l` is the current label's start, `t` whether it is letters-only.\n \"var l=++i,d=0,t=true;\" +\n \"for(;i<n;i++){c=s.charCodeAt(i);\" +\n \"if((c>=97&&c<=122)||(c>=65&&c<=90))continue;\" +\n \"if(c===46){if(i===l)return false;d++;l=i+1;t=true;continue;}\" +\n \"if((c>=48&&c<=57)||c===45){if(c===45&&i===l)return false;t=false;continue;}\" +\n \"return false;}\" +\n \"return d>0&&t&&n-l>=2;}\";\n\n/**\n * Ports of `util.getLengthableOrigin` / `util.getSizableOrigin` — the `origin` a\n * length/size check puts on its issue, computed from the RUNTIME INPUT rather\n * than from the schema.\n *\n * They only matter because those checks declare a `when` predicate\n * (`!nullish(value) && value.length/size !== undefined`), which bypasses zod's\n * abort gate: `z.string().min(2)` handed `[]` reports the `invalid_type` AND a\n * `too_small` whose origin is `\"array\"`, because the empty array satisfies the\n * `when`. Inside the matching type branch the origin is statically known and\n * these are not used; they exist for the type-MISMATCH branch, where the input\n * can be anything with a `.length` or a `.size`.\n *\n * `File` is probed through `typeof` first: zod tests `input instanceof File`\n * unguarded, which throws where the global is absent — an environment zod does\n * not run in, and not one worth reproducing a crash for.\n */\nexport const ZC_LENGTH_ORIGIN_DECL =\n 'function __zcLo(v){return Array.isArray(v)?\"array\":typeof v===\"string\"?\"string\":\"unknown\";}';\n\n/**\n * Drop an own `__proto__` from a container the parse hands back BY REFERENCE.\n *\n * zod never lets the key into an output: `$ZodObject`'s shape loop strips a\n * declared one, `handleCatchall` skips an undeclared one, and `$ZodRecord` skips\n * it while copying — all so the assignment into their fresh `{}` cannot replace\n * the result's prototype. A compiled loose/catchall object or record IS its\n * input, so the key has to be removed here instead; leaving it made\n * `Object.assign({}, parsed)` a prototype-pollution sink, since [[Set]] runs the\n * inherited setter the spread that built the value did not.\n *\n * Copies rather than editing in place: the divergence note promises the caller\n * its own container back, not one with a key silently deleted from it. The\n * common object has no such key and is returned untouched, so the cost is one\n * `hasOwnProperty` call.\n */\nexport const ZC_PROTO_SCRUB_DECL =\n 'function __zcPs(o){if(!Object.prototype.hasOwnProperty.call(o,\"__proto__\"))return o;' +\n 'var c={...o};delete c[\"__proto__\"];return c;}';\n\n/**\n * Code points in a string — zod's `util.codePointLength`, verbatim. A surrogate\n * pair counts once and a lone surrogate as itself. The regex probe is the fast\n * exit for a string with no astral characters, and the hand-rolled loop avoids\n * the allocating string iterator. Only reached from a length check whose\n * UTF-16 count leaves the verdict in doubt (see stringLengthTests).\n */\nexport const ZC_CPL_DECL =\n \"function __zcCpl(s){var n=s.length;if(!/[\\\\uD800-\\\\uDBFF]/.test(s))return n;var c=n;for(var i=0;i<n-1;i++){if((s.charCodeAt(i)&0xfc00)===0xd800&&(s.charCodeAt(i+1)&0xfc00)===0xdc00){c--;i++;}}return c;}\";\n\nexport const ZC_SIZE_ORIGIN_DECL =\n 'function __zcSo(v){return v instanceof Set?\"set\":v instanceof Map?\"map\":' +\n '(typeof File!==\"undefined\"&&v instanceof File)?\"file\":\"unknown\";}';\n\n/**\n * Issue codes zod raises from a schema's `_zod.parse` rather than from a check,\n * and which therefore carry `continue !== true` — what `util.aborted` looks for.\n *\n * Everything a CHECK produces (`too_small`, `too_big`, `invalid_format`,\n * `not_multiple_of`, a refine's `custom`) is continuable, because `$ZodCheck`\n * sets `continue: !def.abort` and an `abort: true` check costs the schema its\n * compiled path anyway — so classifying by code alone is exact for generated\n * issues.\n *\n * `unrecognized_keys` is the one parse-level issue zod pushes WITH\n * `continue: true`: it describes the shape of the input rather than the\n * validity of the parsed value, so the parse still fails but the object's own\n * refines run first and a union does not count the option as aborted.\n *\n * Read by {@link ZC_AB_DECL} and by the union's option-pruning loop, which\n * applies the same rule inline over a per-option issue array.\n */\nconst ABORTING_ISSUE_CODES: readonly string[] = [\n \"invalid_type\",\n \"invalid_value\",\n \"invalid_union\",\n \"invalid_key\",\n \"invalid_element\",\n];\n\n/** `c===\"invalid_type\"||c===\"invalid_value\"||…` over the code held in `codeExpr`. */\nexport function abortingCodeTest(codeExpr: string): string {\n return ABORTING_ISSUE_CODES.map((code) => `${codeExpr}===${JSON.stringify(code)}`).join(\"||\");\n}\n\n/**\n * Port of zod's `util.aborted(payload, startIndex)`: has anything since\n * `startIndex` produced a NON-continuable issue?\n *\n * zod gates a schema's check chain on this (`runChecks`: `else if (isAborted)\n * continue`), which is what makes a container's `.refine()` still run after a\n * property or element failed its own `min`/`max`/format check, and stop running\n * once one failed to parse at all. The `startIndex` is the issue count when the\n * node was entered, mirroring the fresh payload zod hands each sub-schema.\n *\n * Size/length checks are exempt in zod — they declare a `when` predicate, which\n * bypasses the abort gate — so generated code leaves those ungated and only\n * wraps the refine/superRefine effects.\n */\nexport const ZC_AB_DECL = `function __zcAb(e,i){for(;i<e.length;i++){var s=e[i];if(s.continue===false)return true;var c=s.code;if(${abortingCodeTest(\"c\")})return true;}return false;}`;\n\n/**\n * Port of zod's `util.finalizeIssue` for issues NESTED inside an\n * `invalid_key` / `invalid_element` wrapper. Those never reach the top-level\n * finalization loop (which walks only the outer array), so zod finalizes them\n * where it builds the wrapper: locale message applied when none was baked in,\n * `input` cleared. Their `path` stays RELATIVE to the key or value schema — zod\n * ran it on a fresh payload — so nothing rewrites it.\n *\n * `input` is `delete`d rather than assigned `undefined`, matching zod's own\n * `delete full.input` and the top-level finalizer: the key's PRESENCE is\n * observable (`\"input\" in issue`, `Object.keys`, spread, a strict deep-equal\n * against a zod issue), so assigning left a nested issue one key wider than\n * zod's. Only reached while an error is being built — never on a successful\n * parse — so the dictionary-mode transition it costs is confined to the path\n * that then constructs a ZodError anyway.\n */\nexport const ZC_FZ_DECL =\n \"function __zcFz(e){for(var i=0;i<e.length;i++){var s=e[i];\" +\n 'if(s.message===undefined&&typeof __zcMsg===\"function\")s.message=__zcMsg(s);' +\n \"delete s.input;delete s.continue;}return e;}\";\n\n/**\n * Port of zod's `util.prefixIssues(key, issues)` for a map entry whose key is a\n * property-key type: each issue's RELATIVE path is spliced onto the map's own\n * path plus the key, and the issue moves into the parent's array.\n *\n * `b.concat(k,x.path)` flattens `x.path` one level, giving exactly\n * `[...base, key, ...relative]`.\n */\nexport const ZC_PFX_DECL =\n \"function __zcPfx(d,s,b,k){for(var i=0;i<s.length;i++){var x=s[i];x.path=b.concat(k,x.path);d.push(x);}}\";\n\n/** Does `keyExpr` hold one of zod's `util.propertyKeyTypes` (string|number|symbol)? */\nexport function propertyKeyTest(keyExpr: string): string {\n return `typeof ${keyExpr}===\"string\"||typeof ${keyExpr}===\"number\"||typeof ${keyExpr}===\"symbol\"`;\n}\n\n/**\n * superRefine fast-check: run the payload callback on a throwaway payload and\n * report whether it both added nothing AND left the value alone. zod's own\n * wrapper (the referenced function) installs `addIssue` and normalizes what the\n * user adds, so the verdict is zod's; the issues themselves are re-collected by\n * the slow walk.\n *\n * The `p.value===v` half is what lets a superRefine node keep a fast path at\n * all. `value` is writable public API ($RefinementCtx extends ParsePayload), so\n * a callback may rewrite it, and the fast path's caller returns the ORIGINAL\n * input on success — which would then be stale. Reporting false when the value\n * moved routes those parses into the slow walk, which propagates the new value\n * (see ZC_SR_DECL). Callbacks that only validate — effectively all of them —\n * still take the fast exit.\n */\nexport const ZC_SR_OK_DECL =\n \"function __zcSrOk(f,v){var p={value:v,issues:[]};__zcSrRun(f,p);\" +\n \"return p.issues.length===0&&p.value===v;}\";\n\n/**\n * Module-local (never imported by generated code) — __zcSr/__zcSrOk call it.\n * Lean mode declares it in the runtime module beside them; inline mode pushes it\n * into the preamble alongside whichever of the two is used.\n *\n * Invoke the referenced wrapper, reproducing zod's synchronous-parse contract:\n * a callback that returns a promise makes zod raise $ZodAsyncError rather than\n * silently accepting. Because the ref points at zod's superRefine WRAPPER, not\n * the user's function, an async callback cannot be detected while extracting —\n * the returned thenable is the only evidence, so the test lives here. Sync\n * callbacks return undefined, so the guard short-circuits on the first operand.\n */\nexport const ZC_SR_RUN_DECL =\n \"function __zcSrRun(f,p){var r=f(p);\" +\n 'if(r&&typeof r.then===\"function\"){throw new __zcCore.$ZodAsyncError();}}';\n\n/**\n * z.custom()/z.instanceof() fast verdict. Zod treats truthy predicate returns\n * as success and raises $ZodAsyncError when a synchronous parse encounters a\n * thenable, including a non-async function that happens to return a Promise.\n */\nexport const ZC_CUSTOM_OK_DECL =\n \"function __zcCu(f,v){var r=f(v);\" +\n 'if(r&&typeof r.then===\"function\"){throw new __zcCore.$ZodAsyncError();}return !!r;}';\n\n/**\n * Raise zod's synchronous-parse error. A user callback that hands back a\n * Promise — a `.refine()` predicate, a `.transform()`, a `z.preprocess()` —\n * makes zod's sync `safeParse` throw `$ZodAsyncError` rather than treat the\n * Promise as a value (a truthy one, for a predicate, which would ACCEPT the\n * input). The callback's source cannot tell: only an `async` function is\n * detectable at extraction time (those are delegated), and a plain function\n * that returns a Promise looks like any other. So the test is on the returned\n * value, at every call site that consumes one, with zod's own\n * `instanceof Promise` — a non-Promise thenable is a plain value to zod too.\n *\n * Hosted rather than inlined so the throw stays out of the hot path's inlining\n * budget: call sites test `x instanceof Promise` themselves and branch here\n * only in the exotic case. The compiled `parseAsync`/`safeParseAsync` wrappers\n * catch this and re-run through zod's async pipeline (see MK_VALIDATOR_DECL),\n * so an async-capable caller still gets zod's answer.\n *\n * `.catch()`, `.default()` and `.overwrite()` callbacks are deliberately NOT\n * guarded: zod substitutes whatever they return, Promise included.\n */\nexport const ZC_ASYNC_DECL = \"function __zcAsy(){throw new __zcCore.$ZodAsyncError();}\";\n\n/**\n * Run a retained zod schema for a delegated sub-schema and return its RAW\n * payload — `_zod.run` on a fresh `{value, issues: []}`, the exact call zod's\n * own `safeParse` makes — rather than the finalized `SafeParseResult`.\n *\n * The raw payload is the only place zod's abort state survives.\n * `finalizeIssue` deletes `continue` from every issue and `safeParse` builds\n * its ZodError from the finalized copies, so a delegate that went through\n * `safeParse` could not tell a `z.custom()` failure (`continue: false` — zod\n * defaults `z.custom()` to `abort: true`) from a `.refine()` one\n * (`continue: true`). A plain union prunes its options on that flag\n * (`util.aborted`): with it lost, an option failing through a delegated\n * aborting check was surfaced as the sole non-aborted option instead of inside\n * `invalid_union`. Reading the payload keeps the flag until __zcRf copies it\n * onto the finalized issue, where the union's pruning loop reads it and the\n * top-level finalizer then deletes it, as zod's does.\n *\n * `_zod.run` is also immune to the aliasing hazard `__rfp_N` guards against:\n * `__zcMkv` installs the compiled methods as own `parse`/`safeParse` slots and\n * never touches `_zod`, so a retained entry that IS the compiled schema still\n * runs zod's implementation here. A Promise result is zod's `$ZodAsyncError`,\n * as in `_safeParse`.\n */\nexport const ZC_RUN_DELEGATE_DECL =\n \"function __zcRd(z,v,c){var r=z.run({value:v,issues:[]},c);\" +\n \"if(r instanceof Promise)throw new __zcCore.$ZodAsyncError();return r;}\";\n\n/**\n * Finalize a delegate's raw issues onto the validator's list. Each goes\n * through zod's own `util.finalizeIssue` — the check's and schema's error\n * maps, the per-call ctx, `customError`, the locale, then \"Invalid input\", with\n * `inst` and `input` stripped — which is the very function `safeParse` maps\n * every issue through, so the messages are zod's byte for byte. The node's\n * path is prefixed onto the issue's relative one as zod's `prefixIssues`\n * would, and the abort marker is re-applied: an issue whose raw `continue` was\n * not `true` aborted in zod's sense (`util.aborted`), which the union pruning\n * loop reads as `continue:false` before the top-level finalizer deletes the\n * key again (see ZC_RUN_DELEGATE_DECL).\n */\nexport const ZC_DELEGATE_ISSUES_DECL =\n \"function __zcRf(s,c,e,p){var g=__zcCore.config();for(var i=0;i<s.length;i++){\" +\n \"var q=s[i],f=__zcCore.util.finalizeIssue(q,c,g);f.path=p.concat(f.path);\" +\n \"if(q.continue!==true)f.continue=false;e.push(f);}}\";\n\n/**\n * superRefine slow-path merge: run the callback, then move its issues onto the\n * validator's list the way zod's finalizeIssue does — the node's path prefixed\n * onto any path the user supplied, the internal `inst`/`continue` fields\n * dropped (they are zod bookkeeping, deleted before the issue is user-visible),\n * and the owning schema's static message `m` applied to an issue that carries\n * none of its own, since zod stamps the owner onto every issue a check raises.\n *\n * Returns the payload, so the caller can write `.value` back (the callback may\n * have rewritten it) and read `.aborted`. Aborted is set when any issue aborts\n * in zod's sense (`continue !== true`, which covers `fatal: true` and the string\n * shorthand, whose issue carries no `continue` at all) — or when the callback\n * set it directly, also public payload API. A union option at whose root the\n * superRefine sits reads the flag to mark itself aborted, matching how zod\n * prunes option errors. The aborting issue ALSO keeps a `continue:false`\n * marker of its own, because zod's `util.aborted` reads the flag off the\n * issues and those travel up through containers where the payload flag does\n * not: a fatal superRefine on an object's property aborts the union option\n * holding the object. The top-level finalizer deletes the marker, as zod's\n * `finalizeIssue` does, so no user-visible issue carries it.\n */\nexport const ZC_SR_DECL =\n \"function __zcSr(f,v,p,e,m){var q={value:v,issues:[]};__zcSrRun(f,q);\" +\n \"for(var i=0;i<q.issues.length;i++){var s=q.issues[i],t={};\" +\n 'for(var k in s){if(k!==\"inst\"&&k!==\"continue\")t[k]=s[k];}' +\n \"if(s.continue!==true){q.aborted=true;t.continue=false;}\" +\n \"t.path=s.path&&s.path.length?p.concat(s.path):p;\" +\n \"if(t.message===undefined&&m!==undefined)t.message=m;e.push(t);}return q;}\";\n\n/** Non-issue runtime helper declarations hosted in the virtual module. */\nexport const RUNTIME_HELPER_DECLS: Readonly<Record<string, string>> = {\n __zcAb: ZC_AB_DECL,\n __zcFsr: ZC_FSR_DECL,\n __zcFz: ZC_FZ_DECL,\n __zcHop: ZC_HOP_DECL,\n __zcLo: ZC_LENGTH_ORIGIN_DECL,\n __zcSo: ZC_SIZE_ORIGIN_DECL,\n __zcCpl: ZC_CPL_DECL,\n __zcEmail: ZC_EMAIL_DECL,\n __zcPs: ZC_PROTO_SCRUB_DECL,\n __zcPlain: ZC_PLAIN_DECL,\n __zcPfx: ZC_PFX_DECL,\n __zcCu: ZC_CUSTOM_OK_DECL,\n __zcSr: ZC_SR_DECL,\n __zcSrOk: ZC_SR_OK_DECL,\n __zcAsy: ZC_ASYNC_DECL,\n __zcRd: ZC_RUN_DELEGATE_DECL,\n __zcRf: ZC_DELEGATE_ISSUES_DECL,\n};\n"],"mappings":";AAkGA,MAAa,cAAgD;CAC3D,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;AACV;;;;;;;;;;;;;AAcA,MAAa,cACX;;;;;;;;;;AAaF,MAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwC3B,MAAa,gBACX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCF,MAAa,gBACX;;;;;;;;;;;;;;;;;;AAiCF,MAAa,wBACX;;;;;;;;;;;;;;;;;AAkBF,MAAa,sBACX;;;;;;;;AAUF,MAAa,cACX;AAEF,MAAa,sBACX;;;;;;;;;;;;;;;;;;;AAqBF,MAAM,uBAA0C;CAC9C;CACA;CACA;CACA;CACA;AACF;;AAGA,SAAgB,iBAAiB,UAA0B;CACzD,OAAO,qBAAqB,KAAK,SAAS,GAAG,SAAS,KAAK,KAAK,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI;AAC9F;;;;;;;;;;;;;;;AAgBA,MAAa,aAAa,0GAA0G,iBAAiB,GAAG,EAAE;;;;;;;;;;;;;;;;;AAkB1J,MAAa,aACX;;;;;;;;;AAYF,MAAa,cACX;;AAGF,SAAgB,gBAAgB,SAAyB;CACvD,OAAO,UAAU,QAAQ,sBAAsB,QAAQ,sBAAsB,QAAQ;AACvF;;;;;;;;;;;;;;;;AAiBA,MAAa,gBACX;;;;;;;;;;;;;AAeF,MAAa,iBACX;;;;;;AAQF,MAAa,oBACX;;;;;;;;;;;;;;;;;;;;;AAuBF,MAAa,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;AAyB7B,MAAa,uBACX;;;;;;;;;;;;;AAeF,MAAa,0BACX;;;;;;;;;;;;;;;;;;;;;;AAyBF,MAAa,aACX;;AAQF,MAAa,uBAAyD;CACpE,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,WAAW;CACX,QAAQ;CACR,WAAW;CACX,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,SAAS;CACT,QAAQ;CACR,QAAQ;AACV"}
|
|
1
|
+
{"version":3,"file":"issue-decls.js","names":[],"sources":["../../../src/core/codegen/issue-decls.ts"],"sourcesContent":["/**\n * Issue factory function bodies (statement form).\n *\n * These functions produce the same `{code, ...}` shapes that lean-mode\n * generated code would otherwise inline at every check site.\n * Hosted in \"virtual:zod-compiler/runtime\" and called as `__zcTS(...)` etc.\n *\n * Argument convention (positional, kept short to minimize call-site bytes):\n * __zcTS(minimum, origin, inclusive, input, path, msg?) — too_small\n * __zcTSt(minimum, origin, input, path, msg?) — too_small, tuple key order\n * __zcTBt(maximum, origin, input, path, msg?) — too_big, tuple key order\n * __zcTB(maximum, origin, inclusive, input, path, msg?) — too_big\n * __zcIT(expected, input, path, msg?) — invalid_type\n * __zcITc(expected, input, path, msg?) — invalid_type, `code` first\n * __zcIF(origin, format, input, path, extra?, msg?) — invalid_format (extra merged into result)\n * __zcIV(values, input, path, extra?, msg?) — invalid_value (extra merged into result)\n * __zcUK(keys, input, path, msg?) — unrecognized_keys\n *\n * The trailing msg argument carries a static custom error message; when\n * absent, the __zcFin finalizer applies the configured locale default.\n *\n * KEY ORDER IS PART OF THE CONTRACT. `ZodError.message` is\n * `JSON.stringify(issues, …, 2)`, so the order these factories insert keys in is\n * printed verbatim in the message every consumer logs, snapshots or serializes.\n * Each literal below therefore reproduces the order of the corresponding\n * `payload.issues.push({…})` in zod, which is irregular by type — `too_small`\n * from a check leads with `origin` while the same code from a tuple's length\n * branch leads with `code` — and every factory writes `message` LAST, because\n * zod's `finalizeIssue` assigns it after the fact (`full.message = …`) even for\n * a custom message baked into the check's error map.\n */\n\nconst ZC_TS_DECL =\n 'function __zcTS(m,o,i,inp,p,msg){var r={origin:o,code:\"too_small\",minimum:m,inclusive:i,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * too_small in the TUPLE under-length key order. $ZodTuple pushes\n * `{ code, minimum, inclusive: true, input, inst, origin }`, so its `origin`\n * trails `inclusive` where every check-created size issue leads with it. Its\n * over-length sibling is __zcTBt.\n */\nconst ZC_TS_TUPLE_DECL =\n 'function __zcTSt(m,o,inp,p,msg){var r={code:\"too_small\",minimum:m,inclusive:true,origin:o,input:inp,path:p,continue:false};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TS_EXACT_DECL =\n 'function __zcTSx(m,o,inp,p,msg){var r={origin:o,code:\"too_small\",minimum:m,inclusive:true,exact:true,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TB_DECL =\n 'function __zcTB(m,o,i,inp,p,msg){var r={origin:o,code:\"too_big\",maximum:m,inclusive:i,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * too_big in the TUPLE over-length key order. $ZodTuple spreads\n * `{ code, maximum, inclusive }` and appends `origin` after `input`/`inst`, so\n * its `origin` trails `inclusive` where every check-created size issue leads\n * with it. Its under-length sibling is __zcTSt.\n */\nconst ZC_TB_TUPLE_DECL =\n 'function __zcTBt(m,o,inp,p,msg){var r={code:\"too_big\",maximum:m,inclusive:true,origin:o,input:inp,path:p,continue:false};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_TB_EXACT_DECL =\n 'function __zcTBx(m,o,inp,p,msg){var r={origin:o,code:\"too_big\",maximum:m,inclusive:true,exact:true,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_IT_DECL =\n 'function __zcIT(e,inp,p,msg){var r={expected:e,code:\"invalid_type\",input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * invalid_type with `code` ahead of `expected`. Every schema in zod spells this\n * issue `{ expected, code }` — except `$ZodDiscriminatedUnion`, whose\n * non-object guard writes `{ code, expected }`. One literal, one key order, and\n * it shows up in `ZodError.message`.\n */\nconst ZC_IT_CODE_FIRST_DECL =\n 'function __zcITc(e,inp,p,msg){var r={code:\"invalid_type\",expected:e,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * `o` is the leading `origin`, present only for the formats whose issue carries\n * one: `$ZodCheckStringFormat`'s default pattern check and the regex /\n * includes / starts_with / ends_with checks all lead with `origin: \"string\"`,\n * while `z.url()`'s own pushes and every `$ZodCustomStringFormat` omit it\n * entirely. `extra` holds the per-format tail (`pattern`, `includes`, `prefix`,\n * `suffix`, `note`) and is merged BEFORE input/path so it lands where zod\n * writes it.\n */\nconst ZC_IF_DECL =\n 'function __zcIF(o,f,inp,p,extra,msg){var r=o===undefined?{code:\"invalid_format\",format:f}:{origin:o,code:\"invalid_format\",format:f};if(extra)Object.assign(r,extra);r.input=inp;r.path=p;if(msg!==undefined)r.message=msg;return r;}';\n\n/**\n * `extra` carries the per-producer fields: enum and literal push `values` only,\n * while z.stringbool()'s codec transform also pushes `expected: \"stringbool\"`.\n * Merged the same way __zcIF merges its own.\n */\nconst ZC_IV_DECL =\n 'function __zcIV(values,inp,p,extra,msg){var r={code:\"invalid_value\"};if(extra)Object.assign(r,extra);r.values=values;r.input=inp;r.path=p;if(msg!==undefined)r.message=msg;return r;}';\n\nconst ZC_UK_DECL =\n 'function __zcUK(k,inp,p,msg){var r={code:\"unrecognized_keys\",keys:k,input:inp,path:p};if(msg!==undefined)r.message=msg;return r;}';\n\n/** All issue factory declarations indexed by helper name. */\nexport const ISSUE_DECLS: Readonly<Record<string, string>> = {\n __zcTS: ZC_TS_DECL,\n __zcTSt: ZC_TS_TUPLE_DECL,\n __zcTSx: ZC_TS_EXACT_DECL,\n __zcTB: ZC_TB_DECL,\n __zcTBt: ZC_TB_TUPLE_DECL,\n __zcTBx: ZC_TB_EXACT_DECL,\n __zcIT: ZC_IT_DECL,\n __zcITc: ZC_IT_CODE_FIRST_DECL,\n __zcIF: ZC_IF_DECL,\n __zcIV: ZC_IV_DECL,\n __zcUK: ZC_UK_DECL,\n};\n\n/**\n * Float-safe remainder — byte-for-byte port of zod's util.floatSafeRemainder.\n * Raw `%` mis-rejects valid multiples of decimal steps (0.3 % 0.1 !== 0).\n *\n * zod 4.5 REPLACED the decimal-scaling implementation this once mirrored with a\n * ratio-and-tolerance one, and the two disagree in both directions: the old form\n * accepted `1e-7` as a multiple of 3 (its `toFixed` scaling collapsed the value\n * to 0) and rejected `1e21` (where `toFixed` yields exponential notation and\n * `parseInt` then reads 1). The tolerance is 4x epsilon because `val` and `step`\n * each round to a double before the division rounds again, so a true decimal\n * multiple's quotient can sit up to 1.5 scaled epsilons from the integer.\n */\nexport const ZC_FSR_DECL =\n \"function __zcFsr(v,s){var r=v/s;var q=Math.round(r);\" +\n \"var t=4*Number.EPSILON*Math.max(Math.abs(r),1);\" +\n \"return Math.abs(r-q)<t?0:r-q;}\";\n\n/**\n * Hoisted `Object.prototype.hasOwnProperty` reference. Record fast/slow paths\n * iterate keys with `for(k in o)` (no `Object.keys` array allocation) and guard\n * each key with `__zcHop.call(o,k)` to skip inherited enumerable properties —\n * yielding the exact own-enumerable string-key set `Object.keys` would, so\n * fast/slow stay in agreement and parity with zod's own-key record semantics is\n * preserved. The hoisted reference inlines in V8; reading the prototype property\n * per call would not.\n */\nexport const ZC_HOP_DECL = \"const __zcHop=Object.prototype.hasOwnProperty;\";\n\n/**\n * Port of zod's `util.isPlainObject` — the guard `$ZodRecord` applies to its\n * input, and a STRICTLY narrower test than the `util.isObject` (`typeof\n * \"object\"`, not null, not an array) that `$ZodObject` uses.\n *\n * The distinction is load-bearing and was a validation hole while records shared\n * the object guard: `z.record(z.string(), z.string())` accepted a `Date`, a\n * `Map`, a `RegExp`, an `Error`, a `File` and any class instance — every one of\n * which zod rejects with `invalid_type`/`expected: \"record\"`, and none of which\n * has own enumerable string keys for the value schema to catch. Compiled output\n * therefore said \"valid\" to inputs zod refuses, which is the one direction a\n * validator must never diverge in.\n *\n * The algorithm is zod's, step for step, because the answer is observable and\n * the edge cases are deliberate:\n * - `constructor === undefined` (a null-prototype object) is PLAIN;\n * - a non-function own `constructor` (`{ constructor: 1 }`) is PLAIN;\n * - otherwise the constructor's `prototype` must be an object carrying its OWN\n * `isPrototypeOf` — which `Object.prototype` does and `Date.prototype`,\n * `Map.prototype` and every user class prototype do not. Testing that rather\n * than `Object.getPrototypeOf(o) === Object.prototype` is what lets a plain\n * object from another realm (a vm context, an iframe) still count as plain.\n *\n * `c===Object` is a short-cut, not a fourth rule: it is exactly the case where\n * zod's remaining steps are foregone — `Object.prototype` is an object and has\n * its own `isPrototypeOf` — so the answer is `true` either way. It is also the\n * case every ordinary record takes (an object literal, `JSON.parse` output, a\n * `Map`-free DTO), and taking it saves the `prototype` load and the\n * `hasOwnProperty` call: measured 9.6 → 5.7 ns on a monomorphic record and\n * 15.7 → 9.2 ns across 16 shapes, i.e. 22% of a five-key record's whole parse.\n * A plain object from another realm has a different `Object` and simply takes\n * the long road to the same verdict, as before.\n *\n * Self-contained (`Object.prototype.hasOwnProperty` spelled out rather than\n * reusing `__zcHop`) so inline mode can emit this decl alone: `emitRuntimeHelper`\n * pushes only the decl it is asked for, and a helper that closed over another\n * name would dangle wherever that one was not also emitted.\n */\nexport const ZC_PLAIN_DECL =\n 'function __zcPlain(o){if(typeof o!==\"object\"||o===null||Array.isArray(o))return false;' +\n 'var c=o.constructor;if(c===Object||c===undefined||typeof c!==\"function\")return true;' +\n 'var p=c.prototype;if(typeof p!==\"object\"||p===null||Array.isArray(p))return false;' +\n 'return Object.prototype.hasOwnProperty.call(p,\"isPrototypeOf\");}';\n\n/**\n * `z.email()`'s default validator, `regexes.email`, as a single linear scan.\n *\n * Zod's pattern is\n * `^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$`,\n * and even its lookahead-free rewrite (EMAIL_FAST_REGEX_SOURCE) backtracks at\n * every dot it fails to find: `(?:[X]+\\.)*` re-tries the run one character\n * shorter each time, and the domain's `(?:label\\.)+` does the same over the\n * TLD. Written as a scanner the language is:\n *\n * local — `[A-Za-z0-9_'+.-]+`, no leading `.`, no `..`, and the character\n * before `@` is neither `.` nor `'` (that last is the `[A-Za-z0-9_+-]`\n * the pattern demands there);\n * domain — one or more labels `[A-Za-z0-9][A-Za-z0-9-]*` each ending in `.`,\n * then a TLD of two or more letters running to the end.\n *\n * A trailing `\\n` is not accepted: the pattern has no `m` flag, so its `$`\n * matches only at the end of input, and the scan reads to `length`.\n *\n * Measured against the fast regex on V8: 32 → 16 ns for `alice@example.com`,\n * 48 → 40 for `bob_smith-99@mail-server.io`, 39 → 20 for a non-address, and a\n * tie from ~35 characters up (the regex's per-character work is cheaper than a\n * `charCodeAt` loop's; its fixed dispatch cost is what the scanner avoids). A\n * lookbehind rewrite runs about as fast but needs ES2018 regex support, which\n * the CLI's React Native / Hermes and older-Safari consumers cannot assume.\n *\n * Equivalence to zod's regex — every string, both verdicts — is pinned by\n * tests/core/codegen/email-scanner.test.ts. Reached only behind a `typeof`\n * string guard, like the `.test()` it replaces; issue sites keep reporting\n * zod's own pattern string (see `emitRegexSourceString`).\n */\nexport const ZC_EMAIL_DECL =\n \"function __zcEmail(s){var n=s.length,i=0,c,p=46;\" +\n // Local part. `p` starts as `.` so a leading dot trips the `..` rule.\n \"for(;;){if(i===n)return false;c=s.charCodeAt(i);if(c===64)break;\" +\n \"if(c===46){if(p===46)return false;}\" +\n \"else if(!((c>=97&&c<=122)||(c>=65&&c<=90)||(c>=48&&c<=57)||c===95||c===39||c===43||c===45))return false;\" +\n \"p=c;i++;}\" +\n \"if(p===46||p===39)return false;\" +\n // Domain. `l` is the current label's start, `t` whether it is letters-only.\n \"var l=++i,d=0,t=true;\" +\n \"for(;i<n;i++){c=s.charCodeAt(i);\" +\n \"if((c>=97&&c<=122)||(c>=65&&c<=90))continue;\" +\n \"if(c===46){if(i===l)return false;d++;l=i+1;t=true;continue;}\" +\n \"if((c>=48&&c<=57)||c===45){if(c===45&&i===l)return false;t=false;continue;}\" +\n \"return false;}\" +\n \"return d>0&&t&&n-l>=2;}\";\n\n/**\n * Does `s` parse as a URL? The verdict `new URL(s)` gives by not throwing,\n * without building the URL object: `URL.canParse` runs the same parser at half\n * the cost (~80 ns against ~160 ns on V8, trim included). Used only where\n * nothing reads the parsed URL — no hostname or protocol test, no `normalize`.\n * A host without `canParse` (Node before 18.17, older browsers, React Native's\n * polyfill) falls back to the constructor, and one without `URL` at all answers\n * false, as the try/catch zod wraps around that constructor does.\n */\nexport const ZC_URL_DECL =\n 'function __zcUrl(s){if(typeof URL===\"function\"&&typeof URL.canParse===\"function\")return URL.canParse(s);' +\n \"try{new URL(s);return true;}catch(_){return false;}}\";\n\n/**\n * Ports of `util.getLengthableOrigin` / `util.getSizableOrigin` — the `origin` a\n * length/size check puts on its issue, computed from the RUNTIME INPUT rather\n * than from the schema.\n *\n * They only matter because those checks declare a `when` predicate\n * (`!nullish(value) && value.length/size !== undefined`), which bypasses zod's\n * abort gate: `z.string().min(2)` handed `[]` reports the `invalid_type` AND a\n * `too_small` whose origin is `\"array\"`, because the empty array satisfies the\n * `when`. Inside the matching type branch the origin is statically known and\n * these are not used; they exist for the type-MISMATCH branch, where the input\n * can be anything with a `.length` or a `.size`.\n *\n * `File` is probed through `typeof` first: zod tests `input instanceof File`\n * unguarded, which throws where the global is absent — an environment zod does\n * not run in, and not one worth reproducing a crash for.\n */\nexport const ZC_LENGTH_ORIGIN_DECL =\n 'function __zcLo(v){return Array.isArray(v)?\"array\":typeof v===\"string\"?\"string\":\"unknown\";}';\n\n/**\n * Drop an own `__proto__` from a container the parse hands back BY REFERENCE.\n *\n * zod never lets the key into an output: `$ZodObject`'s shape loop strips a\n * declared one, `handleCatchall` skips an undeclared one, and `$ZodRecord` skips\n * it while copying — all so the assignment into their fresh `{}` cannot replace\n * the result's prototype. A compiled loose/catchall object or record IS its\n * input, so the key has to be removed here instead; leaving it made\n * `Object.assign({}, parsed)` a prototype-pollution sink, since [[Set]] runs the\n * inherited setter the spread that built the value did not.\n *\n * Copies rather than editing in place: the divergence note promises the caller\n * its own container back, not one with a key silently deleted from it. The\n * common object has no such key and is returned untouched, so the cost is one\n * `hasOwnProperty` call.\n */\nexport const ZC_PROTO_SCRUB_DECL =\n 'function __zcPs(o){if(!Object.prototype.hasOwnProperty.call(o,\"__proto__\"))return o;' +\n 'var c={...o};delete c[\"__proto__\"];return c;}';\n\n/**\n * Code points in a string — zod's `util.codePointLength`, verbatim. A surrogate\n * pair counts once and a lone surrogate as itself. The regex probe is the fast\n * exit for a string with no astral characters, and the hand-rolled loop avoids\n * the allocating string iterator. Only reached from a length check whose\n * UTF-16 count leaves the verdict in doubt (see stringLengthTests).\n */\nexport const ZC_CPL_DECL =\n \"function __zcCpl(s){var n=s.length;if(!/[\\\\uD800-\\\\uDBFF]/.test(s))return n;var c=n;for(var i=0;i<n-1;i++){if((s.charCodeAt(i)&0xfc00)===0xd800&&(s.charCodeAt(i+1)&0xfc00)===0xdc00){c--;i++;}}return c;}\";\n\nexport const ZC_SIZE_ORIGIN_DECL =\n 'function __zcSo(v){return v instanceof Set?\"set\":v instanceof Map?\"map\":' +\n '(typeof File!==\"undefined\"&&v instanceof File)?\"file\":\"unknown\";}';\n\n/**\n * Issue codes zod raises from a schema's `_zod.parse` rather than from a check,\n * and which therefore carry `continue !== true` — what `util.aborted` looks for.\n *\n * Everything a CHECK produces (`too_small`, `too_big`, `invalid_format`,\n * `not_multiple_of`, a refine's `custom`) is continuable, because `$ZodCheck`\n * sets `continue: !def.abort` and an `abort: true` check costs the schema its\n * compiled path anyway — so classifying by code alone is exact for generated\n * issues.\n *\n * `unrecognized_keys` is the one parse-level issue zod pushes WITH\n * `continue: true`: it describes the shape of the input rather than the\n * validity of the parsed value, so the parse still fails but the object's own\n * refines run first and a union does not count the option as aborted.\n *\n * Read by {@link ZC_AB_DECL} and by the union's option-pruning loop, which\n * applies the same rule inline over a per-option issue array.\n */\nconst ABORTING_ISSUE_CODES: readonly string[] = [\n \"invalid_type\",\n \"invalid_value\",\n \"invalid_union\",\n \"invalid_key\",\n \"invalid_element\",\n];\n\n/** `c===\"invalid_type\"||c===\"invalid_value\"||…` over the code held in `codeExpr`. */\nexport function abortingCodeTest(codeExpr: string): string {\n return ABORTING_ISSUE_CODES.map((code) => `${codeExpr}===${JSON.stringify(code)}`).join(\"||\");\n}\n\n/**\n * Port of zod's `util.aborted(payload, startIndex)`: has anything since\n * `startIndex` produced a NON-continuable issue?\n *\n * zod gates a schema's check chain on this (`runChecks`: `else if (isAborted)\n * continue`), which is what makes a container's `.refine()` still run after a\n * property or element failed its own `min`/`max`/format check, and stop running\n * once one failed to parse at all. The `startIndex` is the issue count when the\n * node was entered, mirroring the fresh payload zod hands each sub-schema.\n *\n * Size/length checks are exempt in zod — they declare a `when` predicate, which\n * bypasses the abort gate — so generated code leaves those ungated and only\n * wraps the refine/superRefine effects.\n */\nexport const ZC_AB_DECL = `function __zcAb(e,i){for(;i<e.length;i++){var s=e[i];if(s.continue===false)return true;var c=s.code;if(${abortingCodeTest(\"c\")})return true;}return false;}`;\n\n/**\n * Port of zod's `util.finalizeIssue` for issues NESTED inside an\n * `invalid_key` / `invalid_element` wrapper. Those never reach the top-level\n * finalization loop (which walks only the outer array), so zod finalizes them\n * where it builds the wrapper: locale message applied when none was baked in,\n * `input` cleared. Their `path` stays RELATIVE to the key or value schema — zod\n * ran it on a fresh payload — so nothing rewrites it.\n *\n * `input` is `delete`d rather than assigned `undefined`, matching zod's own\n * `delete full.input` and the top-level finalizer: the key's PRESENCE is\n * observable (`\"input\" in issue`, `Object.keys`, spread, a strict deep-equal\n * against a zod issue), so assigning left a nested issue one key wider than\n * zod's. Only reached while an error is being built — never on a successful\n * parse — so the dictionary-mode transition it costs is confined to the path\n * that then constructs a ZodError anyway.\n */\nexport const ZC_FZ_DECL =\n \"function __zcFz(e){for(var i=0;i<e.length;i++){var s=e[i];\" +\n 'if(s.message===undefined&&typeof __zcMsg===\"function\")s.message=__zcMsg(s);' +\n \"delete s.input;delete s.continue;}return e;}\";\n\n/**\n * Port of zod's `util.prefixIssues(key, issues)` for a map entry whose key is a\n * property-key type: each issue's RELATIVE path is spliced onto the map's own\n * path plus the key, and the issue moves into the parent's array.\n *\n * `b.concat(k,x.path)` flattens `x.path` one level, giving exactly\n * `[...base, key, ...relative]`.\n */\nexport const ZC_PFX_DECL =\n \"function __zcPfx(d,s,b,k){for(var i=0;i<s.length;i++){var x=s[i];x.path=b.concat(k,x.path);d.push(x);}}\";\n\n/**\n * `[...p, k]`: a path with one segment appended, as a fresh array.\n *\n * `extendPath` splices a segment into a path that is still an array literal,\n * but a shared walk receives its path as a parameter, opaque at build time, so\n * there the segment is appended at run time. A nested shared walk's call site\n * evaluates that append up front — on a valid parse too, once per property and\n * per array element, whenever the schema runs its walk eagerly because it has\n * no build path (a `z.url()`, a `.catch()`, a `superRefine()`).\n *\n * `Array.prototype.concat`, which this replaces, is a C++ builtin in V8: ~70 ns\n * a call against ~7 ns for the copy below. On the eager walk of a 14-property\n * product schema calling six shared sub-walks, a valid parse went from 713 to\n * 299 ns and an `.error` read from 2.05 to 1.44 µs. The preallocated copy also\n * beat `slice()` + `push` (391 ns), a `push` loop (338 ns) and spread (361 ns).\n */\nexport const ZC_PATH_APPEND_DECL =\n \"function __zcPa(p,k){var n=p.length,r=new Array(n+1);for(var i=0;i<n;i++)r[i]=p[i];r[n]=k;return r;}\";\n\n/** Does `keyExpr` hold one of zod's `util.propertyKeyTypes` (string|number|symbol)? */\nexport function propertyKeyTest(keyExpr: string): string {\n return `typeof ${keyExpr}===\"string\"||typeof ${keyExpr}===\"number\"||typeof ${keyExpr}===\"symbol\"`;\n}\n\n/**\n * superRefine fast-check: run the payload callback on a throwaway payload and\n * report whether it both added nothing AND left the value alone. zod's own\n * wrapper (the referenced function) installs `addIssue` and normalizes what the\n * user adds, so the verdict is zod's; the issues themselves are re-collected by\n * the slow walk.\n *\n * The `p.value===v` half is what lets a superRefine node keep a fast path at\n * all. `value` is writable public API ($RefinementCtx extends ParsePayload), so\n * a callback may rewrite it, and the fast path's caller returns the ORIGINAL\n * input on success — which would then be stale. Reporting false when the value\n * moved routes those parses into the slow walk, which propagates the new value\n * (see ZC_SR_DECL). Callbacks that only validate — effectively all of them —\n * still take the fast exit.\n */\nexport const ZC_SR_OK_DECL =\n \"function __zcSrOk(f,v){var p={value:v,issues:[]};__zcSrRun(f,p);\" +\n \"return p.issues.length===0&&p.value===v;}\";\n\n/**\n * Module-local (never imported by generated code) — __zcSr/__zcSrOk call it.\n * Lean mode declares it in the runtime module beside them; inline mode pushes it\n * into the preamble alongside whichever of the two is used.\n *\n * Invoke the referenced wrapper, reproducing zod's synchronous-parse contract:\n * a callback that returns a promise makes zod raise $ZodAsyncError rather than\n * silently accepting. Because the ref points at zod's superRefine WRAPPER, not\n * the user's function, an async callback cannot be detected while extracting —\n * the returned thenable is the only evidence, so the test lives here. Sync\n * callbacks return undefined, so the guard short-circuits on the first operand.\n */\nexport const ZC_SR_RUN_DECL =\n \"function __zcSrRun(f,p){var r=f(p);\" +\n 'if(r&&typeof r.then===\"function\"){throw new __zcCore.$ZodAsyncError();}}';\n\n/**\n * z.custom()/z.instanceof() fast verdict. Zod treats truthy predicate returns\n * as success and raises $ZodAsyncError when a synchronous parse encounters a\n * thenable, including a non-async function that happens to return a Promise.\n */\nexport const ZC_CUSTOM_OK_DECL =\n \"function __zcCu(f,v){var r=f(v);\" +\n 'if(r&&typeof r.then===\"function\"){throw new __zcCore.$ZodAsyncError();}return !!r;}';\n\n/**\n * Raise zod's synchronous-parse error. A user callback that hands back a\n * Promise — a `.refine()` predicate, a `.transform()`, a `z.preprocess()` —\n * makes zod's sync `safeParse` throw `$ZodAsyncError` rather than treat the\n * Promise as a value (a truthy one, for a predicate, which would ACCEPT the\n * input). The callback's source cannot tell: only an `async` function is\n * detectable at extraction time (those are delegated), and a plain function\n * that returns a Promise looks like any other. So the test is on the returned\n * value, at every call site that consumes one, with zod's own\n * `instanceof Promise` — a non-Promise thenable is a plain value to zod too.\n *\n * Hosted rather than inlined so the throw stays out of the hot path's inlining\n * budget: call sites test `x instanceof Promise` themselves and branch here\n * only in the exotic case. The compiled `parseAsync`/`safeParseAsync` wrappers\n * catch this and re-run through zod's async pipeline (see MK_VALIDATOR_DECL),\n * so an async-capable caller still gets zod's answer.\n *\n * `.catch()`, `.default()` and `.overwrite()` callbacks are deliberately NOT\n * guarded: zod substitutes whatever they return, Promise included.\n */\nexport const ZC_ASYNC_DECL = \"function __zcAsy(){throw new __zcCore.$ZodAsyncError();}\";\n\n/**\n * Run a retained zod schema for a delegated sub-schema and return its RAW\n * payload — `_zod.run` on a fresh `{value, issues: []}`, the exact call zod's\n * own `safeParse` makes — rather than the finalized `SafeParseResult`.\n *\n * The raw payload is the only place zod's abort state survives.\n * `finalizeIssue` deletes `continue` from every issue and `safeParse` builds\n * its ZodError from the finalized copies, so a delegate that went through\n * `safeParse` could not tell a `z.custom()` failure (`continue: false` — zod\n * defaults `z.custom()` to `abort: true`) from a `.refine()` one\n * (`continue: true`). A plain union prunes its options on that flag\n * (`util.aborted`): with it lost, an option failing through a delegated\n * aborting check was surfaced as the sole non-aborted option instead of inside\n * `invalid_union`. Reading the payload keeps the flag until __zcRf copies it\n * onto the finalized issue, where the union's pruning loop reads it and the\n * top-level finalizer then deletes it, as zod's does.\n *\n * `_zod.run` is also immune to the aliasing hazard `__rfp_N` guards against:\n * `__zcMkv` installs the compiled methods as own `parse`/`safeParse` slots and\n * never touches `_zod`, so a retained entry that IS the compiled schema still\n * runs zod's implementation here. A Promise result is zod's `$ZodAsyncError`,\n * as in `_safeParse`.\n */\nexport const ZC_RUN_DELEGATE_DECL =\n \"function __zcRd(z,v,c){var r=z.run({value:v,issues:[]},c);\" +\n \"if(r instanceof Promise)throw new __zcCore.$ZodAsyncError();return r;}\";\n\n/**\n * Finalize a delegate's raw issues onto the validator's list. Each goes\n * through zod's own `util.finalizeIssue` — the check's and schema's error\n * maps, the per-call ctx, `customError`, the locale, then \"Invalid input\", with\n * `inst` and `input` stripped — which is the very function `safeParse` maps\n * every issue through, so the messages are zod's byte for byte. The node's\n * path is prefixed onto the issue's relative one as zod's `prefixIssues`\n * would, and the abort marker is re-applied: an issue whose raw `continue` was\n * not `true` aborted in zod's sense (`util.aborted`), which the union pruning\n * loop reads as `continue:false` before the top-level finalizer deletes the\n * key again (see ZC_RUN_DELEGATE_DECL).\n */\nexport const ZC_DELEGATE_ISSUES_DECL =\n \"function __zcRf(s,c,e,p){var g=__zcCore.config();for(var i=0;i<s.length;i++){\" +\n \"var q=s[i],f=__zcCore.util.finalizeIssue(q,c,g);f.path=p.concat(f.path);\" +\n \"if(q.continue!==true)f.continue=false;e.push(f);}}\";\n\n/**\n * superRefine slow-path merge: run the callback, then move its issues onto the\n * validator's list the way zod's finalizeIssue does — the node's path prefixed\n * onto any path the user supplied, the internal `inst`/`continue` fields\n * dropped (they are zod bookkeeping, deleted before the issue is user-visible),\n * and the owning schema's static message `m` applied to an issue that carries\n * none of its own, since zod stamps the owner onto every issue a check raises.\n *\n * Returns the payload, so the caller can write `.value` back (the callback may\n * have rewritten it) and read `.aborted`. Aborted is set when any issue aborts\n * in zod's sense (`continue !== true`, which covers `fatal: true` and the string\n * shorthand, whose issue carries no `continue` at all) — or when the callback\n * set it directly, also public payload API. A union option at whose root the\n * superRefine sits reads the flag to mark itself aborted, matching how zod\n * prunes option errors. The aborting issue ALSO keeps a `continue:false`\n * marker of its own, because zod's `util.aborted` reads the flag off the\n * issues and those travel up through containers where the payload flag does\n * not: a fatal superRefine on an object's property aborts the union option\n * holding the object. The top-level finalizer deletes the marker, as zod's\n * `finalizeIssue` does, so no user-visible issue carries it.\n */\nexport const ZC_SR_DECL =\n \"function __zcSr(f,v,p,e,m){var q={value:v,issues:[]};__zcSrRun(f,q);\" +\n \"for(var i=0;i<q.issues.length;i++){var s=q.issues[i],t={};\" +\n 'for(var k in s){if(k!==\"inst\"&&k!==\"continue\")t[k]=s[k];}' +\n \"if(s.continue!==true){q.aborted=true;t.continue=false;}\" +\n \"t.path=s.path&&s.path.length?p.concat(s.path):p;\" +\n \"if(t.message===undefined&&m!==undefined)t.message=m;e.push(t);}return q;}\";\n\n/** Non-issue runtime helper declarations hosted in the virtual module. */\nexport const RUNTIME_HELPER_DECLS: Readonly<Record<string, string>> = {\n __zcAb: ZC_AB_DECL,\n __zcFsr: ZC_FSR_DECL,\n __zcFz: ZC_FZ_DECL,\n __zcHop: ZC_HOP_DECL,\n __zcLo: ZC_LENGTH_ORIGIN_DECL,\n __zcSo: ZC_SIZE_ORIGIN_DECL,\n __zcCpl: ZC_CPL_DECL,\n __zcEmail: ZC_EMAIL_DECL,\n __zcUrl: ZC_URL_DECL,\n __zcPs: ZC_PROTO_SCRUB_DECL,\n __zcPlain: ZC_PLAIN_DECL,\n __zcPfx: ZC_PFX_DECL,\n __zcPa: ZC_PATH_APPEND_DECL,\n __zcCu: ZC_CUSTOM_OK_DECL,\n __zcSr: ZC_SR_DECL,\n __zcSrOk: ZC_SR_OK_DECL,\n __zcAsy: ZC_ASYNC_DECL,\n __zcRd: ZC_RUN_DELEGATE_DECL,\n __zcRf: ZC_DELEGATE_ISSUES_DECL,\n};\n"],"mappings":";AAkGA,MAAa,cAAgD;CAC3D,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;CACR,SAAS;CACT,SAAS;CACT,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;AACV;;;;;;;;;;;;;AAcA,MAAa,cACX;;;;;;;;;;AAaF,MAAa,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwC3B,MAAa,gBACX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCF,MAAa,gBACX;;;;;;;;;;AAyBF,MAAa,cACX;;;;;;;;;;;;;;;;;;AAoBF,MAAa,wBACX;;;;;;;;;;;;;;;;;AAkBF,MAAa,sBACX;;;;;;;;AAUF,MAAa,cACX;AAEF,MAAa,sBACX;;;;;;;;;;;;;;;;;;;AAqBF,MAAM,uBAA0C;CAC9C;CACA;CACA;CACA;CACA;AACF;;AAGA,SAAgB,iBAAiB,UAA0B;CACzD,OAAO,qBAAqB,KAAK,SAAS,GAAG,SAAS,KAAK,KAAK,UAAU,IAAI,GAAG,CAAC,CAAC,KAAK,IAAI;AAC9F;;;;;;;;;;;;;;;AAgBA,MAAa,aAAa,0GAA0G,iBAAiB,GAAG,EAAE;;;;;;;;;;;;;;;;;AAkB1J,MAAa,aACX;;;;;;;;;AAYF,MAAa,cACX;;;;;;;;;;;;;;;;;AAkBF,MAAa,sBACX;;AAGF,SAAgB,gBAAgB,SAAyB;CACvD,OAAO,UAAU,QAAQ,sBAAsB,QAAQ,sBAAsB,QAAQ;AACvF;;;;;;;;;;;;;;;;AAiBA,MAAa,gBACX;;;;;;;;;;;;;AAeF,MAAa,iBACX;;;;;;AAQF,MAAa,oBACX;;;;;;;;;;;;;;;;;;;;;AAuBF,MAAa,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;AAyB7B,MAAa,uBACX;;;;;;;;;;;;;AAeF,MAAa,0BACX;;;;;;;;;;;;;;;;;;;;;;AAyBF,MAAa,aACX;;AAQF,MAAa,uBAAyD;CACpE,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,WAAW;CACX,SAAS;CACT,QAAQ;CACR,WAAW;CACX,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,SAAS;CACT,QAAQ;CACR,QAAQ;AACV"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ZC_AB_DECL } from "../issue-decls.js";
|
|
1
2
|
import { checkPriority, declareFastTemps, emitRuntimeHelper, extendPath, hasMutation, visitMember } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
4
|
import { invalidType, tooBig, tooSmall } from "../emit-issue.js";
|
|
4
|
-
import { ZC_AB_DECL } from "../issue-decls.js";
|
|
5
5
|
import { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from "./effect.js";
|
|
6
6
|
import { whenGatedSizeChecks } from "./sizeable.js";
|
|
7
7
|
//#region src/core/codegen/schemas/array.ts
|
|
@@ -22,7 +22,7 @@ function slowArray(ir, g) {
|
|
|
22
22
|
original: g.input,
|
|
23
23
|
copy: `${arr}.slice()`,
|
|
24
24
|
key: idxVar,
|
|
25
|
-
path: extendPath(g.path, idxVar),
|
|
25
|
+
path: extendPath(g.ctx, g.path, idxVar),
|
|
26
26
|
issues: g.issues
|
|
27
27
|
});
|
|
28
28
|
code += emit`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.js","names":[],"sources":["../../../../src/core/codegen/schemas/array.ts"],"sourcesContent":["import type { ArrayIR, CheckIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n checkPriority,\n declareFastTemps,\n emitRuntimeHelper,\n extendPath,\n hasMutation,\n visitMember,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { ZC_AB_DECL } from \"../issue-decls.js\";\nimport { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\nimport { whenGatedSizeChecks } from \"./sizeable.js\";\n\nexport function slowArray(ir: SchemaIR & { type: \"array\" }, g: SlowGen): string {\n let code = emit`\n if(!Array.isArray(${g.input})){\n ${invalidType(g, \"array\")}\n ${whenGatedSizeChecks(ir.checks, g, \"length\", true)}\n }else{`;\n\n // Every element is read and written through ONE binding, handed back as the\n // output after the loop — slowTuple's discipline, for slowTuple's reason: a\n // parent can hand this node `g.input` and `g.output` as two different\n // bindings, and copying into `g.output` while the elements went on being\n // written through `g.input` returned the ORIGINAL elements and rewrote the\n // caller's array. A mutating element schema rewrites values as a matter of\n // course, so its copy is taken up front; anything else copies only once an\n // element hands back a replacement (see visitMember).\n const arr = g.temp(\"ar\");\n code += `var ${arr}=${g.input};`;\n if (hasMutation(ir.element)) {\n code += `${arr}=${arr}.slice();`;\n }\n\n // Element validation precedes the size/refine checks: Zod parses elements\n // (the base type) first and only then runs its checks, so for an input that\n // both has an invalid element AND fails a size check, the per-element issue\n // is surfaced before too_small/too_big. Emitting the checks first would\n // reverse that order (the slow path collects all issues with no\n // short-circuit, so insertion order IS issue order).\n\n // Snapshot before the elements, for the same reason slowObject does: the\n // array's refine effects are gated on zod's abort rule over the issues THIS\n // node's parse produced. Size checks are exempt — zod's length checks declare\n // a `when` predicate, which bypasses the abort gate, so\n // `z.array(z.string()).min(2)` still reports too_small next to a bad element's\n // invalid_type.\n const hasRefine = ir.checks.some(\n (c) => c.kind === \"refine_effect\" || c.kind === \"super_refine_effect\",\n );\n const refineMark = hasRefine ? g.temp(\"rm\") : \"\";\n if (refineMark) code += `var ${refineMark}=${g.issues}.length;`;\n\n const idxVar = g.temp(\"i\");\n const element = visitMember(g, ir.element, {\n container: arr,\n original: g.input,\n copy: `${arr}.slice()`,\n key: idxVar,\n path: extendPath(g.path, idxVar),\n issues: g.issues,\n });\n code += emit`\n for(var ${idxVar}=0;${idxVar}<${arr}.length;${idxVar}++){\n ${element}\n }\n ${g.output}=${arr};`;\n\n /** Wrap one refine effect in zod's abort gate, preserving declaration order. */\n const gated = (body: string): string => {\n const aborted = emitRuntimeHelper(g.ctx, \"__zcAb\", ZC_AB_DECL);\n return `if(!${aborted}(${g.issues},${refineMark})){${body}}`;\n };\n\n // The checks run on the parsed array, as zod's run on `payload.value`: the\n // output, which carries any replacement an element handed back, and is what\n // a superRefine rewrites for the checks after it.\n const parsed = g.output;\n for (const check of ir.checks) {\n switch (check.kind) {\n case \"min_length\":\n code += emit`\n if(${parsed}.length<${check.minimum}){\n ${tooSmall(g, check.minimum, \"array\", true, { message: check.message })}\n }`;\n break;\n case \"max_length\":\n code += emit`\n if(${parsed}.length>${check.maximum}){\n ${tooBig(g, check.maximum, \"array\", true, { message: check.message })}\n }`;\n break;\n case \"length_equals\":\n code += emit`\n if(${parsed}.length<${check.length}){\n ${tooSmall(g, check.length, \"array\", true, { exact: true, message: check.message })}\n }else if(${parsed}.length>${check.length}){\n ${tooBig(g, check.length, \"array\", true, { exact: true, message: check.message })}\n }`;\n break;\n case \"refine_effect\":\n code += gated(refineCheck(check, parsed, g));\n break;\n case \"super_refine_effect\":\n code += gated(superRefineCheck(check, parsed, g));\n break;\n }\n }\n\n code += `}`;\n return `${code}\\n`;\n}\n\nexport function fastArray(ir: ArrayIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`Array.isArray(${x})`];\n const checks = ir.checks.filter((c): c is CheckIR => c.kind !== \"refine_effect\");\n\n // Size checks\n for (const check of checks.sort(checkPriority)) {\n switch (check.kind) {\n case \"min_length\":\n parts.push(`${x}.length>=${check.minimum}`);\n break;\n case \"max_length\":\n parts.push(`${x}.length<=${check.maximum}`);\n break;\n case \"length_equals\":\n parts.push(`${x}.length===${check.length}`);\n break;\n }\n }\n\n // Element validation via preamble helper (avoids .every() closure allocation).\n // Fresh scope: the helper is its own function, size-gated independently.\n const elemVar = g.temp(\"ae\");\n const elemGen = g.scoped(elemVar);\n const elemCheck = elemGen.visit(ir.element);\n if (elemCheck === null) return null;\n if (elemCheck !== \"true\") {\n const helperName = g.temp(\"af\");\n g.ctx.preamble.push(\n `function ${helperName}(a){${declareFastTemps(elemGen.scope)}for(var ${elemVar},i=0;i<a.length;i++){${elemVar}=a[i];if(!(${elemCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n // Refine effect checks (appended last — run after cheap checks short-circuit)\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(fastRefineTest(check, x, g));\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":";;;;;;;AAgBA,SAAgB,UAAU,IAAkC,GAAoB;CAC9E,IAAI,OAAO,IAAI;wBACO,EAAE,MAAM;QACxB,YAAY,GAAG,OAAO,EAAE;QACxB,oBAAoB,GAAG,QAAQ,GAAG,UAAU,IAAI,EAAE;;CAWxD,MAAM,MAAM,EAAE,KAAK,IAAI;CACvB,QAAQ,OAAO,IAAI,GAAG,EAAE,MAAM;CAC9B,IAAI,YAAY,GAAG,OAAO,GACxB,QAAQ,GAAG,IAAI,GAAG,IAAI;CAmBxB,MAAM,aAHY,GAAG,OAAO,MACzB,MAAM,EAAE,SAAS,mBAAmB,EAAE,SAAS,qBAEvB,IAAI,EAAE,KAAK,IAAI,IAAI;CAC9C,IAAI,YAAY,QAAQ,OAAO,WAAW,GAAG,EAAE,OAAO;CAEtD,MAAM,SAAS,EAAE,KAAK,GAAG;CACzB,MAAM,UAAU,YAAY,GAAG,GAAG,SAAS;EACzC,WAAW;EACX,UAAU,EAAE;EACZ,MAAM,GAAG,IAAI;EACb,KAAK;EACL,MAAM,WAAW,EAAE,MAAM,MAAM;
|
|
1
|
+
{"version":3,"file":"array.js","names":[],"sources":["../../../../src/core/codegen/schemas/array.ts"],"sourcesContent":["import type { ArrayIR, CheckIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n checkPriority,\n declareFastTemps,\n emitRuntimeHelper,\n extendPath,\n hasMutation,\n visitMember,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { ZC_AB_DECL } from \"../issue-decls.js\";\nimport { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\nimport { whenGatedSizeChecks } from \"./sizeable.js\";\n\nexport function slowArray(ir: SchemaIR & { type: \"array\" }, g: SlowGen): string {\n let code = emit`\n if(!Array.isArray(${g.input})){\n ${invalidType(g, \"array\")}\n ${whenGatedSizeChecks(ir.checks, g, \"length\", true)}\n }else{`;\n\n // Every element is read and written through ONE binding, handed back as the\n // output after the loop — slowTuple's discipline, for slowTuple's reason: a\n // parent can hand this node `g.input` and `g.output` as two different\n // bindings, and copying into `g.output` while the elements went on being\n // written through `g.input` returned the ORIGINAL elements and rewrote the\n // caller's array. A mutating element schema rewrites values as a matter of\n // course, so its copy is taken up front; anything else copies only once an\n // element hands back a replacement (see visitMember).\n const arr = g.temp(\"ar\");\n code += `var ${arr}=${g.input};`;\n if (hasMutation(ir.element)) {\n code += `${arr}=${arr}.slice();`;\n }\n\n // Element validation precedes the size/refine checks: Zod parses elements\n // (the base type) first and only then runs its checks, so for an input that\n // both has an invalid element AND fails a size check, the per-element issue\n // is surfaced before too_small/too_big. Emitting the checks first would\n // reverse that order (the slow path collects all issues with no\n // short-circuit, so insertion order IS issue order).\n\n // Snapshot before the elements, for the same reason slowObject does: the\n // array's refine effects are gated on zod's abort rule over the issues THIS\n // node's parse produced. Size checks are exempt — zod's length checks declare\n // a `when` predicate, which bypasses the abort gate, so\n // `z.array(z.string()).min(2)` still reports too_small next to a bad element's\n // invalid_type.\n const hasRefine = ir.checks.some(\n (c) => c.kind === \"refine_effect\" || c.kind === \"super_refine_effect\",\n );\n const refineMark = hasRefine ? g.temp(\"rm\") : \"\";\n if (refineMark) code += `var ${refineMark}=${g.issues}.length;`;\n\n const idxVar = g.temp(\"i\");\n const element = visitMember(g, ir.element, {\n container: arr,\n original: g.input,\n copy: `${arr}.slice()`,\n key: idxVar,\n path: extendPath(g.ctx, g.path, idxVar),\n issues: g.issues,\n });\n code += emit`\n for(var ${idxVar}=0;${idxVar}<${arr}.length;${idxVar}++){\n ${element}\n }\n ${g.output}=${arr};`;\n\n /** Wrap one refine effect in zod's abort gate, preserving declaration order. */\n const gated = (body: string): string => {\n const aborted = emitRuntimeHelper(g.ctx, \"__zcAb\", ZC_AB_DECL);\n return `if(!${aborted}(${g.issues},${refineMark})){${body}}`;\n };\n\n // The checks run on the parsed array, as zod's run on `payload.value`: the\n // output, which carries any replacement an element handed back, and is what\n // a superRefine rewrites for the checks after it.\n const parsed = g.output;\n for (const check of ir.checks) {\n switch (check.kind) {\n case \"min_length\":\n code += emit`\n if(${parsed}.length<${check.minimum}){\n ${tooSmall(g, check.minimum, \"array\", true, { message: check.message })}\n }`;\n break;\n case \"max_length\":\n code += emit`\n if(${parsed}.length>${check.maximum}){\n ${tooBig(g, check.maximum, \"array\", true, { message: check.message })}\n }`;\n break;\n case \"length_equals\":\n code += emit`\n if(${parsed}.length<${check.length}){\n ${tooSmall(g, check.length, \"array\", true, { exact: true, message: check.message })}\n }else if(${parsed}.length>${check.length}){\n ${tooBig(g, check.length, \"array\", true, { exact: true, message: check.message })}\n }`;\n break;\n case \"refine_effect\":\n code += gated(refineCheck(check, parsed, g));\n break;\n case \"super_refine_effect\":\n code += gated(superRefineCheck(check, parsed, g));\n break;\n }\n }\n\n code += `}`;\n return `${code}\\n`;\n}\n\nexport function fastArray(ir: ArrayIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`Array.isArray(${x})`];\n const checks = ir.checks.filter((c): c is CheckIR => c.kind !== \"refine_effect\");\n\n // Size checks\n for (const check of checks.sort(checkPriority)) {\n switch (check.kind) {\n case \"min_length\":\n parts.push(`${x}.length>=${check.minimum}`);\n break;\n case \"max_length\":\n parts.push(`${x}.length<=${check.maximum}`);\n break;\n case \"length_equals\":\n parts.push(`${x}.length===${check.length}`);\n break;\n }\n }\n\n // Element validation via preamble helper (avoids .every() closure allocation).\n // Fresh scope: the helper is its own function, size-gated independently.\n const elemVar = g.temp(\"ae\");\n const elemGen = g.scoped(elemVar);\n const elemCheck = elemGen.visit(ir.element);\n if (elemCheck === null) return null;\n if (elemCheck !== \"true\") {\n const helperName = g.temp(\"af\");\n g.ctx.preamble.push(\n `function ${helperName}(a){${declareFastTemps(elemGen.scope)}for(var ${elemVar},i=0;i<a.length;i++){${elemVar}=a[i];if(!(${elemCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n // Refine effect checks (appended last — run after cheap checks short-circuit)\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(fastRefineTest(check, x, g));\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { emitEffectCallable, emitRuntimeHelper } from "../context.js";
|
|
2
1
|
import { ZC_CUSTOM_OK_DECL } from "../issue-decls.js";
|
|
2
|
+
import { emitEffectCallable, emitRuntimeHelper } from "../context.js";
|
|
3
3
|
import { slowZodDelegate } from "./fallback.js";
|
|
4
4
|
//#region src/core/codegen/schemas/custom.ts
|
|
5
5
|
/** Total hot-path predicate for z.custom() and z.instanceof(). */
|
|
@@ -24,7 +24,7 @@ function slowDiscriminatedUnion(ir, g) {
|
|
|
24
24
|
const optionsList = ir.cases.map(({ value }) => literalToJs(value)).join(",");
|
|
25
25
|
code += emit`
|
|
26
26
|
default:
|
|
27
|
-
${g.issues}.push({code:"invalid_union",errors:[],note:"No matching discriminator",discriminator:${discKey},options:[${optionsList}],input:${g.input},path:${extendPath(g.path, discKey)}${msgProp}});
|
|
27
|
+
${g.issues}.push({code:"invalid_union",errors:[],note:"No matching discriminator",discriminator:${discKey},options:[${optionsList}],input:${g.input},path:${extendPath(g.ctx, g.path, discKey)}${msgProp}});
|
|
28
28
|
}`;
|
|
29
29
|
code += `${g.output}=${objVar};`;
|
|
30
30
|
code += `}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discriminated-union.js","names":[],"sources":["../../../../src/core/codegen/schemas/discriminated-union.ts"],"sourcesContent":["import type { DiscriminatedUnionIR, LiteralValue, ObjectIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { declareFastTemps, escapeString, extendPath, literalToJs } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType } from \"../emit-issue.js\";\n\n/** One `discriminator value → option index` dispatch entry. */\ntype DiscriminatorCase = DiscriminatedUnionIR[\"cases\"][number];\n\nexport function slowDiscriminatedUnion(\n ir: SchemaIR & { type: \"discriminatedUnion\" },\n g: SlowGen,\n): string {\n const discKey = escapeString(ir.discriminator);\n\n let code = emit`\n if(typeof ${g.input}!==\"object\"||${g.input}===null||Array.isArray(${g.input})){\n ${invalidType(g, \"object\", { codeFirst: true })}\n }else{`;\n\n const objVar = g.temp(\"du\");\n code += `var ${objVar}=${g.input};switch(${objVar}[${discKey}]){`;\n\n for (const { value, option: index } of ir.cases) {\n const option = ir.options[index] as SchemaIR;\n code += emit`\n case ${literalToJs(value)}:\n ${g.visit(option, { input: objVar, output: objVar })}\n break;`;\n }\n\n const msgProp = g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`;\n // Field for field what $ZodDiscriminatedUnion pushes when no option matches:\n // `{ code, errors: [], note: \"No matching discriminator\", discriminator,\n // options, input, path: [def.discriminator] }`. `options` is\n // `Array.from(disc.value.keys())` — every dispatch value in map insertion\n // order, which is exactly `ir.cases` (option order, then each option's\n // `propValues[discriminator]` in ITS order, so an omittable discriminator\n // lists `undefined` right after its own values). The locale reads the list\n // for \"Invalid discriminator value. Expected 'a' | 'b'\". A fresh array\n // literal per push, as zod allocates one, so consumers never share or\n // mutate a hoisted table.\n const optionsList = ir.cases.map(({ value }) => literalToJs(value)).join(\",\");\n code += emit`\n default:\n ${g.issues}.push({code:\"invalid_union\",errors:[],note:\"No matching discriminator\",discriminator:${discKey},options:[${optionsList}],input:${g.input},path:${extendPath(g.path, discKey)}${msgProp}});\n }`;\n // Propagate what the matched option produced back to the output location.\n // Each option is visited with output:objVar — a fresh local — so its result is\n // reassigned into objVar and stranded there; without this write-back the\n // caller gets the ORIGINAL input by reference and the result is silently lost.\n // That is as true of an option that rewrites nothing as of a mutating one\n // (defaults, coercions, transforms, overwrite checks, stringbool): it can\n // still hand back a replacement — a `__proto__`-scrubbed copy, or a copy a\n // nested replacement landed on — so the write is not gated on mutation. Where\n // nothing was replaced, and on the no-match path, objVar is still the input.\n code += `${g.output}=${objVar};`;\n code += `}`;\n return `${code}\\n`;\n}\n\n/**\n * Emit an O(1) switch-dispatch fast-check for a discriminated union — real\n * (`z.discriminatedUnion`) or one detected inside a plain `z.union`\n * (see {@link detectUnionDiscriminator}). Both share this so the detected case\n * inherits the size-gating and the per-case guard strip.\n *\n * `discSkipKey` tells each object option to drop its own type-guard and\n * discriminator re-check: the caller's guard (`typeof x===\"object\"&&…` below)\n * already proved object-ness, and the matched switch case has fixed the\n * discriminator value, so re-emitting either is pure redundancy the optimizer\n * only removes when it inlines this helper — which a union large enough to\n * matter won't. Routed through the normal `visit` so size-gated extraction\n * still bounds the switch (the strip survives into any hoisted helper);\n * non-object options ignore the hint and keep their own guard.\n *\n * Returns null if any option is fast-path-ineligible.\n */\nexport function emitFastDiscriminatedSwitch(\n g: FastGen,\n discriminator: string,\n cases: readonly DiscriminatorCase[],\n options: readonly SchemaIR[],\n): string | null {\n const x = g.input;\n const discKey = escapeString(discriminator);\n const helperName = g.temp(\"du\");\n const helperParam = g.temp(\"dx\");\n\n // The switch body is its own function: size-gate the options against the cap\n // in a fresh scope, otherwise many small options accumulate into the caller's\n // scope while this helper itself grows unbounded past the TurboFan budget.\n //\n // The switch is over the literal labels themselves. An earlier revision\n // routed three or more string labels through a `{value: ordinal}` table and\n // switched on the ordinal, on the theory that V8 compiles a string switch as\n // sequential comparisons and a dense integer one as a jump table. Measured on\n // V8 13.x (node 24) that is a loss at every size: the table's `t[v]` is a\n // keyed load whose key varies per parse, which goes megamorphic the moment\n // the input rotates through the options, while the string switch stays\n // nearly flat (8.6 ns at 8 cases, 10.1 at 32, 17.3 at 80, rotating input)\n // against the table's 12.9, 15.8 and 20.8. The build path switches the same\n // way (see `buildDispatch`).\n const body = g.scoped(helperParam);\n const caseStrs: string[] = [];\n for (const { value, option: index } of cases) {\n const check = body.visit(options[index] as SchemaIR, { discSkipKey: discriminator });\n if (check === null) return null;\n caseStrs.push(`case ${literalToJs(value)}:return ${check};`);\n }\n g.ctx.preamble.push(\n `function ${helperName}(${helperParam}){${declareFastTemps(body.scope)}switch(${helperParam}[${discKey}]){${caseStrs.join(\"\")}default:return false;}}`,\n );\n\n return `typeof ${x}===\"object\"&&${x}!==null&&!Array.isArray(${x})&&${helperName}(${x})`;\n}\n\nexport function fastDiscriminatedUnion(ir: DiscriminatedUnionIR, g: FastGen): string | null {\n return emitFastDiscriminatedSwitch(g, ir.discriminator, ir.cases, ir.options);\n}\n\n/**\n * Minimum option count for rewriting a plain `z.union` to switch dispatch. Below\n * this the switch helper's fixed call overhead loses to a fully-inlined\n * `||`-chain that V8 keeps flat: measured crossover is ~4 options (n=3 can hit\n * 0.6x — a regression — while n=5 is 1.27x and n=32 is 2.34x), so 5 captures the\n * stable wins with margin and never regresses a small union. Real\n * `z.discriminatedUnion` is unaffected — it dispatches via switch by construction\n * regardless of size.\n */\nconst MIN_AUTO_DISCRIMINATE_OPTIONS = 5;\n\n/**\n * Values that switch correctly under `===` (excludes `undefined` and `NaN`).\n *\n * Also excludes a SYMBOL — now that `LiteralIR.values` admits one, this is the\n * guard that keeps it out. A symbol discriminant has no source form, so there\n * is no `case` label to emit for it (`literalToJs` refuses it by type), and the\n * ordinal-table variant is string-keyed besides. Detection bails to the\n * `||`-chain, where the option's own literal check does the right thing by\n * reading the value list off the retained schema.\n */\nfunction isSwitchableDiscriminant(v: LiteralValue): v is string | number | boolean | bigint | null {\n return (\n v === null ||\n typeof v === \"string\" ||\n typeof v === \"boolean\" ||\n typeof v === \"bigint\" ||\n (typeof v === \"number\" && !Number.isNaN(v))\n );\n}\n\n/**\n * Detect whether a plain (untagged) `z.union` is *structurally* a discriminated\n * union, so its fast path can use O(1) switch dispatch instead of probing every\n * arm. Returns the discriminator + dispatch table, or null to keep the\n * `||`-chain.\n *\n * Requires (proving the switch accepts exactly what the `||`-chain would): every\n * option is a plain object that pins one shared key to a REQUIRED literal\n * (`prop.type === \"literal\"` — an optional/non-literal key is rejected), and the\n * literal values are pairwise DISJOINT across options. Disjointness is the crux:\n * it guarantees at most one option can accept any given input, so dispatching to\n * that single option is equivalent to trying them all. Any value shared by two\n * options (ambiguous), a non-switchable value (`undefined`/`NaN`), or a\n * non-object option makes detection bail to the safe `||`-chain.\n *\n * The slow path is untouched: it keeps `z.union`'s sequential trial and its\n * `invalid_union` error shape, so failure output stays byte-identical to Zod.\n * The fast path and the build path both dispatch on the result — the build\n * path from two options up (`minOptions`), since its options are hosted calls\n * either way and a switch only ever replaces probes with one call; see\n * `buildUnion`.\n */\nexport function detectUnionDiscriminator(\n options: readonly SchemaIR[],\n minOptions: number = MIN_AUTO_DISCRIMINATE_OPTIONS,\n): { discriminator: string; cases: DiscriminatorCase[] } | null {\n if (options.length < minOptions) return null;\n const objects: ObjectIR[] = [];\n for (const option of options) {\n if (option.type !== \"object\") return null;\n objects.push(option);\n }\n const first = objects[0];\n if (first === undefined) return null; // unreachable (length checked above)\n\n // Only keys present in the first option can be shared by all; try each.\n candidate: for (const key of Object.keys(first.properties)) {\n const seen = new Set<string | number | boolean | bigint | null>();\n const cases: DiscriminatorCase[] = [];\n for (const [i, object] of objects.entries()) {\n const prop = object.properties[key];\n if (prop === undefined || prop.type !== \"literal\") continue candidate;\n for (const value of prop.values) {\n if (!isSwitchableDiscriminant(value)) continue candidate;\n if (seen.has(value)) continue candidate; // shared value → ambiguous dispatch\n seen.add(value);\n cases.push({ value, option: i });\n }\n }\n return { discriminator: key, cases };\n }\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"discriminated-union.js","names":[],"sources":["../../../../src/core/codegen/schemas/discriminated-union.ts"],"sourcesContent":["import type { DiscriminatedUnionIR, LiteralValue, ObjectIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { declareFastTemps, escapeString, extendPath, literalToJs } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType } from \"../emit-issue.js\";\n\n/** One `discriminator value → option index` dispatch entry. */\ntype DiscriminatorCase = DiscriminatedUnionIR[\"cases\"][number];\n\nexport function slowDiscriminatedUnion(\n ir: SchemaIR & { type: \"discriminatedUnion\" },\n g: SlowGen,\n): string {\n const discKey = escapeString(ir.discriminator);\n\n let code = emit`\n if(typeof ${g.input}!==\"object\"||${g.input}===null||Array.isArray(${g.input})){\n ${invalidType(g, \"object\", { codeFirst: true })}\n }else{`;\n\n const objVar = g.temp(\"du\");\n code += `var ${objVar}=${g.input};switch(${objVar}[${discKey}]){`;\n\n for (const { value, option: index } of ir.cases) {\n const option = ir.options[index] as SchemaIR;\n code += emit`\n case ${literalToJs(value)}:\n ${g.visit(option, { input: objVar, output: objVar })}\n break;`;\n }\n\n const msgProp = g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`;\n // Field for field what $ZodDiscriminatedUnion pushes when no option matches:\n // `{ code, errors: [], note: \"No matching discriminator\", discriminator,\n // options, input, path: [def.discriminator] }`. `options` is\n // `Array.from(disc.value.keys())` — every dispatch value in map insertion\n // order, which is exactly `ir.cases` (option order, then each option's\n // `propValues[discriminator]` in ITS order, so an omittable discriminator\n // lists `undefined` right after its own values). The locale reads the list\n // for \"Invalid discriminator value. Expected 'a' | 'b'\". A fresh array\n // literal per push, as zod allocates one, so consumers never share or\n // mutate a hoisted table.\n const optionsList = ir.cases.map(({ value }) => literalToJs(value)).join(\",\");\n code += emit`\n default:\n ${g.issues}.push({code:\"invalid_union\",errors:[],note:\"No matching discriminator\",discriminator:${discKey},options:[${optionsList}],input:${g.input},path:${extendPath(g.ctx, g.path, discKey)}${msgProp}});\n }`;\n // Propagate what the matched option produced back to the output location.\n // Each option is visited with output:objVar — a fresh local — so its result is\n // reassigned into objVar and stranded there; without this write-back the\n // caller gets the ORIGINAL input by reference and the result is silently lost.\n // That is as true of an option that rewrites nothing as of a mutating one\n // (defaults, coercions, transforms, overwrite checks, stringbool): it can\n // still hand back a replacement — a `__proto__`-scrubbed copy, or a copy a\n // nested replacement landed on — so the write is not gated on mutation. Where\n // nothing was replaced, and on the no-match path, objVar is still the input.\n code += `${g.output}=${objVar};`;\n code += `}`;\n return `${code}\\n`;\n}\n\n/**\n * Emit an O(1) switch-dispatch fast-check for a discriminated union — real\n * (`z.discriminatedUnion`) or one detected inside a plain `z.union`\n * (see {@link detectUnionDiscriminator}). Both share this so the detected case\n * inherits the size-gating and the per-case guard strip.\n *\n * `discSkipKey` tells each object option to drop its own type-guard and\n * discriminator re-check: the caller's guard (`typeof x===\"object\"&&…` below)\n * already proved object-ness, and the matched switch case has fixed the\n * discriminator value, so re-emitting either is pure redundancy the optimizer\n * only removes when it inlines this helper — which a union large enough to\n * matter won't. Routed through the normal `visit` so size-gated extraction\n * still bounds the switch (the strip survives into any hoisted helper);\n * non-object options ignore the hint and keep their own guard.\n *\n * Returns null if any option is fast-path-ineligible.\n */\nexport function emitFastDiscriminatedSwitch(\n g: FastGen,\n discriminator: string,\n cases: readonly DiscriminatorCase[],\n options: readonly SchemaIR[],\n): string | null {\n const x = g.input;\n const discKey = escapeString(discriminator);\n const helperName = g.temp(\"du\");\n const helperParam = g.temp(\"dx\");\n\n // The switch body is its own function: size-gate the options against the cap\n // in a fresh scope, otherwise many small options accumulate into the caller's\n // scope while this helper itself grows unbounded past the TurboFan budget.\n //\n // The switch is over the literal labels themselves. An earlier revision\n // routed three or more string labels through a `{value: ordinal}` table and\n // switched on the ordinal, on the theory that V8 compiles a string switch as\n // sequential comparisons and a dense integer one as a jump table. Measured on\n // V8 13.x (node 24) that is a loss at every size: the table's `t[v]` is a\n // keyed load whose key varies per parse, which goes megamorphic the moment\n // the input rotates through the options, while the string switch stays\n // nearly flat (8.6 ns at 8 cases, 10.1 at 32, 17.3 at 80, rotating input)\n // against the table's 12.9, 15.8 and 20.8. The build path switches the same\n // way (see `buildDispatch`).\n const body = g.scoped(helperParam);\n const caseStrs: string[] = [];\n for (const { value, option: index } of cases) {\n const check = body.visit(options[index] as SchemaIR, { discSkipKey: discriminator });\n if (check === null) return null;\n caseStrs.push(`case ${literalToJs(value)}:return ${check};`);\n }\n g.ctx.preamble.push(\n `function ${helperName}(${helperParam}){${declareFastTemps(body.scope)}switch(${helperParam}[${discKey}]){${caseStrs.join(\"\")}default:return false;}}`,\n );\n\n return `typeof ${x}===\"object\"&&${x}!==null&&!Array.isArray(${x})&&${helperName}(${x})`;\n}\n\nexport function fastDiscriminatedUnion(ir: DiscriminatedUnionIR, g: FastGen): string | null {\n return emitFastDiscriminatedSwitch(g, ir.discriminator, ir.cases, ir.options);\n}\n\n/**\n * Minimum option count for rewriting a plain `z.union` to switch dispatch. Below\n * this the switch helper's fixed call overhead loses to a fully-inlined\n * `||`-chain that V8 keeps flat: measured crossover is ~4 options (n=3 can hit\n * 0.6x — a regression — while n=5 is 1.27x and n=32 is 2.34x), so 5 captures the\n * stable wins with margin and never regresses a small union. Real\n * `z.discriminatedUnion` is unaffected — it dispatches via switch by construction\n * regardless of size.\n */\nconst MIN_AUTO_DISCRIMINATE_OPTIONS = 5;\n\n/**\n * Values that switch correctly under `===` (excludes `undefined` and `NaN`).\n *\n * Also excludes a SYMBOL — now that `LiteralIR.values` admits one, this is the\n * guard that keeps it out. A symbol discriminant has no source form, so there\n * is no `case` label to emit for it (`literalToJs` refuses it by type), and the\n * ordinal-table variant is string-keyed besides. Detection bails to the\n * `||`-chain, where the option's own literal check does the right thing by\n * reading the value list off the retained schema.\n */\nfunction isSwitchableDiscriminant(v: LiteralValue): v is string | number | boolean | bigint | null {\n return (\n v === null ||\n typeof v === \"string\" ||\n typeof v === \"boolean\" ||\n typeof v === \"bigint\" ||\n (typeof v === \"number\" && !Number.isNaN(v))\n );\n}\n\n/**\n * Detect whether a plain (untagged) `z.union` is *structurally* a discriminated\n * union, so its fast path can use O(1) switch dispatch instead of probing every\n * arm. Returns the discriminator + dispatch table, or null to keep the\n * `||`-chain.\n *\n * Requires (proving the switch accepts exactly what the `||`-chain would): every\n * option is a plain object that pins one shared key to a REQUIRED literal\n * (`prop.type === \"literal\"` — an optional/non-literal key is rejected), and the\n * literal values are pairwise DISJOINT across options. Disjointness is the crux:\n * it guarantees at most one option can accept any given input, so dispatching to\n * that single option is equivalent to trying them all. Any value shared by two\n * options (ambiguous), a non-switchable value (`undefined`/`NaN`), or a\n * non-object option makes detection bail to the safe `||`-chain.\n *\n * The slow path is untouched: it keeps `z.union`'s sequential trial and its\n * `invalid_union` error shape, so failure output stays byte-identical to Zod.\n * The fast path and the build path both dispatch on the result — the build\n * path from two options up (`minOptions`), since its options are hosted calls\n * either way and a switch only ever replaces probes with one call; see\n * `buildUnion`.\n */\nexport function detectUnionDiscriminator(\n options: readonly SchemaIR[],\n minOptions: number = MIN_AUTO_DISCRIMINATE_OPTIONS,\n): { discriminator: string; cases: DiscriminatorCase[] } | null {\n if (options.length < minOptions) return null;\n const objects: ObjectIR[] = [];\n for (const option of options) {\n if (option.type !== \"object\") return null;\n objects.push(option);\n }\n const first = objects[0];\n if (first === undefined) return null; // unreachable (length checked above)\n\n // Only keys present in the first option can be shared by all; try each.\n candidate: for (const key of Object.keys(first.properties)) {\n const seen = new Set<string | number | boolean | bigint | null>();\n const cases: DiscriminatorCase[] = [];\n for (const [i, object] of objects.entries()) {\n const prop = object.properties[key];\n if (prop === undefined || prop.type !== \"literal\") continue candidate;\n for (const value of prop.values) {\n if (!isSwitchableDiscriminant(value)) continue candidate;\n if (seen.has(value)) continue candidate; // shared value → ambiguous dispatch\n seen.add(value);\n cases.push({ value, option: i });\n }\n }\n return { discriminator: key, cases };\n }\n return null;\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { ZC_ASYNC_DECL, ZC_SR_DECL, ZC_SR_OK_DECL, ZC_SR_RUN_DECL } from "../issue-decls.js";
|
|
1
2
|
import { emitConstant, emitEffectCallable, emitRuntimeHelper, extendStaticPath, extendStaticPathIndex } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
|
-
import { ZC_ASYNC_DECL, ZC_SR_DECL, ZC_SR_OK_DECL, ZC_SR_RUN_DECL } from "../issue-decls.js";
|
|
4
4
|
//#region src/core/codegen/schemas/effect.ts
|
|
5
5
|
/**
|
|
6
6
|
* Generate code for a TransformEffectIR node.
|
|
@@ -44,7 +44,7 @@ function slowEffect(ir, g) {
|
|
|
44
44
|
function refineCheck(check, expr, g) {
|
|
45
45
|
const message = check.message ?? g.typeMsg;
|
|
46
46
|
const messageProp = message === void 0 ? "" : `,message:${JSON.stringify(message)}`;
|
|
47
|
-
const path = (check.path ?? []).reduce((acc, segment) => typeof segment === "number" ? extendStaticPathIndex(acc, segment) : extendStaticPath(acc, segment), g.path);
|
|
47
|
+
const path = (check.path ?? []).reduce((acc, segment) => typeof segment === "number" ? extendStaticPathIndex(g.ctx, acc, segment) : extendStaticPath(g.ctx, acc, segment), g.path);
|
|
48
48
|
const paramsProp = check.paramsRefIndex === void 0 ? "" : `,params:${emitConstant(g.ctx, "rpa", `__rf[${check.paramsRefIndex}]`)}`;
|
|
49
49
|
const asy = emitRuntimeHelper(g.ctx, "__zcAsy", ZC_ASYNC_DECL);
|
|
50
50
|
const result = g.temp("rr");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effect.js","names":[],"sources":["../../../../src/core/codegen/schemas/effect.ts"],"sourcesContent":["import type {\n PreprocessEffectIR,\n RefineEffectCheckIR,\n SuperRefineEffectCheckIR,\n TransformEffectIR,\n} from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n emitConstant,\n emitEffectCallable,\n emitRuntimeHelper,\n extendStaticPath,\n extendStaticPathIndex,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { ZC_ASYNC_DECL, ZC_SR_DECL, ZC_SR_OK_DECL, ZC_SR_RUN_DECL } from \"../issue-decls.js\";\n\n/**\n * Generate code for a TransformEffectIR node.\n * Validates the inner schema, then applies the transform function and writes back the result.\n */\nexport function slowEffect(ir: TransformEffectIR | PreprocessEffectIR, g: SlowGen): string {\n // A callback that returns a Promise is zod's synchronous-parse error, not a\n // value (see ZC_ASYNC_DECL); zod tests `_out instanceof Promise` right after\n // the call, so the guard sits at the same point.\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n if (ir.effectKind === \"preprocess\") {\n const valueVar = g.temp(\"pv\");\n // The callback's result is written to the output first, and the inner\n // schema then reads and writes it through that ONE expression, as a root\n // does. A rewriting inner reads back what it wrote — `.trim().min(1)`\n // measures the trimmed string, a coercion checks the converted value — so\n // handing it the result as its input and the output as its output made those\n // checks see the value from before the rewrite: nested in a walk that runs\n // eagerly, `z.preprocess(fn, z.string().trim().min(1))` accepted `\" \"`.\n return `${emit`\n var ${valueVar}=${emitEffectCallable(g.ctx, ir)}(${g.input});\n if(${valueVar} instanceof Promise)${asy}();\n ${g.output}=${valueVar};\n ${g.visit(ir.inner, { input: g.output, output: g.output, aborted: g.aborted })}\n `}\\n`;\n }\n\n const beforeVar = g.temp(\"ib\");\n const innerCode = g.visit(ir.inner);\n // A transform is `inner.transform(fn)` = a pipe(inner, transform): zod's\n // handlePipeResult aborts when `inner` produces any issue. Inside a union the\n // option must therefore count as aborted even if `inner`'s only issue is a\n // non-aborting `custom`/check-level code (mirrors slowPipe's abort branch).\n const abortBranch = g.aborted ? `else{${g.aborted}=true;}` : \"\";\n\n return `${emit`\n var ${beforeVar}=${g.issues}.length;\n ${innerCode}\n if(${g.issues}.length===${beforeVar}){\n ${g.output}=${emitEffectCallable(g.ctx, ir)}(${g.output});\n if(${g.output} instanceof Promise)${asy}();\n }${abortBranch}\n `}\\n`;\n}\n\n/**\n * Generate code for a RefineEffectCheckIR (inline refine function call).\n * Called from string/number/object check loops when a refine_effect is encountered.\n *\n * @param check - The refine effect check IR\n * @param expr - The expression to validate (may differ from g.input, e.g. objVar in object generators)\n * @param g - SlowGen context (provides path, issues)\n */\nexport function refineCheck(check: RefineEffectCheckIR, expr: string, g: SlowGen): string {\n // The refine's own message wins; without one, zod's finalizeIssue falls\n // through to the error map of the schema the check is attached to (the check\n // stamps its owner onto the issue), so the node's schema-level message is the\n // next rung. With neither, __zcFin applies the locale default.\n const message = check.message ?? g.typeMsg;\n const messageProp = message === undefined ? \"\" : `,message:${JSON.stringify(message)}`;\n // `.refine(fn, { path })` reports against a member of the refined value, so\n // the configured segments extend this node's path.\n const path = (check.path ?? []).reduce<string>(\n (acc, segment) =>\n typeof segment === \"number\"\n ? extendStaticPathIndex(acc, segment)\n : extendStaticPath(acc, segment),\n g.path,\n );\n // `.refine(fn, { params })`: $ZodCustom's check does\n // `if (def.params) _iss.params = def.params`, so the key is present only when\n // the schema declared one, and holds the ORIGINAL object — the extractor\n // parked it in `__rf` precisely so the reference survives (see\n // RefineEffectCheckIR.paramsRefIndex). Placed before `message` to keep the\n // key order zod produces.\n const paramsProp =\n check.paramsRefIndex === undefined\n ? \"\"\n : `,params:${emitConstant(g.ctx, \"rpa\", `__rf[${check.paramsRefIndex}]`)}`;\n // The predicate's return value is tested for a Promise before its truthiness\n // (see ZC_ASYNC_DECL): a Promise is truthy, so without the guard a plain\n // function returning one would ACCEPT every input where zod throws.\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n const result = g.temp(\"rr\");\n return emit`\n var ${result}=${emitEffectCallable(g.ctx, check)}(${expr});\n if(${result} instanceof Promise)${asy}();\n if(!${result}){\n ${g.issues}.push({code:\"custom\",path:${path}${paramsProp},input:${expr}${messageProp}});\n }`;\n}\n\n/**\n * Fast-path test for a RefineEffectCheckIR: the predicate's verdict, bound to a\n * local so a Promise can be told apart from a truthy value. A Promise throws\n * zod's `$ZodAsyncError` right here, EAGERLY: zod's `runChecks` throws the\n * moment a check returns a Promise under a synchronous parse — before any later\n * check, and even inside a union whose next option would have matched — so\n * deferring the throw to the slow walk (which a fast-eligible schema only runs\n * when `.error` is read) would turn zod's throw into a failure result. The\n * throw itself lives in a hosted helper, so the hot expression only pays the\n * `instanceof` test.\n */\nexport function fastRefineTest(check: RefineEffectCheckIR, expr: string, g: FastGen): string {\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n const verdict = g.local(\"fr\");\n return `((${verdict}=${emitEffectCallable(g.ctx, check)}(${expr})) instanceof Promise?${asy}():${verdict})`;\n}\n\n/**\n * Declare the shared invoker both superRefine helpers call. It is module-local\n * rather than an imported helper (lean mode declares it in the runtime module\n * beside them), so inline mode must place it in the preamble itself.\n */\nfunction emitSuperRefineRunner(ctx: SlowGen[\"ctx\"]): void {\n if (ctx.mode !== \"lean\" && !ctx.preamble.includes(ZC_SR_RUN_DECL)) {\n ctx.preamble.push(ZC_SR_RUN_DECL);\n }\n}\n\n/**\n * Fast-path test for a SuperRefineEffectCheckIR: a boolean term reporting that\n * the callback added no issue and left the value alone (see ZC_SR_OK_DECL).\n */\nexport function superRefineFastTest(\n check: SuperRefineEffectCheckIR,\n expr: string,\n g: FastGen,\n): string {\n emitSuperRefineRunner(g.ctx);\n const ok = emitRuntimeHelper(g.ctx, \"__zcSrOk\", ZC_SR_OK_DECL);\n return `${ok}(${emitEffectCallable(g.ctx, check)},${expr})`;\n}\n\n/**\n * Generate code for a SuperRefineEffectCheckIR: call the payload-taking\n * callback with a synthesized `{ value, issues }` and merge what it collected.\n * zod's own wrapper installs `addIssue` and normalizes the result, so the\n * issues are zod's — the helper only reprojects them onto this node's path and\n * strips the internal bookkeeping zod deletes before they become visible.\n *\n * The payload's `value` is writable public API, so it is written back to the\n * output slot the way an overwrite effect is. This walk is always the eager one\n * (the node reports as mutating, see hasMutation), so the write-back lands on\n * every parse that reaches it — not only on failures.\n */\nexport function superRefineCheck(\n check: SuperRefineEffectCheckIR,\n expr: string,\n g: SlowGen,\n): string {\n emitSuperRefineRunner(g.ctx);\n const helper = emitRuntimeHelper(g.ctx, \"__zcSr\", ZC_SR_DECL);\n const fn = emitEffectCallable(g.ctx, check);\n const p = g.temp(\"sp\");\n // The owning schema's message covers an added issue that carries none of its\n // own, as it does for a refine (see refineCheck); the helper applies it.\n const msgArg = g.typeMsg === undefined ? \"\" : `,${JSON.stringify(g.typeMsg)}`;\n let code = `var ${p}=${helper}(${fn},${expr},${g.path},${g.issues}${msgArg});${g.output}=${p}.value;`;\n // Inside a union option, an aborting issue must mark the option aborted so\n // pruning matches zod (see ZC_SR_DECL); elsewhere the flag is unobserved.\n if (g.aborted) code += `if(${p}.aborted){${g.aborted}=true;}`;\n return code;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"effect.js","names":[],"sources":["../../../../src/core/codegen/schemas/effect.ts"],"sourcesContent":["import type {\n PreprocessEffectIR,\n RefineEffectCheckIR,\n SuperRefineEffectCheckIR,\n TransformEffectIR,\n} from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n emitConstant,\n emitEffectCallable,\n emitRuntimeHelper,\n extendStaticPath,\n extendStaticPathIndex,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { ZC_ASYNC_DECL, ZC_SR_DECL, ZC_SR_OK_DECL, ZC_SR_RUN_DECL } from \"../issue-decls.js\";\n\n/**\n * Generate code for a TransformEffectIR node.\n * Validates the inner schema, then applies the transform function and writes back the result.\n */\nexport function slowEffect(ir: TransformEffectIR | PreprocessEffectIR, g: SlowGen): string {\n // A callback that returns a Promise is zod's synchronous-parse error, not a\n // value (see ZC_ASYNC_DECL); zod tests `_out instanceof Promise` right after\n // the call, so the guard sits at the same point.\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n if (ir.effectKind === \"preprocess\") {\n const valueVar = g.temp(\"pv\");\n // The callback's result is written to the output first, and the inner\n // schema then reads and writes it through that ONE expression, as a root\n // does. A rewriting inner reads back what it wrote — `.trim().min(1)`\n // measures the trimmed string, a coercion checks the converted value — so\n // handing it the result as its input and the output as its output made those\n // checks see the value from before the rewrite: nested in a walk that runs\n // eagerly, `z.preprocess(fn, z.string().trim().min(1))` accepted `\" \"`.\n return `${emit`\n var ${valueVar}=${emitEffectCallable(g.ctx, ir)}(${g.input});\n if(${valueVar} instanceof Promise)${asy}();\n ${g.output}=${valueVar};\n ${g.visit(ir.inner, { input: g.output, output: g.output, aborted: g.aborted })}\n `}\\n`;\n }\n\n const beforeVar = g.temp(\"ib\");\n const innerCode = g.visit(ir.inner);\n // A transform is `inner.transform(fn)` = a pipe(inner, transform): zod's\n // handlePipeResult aborts when `inner` produces any issue. Inside a union the\n // option must therefore count as aborted even if `inner`'s only issue is a\n // non-aborting `custom`/check-level code (mirrors slowPipe's abort branch).\n const abortBranch = g.aborted ? `else{${g.aborted}=true;}` : \"\";\n\n return `${emit`\n var ${beforeVar}=${g.issues}.length;\n ${innerCode}\n if(${g.issues}.length===${beforeVar}){\n ${g.output}=${emitEffectCallable(g.ctx, ir)}(${g.output});\n if(${g.output} instanceof Promise)${asy}();\n }${abortBranch}\n `}\\n`;\n}\n\n/**\n * Generate code for a RefineEffectCheckIR (inline refine function call).\n * Called from string/number/object check loops when a refine_effect is encountered.\n *\n * @param check - The refine effect check IR\n * @param expr - The expression to validate (may differ from g.input, e.g. objVar in object generators)\n * @param g - SlowGen context (provides path, issues)\n */\nexport function refineCheck(check: RefineEffectCheckIR, expr: string, g: SlowGen): string {\n // The refine's own message wins; without one, zod's finalizeIssue falls\n // through to the error map of the schema the check is attached to (the check\n // stamps its owner onto the issue), so the node's schema-level message is the\n // next rung. With neither, __zcFin applies the locale default.\n const message = check.message ?? g.typeMsg;\n const messageProp = message === undefined ? \"\" : `,message:${JSON.stringify(message)}`;\n // `.refine(fn, { path })` reports against a member of the refined value, so\n // the configured segments extend this node's path.\n const path = (check.path ?? []).reduce<string>(\n (acc, segment) =>\n typeof segment === \"number\"\n ? extendStaticPathIndex(g.ctx, acc, segment)\n : extendStaticPath(g.ctx, acc, segment),\n g.path,\n );\n // `.refine(fn, { params })`: $ZodCustom's check does\n // `if (def.params) _iss.params = def.params`, so the key is present only when\n // the schema declared one, and holds the ORIGINAL object — the extractor\n // parked it in `__rf` precisely so the reference survives (see\n // RefineEffectCheckIR.paramsRefIndex). Placed before `message` to keep the\n // key order zod produces.\n const paramsProp =\n check.paramsRefIndex === undefined\n ? \"\"\n : `,params:${emitConstant(g.ctx, \"rpa\", `__rf[${check.paramsRefIndex}]`)}`;\n // The predicate's return value is tested for a Promise before its truthiness\n // (see ZC_ASYNC_DECL): a Promise is truthy, so without the guard a plain\n // function returning one would ACCEPT every input where zod throws.\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n const result = g.temp(\"rr\");\n return emit`\n var ${result}=${emitEffectCallable(g.ctx, check)}(${expr});\n if(${result} instanceof Promise)${asy}();\n if(!${result}){\n ${g.issues}.push({code:\"custom\",path:${path}${paramsProp},input:${expr}${messageProp}});\n }`;\n}\n\n/**\n * Fast-path test for a RefineEffectCheckIR: the predicate's verdict, bound to a\n * local so a Promise can be told apart from a truthy value. A Promise throws\n * zod's `$ZodAsyncError` right here, EAGERLY: zod's `runChecks` throws the\n * moment a check returns a Promise under a synchronous parse — before any later\n * check, and even inside a union whose next option would have matched — so\n * deferring the throw to the slow walk (which a fast-eligible schema only runs\n * when `.error` is read) would turn zod's throw into a failure result. The\n * throw itself lives in a hosted helper, so the hot expression only pays the\n * `instanceof` test.\n */\nexport function fastRefineTest(check: RefineEffectCheckIR, expr: string, g: FastGen): string {\n const asy = emitRuntimeHelper(g.ctx, \"__zcAsy\", ZC_ASYNC_DECL);\n const verdict = g.local(\"fr\");\n return `((${verdict}=${emitEffectCallable(g.ctx, check)}(${expr})) instanceof Promise?${asy}():${verdict})`;\n}\n\n/**\n * Declare the shared invoker both superRefine helpers call. It is module-local\n * rather than an imported helper (lean mode declares it in the runtime module\n * beside them), so inline mode must place it in the preamble itself.\n */\nfunction emitSuperRefineRunner(ctx: SlowGen[\"ctx\"]): void {\n if (ctx.mode !== \"lean\" && !ctx.preamble.includes(ZC_SR_RUN_DECL)) {\n ctx.preamble.push(ZC_SR_RUN_DECL);\n }\n}\n\n/**\n * Fast-path test for a SuperRefineEffectCheckIR: a boolean term reporting that\n * the callback added no issue and left the value alone (see ZC_SR_OK_DECL).\n */\nexport function superRefineFastTest(\n check: SuperRefineEffectCheckIR,\n expr: string,\n g: FastGen,\n): string {\n emitSuperRefineRunner(g.ctx);\n const ok = emitRuntimeHelper(g.ctx, \"__zcSrOk\", ZC_SR_OK_DECL);\n return `${ok}(${emitEffectCallable(g.ctx, check)},${expr})`;\n}\n\n/**\n * Generate code for a SuperRefineEffectCheckIR: call the payload-taking\n * callback with a synthesized `{ value, issues }` and merge what it collected.\n * zod's own wrapper installs `addIssue` and normalizes the result, so the\n * issues are zod's — the helper only reprojects them onto this node's path and\n * strips the internal bookkeeping zod deletes before they become visible.\n *\n * The payload's `value` is writable public API, so it is written back to the\n * output slot the way an overwrite effect is. This walk is always the eager one\n * (the node reports as mutating, see hasMutation), so the write-back lands on\n * every parse that reaches it — not only on failures.\n */\nexport function superRefineCheck(\n check: SuperRefineEffectCheckIR,\n expr: string,\n g: SlowGen,\n): string {\n emitSuperRefineRunner(g.ctx);\n const helper = emitRuntimeHelper(g.ctx, \"__zcSr\", ZC_SR_DECL);\n const fn = emitEffectCallable(g.ctx, check);\n const p = g.temp(\"sp\");\n // The owning schema's message covers an added issue that carries none of its\n // own, as it does for a refine (see refineCheck); the helper applies it.\n const msgArg = g.typeMsg === undefined ? \"\" : `,${JSON.stringify(g.typeMsg)}`;\n let code = `var ${p}=${helper}(${fn},${expr},${g.path},${g.issues}${msgArg});${g.output}=${p}.value;`;\n // Inside a union option, an aborting issue must mark the option aborted so\n // pruning matches zod (see ZC_SR_DECL); elsewhere the flag is unobserved.\n if (g.aborted) code += `if(${p}.aborted){${g.aborted}=true;}`;\n return code;\n}\n"],"mappings":";;;;;;;;AAqBA,SAAgB,WAAW,IAA4C,GAAoB;CAIzF,MAAM,MAAM,kBAAkB,EAAE,KAAK,WAAW,aAAa;CAC7D,IAAI,GAAG,eAAe,cAAc;EAClC,MAAM,WAAW,EAAE,KAAK,IAAI;EAQ5B,OAAO,GAAG,IAAI;YACN,SAAS,GAAG,mBAAmB,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM;WACtD,SAAS,sBAAsB,IAAI;QACtC,EAAE,OAAO,GAAG,SAAS;QACrB,EAAE,MAAM,GAAG,OAAO;GAAE,OAAO,EAAE;GAAQ,QAAQ,EAAE;GAAQ,SAAS,EAAE;EAAQ,CAAC,EAAE;MAC/E;CACJ;CAEA,MAAM,YAAY,EAAE,KAAK,IAAI;CAC7B,MAAM,YAAY,EAAE,MAAM,GAAG,KAAK;CAKlC,MAAM,cAAc,EAAE,UAAU,QAAQ,EAAE,QAAQ,WAAW;CAE7D,OAAO,GAAG,IAAI;UACN,UAAU,GAAG,EAAE,OAAO;MAC1B,UAAU;SACP,EAAE,OAAO,YAAY,UAAU;QAChC,EAAE,OAAO,GAAG,mBAAmB,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,OAAO;WACnD,EAAE,OAAO,sBAAsB,IAAI;OACvC,YAAY;IACf;AACJ;;;;;;;;;AAUA,SAAgB,YAAY,OAA4B,MAAc,GAAoB;CAKxF,MAAM,UAAU,MAAM,WAAW,EAAE;CACnC,MAAM,cAAc,YAAY,KAAA,IAAY,KAAK,YAAY,KAAK,UAAU,OAAO;CAGnF,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAA,CAAG,QAC7B,KAAK,YACJ,OAAO,YAAY,WACf,sBAAsB,EAAE,KAAK,KAAK,OAAO,IACzC,iBAAiB,EAAE,KAAK,KAAK,OAAO,GAC1C,EAAE,IACJ;CAOA,MAAM,aACJ,MAAM,mBAAmB,KAAA,IACrB,KACA,WAAW,aAAa,EAAE,KAAK,OAAO,QAAQ,MAAM,eAAe,EAAE;CAI3E,MAAM,MAAM,kBAAkB,EAAE,KAAK,WAAW,aAAa;CAC7D,MAAM,SAAS,EAAE,KAAK,IAAI;CAC1B,OAAO,IAAI;UACH,OAAO,GAAG,mBAAmB,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK;SACpD,OAAO,sBAAsB,IAAI;UAChC,OAAO;QACT,EAAE,OAAO,4BAA4B,OAAO,WAAW,SAAS,OAAO,YAAY;;AAE3F;;;;;;;;;;;;AAaA,SAAgB,eAAe,OAA4B,MAAc,GAAoB;CAC3F,MAAM,MAAM,kBAAkB,EAAE,KAAK,WAAW,aAAa;CAC7D,MAAM,UAAU,EAAE,MAAM,IAAI;CAC5B,OAAO,KAAK,QAAQ,GAAG,mBAAmB,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK,wBAAwB,IAAI,KAAK,QAAQ;AAC3G;;;;;;AAOA,SAAS,sBAAsB,KAA2B;CACxD,IAAI,IAAI,SAAS,UAAU,CAAC,IAAI,SAAS,SAAA,+GAAuB,GAC9D,IAAI,SAAS,KAAK,cAAc;AAEpC;;;;;AAMA,SAAgB,oBACd,OACA,MACA,GACQ;CACR,sBAAsB,EAAE,GAAG;CAE3B,OAAO,GADI,kBAAkB,EAAE,KAAK,YAAY,aACrC,EAAE,GAAG,mBAAmB,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK;AAC3D;;;;;;;;;;;;;AAcA,SAAgB,iBACd,OACA,MACA,GACQ;CACR,sBAAsB,EAAE,GAAG;CAC3B,MAAM,SAAS,kBAAkB,EAAE,KAAK,UAAU,UAAU;CAC5D,MAAM,KAAK,mBAAmB,EAAE,KAAK,KAAK;CAC1C,MAAM,IAAI,EAAE,KAAK,IAAI;CAGrB,MAAM,SAAS,EAAE,YAAY,KAAA,IAAY,KAAK,IAAI,KAAK,UAAU,EAAE,OAAO;CAC1E,IAAI,OAAO,OAAO,EAAE,GAAG,OAAO,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS,OAAO,IAAI,EAAE,OAAO,GAAG,EAAE;CAG7F,IAAI,EAAE,SAAS,QAAQ,MAAM,EAAE,YAAY,EAAE,QAAQ;CACrD,OAAO;AACT"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { ZC_DELEGATE_ISSUES_DECL, ZC_RUN_DELEGATE_DECL } from "../issue-decls.js";
|
|
1
2
|
import { emitRfZod, emitRuntimeHelper } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
|
-
import { ZC_DELEGATE_ISSUES_DECL, ZC_RUN_DELEGATE_DECL } from "../issue-decls.js";
|
|
4
4
|
//#region src/core/codegen/schemas/fallback.ts
|
|
5
5
|
function slowFallback(ir, g) {
|
|
6
6
|
if (ir.refIndex !== void 0) return slowZodDelegate(ir.refIndex, g);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ZC_FZ_DECL, ZC_PFX_DECL, propertyKeyTest } from "../issue-decls.js";
|
|
1
2
|
import { declareFastTemps, emitRuntimeHelper, hasMutation } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
4
|
import { invalidType } from "../emit-issue.js";
|
|
4
|
-
import { ZC_FZ_DECL, ZC_PFX_DECL, propertyKeyTest } from "../issue-decls.js";
|
|
5
5
|
//#region src/core/codegen/schemas/map.ts
|
|
6
6
|
/**
|
|
7
7
|
* Map entries report through zod's `handleMapResult`, which branches on the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ZC_FSR_DECL } from "../issue-decls.js";
|
|
1
2
|
import { checkPriority, emitRuntimeHelper } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
4
|
import { invalidType, tooBig, tooSmall } from "../emit-issue.js";
|
|
4
|
-
import { ZC_FSR_DECL } from "../issue-decls.js";
|
|
5
5
|
import { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from "./effect.js";
|
|
6
6
|
//#region src/core/codegen/schemas/number.ts
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ZC_AB_DECL, ZC_PROTO_SCRUB_DECL } from "../issue-decls.js";
|
|
1
2
|
import { declareFastTemps, emitRuntimeHelper, escapeString, extendPath, extendStaticPath, hasMutation, keyMembershipTest, outputAlwaysDefined } from "../context.js";
|
|
2
3
|
import { emit } from "../emit.js";
|
|
3
4
|
import { invalidType, unrecognizedKeys } from "../emit-issue.js";
|
|
4
|
-
import { ZC_AB_DECL, ZC_PROTO_SCRUB_DECL } from "../issue-decls.js";
|
|
5
5
|
import { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from "./effect.js";
|
|
6
6
|
import { orderByRuntimeCost } from "../fast-size.js";
|
|
7
7
|
//#region src/core/codegen/schemas/object.ts
|
|
@@ -53,7 +53,7 @@ function slowObject(ir, g) {
|
|
|
53
53
|
const slots = [];
|
|
54
54
|
for (const [key, propIR] of parsedProperties(ir)) {
|
|
55
55
|
const keyStr = escapeString(key);
|
|
56
|
-
const propPath = extendStaticPath(g.path, key);
|
|
56
|
+
const propPath = extendStaticPath(g.ctx, g.path, key);
|
|
57
57
|
const propExpr = g.temp("sv");
|
|
58
58
|
code += `var ${propExpr}=${g.input}[${keyStr}];`;
|
|
59
59
|
let outExpr = propExpr;
|
|
@@ -144,7 +144,7 @@ function slowObject(ir, g) {
|
|
|
144
144
|
const keys = Object.keys(ir.properties);
|
|
145
145
|
const kVar = g.temp("ck");
|
|
146
146
|
const test = keyMembershipTest(g.ctx, keys, kVar);
|
|
147
|
-
const catchallPath = extendPath(g.path, kVar);
|
|
147
|
+
const catchallPath = extendPath(g.ctx, g.path, kVar);
|
|
148
148
|
let body;
|
|
149
149
|
if (rebuild) {
|
|
150
150
|
const slot = `${objVar}[${kVar}]`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object.js","names":[],"sources":["../../../../src/core/codegen/schemas/object.ts"],"sourcesContent":["import type { ObjectIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n declareFastTemps,\n emitRuntimeHelper,\n escapeString,\n extendPath,\n extendStaticPath,\n hasMutation,\n keyMembershipTest,\n outputAlwaysDefined,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, unrecognizedKeys } from \"../emit-issue.js\";\nimport { ZC_AB_DECL, ZC_PROTO_SCRUB_DECL } from \"../issue-decls.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\n\n/**\n * The shape entries whose schemas actually RUN. `$ZodObject` skips a declared\n * `__proto__` key in its shape loop (`if (key === \"__proto__\") continue`), so\n * that property is never validated and never written to the output — it is\n * only a recognized name for the strict/catchall passes, which read\n * `Object.keys(ir.properties)` directly. Writing it would be worse than\n * pointless: `{__proto__: v}` in an object literal, and `o[\"__proto__\"] = v`\n * on a plain object, both SET THE PROTOTYPE rather than define a key.\n */\nexport function parsedProperties(ir: ObjectIR): [string, SchemaIR][] {\n return Object.entries(ir.properties).filter(([key]) => key !== \"__proto__\");\n}\n\nexport function slowObject(ir: SchemaIR & { type: \"object\" }, g: SlowGen): string {\n let code = emit`\n if(typeof ${g.input}!==\"object\"||${g.input}===null||Array.isArray(${g.input})){\n ${invalidType(g, \"object\")}\n }else{`;\n\n // zod parses every object into a FRESH `{}`: the shape keys land first, in\n // shape order (handlePropertyResult), and a loose or catchall object then\n // appends the unknown keys in the input's for-in order (handleCatchall).\n //\n // Two modes reproduce that. REBUILD assembles exactly that object: always\n // for strip mode (zod's default z.object() output is only the declared keys),\n // and for a loose, strict or catchall object whenever a property or the\n // catchall rewrites its value — a rewritten value has to land somewhere, and\n // a spread clone of the input (what this once did) put it at the wrong\n // position: the input's key order, with a substituted key appended last.\n // PASS-THROUGH hands the input back by reference when nothing rewrites\n // anything; identity, key order and inherited keys then ride along with it,\n // which is the documented container-identity divergence (see\n // known-divergences.test.ts).\n const strip = ir.stripUnknownKeys === true;\n const rebuild =\n strip ||\n (ir.catchall !== undefined && hasMutation(ir.catchall)) ||\n Object.values(ir.properties).some(hasMutation);\n const objVar = g.temp(\"o\");\n if (!rebuild) {\n code += `var ${objVar}=${g.input};`;\n // The pass-through output is the input, and an own `__proto__` must not\n // ride along on it where zod's fresh `{}` never receives the key. Scrub it\n // (see ZC_PROTO_SCRUB_DECL); a rebuilt object never copies the key in the\n // first place.\n const scrub = emitRuntimeHelper(g.ctx, \"__zcPs\", ZC_PROTO_SCRUB_DECL);\n code += `${objVar}=${scrub}(${objVar});`;\n }\n /**\n * Pass-through only: land a nested node's REPLACEMENT value on the output.\n * A pass-through property never rewrites its value (that is what\n * pass-through means), but a nested object or record can still hand back a\n * proto-scrubbed COPY of its input, and that copy has to reach the output\n * object — not the caller's object. Writing it straight into `objVar` did\n * exactly that when `objVar` was the input: the caller's own object was\n * edited in place (its nested value swapped for the copy), and a frozen\n * input threw \"Cannot assign to read only property\" out of `safeParse`. So\n * the output becomes a copy of its own the first time a replacement lands,\n * and only then. Spread is safe here: `objVar` is still the input only when\n * the scrub above found no own `__proto__` on it.\n */\n const handoff = (outVar: string, inVar: string, keyExpr: string): string =>\n `if(${outVar}!==${inVar}){if(${objVar}===${g.input}){${objVar}={...${g.input}};}${objVar}[${keyExpr}]=${outVar};}`;\n\n // Object-level refines are gated on zod's ABORT rule, not on \"did anything\n // fail\": zod parses the properties (plus the strict/catchall passes) into the\n // payload and then skips its check chain only when `util.aborted` holds — i.e.\n // when one of those issues is non-continuable. A property that failed its own\n // `min`/format check reports a CONTINUABLE issue, so the outer refine still\n // runs and both messages surface — and so does an unrecognized key, which zod\n // pushes with `continue: true`; a property that failed to parse at all\n // (`invalid_type`, a bad record key) aborts and suppresses it. Snapshot the\n // issue count before the properties so the scan covers exactly this node's\n // own parse, as zod's fresh sub-payload does.\n const refineMark = ir.checks && ir.checks.length > 0 ? g.temp(\"rm\") : \"\";\n if (refineMark) code += `var ${refineMark}=${g.issues}.length;`;\n\n const skipAbsent = new Set(ir.skipAbsentKeys ?? []);\n const suppressAbsent = new Set(ir.suppressAbsentKeys ?? []);\n const nonoptional = new Set(ir.nonoptionalKeys ?? []);\n /** Rebuild only: per-property output slot + whether it is always in the result. */\n const slots: { always: boolean; keyStr: string; value: string }[] = [];\n\n for (const [key, propIR] of parsedProperties(ir)) {\n const keyStr = escapeString(key);\n const propPath = extendStaticPath(g.path, key);\n // Every mode validates the value read from the ORIGINAL input, held in a\n // local. zod parses `input[key]` — a prototype-inclusive read — so a value\n // found on the prototype is accepted and, on a rebuild, copied out as an\n // own key. Reading through a spread clone, as the loose/strict/catchall\n // branch once did, turned such a value into `undefined` (spread copies own\n // keys only): the fast and build paths, which read `input[key]`, rejected\n // the input, this walk then found nothing wrong with it, and a strict\n // object came back as a failure with an EMPTY issue list. The local also\n // spares every check the megamorphic re-load of `o[key]` — the clone's map\n // changed with every key added.\n const propExpr = g.temp(\"sv\");\n code += `var ${propExpr}=${g.input}[${keyStr}];`;\n // A rebuild assembles the output from the local afterwards (in shape order,\n // below). A pass-through property is handed a slot of its own to write a\n // replacement into, which `handoff` then lands on the output.\n let outExpr = propExpr;\n if (rebuild) {\n slots.push({ always: outputAlwaysDefined(propIR), keyStr, value: propExpr });\n } else {\n outExpr = g.temp(\"ov\");\n code += `var ${outExpr}=${propExpr};`;\n }\n const propCode = g.visit(propIR, { input: propExpr, output: outExpr, path: propPath });\n // The three absent-key rules of zod's handlePropertyResult (see ObjectIR).\n // Presence is tested on the ORIGINAL input, as zod's `key in input` is —\n // a clone would hide an inherited key.\n //\n // The two rules that test presence AFTER running the property snapshot it\n // FIRST, exactly as zod reads `isPresent` before it looks at the result. A\n // property writes nowhere but its own local, so nothing it makes of\n // `undefined` can create the very key it is asked about (writing straight\n // into the output object once did that: `z.looseObject({a: z.custom()})` on\n // `{}` lost its `nonoptional` issue and left the caller's object carrying\n // an `a` zod never writes); dropping its value is resetting that local.\n const dropValue = rebuild ? `${propExpr}=undefined;` : `${outExpr}=${propExpr};`;\n if (skipAbsent.has(key)) {\n code += emit`if(${keyStr} in ${g.input}){${propCode}}`;\n } else if (suppressAbsent.has(key)) {\n // A defaulted optional-out property runs, but a failure on an absent key\n // is discarded whole: issues and whatever value it wrote before failing.\n const beforeVar = g.temp(\"ob\");\n const presentVar = g.temp(\"op\");\n code += emit`\n var ${presentVar}=${keyStr} in ${g.input};\n var ${beforeVar}=${g.issues}.length;\n ${propCode}\n if(!${presentVar}&&${g.issues}.length>${beforeVar}){\n ${g.issues}.length=${beforeVar};${dropValue}\n }`;\n } else if (nonoptional.has(key)) {\n // A required key that is absent fails as such when its schema raised\n // nothing for the `undefined` it saw. zod pushes this one without an\n // `inst`, so no schema-level message reaches it — and it returns without\n // assigning, so whatever the property made of `undefined` is dropped.\n const beforeVar = g.temp(\"ob\");\n const presentVar = g.temp(\"op\");\n code += emit`\n var ${presentVar}=${keyStr} in ${g.input};\n var ${beforeVar}=${g.issues}.length;\n ${propCode}\n if(!${presentVar}){\n ${dropValue}\n if(${g.issues}.length===${beforeVar}){\n ${invalidType(g, \"nonoptional\", { input: \"undefined\", path: propPath, codeFirst: true, useTypeMsg: false })}\n }\n }`;\n } else {\n code += propCode;\n }\n if (!rebuild) code += handoff(outExpr, propExpr, keyStr);\n }\n\n if (rebuild) {\n // Assemble the result in shape order (zod's key order), taking as long a\n // LEADING run of always-present keys as possible into one object literal:\n // V8 stamps a literal out of a cached boilerplate map in a single\n // allocation, where adding keys one at a time walks a transition chain and\n // re-checks the map on every store — measured 8.1x (20 keys) / 2.8x (7\n // keys, one optional) on the whole safeParse.\n //\n // Everything after the first conditional key is appended so insertion order\n // still matches zod. The per-key test is zod's own: keep the key when the\n // parsed value is defined, or when it was present on the input at all\n // (`key in input`, prototype included — an own `k: undefined` survives).\n const literal: string[] = [];\n let appends = \"\";\n let leading = true;\n for (const slot of slots) {\n if (leading && slot.always) {\n literal.push(`${slot.keyStr}:${slot.value}`);\n continue;\n }\n leading = false;\n appends += slot.always\n ? `${objVar}[${slot.keyStr}]=${slot.value};`\n : `if(${slot.value}!==undefined||(${slot.keyStr} in ${g.input})){${objVar}[${slot.keyStr}]=${slot.value};}`;\n }\n code += `var ${objVar}={${literal.join(\",\")}};${appends}`;\n\n // A rebuilt loose object then takes every unknown key, in the input's\n // for-in order — zod's handleCatchall running its `unknown` catchall, which\n // hands each value back as it is and assigns it as an own key, inherited\n // ones included. (A catchall with a schema does the same in its own pass\n // below; a strict object reports the keys instead.)\n if (!strip && !ir.strict && ir.catchall === undefined) {\n const kVar = g.temp(\"lk\");\n const test = keyMembershipTest(g.ctx, Object.keys(ir.properties), kVar);\n code += emit`\n for(var ${kVar} in ${g.input}){\n if(!(${test})&&${kVar}!==\"__proto__\"){${objVar}[${kVar}]=${g.input}[${kVar}];}\n }`;\n }\n }\n\n // Strict unknown-key pass — zod's handleCatchall, byte-exact: for-in over\n // the ORIGINAL input (inherited enumerable keys count, no hasOwnProperty),\n // ALL unknown keys collected into one issue, pushed AFTER property issues\n // and before object-level refines.\n if (ir.strict) {\n const keys = Object.keys(ir.properties);\n const ukVar = g.temp(\"uk\");\n const kVar = g.temp(\"k\");\n const test = keyMembershipTest(g.ctx, keys, kVar);\n code += emit`\n var ${ukVar}=null;\n for(var ${kVar} in ${g.input}){\n if(!(${test})){(${ukVar}=${ukVar}||[]).push(${kVar});}\n }\n if(${ukVar}!==null){\n ${unrecognizedKeys(g, ukVar)}\n }`;\n }\n\n // .catchall(schema): validate every key NOT in the shape, mirroring zod's\n // handleCatchall — same bare for-in over the ORIGINAL input as the strict\n // pass (inherited enumerable keys count, no hasOwnProperty guard), each\n // issue reported at the key. Runs after the properties, as zod does. An\n // undeclared `__proto__` is skipped like zod skips it: never validated, and\n // never assigned, since `o[\"__proto__\"]=v` on a plain object would replace\n // its prototype instead of adding a key. (The strict pass above still\n // REPORTS it — there it is an unknown key like any other.)\n //\n // On a rebuild each unknown key is copied onto the fresh output before it is\n // validated — which reproduces zod, whose fresh output object gains an OWN\n // key for every for-in key it saw, inherited ones included, whether or not\n // the catchall accepted its value. The key's slot is then BOTH the input and\n // the output, exactly as a shape property's local is: a value-rewriting\n // catchall (coerce, .trim(), a default) writes through the same expression\n // it later re-reads, so splitting them makes the rewrite invisible to its own\n // checks. A pass-through catchall writes nothing, so the object stays by\n // reference; it gets the same replacement slot a pass-through property does,\n // for the same reason.\n if (ir.catchall) {\n const keys = Object.keys(ir.properties);\n const kVar = g.temp(\"ck\");\n const test = keyMembershipTest(g.ctx, keys, kVar);\n const catchallPath = extendPath(g.path, kVar);\n let body: string;\n if (rebuild) {\n const slot = `${objVar}[${kVar}]`;\n body = `${slot}=${g.input}[${kVar}];${g.visit(ir.catchall, { input: slot, output: slot, path: catchallPath })}`;\n } else {\n const inVar = g.temp(\"cv\");\n const outVar = g.temp(\"co\");\n body =\n `var ${inVar}=${g.input}[${kVar}];var ${outVar}=${inVar};` +\n g.visit(ir.catchall, { input: inVar, output: outVar, path: catchallPath }) +\n handoff(outVar, inVar, kVar);\n }\n code += emit`\n for(var ${kVar} in ${g.input}){\n if(!(${test})&&${kVar}!==\"__proto__\"){${body}}\n }`;\n }\n\n // Always written back: a rebuild is a fresh object, and a pass-through may\n // have become a copy (the scrub above, or a handoff) even where nothing\n // rewrote a value.\n code += `${g.output}=${objVar};`;\n\n // Object-level refine effects: z.object({...}).refine(fn), suppressed when the\n // parse phase aborted (see refineMark). One gate covers every effect: each of\n // them can only add a continuable `custom` issue, so zod's per-check\n // re-evaluation of `isAborted` can never flip between them.\n if (ir.checks && ir.checks.length > 0) {\n let refines = \"\";\n for (const check of ir.checks) {\n refines +=\n check.kind === \"super_refine_effect\"\n ? superRefineCheck(check, objVar, g)\n : refineCheck(check, objVar, g);\n }\n const aborted = emitRuntimeHelper(g.ctx, \"__zcAb\", ZC_AB_DECL);\n code += `if(!${aborted}(${g.issues},${refineMark})){${refines}}`;\n }\n\n code += `}\\n`;\n return code;\n}\n\n/**\n * Property entries in the order their fast-checks should be `&&`-chained:\n * cheapest first, declaration order preserved among equals (Array#sort is\n * stable). Valid input runs every conjunct whatever the order, so this costs\n * nothing on the hot path; a REJECT stops at the first false conjunct, so\n * pricing a `z.email()` behind the `kind` literal that actually discriminates\n * is what makes union probing and `.is()` misses cheap (see\n * estimateRuntimeCost). The SLOW path keeps declaration order — that one's\n * output is the issue list, whose order is part of zod parity.\n */\nfunction orderedProperties(ir: ObjectIR, g: FastGen): [string, SchemaIR][] {\n return orderByRuntimeCost(parsedProperties(ir), ([, propIR]) => propIR, g.ctx);\n}\n\n/**\n * Property/strict/refine fast-checks for an object, WITHOUT the leading\n * `typeof===object && !==null && !Array.isArray` type-guard. Returns the\n * conjunct parts (joinable with `&&`), or null if any child is fast-ineligible.\n *\n * `skipKey`, when given, omits that one property's check. Used by the\n * discriminated-union fast path (via `g.discSkipKey`): the enclosing `switch`\n * has already matched the discriminator's value, so re-checking it is redundant.\n */\nfunction fastObjectBody(ir: ObjectIR, g: FastGen, skipKey?: string): string[] | null {\n const x = g.input;\n const parts: string[] = [];\n const absentAccepts = new Set([...(ir.skipAbsentKeys ?? []), ...(ir.suppressAbsentKeys ?? [])]);\n const nonoptional = new Set(ir.nonoptionalKeys ?? []);\n\n for (const [key, propIR] of orderedProperties(ir, g)) {\n if (key === skipKey) continue;\n const keyStr = escapeString(key);\n const propCheck = g.visit(propIR, { input: `${x}[${keyStr}]` });\n if (propCheck === null) return null; // All-or-nothing\n // Presence rules keyed on the schema's `optin`/`optout` (see ObjectIR): a\n // required key must be there whatever its schema makes of `undefined`, and\n // an optional-out key on the \"optional\"/\"defaulted\" rungs is accepted when\n // it is not, whatever the property would say.\n if (nonoptional.has(key)) {\n parts.push(propCheck === \"true\" ? `${keyStr} in ${x}` : `${keyStr} in ${x}&&${propCheck}`);\n } else if (absentAccepts.has(key)) {\n parts.push(`(!(${keyStr} in ${x})||${propCheck})`);\n } else {\n parts.push(propCheck);\n }\n }\n\n // Strict unknown-key pass: hosted boolean helper (a for-in loop cannot live\n // in the && chain). Same for-in iteration as the slow path — fast/slow\n // agreement is load-bearing under the __zcFinD deferral. The membership set is\n // the FULL key list (the discriminator is a recognized key), independent of\n // skipKey, which only suppresses re-validating the discriminator's value.\n if (ir.strict) {\n const keys = Object.keys(ir.properties);\n const fnName = g.temp(\"so\");\n const test = keyMembershipTest(g.ctx, keys, \"k\");\n g.ctx.preamble.push(\n `function ${fnName}(o){for(var k in o){if(!(${test}))return false;}return true;}`,\n );\n parts.push(`${fnName}(${x})`);\n }\n\n // .catchall(schema): same hosted for-in as strict, but each unrecognized key\n // is checked against the catchall rather than rejected outright. The value is\n // hoisted into a local for the same reason fastRecord does it — repeated\n // `o[k]` computed loads are not eliminated across check boundaries.\n if (ir.catchall) {\n const kv = g.temp(\"cak\");\n const vv = g.temp(\"cav\");\n const catchallGen = g.scoped(vv);\n const valCheck = catchallGen.visit(ir.catchall, { input: vv });\n if (valCheck === null) return null;\n if (valCheck !== \"true\") {\n const fnName = g.temp(\"co\");\n const test = keyMembershipTest(g.ctx, Object.keys(ir.properties), kv);\n g.ctx.preamble.push(\n `function ${fnName}(o){${declareFastTemps(catchallGen.scope)}var ${kv},${vv};for(${kv} in o){if(!(${test})&&${kv}!==\"__proto__\"){${vv}=o[${kv}];if(!(${valCheck}))return false;}}return true;}`,\n );\n parts.push(`${fnName}(${x})`);\n }\n }\n\n // Object-level refine effects (appended last — run after property checks short-circuit)\n if (ir.checks) {\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(fastRefineTest(check, x, g));\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n }\n\n return parts;\n}\n\nexport function fastObject(ir: ObjectIR, g: FastGen): string | null {\n // A strip object still gets an expression. Stripping reshapes the OUTPUT, not\n // the verdict, so this remains an exact acceptance predicate — which is what\n // `.is()` installs, and what the build path reuses to validate the subtrees it\n // passes through by reference. What it must NOT do is stand in for the parse\n // result: generateValidator withholds the `data:input` shortcut whenever the\n // schema rebuilds (see rebuildsOutput).\n const x = g.input;\n const body = fastObjectBody(ir, g, g.discSkipKey);\n if (body === null) return null;\n // Discriminated-union option: the enclosing switch (and the caller's guard)\n // already established object-ness and the discriminator value, so emit only\n // the remaining checks — no leading type-guard. An option with nothing left\n // to check accepts unconditionally (\"true\").\n if (g.discSkipKey !== undefined) {\n return body.length > 0 ? body.join(\"&&\") : \"true\";\n }\n return [`typeof ${x}===\"object\"`, `${x}!==null`, `!Array.isArray(${x})`, ...body].join(\"&&\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"object.js","names":[],"sources":["../../../../src/core/codegen/schemas/object.ts"],"sourcesContent":["import type { ObjectIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n declareFastTemps,\n emitRuntimeHelper,\n escapeString,\n extendPath,\n extendStaticPath,\n hasMutation,\n keyMembershipTest,\n outputAlwaysDefined,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, unrecognizedKeys } from \"../emit-issue.js\";\nimport { ZC_AB_DECL, ZC_PROTO_SCRUB_DECL } from \"../issue-decls.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from \"./effect.js\";\n\n/**\n * The shape entries whose schemas actually RUN. `$ZodObject` skips a declared\n * `__proto__` key in its shape loop (`if (key === \"__proto__\") continue`), so\n * that property is never validated and never written to the output — it is\n * only a recognized name for the strict/catchall passes, which read\n * `Object.keys(ir.properties)` directly. Writing it would be worse than\n * pointless: `{__proto__: v}` in an object literal, and `o[\"__proto__\"] = v`\n * on a plain object, both SET THE PROTOTYPE rather than define a key.\n */\nexport function parsedProperties(ir: ObjectIR): [string, SchemaIR][] {\n return Object.entries(ir.properties).filter(([key]) => key !== \"__proto__\");\n}\n\nexport function slowObject(ir: SchemaIR & { type: \"object\" }, g: SlowGen): string {\n let code = emit`\n if(typeof ${g.input}!==\"object\"||${g.input}===null||Array.isArray(${g.input})){\n ${invalidType(g, \"object\")}\n }else{`;\n\n // zod parses every object into a FRESH `{}`: the shape keys land first, in\n // shape order (handlePropertyResult), and a loose or catchall object then\n // appends the unknown keys in the input's for-in order (handleCatchall).\n //\n // Two modes reproduce that. REBUILD assembles exactly that object: always\n // for strip mode (zod's default z.object() output is only the declared keys),\n // and for a loose, strict or catchall object whenever a property or the\n // catchall rewrites its value — a rewritten value has to land somewhere, and\n // a spread clone of the input (what this once did) put it at the wrong\n // position: the input's key order, with a substituted key appended last.\n // PASS-THROUGH hands the input back by reference when nothing rewrites\n // anything; identity, key order and inherited keys then ride along with it,\n // which is the documented container-identity divergence (see\n // known-divergences.test.ts).\n const strip = ir.stripUnknownKeys === true;\n const rebuild =\n strip ||\n (ir.catchall !== undefined && hasMutation(ir.catchall)) ||\n Object.values(ir.properties).some(hasMutation);\n const objVar = g.temp(\"o\");\n if (!rebuild) {\n code += `var ${objVar}=${g.input};`;\n // The pass-through output is the input, and an own `__proto__` must not\n // ride along on it where zod's fresh `{}` never receives the key. Scrub it\n // (see ZC_PROTO_SCRUB_DECL); a rebuilt object never copies the key in the\n // first place.\n const scrub = emitRuntimeHelper(g.ctx, \"__zcPs\", ZC_PROTO_SCRUB_DECL);\n code += `${objVar}=${scrub}(${objVar});`;\n }\n /**\n * Pass-through only: land a nested node's REPLACEMENT value on the output.\n * A pass-through property never rewrites its value (that is what\n * pass-through means), but a nested object or record can still hand back a\n * proto-scrubbed COPY of its input, and that copy has to reach the output\n * object — not the caller's object. Writing it straight into `objVar` did\n * exactly that when `objVar` was the input: the caller's own object was\n * edited in place (its nested value swapped for the copy), and a frozen\n * input threw \"Cannot assign to read only property\" out of `safeParse`. So\n * the output becomes a copy of its own the first time a replacement lands,\n * and only then. Spread is safe here: `objVar` is still the input only when\n * the scrub above found no own `__proto__` on it.\n */\n const handoff = (outVar: string, inVar: string, keyExpr: string): string =>\n `if(${outVar}!==${inVar}){if(${objVar}===${g.input}){${objVar}={...${g.input}};}${objVar}[${keyExpr}]=${outVar};}`;\n\n // Object-level refines are gated on zod's ABORT rule, not on \"did anything\n // fail\": zod parses the properties (plus the strict/catchall passes) into the\n // payload and then skips its check chain only when `util.aborted` holds — i.e.\n // when one of those issues is non-continuable. A property that failed its own\n // `min`/format check reports a CONTINUABLE issue, so the outer refine still\n // runs and both messages surface — and so does an unrecognized key, which zod\n // pushes with `continue: true`; a property that failed to parse at all\n // (`invalid_type`, a bad record key) aborts and suppresses it. Snapshot the\n // issue count before the properties so the scan covers exactly this node's\n // own parse, as zod's fresh sub-payload does.\n const refineMark = ir.checks && ir.checks.length > 0 ? g.temp(\"rm\") : \"\";\n if (refineMark) code += `var ${refineMark}=${g.issues}.length;`;\n\n const skipAbsent = new Set(ir.skipAbsentKeys ?? []);\n const suppressAbsent = new Set(ir.suppressAbsentKeys ?? []);\n const nonoptional = new Set(ir.nonoptionalKeys ?? []);\n /** Rebuild only: per-property output slot + whether it is always in the result. */\n const slots: { always: boolean; keyStr: string; value: string }[] = [];\n\n for (const [key, propIR] of parsedProperties(ir)) {\n const keyStr = escapeString(key);\n const propPath = extendStaticPath(g.ctx, g.path, key);\n // Every mode validates the value read from the ORIGINAL input, held in a\n // local. zod parses `input[key]` — a prototype-inclusive read — so a value\n // found on the prototype is accepted and, on a rebuild, copied out as an\n // own key. Reading through a spread clone, as the loose/strict/catchall\n // branch once did, turned such a value into `undefined` (spread copies own\n // keys only): the fast and build paths, which read `input[key]`, rejected\n // the input, this walk then found nothing wrong with it, and a strict\n // object came back as a failure with an EMPTY issue list. The local also\n // spares every check the megamorphic re-load of `o[key]` — the clone's map\n // changed with every key added.\n const propExpr = g.temp(\"sv\");\n code += `var ${propExpr}=${g.input}[${keyStr}];`;\n // A rebuild assembles the output from the local afterwards (in shape order,\n // below). A pass-through property is handed a slot of its own to write a\n // replacement into, which `handoff` then lands on the output.\n let outExpr = propExpr;\n if (rebuild) {\n slots.push({ always: outputAlwaysDefined(propIR), keyStr, value: propExpr });\n } else {\n outExpr = g.temp(\"ov\");\n code += `var ${outExpr}=${propExpr};`;\n }\n const propCode = g.visit(propIR, { input: propExpr, output: outExpr, path: propPath });\n // The three absent-key rules of zod's handlePropertyResult (see ObjectIR).\n // Presence is tested on the ORIGINAL input, as zod's `key in input` is —\n // a clone would hide an inherited key.\n //\n // The two rules that test presence AFTER running the property snapshot it\n // FIRST, exactly as zod reads `isPresent` before it looks at the result. A\n // property writes nowhere but its own local, so nothing it makes of\n // `undefined` can create the very key it is asked about (writing straight\n // into the output object once did that: `z.looseObject({a: z.custom()})` on\n // `{}` lost its `nonoptional` issue and left the caller's object carrying\n // an `a` zod never writes); dropping its value is resetting that local.\n const dropValue = rebuild ? `${propExpr}=undefined;` : `${outExpr}=${propExpr};`;\n if (skipAbsent.has(key)) {\n code += emit`if(${keyStr} in ${g.input}){${propCode}}`;\n } else if (suppressAbsent.has(key)) {\n // A defaulted optional-out property runs, but a failure on an absent key\n // is discarded whole: issues and whatever value it wrote before failing.\n const beforeVar = g.temp(\"ob\");\n const presentVar = g.temp(\"op\");\n code += emit`\n var ${presentVar}=${keyStr} in ${g.input};\n var ${beforeVar}=${g.issues}.length;\n ${propCode}\n if(!${presentVar}&&${g.issues}.length>${beforeVar}){\n ${g.issues}.length=${beforeVar};${dropValue}\n }`;\n } else if (nonoptional.has(key)) {\n // A required key that is absent fails as such when its schema raised\n // nothing for the `undefined` it saw. zod pushes this one without an\n // `inst`, so no schema-level message reaches it — and it returns without\n // assigning, so whatever the property made of `undefined` is dropped.\n const beforeVar = g.temp(\"ob\");\n const presentVar = g.temp(\"op\");\n code += emit`\n var ${presentVar}=${keyStr} in ${g.input};\n var ${beforeVar}=${g.issues}.length;\n ${propCode}\n if(!${presentVar}){\n ${dropValue}\n if(${g.issues}.length===${beforeVar}){\n ${invalidType(g, \"nonoptional\", { input: \"undefined\", path: propPath, codeFirst: true, useTypeMsg: false })}\n }\n }`;\n } else {\n code += propCode;\n }\n if (!rebuild) code += handoff(outExpr, propExpr, keyStr);\n }\n\n if (rebuild) {\n // Assemble the result in shape order (zod's key order), taking as long a\n // LEADING run of always-present keys as possible into one object literal:\n // V8 stamps a literal out of a cached boilerplate map in a single\n // allocation, where adding keys one at a time walks a transition chain and\n // re-checks the map on every store — measured 8.1x (20 keys) / 2.8x (7\n // keys, one optional) on the whole safeParse.\n //\n // Everything after the first conditional key is appended so insertion order\n // still matches zod. The per-key test is zod's own: keep the key when the\n // parsed value is defined, or when it was present on the input at all\n // (`key in input`, prototype included — an own `k: undefined` survives).\n const literal: string[] = [];\n let appends = \"\";\n let leading = true;\n for (const slot of slots) {\n if (leading && slot.always) {\n literal.push(`${slot.keyStr}:${slot.value}`);\n continue;\n }\n leading = false;\n appends += slot.always\n ? `${objVar}[${slot.keyStr}]=${slot.value};`\n : `if(${slot.value}!==undefined||(${slot.keyStr} in ${g.input})){${objVar}[${slot.keyStr}]=${slot.value};}`;\n }\n code += `var ${objVar}={${literal.join(\",\")}};${appends}`;\n\n // A rebuilt loose object then takes every unknown key, in the input's\n // for-in order — zod's handleCatchall running its `unknown` catchall, which\n // hands each value back as it is and assigns it as an own key, inherited\n // ones included. (A catchall with a schema does the same in its own pass\n // below; a strict object reports the keys instead.)\n if (!strip && !ir.strict && ir.catchall === undefined) {\n const kVar = g.temp(\"lk\");\n const test = keyMembershipTest(g.ctx, Object.keys(ir.properties), kVar);\n code += emit`\n for(var ${kVar} in ${g.input}){\n if(!(${test})&&${kVar}!==\"__proto__\"){${objVar}[${kVar}]=${g.input}[${kVar}];}\n }`;\n }\n }\n\n // Strict unknown-key pass — zod's handleCatchall, byte-exact: for-in over\n // the ORIGINAL input (inherited enumerable keys count, no hasOwnProperty),\n // ALL unknown keys collected into one issue, pushed AFTER property issues\n // and before object-level refines.\n if (ir.strict) {\n const keys = Object.keys(ir.properties);\n const ukVar = g.temp(\"uk\");\n const kVar = g.temp(\"k\");\n const test = keyMembershipTest(g.ctx, keys, kVar);\n code += emit`\n var ${ukVar}=null;\n for(var ${kVar} in ${g.input}){\n if(!(${test})){(${ukVar}=${ukVar}||[]).push(${kVar});}\n }\n if(${ukVar}!==null){\n ${unrecognizedKeys(g, ukVar)}\n }`;\n }\n\n // .catchall(schema): validate every key NOT in the shape, mirroring zod's\n // handleCatchall — same bare for-in over the ORIGINAL input as the strict\n // pass (inherited enumerable keys count, no hasOwnProperty guard), each\n // issue reported at the key. Runs after the properties, as zod does. An\n // undeclared `__proto__` is skipped like zod skips it: never validated, and\n // never assigned, since `o[\"__proto__\"]=v` on a plain object would replace\n // its prototype instead of adding a key. (The strict pass above still\n // REPORTS it — there it is an unknown key like any other.)\n //\n // On a rebuild each unknown key is copied onto the fresh output before it is\n // validated — which reproduces zod, whose fresh output object gains an OWN\n // key for every for-in key it saw, inherited ones included, whether or not\n // the catchall accepted its value. The key's slot is then BOTH the input and\n // the output, exactly as a shape property's local is: a value-rewriting\n // catchall (coerce, .trim(), a default) writes through the same expression\n // it later re-reads, so splitting them makes the rewrite invisible to its own\n // checks. A pass-through catchall writes nothing, so the object stays by\n // reference; it gets the same replacement slot a pass-through property does,\n // for the same reason.\n if (ir.catchall) {\n const keys = Object.keys(ir.properties);\n const kVar = g.temp(\"ck\");\n const test = keyMembershipTest(g.ctx, keys, kVar);\n const catchallPath = extendPath(g.ctx, g.path, kVar);\n let body: string;\n if (rebuild) {\n const slot = `${objVar}[${kVar}]`;\n body = `${slot}=${g.input}[${kVar}];${g.visit(ir.catchall, { input: slot, output: slot, path: catchallPath })}`;\n } else {\n const inVar = g.temp(\"cv\");\n const outVar = g.temp(\"co\");\n body =\n `var ${inVar}=${g.input}[${kVar}];var ${outVar}=${inVar};` +\n g.visit(ir.catchall, { input: inVar, output: outVar, path: catchallPath }) +\n handoff(outVar, inVar, kVar);\n }\n code += emit`\n for(var ${kVar} in ${g.input}){\n if(!(${test})&&${kVar}!==\"__proto__\"){${body}}\n }`;\n }\n\n // Always written back: a rebuild is a fresh object, and a pass-through may\n // have become a copy (the scrub above, or a handoff) even where nothing\n // rewrote a value.\n code += `${g.output}=${objVar};`;\n\n // Object-level refine effects: z.object({...}).refine(fn), suppressed when the\n // parse phase aborted (see refineMark). One gate covers every effect: each of\n // them can only add a continuable `custom` issue, so zod's per-check\n // re-evaluation of `isAborted` can never flip between them.\n if (ir.checks && ir.checks.length > 0) {\n let refines = \"\";\n for (const check of ir.checks) {\n refines +=\n check.kind === \"super_refine_effect\"\n ? superRefineCheck(check, objVar, g)\n : refineCheck(check, objVar, g);\n }\n const aborted = emitRuntimeHelper(g.ctx, \"__zcAb\", ZC_AB_DECL);\n code += `if(!${aborted}(${g.issues},${refineMark})){${refines}}`;\n }\n\n code += `}\\n`;\n return code;\n}\n\n/**\n * Property entries in the order their fast-checks should be `&&`-chained:\n * cheapest first, declaration order preserved among equals (Array#sort is\n * stable). Valid input runs every conjunct whatever the order, so this costs\n * nothing on the hot path; a REJECT stops at the first false conjunct, so\n * pricing a `z.email()` behind the `kind` literal that actually discriminates\n * is what makes union probing and `.is()` misses cheap (see\n * estimateRuntimeCost). The SLOW path keeps declaration order — that one's\n * output is the issue list, whose order is part of zod parity.\n */\nfunction orderedProperties(ir: ObjectIR, g: FastGen): [string, SchemaIR][] {\n return orderByRuntimeCost(parsedProperties(ir), ([, propIR]) => propIR, g.ctx);\n}\n\n/**\n * Property/strict/refine fast-checks for an object, WITHOUT the leading\n * `typeof===object && !==null && !Array.isArray` type-guard. Returns the\n * conjunct parts (joinable with `&&`), or null if any child is fast-ineligible.\n *\n * `skipKey`, when given, omits that one property's check. Used by the\n * discriminated-union fast path (via `g.discSkipKey`): the enclosing `switch`\n * has already matched the discriminator's value, so re-checking it is redundant.\n */\nfunction fastObjectBody(ir: ObjectIR, g: FastGen, skipKey?: string): string[] | null {\n const x = g.input;\n const parts: string[] = [];\n const absentAccepts = new Set([...(ir.skipAbsentKeys ?? []), ...(ir.suppressAbsentKeys ?? [])]);\n const nonoptional = new Set(ir.nonoptionalKeys ?? []);\n\n for (const [key, propIR] of orderedProperties(ir, g)) {\n if (key === skipKey) continue;\n const keyStr = escapeString(key);\n const propCheck = g.visit(propIR, { input: `${x}[${keyStr}]` });\n if (propCheck === null) return null; // All-or-nothing\n // Presence rules keyed on the schema's `optin`/`optout` (see ObjectIR): a\n // required key must be there whatever its schema makes of `undefined`, and\n // an optional-out key on the \"optional\"/\"defaulted\" rungs is accepted when\n // it is not, whatever the property would say.\n if (nonoptional.has(key)) {\n parts.push(propCheck === \"true\" ? `${keyStr} in ${x}` : `${keyStr} in ${x}&&${propCheck}`);\n } else if (absentAccepts.has(key)) {\n parts.push(`(!(${keyStr} in ${x})||${propCheck})`);\n } else {\n parts.push(propCheck);\n }\n }\n\n // Strict unknown-key pass: hosted boolean helper (a for-in loop cannot live\n // in the && chain). Same for-in iteration as the slow path — fast/slow\n // agreement is load-bearing under the __zcFinD deferral. The membership set is\n // the FULL key list (the discriminator is a recognized key), independent of\n // skipKey, which only suppresses re-validating the discriminator's value.\n if (ir.strict) {\n const keys = Object.keys(ir.properties);\n const fnName = g.temp(\"so\");\n const test = keyMembershipTest(g.ctx, keys, \"k\");\n g.ctx.preamble.push(\n `function ${fnName}(o){for(var k in o){if(!(${test}))return false;}return true;}`,\n );\n parts.push(`${fnName}(${x})`);\n }\n\n // .catchall(schema): same hosted for-in as strict, but each unrecognized key\n // is checked against the catchall rather than rejected outright. The value is\n // hoisted into a local for the same reason fastRecord does it — repeated\n // `o[k]` computed loads are not eliminated across check boundaries.\n if (ir.catchall) {\n const kv = g.temp(\"cak\");\n const vv = g.temp(\"cav\");\n const catchallGen = g.scoped(vv);\n const valCheck = catchallGen.visit(ir.catchall, { input: vv });\n if (valCheck === null) return null;\n if (valCheck !== \"true\") {\n const fnName = g.temp(\"co\");\n const test = keyMembershipTest(g.ctx, Object.keys(ir.properties), kv);\n g.ctx.preamble.push(\n `function ${fnName}(o){${declareFastTemps(catchallGen.scope)}var ${kv},${vv};for(${kv} in o){if(!(${test})&&${kv}!==\"__proto__\"){${vv}=o[${kv}];if(!(${valCheck}))return false;}}return true;}`,\n );\n parts.push(`${fnName}(${x})`);\n }\n }\n\n // Object-level refine effects (appended last — run after property checks short-circuit)\n if (ir.checks) {\n for (const check of ir.checks) {\n if (check.kind === \"refine_effect\") {\n parts.push(fastRefineTest(check, x, g));\n } else if (check.kind === \"super_refine_effect\") {\n parts.push(superRefineFastTest(check, x, g));\n }\n }\n }\n\n return parts;\n}\n\nexport function fastObject(ir: ObjectIR, g: FastGen): string | null {\n // A strip object still gets an expression. Stripping reshapes the OUTPUT, not\n // the verdict, so this remains an exact acceptance predicate — which is what\n // `.is()` installs, and what the build path reuses to validate the subtrees it\n // passes through by reference. What it must NOT do is stand in for the parse\n // result: generateValidator withholds the `data:input` shortcut whenever the\n // schema rebuilds (see rebuildsOutput).\n const x = g.input;\n const body = fastObjectBody(ir, g, g.discSkipKey);\n if (body === null) return null;\n // Discriminated-union option: the enclosing switch (and the caller's guard)\n // already established object-ness and the discriminator value, so emit only\n // the remaining checks — no leading type-guard. An option with nothing left\n // to check accepts unconditionally (\"true\").\n if (g.discSkipKey !== undefined) {\n return body.length > 0 ? body.join(\"&&\") : \"true\";\n }\n return [`typeof ${x}===\"object\"`, `${x}!==null`, `!Array.isArray(${x})`, ...body].join(\"&&\");\n}\n"],"mappings":"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"}
|