zod-compiler 2.0.4 → 2.0.6

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.
Files changed (46) hide show
  1. package/README.md +97 -118
  2. package/dist/core/codegen/build-path.js +1 -1
  3. package/dist/core/codegen/context.d.ts +44 -6
  4. package/dist/core/codegen/context.d.ts.map +1 -1
  5. package/dist/core/codegen/context.js +61 -9
  6. package/dist/core/codegen/context.js.map +1 -1
  7. package/dist/core/codegen/index.js +1 -1
  8. package/dist/core/codegen/issue-decls.d.ts +18 -1
  9. package/dist/core/codegen/issue-decls.d.ts.map +1 -1
  10. package/dist/core/codegen/issue-decls.js +19 -1
  11. package/dist/core/codegen/issue-decls.js.map +1 -1
  12. package/dist/core/codegen/schemas/array.d.ts.map +1 -1
  13. package/dist/core/codegen/schemas/array.js +24 -18
  14. package/dist/core/codegen/schemas/array.js.map +1 -1
  15. package/dist/core/codegen/schemas/custom.js +1 -1
  16. package/dist/core/codegen/schemas/discriminated-union.d.ts.map +1 -1
  17. package/dist/core/codegen/schemas/discriminated-union.js +3 -3
  18. package/dist/core/codegen/schemas/discriminated-union.js.map +1 -1
  19. package/dist/core/codegen/schemas/effect.d.ts.map +1 -1
  20. package/dist/core/codegen/schemas/effect.js +3 -3
  21. package/dist/core/codegen/schemas/effect.js.map +1 -1
  22. package/dist/core/codegen/schemas/fallback.js +1 -1
  23. package/dist/core/codegen/schemas/map.d.ts.map +1 -1
  24. package/dist/core/codegen/schemas/map.js +71 -18
  25. package/dist/core/codegen/schemas/map.js.map +1 -1
  26. package/dist/core/codegen/schemas/number.js +1 -1
  27. package/dist/core/codegen/schemas/object.js +3 -3
  28. package/dist/core/codegen/schemas/object.js.map +1 -1
  29. package/dist/core/codegen/schemas/record.d.ts.map +1 -1
  30. package/dist/core/codegen/schemas/record.js +25 -19
  31. package/dist/core/codegen/schemas/record.js.map +1 -1
  32. package/dist/core/codegen/schemas/set.d.ts.map +1 -1
  33. package/dist/core/codegen/schemas/set.js +51 -13
  34. package/dist/core/codegen/schemas/set.js.map +1 -1
  35. package/dist/core/codegen/schemas/sizeable.js +1 -1
  36. package/dist/core/codegen/schemas/string.js +1 -1
  37. package/dist/core/codegen/schemas/tuple.d.ts.map +1 -1
  38. package/dist/core/codegen/schemas/tuple.js +16 -13
  39. package/dist/core/codegen/schemas/tuple.js.map +1 -1
  40. package/dist/core/codegen/schemas/union.d.ts.map +1 -1
  41. package/dist/core/codegen/schemas/union.js +22 -16
  42. package/dist/core/codegen/schemas/union.js.map +1 -1
  43. package/dist/runtime.d.ts +1 -0
  44. package/dist/runtime.js +1 -0
  45. package/dist/unplugin/virtual.js +1 -1
  46. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
+ import { ZC_FZ_DECL, abortingCodeTest } from "../issue-decls.js";
1
2
  import { emitRuntimeHelper, hasMutation } from "../context.js";
2
3
  import { emit } from "../emit.js";
3
- import { ZC_FZ_DECL, abortingCodeTest } from "../issue-decls.js";
4
4
  import { detectUnionDiscriminator, emitFastDiscriminatedSwitch } from "./discriminated-union.js";
5
5
  import { orderByRuntimeCost } from "../fast-size.js";
6
6
  //#region src/core/codegen/schemas/union.ts
@@ -16,20 +16,19 @@ function slowUnion(ir, g) {
16
16
  for (const option of ir.options) {
17
17
  const tmpIssues = g.temp("ui");
18
18
  const optAborted = g.temp("uoa");
19
- if (needsOutputIsolation) {
20
- const tmpOutput = g.temp("uo");
21
- code += emit`
19
+ const tmpOutput = g.temp("uo");
20
+ if (needsOutputIsolation) code += emit`
22
21
  if(!${resultVar}){
23
22
  var ${tmpIssues}=[];
24
23
  var ${optAborted}=false;
25
24
  var ${tmpOutput}=${g.input};
26
25
  ${g.visit(option, {
27
- issues: tmpIssues,
28
- input: tmpOutput,
29
- output: tmpOutput,
30
- path: "[]",
31
- aborted: optAborted
32
- })}
26
+ issues: tmpIssues,
27
+ input: tmpOutput,
28
+ output: tmpOutput,
29
+ path: "[]",
30
+ aborted: optAborted
31
+ })}
33
32
  if(${tmpIssues}.length===0){
34
33
  ${resultVar}=true;
35
34
  ${g.output}=${tmpOutput};
@@ -38,22 +37,29 @@ function slowUnion(ir, g) {
38
37
  ${abortedVar}.push(${optAborted});
39
38
  }
40
39
  }`;
41
- } else code += emit`
40
+ else {
41
+ const optionCode = g.visit(option, {
42
+ issues: tmpIssues,
43
+ output: tmpOutput,
44
+ path: "[]",
45
+ aborted: optAborted
46
+ });
47
+ const writes = optionCode.includes(tmpOutput);
48
+ code += emit`
42
49
  if(!${resultVar}){
43
50
  var ${tmpIssues}=[];
44
51
  var ${optAborted}=false;
45
- ${g.visit(option, {
46
- issues: tmpIssues,
47
- path: "[]",
48
- aborted: optAborted
49
- })}
52
+ ${writes ? `var ${tmpOutput}=${g.input};` : ""}
53
+ ${optionCode}
50
54
  if(${tmpIssues}.length===0){
51
55
  ${resultVar}=true;
56
+ ${writes ? `${g.output}=${tmpOutput};` : ""}
52
57
  }else{
53
58
  ${errorsVar}.push(${tmpIssues});
54
59
  ${abortedVar}.push(${optAborted});
55
60
  }
56
61
  }`;
62
+ }
57
63
  }
58
64
  const msgProp = g.typeMsg === void 0 ? "" : `,message:${JSON.stringify(g.typeMsg)}`;
59
65
  const fz = emitRuntimeHelper(g.ctx, "__zcFz", ZC_FZ_DECL);
@@ -1 +1 @@
1
- {"version":3,"file":"union.js","names":[],"sources":["../../../../src/core/codegen/schemas/union.ts"],"sourcesContent":["import type { SchemaIR, UnionIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { emitRuntimeHelper, hasMutation } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { abortingCodeTest, ZC_FZ_DECL } from \"../issue-decls.js\";\nimport { detectUnionDiscriminator, emitFastDiscriminatedSwitch } from \"./discriminated-union.js\";\n\nexport function slowUnion(ir: SchemaIR & { type: \"union\" }, g: SlowGen): string {\n const resultVar = g.temp(\"u\");\n const errorsVar = g.temp(\"ue\");\n // Parallel to errorsVar: zod's `payload.aborted` for each failed option. Set\n // by a pipe/codec option whose `in` failed (see slowPipe); read during pruning\n // alongside the per-issue code check.\n const abortedVar = g.temp(\"uea\");\n let code = `var ${resultVar}=false;var ${errorsVar}=[];var ${abortedVar}=[];`;\n\n // Options run at a path RELATIVE to the union, not at the union's own path.\n //\n // $ZodUnion hands each option a FRESH payload — `{ value: payload.value,\n // issues: [] }` — so every issue an option raises is numbered from the union's\n // position, and handleUnionResults copies those relative paths into the\n // `invalid_union` groups unchanged. Walking options at the union's absolute\n // path instead leaked it into all of them: `{a: z.union([...])}` reported the\n // nested errors at `[\"a\"]` where zod reports `[]`. Same model record/map\n // already use for their key and value schemas.\n //\n // The union's own path is re-applied in exactly one place, mirroring the one\n // place zod re-applies it: handleUnionResults' shortcut for a single\n // non-aborted option returns THAT OPTION'S payload, whose issues are still\n // relative, and the PARENT (an object's handlePropertyResult, say) prefixes\n // them exactly once. Compiled parents bake their path into each issue at\n // creation, so the union has to do that prefixing itself.\n //\n // That path expression is read ONCE, into `pathVar`, rather than at each issue\n // below — it may allocate a fresh array per evaluation (`[\"items\",__i_7]`).\n // The binding is emitted inside the failure block further down, not here: both\n // readers live there, so a union that matches an option never evaluates it at\n // all, and the whole of this generator's output is one contiguous block at the\n // union's site, so any enclosing loop variable the expression names is equally\n // in scope there. A union already at `[]` prefixes nothing (concat would only\n // copy the array), so it skips the binding entirely.\n const atPathRoot = g.path === \"[]\";\n const pathVar = atPathRoot ? null : g.temp(\"up\");\n const unionPath = pathVar ?? \"[]\";\n\n // If any option can mutate output (default, catch, coerce, effect),\n // each branch gets its own temp output to prevent cross-branch leaks.\n const needsOutputIsolation = ir.options.some(hasMutation);\n\n for (const option of ir.options) {\n const tmpIssues = g.temp(\"ui\");\n // This option's abort flag, forwarded into the option so a pipe `in` failure\n // can raise it (zod's handlePipeResult). Stays false for every other shape.\n const optAborted = g.temp(\"uoa\");\n\n if (needsOutputIsolation) {\n const tmpOutput = g.temp(\"uo\");\n code += emit`\n if(!${resultVar}){\n var ${tmpIssues}=[];\n var ${optAborted}=false;\n var ${tmpOutput}=${g.input};\n ${g.visit(option, { issues: tmpIssues, input: tmpOutput, output: tmpOutput, path: \"[]\", aborted: optAborted })}\n if(${tmpIssues}.length===0){\n ${resultVar}=true;\n ${g.output}=${tmpOutput};\n }else{\n ${errorsVar}.push(${tmpIssues});\n ${abortedVar}.push(${optAborted});\n }\n }`;\n } else {\n code += emit`\n if(!${resultVar}){\n var ${tmpIssues}=[];\n var ${optAborted}=false;\n ${g.visit(option, { issues: tmpIssues, path: \"[]\", aborted: optAborted })}\n if(${tmpIssues}.length===0){\n ${resultVar}=true;\n }else{\n ${errorsVar}.push(${tmpIssues});\n ${abortedVar}.push(${optAborted});\n }\n }`;\n }\n }\n\n // Mirrors zod's handleUnionResults pruning (`util.aborted`): an option is\n // \"aborted\" when its result carries `payload.aborted` (a pipe whose `in`\n // failed — tracked in abortedVar) OR it produced a parse-level issue\n // (continue !== true in zod — invalid_type and friends). Check-level issues\n // (too_small, invalid_format, custom, ...) alone don't abort. If exactly ONE\n // option is non-aborted, its issues are surfaced directly instead of an\n // invalid_union wrapper.\n const msgProp = g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`;\n const fz = emitRuntimeHelper(g.ctx, \"__zcFz\", ZC_FZ_DECL);\n const naVar = g.temp(\"una\");\n const oiVar = g.temp(\"uoi\");\n const ojVar = g.temp(\"uoj\");\n const abVar = g.temp(\"uab\");\n const ocVar = g.temp(\"uoc\");\n // zod prunes with `util.aborted`, i.e. `continue !== true` on ANY issue — a\n // superset of the code test below, and the only thing that catches a tuple's\n // length issue (schema-created, same code a continuable check uses). See\n // `abortsProp` in emit-issue.ts.\n const oiIssue = g.temp(\"uoq\");\n const okVar = g.temp(\"uok\");\n const ofVar = g.temp(\"uof\");\n const surfaced = `${naVar}[0][${okVar}]`;\n // Which branch fires decides where an option's issues are finalized, because\n // the two branches finalize at DIFFERENT paths — so neither can be done up\n // front, in the option loop, without being wrong for the other half:\n //\n // - invalid_union: zod maps each group through `finalizeIssue` while the paths\n // are still relative, so an error map reading `issue.path` sees `[]`.\n // __zcFz is that same locale-fill + input-strip, and is what record/map\n // already use for the issues they nest.\n // - sole non-aborted: zod surfaces the option's own issues, which reach the\n // top-level finalizer with the FULL path, so the message is computed from\n // the absolute path. Prefix here and leave them unfinalized — they land in\n // the parent's issue array, which is finalized at the top exactly once.\n code += emit`\n if(!${resultVar}){\n ${pathVar === null ? \"\" : `var ${pathVar}=${g.path};`}\n var ${naVar}=[];\n for(var ${oiVar}=0;${oiVar}<${errorsVar}.length;${oiVar}++){\n var ${abVar}=${abortedVar}[${oiVar}]===true;\n if(!${abVar}){\n for(var ${ojVar}=0;${ojVar}<${errorsVar}[${oiVar}].length;${ojVar}++){\n var ${oiIssue}=${errorsVar}[${oiVar}][${ojVar}];\n if(${oiIssue}.continue===false){${abVar}=true;break;}\n var ${ocVar}=${oiIssue}.code;\n if(${abortingCodeTest(ocVar)}){${abVar}=true;break;}\n }\n }\n if(!${abVar}){${naVar}.push(${errorsVar}[${oiVar}]);}\n }\n if(${naVar}.length===1){\n for(var ${okVar}=0;${okVar}<${naVar}[0].length;${okVar}++){\n ${atPathRoot ? \"\" : `${surfaced}.path=${unionPath}.concat(${surfaced}.path);`}\n ${g.issues}.push(${surfaced});\n }\n }else{\n for(var ${ofVar}=0;${ofVar}<${errorsVar}.length;${ofVar}++){${fz}(${errorsVar}[${ofVar}]);}\n ${g.issues}.push({code:\"invalid_union\",errors:${errorsVar},input:${g.input},path:${unionPath}${msgProp}});\n }\n }`;\n return `${code}\\n`;\n}\n\nexport function fastUnion(ir: UnionIR, g: FastGen): string | null {\n // A plain `z.union` of objects that all pin a shared key to disjoint literals\n // is structurally a discriminated union: dispatch on that key with an O(1)\n // switch instead of probing every arm in sequence. detectUnionDiscriminator\n // returns non-null only when the switch provably accepts exactly what the\n // ||-chain would (disjoint required literals). The slow path is untouched, so\n // error output stays identical to Zod's plain-union behavior.\n const discriminated = detectUnionDiscriminator(ir.options);\n if (discriminated !== null) {\n return emitFastDiscriminatedSwitch(\n g,\n discriminated.discriminator,\n discriminated.cases,\n ir.options,\n );\n }\n\n // Probe cheap options first: the ||-chain stops at the first match, and an\n // option that cannot match is rejected by its own cheapest-first conjunct\n // chain. Which option matches is unobservable here (the result is a single\n // boolean), and the slow path — where option order IS observable, through\n // zod's first-match output and invalid_union issue order — is untouched.\n //\n // That \"unobservable\" holds for the VERDICT this expression reports, which is\n // all a nested conjunct or a `.is()` guard consumes. It does NOT hold for the\n // by-reference shortcut a root schema takes on a passing check, where WHICH\n // option zod picked decides the output value — see `fastResultIsInput`, which\n // withholds that shortcut rather than costing every union its fast check.\n const optionChecks: string[] = [];\n for (const option of orderByRuntimeCost(ir.options, (o) => o, g.ctx)) {\n const check = g.visit(option);\n if (check === null) return null;\n optionChecks.push(`(${check})`);\n }\n // Wrap in parens — || has lower precedence than && in parent expressions\n return `(${optionChecks.join(\"||\")})`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"union.js","names":[],"sources":["../../../../src/core/codegen/schemas/union.ts"],"sourcesContent":["import type { SchemaIR, UnionIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { emitRuntimeHelper, hasMutation } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { abortingCodeTest, ZC_FZ_DECL } from \"../issue-decls.js\";\nimport { detectUnionDiscriminator, emitFastDiscriminatedSwitch } from \"./discriminated-union.js\";\n\nexport function slowUnion(ir: SchemaIR & { type: \"union\" }, g: SlowGen): string {\n const resultVar = g.temp(\"u\");\n const errorsVar = g.temp(\"ue\");\n // Parallel to errorsVar: zod's `payload.aborted` for each failed option. Set\n // by a pipe/codec option whose `in` failed (see slowPipe); read during pruning\n // alongside the per-issue code check.\n const abortedVar = g.temp(\"uea\");\n let code = `var ${resultVar}=false;var ${errorsVar}=[];var ${abortedVar}=[];`;\n\n // Options run at a path RELATIVE to the union, not at the union's own path.\n //\n // $ZodUnion hands each option a FRESH payload — `{ value: payload.value,\n // issues: [] }` — so every issue an option raises is numbered from the union's\n // position, and handleUnionResults copies those relative paths into the\n // `invalid_union` groups unchanged. Walking options at the union's absolute\n // path instead leaked it into all of them: `{a: z.union([...])}` reported the\n // nested errors at `[\"a\"]` where zod reports `[]`. Same model record/map\n // already use for their key and value schemas.\n //\n // The union's own path is re-applied in exactly one place, mirroring the one\n // place zod re-applies it: handleUnionResults' shortcut for a single\n // non-aborted option returns THAT OPTION'S payload, whose issues are still\n // relative, and the PARENT (an object's handlePropertyResult, say) prefixes\n // them exactly once. Compiled parents bake their path into each issue at\n // creation, so the union has to do that prefixing itself.\n //\n // That path expression is read ONCE, into `pathVar`, rather than at each issue\n // below — it may allocate a fresh array per evaluation (`[\"items\",__i_7]`).\n // The binding is emitted inside the failure block further down, not here: both\n // readers live there, so a union that matches an option never evaluates it at\n // all, and the whole of this generator's output is one contiguous block at the\n // union's site, so any enclosing loop variable the expression names is equally\n // in scope there. A union already at `[]` prefixes nothing (concat would only\n // copy the array), so it skips the binding entirely.\n const atPathRoot = g.path === \"[]\";\n const pathVar = atPathRoot ? null : g.temp(\"up\");\n const unionPath = pathVar ?? \"[]\";\n\n // If any option can mutate output (default, catch, coerce, effect),\n // each branch gets its own temp output to prevent cross-branch leaks.\n const needsOutputIsolation = ir.options.some(hasMutation);\n\n for (const option of ir.options) {\n const tmpIssues = g.temp(\"ui\");\n // This option's abort flag, forwarded into the option so a pipe `in` failure\n // can raise it (zod's handlePipeResult). Stays false for every other shape.\n const optAborted = g.temp(\"uoa\");\n const tmpOutput = g.temp(\"uo\");\n\n if (needsOutputIsolation) {\n code += emit`\n if(!${resultVar}){\n var ${tmpIssues}=[];\n var ${optAborted}=false;\n var ${tmpOutput}=${g.input};\n ${g.visit(option, { issues: tmpIssues, input: tmpOutput, output: tmpOutput, path: \"[]\", aborted: optAborted })}\n if(${tmpIssues}.length===0){\n ${resultVar}=true;\n ${g.output}=${tmpOutput};\n }else{\n ${errorsVar}.push(${tmpIssues});\n ${abortedVar}.push(${optAborted});\n }\n }`;\n } else {\n // An option that rewrites nothing still writes its output — a loose object\n // hands back its input, or a copy an own `__proto__` was scrubbed from —\n // and zod's result is the output of the option that SUCCEEDED. Written\n // straight to the union's output, a failed option's copy stayed there\n // whenever the option that did succeed wrote nothing (`z.any()`), so an\n // option that names its output gets a local of its own, taken only on\n // success. Its input stays the union's: an option that rewrites nothing\n // does not need its input and output to be one expression (see\n // visitMember).\n const optionCode = g.visit(option, {\n issues: tmpIssues,\n output: tmpOutput,\n path: \"[]\",\n aborted: optAborted,\n });\n const writes = optionCode.includes(tmpOutput);\n code += emit`\n if(!${resultVar}){\n var ${tmpIssues}=[];\n var ${optAborted}=false;\n ${writes ? `var ${tmpOutput}=${g.input};` : \"\"}\n ${optionCode}\n if(${tmpIssues}.length===0){\n ${resultVar}=true;\n ${writes ? `${g.output}=${tmpOutput};` : \"\"}\n }else{\n ${errorsVar}.push(${tmpIssues});\n ${abortedVar}.push(${optAborted});\n }\n }`;\n }\n }\n\n // Mirrors zod's handleUnionResults pruning (`util.aborted`): an option is\n // \"aborted\" when its result carries `payload.aborted` (a pipe whose `in`\n // failed — tracked in abortedVar) OR it produced a parse-level issue\n // (continue !== true in zod — invalid_type and friends). Check-level issues\n // (too_small, invalid_format, custom, ...) alone don't abort. If exactly ONE\n // option is non-aborted, its issues are surfaced directly instead of an\n // invalid_union wrapper.\n const msgProp = g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`;\n const fz = emitRuntimeHelper(g.ctx, \"__zcFz\", ZC_FZ_DECL);\n const naVar = g.temp(\"una\");\n const oiVar = g.temp(\"uoi\");\n const ojVar = g.temp(\"uoj\");\n const abVar = g.temp(\"uab\");\n const ocVar = g.temp(\"uoc\");\n // zod prunes with `util.aborted`, i.e. `continue !== true` on ANY issue — a\n // superset of the code test below, and the only thing that catches a tuple's\n // length issue (schema-created, same code a continuable check uses). See\n // `abortsProp` in emit-issue.ts.\n const oiIssue = g.temp(\"uoq\");\n const okVar = g.temp(\"uok\");\n const ofVar = g.temp(\"uof\");\n const surfaced = `${naVar}[0][${okVar}]`;\n // Which branch fires decides where an option's issues are finalized, because\n // the two branches finalize at DIFFERENT paths — so neither can be done up\n // front, in the option loop, without being wrong for the other half:\n //\n // - invalid_union: zod maps each group through `finalizeIssue` while the paths\n // are still relative, so an error map reading `issue.path` sees `[]`.\n // __zcFz is that same locale-fill + input-strip, and is what record/map\n // already use for the issues they nest.\n // - sole non-aborted: zod surfaces the option's own issues, which reach the\n // top-level finalizer with the FULL path, so the message is computed from\n // the absolute path. Prefix here and leave them unfinalized — they land in\n // the parent's issue array, which is finalized at the top exactly once.\n code += emit`\n if(!${resultVar}){\n ${pathVar === null ? \"\" : `var ${pathVar}=${g.path};`}\n var ${naVar}=[];\n for(var ${oiVar}=0;${oiVar}<${errorsVar}.length;${oiVar}++){\n var ${abVar}=${abortedVar}[${oiVar}]===true;\n if(!${abVar}){\n for(var ${ojVar}=0;${ojVar}<${errorsVar}[${oiVar}].length;${ojVar}++){\n var ${oiIssue}=${errorsVar}[${oiVar}][${ojVar}];\n if(${oiIssue}.continue===false){${abVar}=true;break;}\n var ${ocVar}=${oiIssue}.code;\n if(${abortingCodeTest(ocVar)}){${abVar}=true;break;}\n }\n }\n if(!${abVar}){${naVar}.push(${errorsVar}[${oiVar}]);}\n }\n if(${naVar}.length===1){\n for(var ${okVar}=0;${okVar}<${naVar}[0].length;${okVar}++){\n ${atPathRoot ? \"\" : `${surfaced}.path=${unionPath}.concat(${surfaced}.path);`}\n ${g.issues}.push(${surfaced});\n }\n }else{\n for(var ${ofVar}=0;${ofVar}<${errorsVar}.length;${ofVar}++){${fz}(${errorsVar}[${ofVar}]);}\n ${g.issues}.push({code:\"invalid_union\",errors:${errorsVar},input:${g.input},path:${unionPath}${msgProp}});\n }\n }`;\n return `${code}\\n`;\n}\n\nexport function fastUnion(ir: UnionIR, g: FastGen): string | null {\n // A plain `z.union` of objects that all pin a shared key to disjoint literals\n // is structurally a discriminated union: dispatch on that key with an O(1)\n // switch instead of probing every arm in sequence. detectUnionDiscriminator\n // returns non-null only when the switch provably accepts exactly what the\n // ||-chain would (disjoint required literals). The slow path is untouched, so\n // error output stays identical to Zod's plain-union behavior.\n const discriminated = detectUnionDiscriminator(ir.options);\n if (discriminated !== null) {\n return emitFastDiscriminatedSwitch(\n g,\n discriminated.discriminator,\n discriminated.cases,\n ir.options,\n );\n }\n\n // Probe cheap options first: the ||-chain stops at the first match, and an\n // option that cannot match is rejected by its own cheapest-first conjunct\n // chain. Which option matches is unobservable here (the result is a single\n // boolean), and the slow path — where option order IS observable, through\n // zod's first-match output and invalid_union issue order — is untouched.\n //\n // That \"unobservable\" holds for the VERDICT this expression reports, which is\n // all a nested conjunct or a `.is()` guard consumes. It does NOT hold for the\n // by-reference shortcut a root schema takes on a passing check, where WHICH\n // option zod picked decides the output value — see `fastResultIsInput`, which\n // withholds that shortcut rather than costing every union its fast check.\n const optionChecks: string[] = [];\n for (const option of orderByRuntimeCost(ir.options, (o) => o, g.ctx)) {\n const check = g.visit(option);\n if (check === null) return null;\n optionChecks.push(`(${check})`);\n }\n // Wrap in parens — || has lower precedence than && in parent expressions\n return `(${optionChecks.join(\"||\")})`;\n}\n"],"mappings":"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"}
package/dist/runtime.d.ts CHANGED
@@ -27,6 +27,7 @@ export declare const __zcEmail: any;
27
27
  export declare const __zcPs: any;
28
28
  export declare const __zcPlain: any;
29
29
  export declare const __zcPfx: any;
30
+ export declare const __zcPa: any;
30
31
  export declare const __zcCu: any;
31
32
  export declare const __zcSr: any;
32
33
  export declare const __zcSrOk: any;
package/dist/runtime.js CHANGED
@@ -29,6 +29,7 @@ export function __zcEmail(s){var n=s.length,i=0,c,p=46;for(;;){if(i===n)return f
29
29
  export function __zcPs(o){if(!Object.prototype.hasOwnProperty.call(o,"__proto__"))return o;var c={...o};delete c["__proto__"];return c;}
30
30
  export function __zcPlain(o){if(typeof o!=="object"||o===null||Array.isArray(o))return false;var c=o.constructor;if(c===Object||c===undefined||typeof c!=="function")return true;var p=c.prototype;if(typeof p!=="object"||p===null||Array.isArray(p))return false;return Object.prototype.hasOwnProperty.call(p,"isPrototypeOf");}
31
31
  export 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);}}
32
+ export 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;}
32
33
  export function __zcCu(f,v){var r=f(v);if(r&&typeof r.then==="function"){throw new __zcCore.$ZodAsyncError();}return !!r;}
33
34
  export function __zcSr(f,v,p,e,m){var q={value:v,issues:[]};__zcSrRun(f,q);for(var i=0;i<q.issues.length;i++){var s=q.issues[i],t={};for(var k in s){if(k!=="inst"&&k!=="continue")t[k]=s[k];}if(s.continue!==true){q.aborted=true;t.continue=false;}t.path=s.path&&s.path.length?p.concat(s.path):p;if(t.message===undefined&&m!==undefined)t.message=m;e.push(t);}return q;}
34
35
  export function __zcSrOk(f,v){var p={value:v,issues:[]};__zcSrRun(f,p);return p.issues.length===0&&p.value===v;}
@@ -1,6 +1,6 @@
1
+ import { ISSUE_DECLS, RUNTIME_HELPER_DECLS, ZC_SR_RUN_DECL } from "../core/codegen/issue-decls.js";
1
2
  import { WELL_KNOWN_REGEXES, fastTestSource } from "../core/codegen/well-known-regex.js";
2
3
  import { FAILZ_CLASS_DECL, FAIL_CLASS_DECL, FINZ_DECL, FIN_DECL, FIN_DEFERRED_DECL, MK_VALIDATOR_DECL, ZOD_CONFIG_IMPORT, ZOD_MSG_DECLARATION } from "../core/iife.js";
3
- import { ISSUE_DECLS, RUNTIME_HELPER_DECLS, ZC_SR_RUN_DECL } from "../core/codegen/issue-decls.js";
4
4
  //#region src/unplugin/virtual.ts
5
5
  /**
6
6
  * Virtual module "virtual:zod-compiler/runtime".
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-compiler",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "Compile Zod schemas into zero-overhead validation functions",
5
5
  "keywords": [
6
6
  "aot",