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 +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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/record.ts"],"mappings":";;;iBA0BgB,WAAW,IAAI;EAAa;GAAkB,GAAG;iBA8DjD,WAAW,IAAI,UAAU,GAAG"}
1
+ {"version":3,"file":"record.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/record.ts"],"mappings":";;;iBAgCgB,WAAW,IAAI;EAAa;GAAkB,GAAG;iBAoFjD,WAAW,IAAI,UAAU,GAAG"}
@@ -1,7 +1,7 @@
1
- import { declareFastTemps, emitRuntimeHelper, extendPath, hasMutation } from "../context.js";
1
+ import { ZC_FZ_DECL, ZC_HOP_DECL, ZC_PLAIN_DECL, ZC_PROTO_SCRUB_DECL } from "../issue-decls.js";
2
+ import { declareFastTemps, emitRuntimeHelper, extendPath, hasMutation, visitMember } from "../context.js";
2
3
  import { emit } from "../emit.js";
3
4
  import { invalidType, unrecognizedKeys } from "../emit-issue.js";
4
- import { ZC_FZ_DECL, ZC_HOP_DECL, ZC_PLAIN_DECL, ZC_PROTO_SCRUB_DECL } from "../issue-decls.js";
5
5
  //#region src/core/codegen/schemas/record.ts
6
6
  /**
7
7
  * `$ZodRecord` gates on `util.isPlainObject`, NOT the looser `util.isObject`
@@ -25,39 +25,45 @@ function slowRecord(ir, g) {
25
25
  if(!${plainObjectTest(g, g.input)}){
26
26
  ${invalidType(g, "record")}
27
27
  }else{`;
28
- if (hasMutation(ir.valueType)) code += `${g.output}={...${g.input}};`;
29
- code += `${g.output}=${emitRuntimeHelper(g.ctx, "__zcPs", ZC_PROTO_SCRUB_DECL)}(${g.input});`;
28
+ const rec = g.temp("rc");
29
+ code += `var ${rec}=${emitRuntimeHelper(g.ctx, "__zcPs", ZC_PROTO_SCRUB_DECL)}(${g.input});`;
30
+ if (hasMutation(ir.valueType)) code += `if(${rec}===${g.input}){${rec}={...${g.input}};}`;
30
31
  const keyVar = g.temp("rkey");
31
32
  const keyIssuesVar = g.temp("rki");
32
- const keyPath = extendPath(g.path, keyVar);
33
- const valExpr = `${g.input}[${keyVar}]`;
33
+ const keyPath = extendPath(g.ctx, g.path, keyVar);
34
34
  const hop = emitRuntimeHelper(g.ctx, "__zcHop", ZC_HOP_DECL);
35
35
  const fz = emitRuntimeHelper(g.ctx, "__zcFz", ZC_FZ_DECL);
36
36
  const unrecognizedVar = ir.enumerableKeys ? g.temp("ruk") : null;
37
37
  const onKeyFailure = unrecognizedVar === null ? `${g.issues}.push({code:"invalid_key",origin:"record",issues:${fz}(${keyIssuesVar}),input:${keyVar},path:${keyPath}${g.typeMsg === void 0 ? "" : `,message:${JSON.stringify(g.typeMsg)}`}});` : `(${unrecognizedVar}=${unrecognizedVar}||[]).push(${keyVar});`;
38
- code += emit`
39
- ${unrecognizedVar === null ? "" : `var ${unrecognizedVar}=null;`}
40
- for(var ${keyVar} in ${g.input}){
41
- if(!${hop}.call(${g.input},${keyVar}))continue;
42
- ${PROTO_SKIP(keyVar)}
43
- var ${keyIssuesVar}=[];
44
- ${g.visit(ir.keyType, {
38
+ const keyCode = g.visit(ir.keyType, {
45
39
  input: keyVar,
46
40
  output: keyVar,
47
41
  path: "[]",
48
42
  issues: keyIssuesVar
49
- })}
43
+ });
44
+ const valueCode = visitMember(g, ir.valueType, {
45
+ container: rec,
46
+ original: g.input,
47
+ copy: `{...${g.input}}`,
48
+ key: keyVar,
49
+ path: keyPath,
50
+ issues: g.issues
51
+ });
52
+ code += emit`
53
+ ${unrecognizedVar === null ? "" : `var ${unrecognizedVar}=null;`}
54
+ for(var ${keyVar} in ${rec}){
55
+ if(!${hop}.call(${rec},${keyVar}))continue;
56
+ ${PROTO_SKIP(keyVar)}
57
+ var ${keyIssuesVar}=[];
58
+ ${keyCode}
50
59
  if(${keyIssuesVar}.length>0){
51
60
  ${onKeyFailure}
52
61
  }else{
53
- ${g.visit(ir.valueType, {
54
- input: valExpr,
55
- output: valExpr,
56
- path: keyPath
57
- })}
62
+ ${valueCode}
58
63
  }
59
64
  }
60
65
  ${unrecognizedVar === null ? "" : `if(${unrecognizedVar}!==null){${unrecognizedKeys(g, unrecognizedVar)}}`}
66
+ ${g.output}=${rec};
61
67
  }`;
62
68
  return `${code}\n`;
63
69
  }
@@ -1 +1 @@
1
- {"version":3,"file":"record.js","names":[],"sources":["../../../../src/core/codegen/schemas/record.ts"],"sourcesContent":["import type { RecordIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { declareFastTemps, emitRuntimeHelper, extendPath, hasMutation } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, unrecognizedKeys } from \"../emit-issue.js\";\nimport { ZC_FZ_DECL, ZC_HOP_DECL, ZC_PLAIN_DECL, ZC_PROTO_SCRUB_DECL } from \"../issue-decls.js\";\n\n/**\n * `$ZodRecord` gates on `util.isPlainObject`, NOT the looser `util.isObject`\n * that `$ZodObject` uses — see {@link ZC_PLAIN_DECL} for why the two differ and\n * what accepting the wrong one lets through.\n */\nfunction plainObjectTest(g: SlowGen | FastGen, input: string): string {\n return `${emitRuntimeHelper(g.ctx, \"__zcPlain\", ZC_PLAIN_DECL)}(${input})`;\n}\n\n/**\n * Zod's record walk opens with `if (key === \"__proto__\") continue`, so an own\n * `__proto__` data property (which `JSON.parse('{\"__proto__\":…}')` creates) is\n * neither key-validated nor value-validated nor copied. Without this the\n * compiled walk reported issues zod does not: `z.record(z.string(), z.number())`\n * over such an object raised a SECOND `invalid_type`, and a constrained key\n * schema a second `invalid_key`, for a key zod never looks at.\n */\nconst PROTO_SKIP = (keyVar: string): string => `if(${keyVar}===\"__proto__\")continue;`;\n\nexport function slowRecord(ir: SchemaIR & { type: \"record\" }, g: SlowGen): string {\n let code = emit`\n if(!${plainObjectTest(g, g.input)}){\n ${invalidType(g, \"record\")}\n }else{`;\n\n if (hasMutation(ir.valueType)) {\n code += `${g.output}={...${g.input}};`;\n }\n // PROTO_SKIP keeps `__proto__` out of the WALK; this keeps it out of the\n // OUTPUT, which zod also does — it copies into a fresh `{}` and skips the key\n // (see ZC_PROTO_SCRUB_DECL). Runs before the walk so the loop iterates the\n // same container the caller gets back.\n code += `${g.output}=${emitRuntimeHelper(g.ctx, \"__zcPs\", ZC_PROTO_SCRUB_DECL)}(${g.input});`;\n\n const keyVar = g.temp(\"rkey\");\n const keyIssuesVar = g.temp(\"rki\");\n const keyPath = extendPath(g.path, keyVar);\n const valExpr = `${g.input}[${keyVar}]`;\n // for-in + hasOwnProperty guard instead of Object.keys(): identical\n // own-enumerable string-key set and iteration order, no keys-array\n // allocation. When the value type mutates (coerce/default/.trim()) the clone\n // above has already replaced g.input, so this iterates the clone exactly as\n // the Object.keys form did — the key set is stable (values change, keys\n // don't). Records whose values mutate run this path eagerly, so they get the\n // same speedup the fast path does.\n const hop = emitRuntimeHelper(g.ctx, \"__zcHop\", ZC_HOP_DECL);\n\n // The key is validated at a RELATIVE path and its issues are finalized before\n // being nested, mirroring zod: `issues: keyResult.issues.map(finalizeIssue)`\n // over a payload zod ran fresh. Nested issues never reach the top-level\n // finalization loop (it walks only the outer array), so an unfinalized nest\n // leaked absolute paths and the raw `input` into the reported error.\n const fz = emitRuntimeHelper(g.ctx, \"__zcFz\", ZC_FZ_DECL);\n\n // A key the enumerable key schema rejects is unrecognized, not invalid: zod\n // collects those and pushes ONE `unrecognized_keys` after the walk, so it\n // trails every value issue (see RecordIR.enumerableKeys).\n const unrecognizedVar = ir.enumerableKeys ? g.temp(\"ruk\") : null;\n const onKeyFailure =\n unrecognizedVar === null\n ? `${g.issues}.push({code:\"invalid_key\",origin:\"record\",issues:${fz}(${keyIssuesVar}),input:${keyVar},path:${keyPath}${g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`}});`\n : `(${unrecognizedVar}=${unrecognizedVar}||[]).push(${keyVar});`;\n\n code += emit`\n ${unrecognizedVar === null ? \"\" : `var ${unrecognizedVar}=null;`}\n for(var ${keyVar} in ${g.input}){\n if(!${hop}.call(${g.input},${keyVar}))continue;\n ${PROTO_SKIP(keyVar)}\n var ${keyIssuesVar}=[];\n ${g.visit(ir.keyType, { input: keyVar, output: keyVar, path: \"[]\", issues: keyIssuesVar })}\n if(${keyIssuesVar}.length>0){\n ${onKeyFailure}\n }else{\n ${g.visit(ir.valueType, { input: valExpr, output: valExpr, path: keyPath })}\n }\n }\n ${unrecognizedVar === null ? \"\" : `if(${unrecognizedVar}!==null){${unrecognizedKeys(g, unrecognizedVar)}}`}\n }`;\n return `${code}\\n`;\n}\n\nexport function fastRecord(ir: RecordIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [plainObjectTest(g, x)];\n\n // Object.keys only yields strings — a plain unconstrained string key schema\n // is always satisfied, so skip generating its check entirely.\n const plainStringKey =\n ir.keyType.type === \"string\" && ir.keyType.checks.length === 0 && ir.keyType.coerce !== true;\n\n const kv = g.temp(\"rk\");\n const vv = g.temp(\"rv\");\n // Key + value checks share one fresh scope — they live in the same emitted\n // helper function, size-gated independently of the caller.\n const body = g.scoped(kv);\n const keyCheck = plainStringKey ? \"true\" : body.visit(ir.keyType, { input: kv });\n // Hoist o[k] into a loop variable: computed-key lookups don't get V8's load\n // elimination across check boundaries, so each repeated o[k] would re-walk\n // the (often dictionary-mode) object.\n const valCheck = body.visit(ir.valueType, { input: vv });\n if (keyCheck === null || valCheck === null) return null;\n\n const conditions: string[] = [];\n if (keyCheck !== \"true\") conditions.push(keyCheck);\n if (valCheck !== \"true\") conditions.push(valCheck);\n\n if (conditions.length > 0) {\n const helperName = g.temp(\"rf\");\n const valAssign = valCheck !== \"true\" ? `${vv}=o[${kv}];` : \"\";\n // for-in (no Object.keys array allocation) + hasOwnProperty guard. The\n // guard restricts iteration to own enumerable string keys — the exact set\n // Object.keys/the slow path produce — so inherited enumerable props can't\n // make the fast check disagree with the deferred slow walk. Measured 2.9x\n // (5 keys) to 5.8x (20 keys) faster than the Object.keys form; the hoisted\n // __zcHop.call inlines, making the guard ~free vs an unguarded for-in.\n const hop = emitRuntimeHelper(g.ctx, \"__zcHop\", ZC_HOP_DECL);\n g.ctx.preamble.push(\n `function ${helperName}(o){${declareFastTemps(body.scope)}var ${kv},${vv};for(${kv} in o){${PROTO_SKIP(kv)}if(${hop}.call(o,${kv})){${valAssign}if(!(${conditions.join(\"&&\")})){return false;}}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"record.js","names":[],"sources":["../../../../src/core/codegen/schemas/record.ts"],"sourcesContent":["import type { RecordIR, SchemaIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n declareFastTemps,\n emitRuntimeHelper,\n extendPath,\n hasMutation,\n visitMember,\n} from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, unrecognizedKeys } from \"../emit-issue.js\";\nimport { ZC_FZ_DECL, ZC_HOP_DECL, ZC_PLAIN_DECL, ZC_PROTO_SCRUB_DECL } from \"../issue-decls.js\";\n\n/**\n * `$ZodRecord` gates on `util.isPlainObject`, NOT the looser `util.isObject`\n * that `$ZodObject` uses — see {@link ZC_PLAIN_DECL} for why the two differ and\n * what accepting the wrong one lets through.\n */\nfunction plainObjectTest(g: SlowGen | FastGen, input: string): string {\n return `${emitRuntimeHelper(g.ctx, \"__zcPlain\", ZC_PLAIN_DECL)}(${input})`;\n}\n\n/**\n * Zod's record walk opens with `if (key === \"__proto__\") continue`, so an own\n * `__proto__` data property (which `JSON.parse('{\"__proto__\":…}')` creates) is\n * neither key-validated nor value-validated nor copied. Without this the\n * compiled walk reported issues zod does not: `z.record(z.string(), z.number())`\n * over such an object raised a SECOND `invalid_type`, and a constrained key\n * schema a second `invalid_key`, for a key zod never looks at.\n */\nconst PROTO_SKIP = (keyVar: string): string => `if(${keyVar}===\"__proto__\")continue;`;\n\nexport function slowRecord(ir: SchemaIR & { type: \"record\" }, g: SlowGen): string {\n let code = emit`\n if(!${plainObjectTest(g, g.input)}){\n ${invalidType(g, \"record\")}\n }else{`;\n\n // One binding for every read and write, handed back as the output after the\n // walk: a parent can hand this node `g.input` and `g.output` as two different\n // bindings (see slowTuple).\n //\n // PROTO_SKIP keeps `__proto__` out of the WALK; the scrub keeps it out of the\n // OUTPUT, which zod also does — it copies into a fresh `{}` and skips the key\n // (see ZC_PROTO_SCRUB_DECL). Runs before the walk so the loop iterates the\n // same container the caller gets back. A mutating value schema rewrites values\n // as a matter of course, so it takes a copy up front unless the scrub already\n // made one; anything else copies only once a value hands back a replacement\n // (see visitMember).\n const rec = g.temp(\"rc\");\n code += `var ${rec}=${emitRuntimeHelper(g.ctx, \"__zcPs\", ZC_PROTO_SCRUB_DECL)}(${g.input});`;\n if (hasMutation(ir.valueType)) {\n code += `if(${rec}===${g.input}){${rec}={...${g.input}};}`;\n }\n\n const keyVar = g.temp(\"rkey\");\n const keyIssuesVar = g.temp(\"rki\");\n const keyPath = extendPath(g.ctx, g.path, keyVar);\n // for-in + hasOwnProperty guard instead of Object.keys(): identical\n // own-enumerable string-key set and iteration order, no keys-array\n // allocation. The loop iterates the binding as the walk found it — the clone,\n // when one was taken above — and a copy taken mid-walk for a replacement has\n // the same keys, so the key set is stable (values change, keys don't).\n // Records whose values mutate run this path eagerly, so they get the same\n // speedup the fast path does.\n const hop = emitRuntimeHelper(g.ctx, \"__zcHop\", ZC_HOP_DECL);\n\n // The key is validated at a RELATIVE path and its issues are finalized before\n // being nested, mirroring zod: `issues: keyResult.issues.map(finalizeIssue)`\n // over a payload zod ran fresh. Nested issues never reach the top-level\n // finalization loop (it walks only the outer array), so an unfinalized nest\n // leaked absolute paths and the raw `input` into the reported error.\n const fz = emitRuntimeHelper(g.ctx, \"__zcFz\", ZC_FZ_DECL);\n\n // A key the enumerable key schema rejects is unrecognized, not invalid: zod\n // collects those and pushes ONE `unrecognized_keys` after the walk, so it\n // trails every value issue (see RecordIR.enumerableKeys).\n const unrecognizedVar = ir.enumerableKeys ? g.temp(\"ruk\") : null;\n const onKeyFailure =\n unrecognizedVar === null\n ? `${g.issues}.push({code:\"invalid_key\",origin:\"record\",issues:${fz}(${keyIssuesVar}),input:${keyVar},path:${keyPath}${g.typeMsg === undefined ? \"\" : `,message:${JSON.stringify(g.typeMsg)}`}});`\n : `(${unrecognizedVar}=${unrecognizedVar}||[]).push(${keyVar});`;\n\n const keyCode = g.visit(ir.keyType, {\n input: keyVar,\n output: keyVar,\n path: \"[]\",\n issues: keyIssuesVar,\n });\n const valueCode = visitMember(g, ir.valueType, {\n container: rec,\n original: g.input,\n copy: `{...${g.input}}`,\n key: keyVar,\n path: keyPath,\n issues: g.issues,\n });\n code += emit`\n ${unrecognizedVar === null ? \"\" : `var ${unrecognizedVar}=null;`}\n for(var ${keyVar} in ${rec}){\n if(!${hop}.call(${rec},${keyVar}))continue;\n ${PROTO_SKIP(keyVar)}\n var ${keyIssuesVar}=[];\n ${keyCode}\n if(${keyIssuesVar}.length>0){\n ${onKeyFailure}\n }else{\n ${valueCode}\n }\n }\n ${unrecognizedVar === null ? \"\" : `if(${unrecognizedVar}!==null){${unrecognizedKeys(g, unrecognizedVar)}}`}\n ${g.output}=${rec};\n }`;\n return `${code}\\n`;\n}\n\nexport function fastRecord(ir: RecordIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [plainObjectTest(g, x)];\n\n // Object.keys only yields strings — a plain unconstrained string key schema\n // is always satisfied, so skip generating its check entirely.\n const plainStringKey =\n ir.keyType.type === \"string\" && ir.keyType.checks.length === 0 && ir.keyType.coerce !== true;\n\n const kv = g.temp(\"rk\");\n const vv = g.temp(\"rv\");\n // Key + value checks share one fresh scope — they live in the same emitted\n // helper function, size-gated independently of the caller.\n const body = g.scoped(kv);\n const keyCheck = plainStringKey ? \"true\" : body.visit(ir.keyType, { input: kv });\n // Hoist o[k] into a loop variable: computed-key lookups don't get V8's load\n // elimination across check boundaries, so each repeated o[k] would re-walk\n // the (often dictionary-mode) object.\n const valCheck = body.visit(ir.valueType, { input: vv });\n if (keyCheck === null || valCheck === null) return null;\n\n const conditions: string[] = [];\n if (keyCheck !== \"true\") conditions.push(keyCheck);\n if (valCheck !== \"true\") conditions.push(valCheck);\n\n if (conditions.length > 0) {\n const helperName = g.temp(\"rf\");\n const valAssign = valCheck !== \"true\" ? `${vv}=o[${kv}];` : \"\";\n // for-in (no Object.keys array allocation) + hasOwnProperty guard. The\n // guard restricts iteration to own enumerable string keys — the exact set\n // Object.keys/the slow path produce — so inherited enumerable props can't\n // make the fast check disagree with the deferred slow walk. Measured 2.9x\n // (5 keys) to 5.8x (20 keys) faster than the Object.keys form; the hoisted\n // __zcHop.call inlines, making the guard ~free vs an unguarded for-in.\n const hop = emitRuntimeHelper(g.ctx, \"__zcHop\", ZC_HOP_DECL);\n g.ctx.preamble.push(\n `function ${helperName}(o){${declareFastTemps(body.scope)}var ${kv},${vv};for(${kv} in o){${PROTO_SKIP(kv)}if(${hop}.call(o,${kv})){${valAssign}if(!(${conditions.join(\"&&\")})){return false;}}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"set.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/set.ts"],"mappings":";;;iBAOgB,QAAQ,IAAI;EAAa;GAAe,GAAG;iBA+D3C,QAAQ,IAAI,OAAO,GAAG"}
1
+ {"version":3,"file":"set.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/set.ts"],"mappings":";;;iBAOgB,QAAQ,IAAI;EAAa;GAAe,GAAG;iBAuG3C,QAAQ,IAAI,OAAO,GAAG"}
@@ -9,20 +9,58 @@ function slowSet(ir, g) {
9
9
  ${invalidType(g, "set")}
10
10
  ${whenGatedSizeChecks(ir.checks ?? [], g, "size")}
11
11
  }else{`;
12
- const mutates = hasMutation(ir.valueType);
13
12
  const iterVar = g.temp("set_v");
14
- const rebuiltVar = mutates ? g.temp("set_n") : "";
15
- if (mutates) code += `var ${rebuiltVar}=new Set();`;
16
- code += emit`
17
- for(var ${iterVar} of ${g.input}){
18
- ${g.visit(ir.valueType, {
19
- input: iterVar,
20
- output: iterVar,
21
- path: g.path
22
- })}
23
- ${mutates ? `${rebuiltVar}.add(${iterVar});` : ""}
24
- }
25
- ${mutates ? `${g.output}=${rebuiltVar};` : ""}`;
13
+ if (hasMutation(ir.valueType)) {
14
+ const rebuiltVar = g.temp("set_n");
15
+ code += emit`
16
+ var ${rebuiltVar}=new Set();
17
+ for(var ${iterVar} of ${g.input}){
18
+ ${g.visit(ir.valueType, {
19
+ input: iterVar,
20
+ output: iterVar,
21
+ path: g.path
22
+ })}
23
+ ${rebuiltVar}.add(${iterVar});
24
+ }
25
+ ${g.output}=${rebuiltVar};`;
26
+ } else {
27
+ const outVar = g.temp("set_o");
28
+ const element = g.visit(ir.valueType, {
29
+ input: iterVar,
30
+ output: outVar,
31
+ path: g.path
32
+ });
33
+ if (!element.includes(outVar)) code += emit`
34
+ for(var ${iterVar} of ${g.input}){
35
+ ${element}
36
+ }`;
37
+ else {
38
+ const rebuiltVar = g.temp("set_n");
39
+ const countVar = g.temp("set_c");
40
+ const skipVar = g.temp("set_j");
41
+ const earlierVar = g.temp("set_p");
42
+ code += emit`
43
+ var ${rebuiltVar}=null;
44
+ var ${countVar}=0;
45
+ for(var ${iterVar} of ${g.input}){
46
+ var ${outVar}=${iterVar};
47
+ ${element}
48
+ if(${rebuiltVar}!==null){
49
+ ${rebuiltVar}.add(${outVar});
50
+ }else if(${outVar}!==${iterVar}){
51
+ ${rebuiltVar}=new Set();
52
+ var ${skipVar}=0;
53
+ for(var ${earlierVar} of ${g.input}){
54
+ if(${skipVar}++===${countVar})break;
55
+ ${rebuiltVar}.add(${earlierVar});
56
+ }
57
+ ${rebuiltVar}.add(${outVar});
58
+ }
59
+ ${countVar}++;
60
+ }
61
+ if(${rebuiltVar}!==null){${g.output}=${rebuiltVar};}`;
62
+ }
63
+ }
26
64
  if (ir.checks) for (const check of ir.checks) switch (check.kind) {
27
65
  case "min_size":
28
66
  code += emit`
@@ -1 +1 @@
1
- {"version":3,"file":"set.js","names":[],"sources":["../../../../src/core/codegen/schemas/set.ts"],"sourcesContent":["import type { SchemaIR, SetIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { checkPriority, declareFastTemps, hasMutation } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { whenGatedSizeChecks } from \"./sizeable.js\";\n\nexport function slowSet(ir: SchemaIR & { type: \"set\" }, g: SlowGen): string {\n let code = emit`\n if(!(${g.input} instanceof Set)){\n ${invalidType(g, \"set\")}\n ${whenGatedSizeChecks(ir.checks ?? [], g, \"size\")}\n }else{`;\n\n // Validate each element BEFORE the size checks: Zod parses the elements\n // first and runs size checks afterward, so an invalid element surfaces ahead\n // of too_small/too_big when both fail. Mutating element schemas (coerce,\n // .trim(), url) rewrite the loop variable, which a Set cannot reflect —\n // rebuild into a fresh Set so the mutated values land in the output.\n const mutates = hasMutation(ir.valueType);\n const iterVar = g.temp(\"set_v\");\n const rebuiltVar = mutates ? g.temp(\"set_n\") : \"\";\n if (mutates) {\n code += `var ${rebuiltVar}=new Set();`;\n }\n // The element's path is the SET's own path, with no index segment: a Set has\n // no stable positional addressing, so zod's handleSetResult pushes each\n // element's issues into the set's payload UNPREFIXED (unlike an array, whose\n // handleArrayResult prefixes the index). Two bad elements therefore report at\n // the same path — that is zod's output, and an index we invented instead made\n // every set-element issue point somewhere zod never points.\n code += emit`\n for(var ${iterVar} of ${g.input}){\n ${g.visit(ir.valueType, { input: iterVar, output: iterVar, path: g.path })}\n ${mutates ? `${rebuiltVar}.add(${iterVar});` : \"\"}\n }\n ${mutates ? `${g.output}=${rebuiltVar};` : \"\"}`;\n\n // Size checks (run after element validation, mirroring Zod's check order).\n if (ir.checks) {\n for (const check of ir.checks) {\n switch (check.kind) {\n case \"min_size\":\n code += emit`\n if(${g.input}.size<${check.minimum}){\n ${tooSmall(g, check.minimum, \"set\", true, { message: check.message })}\n }`;\n break;\n case \"max_size\":\n code += emit`\n if(${g.input}.size>${check.maximum}){\n ${tooBig(g, check.maximum, \"set\", true, { message: check.message })}\n }`;\n break;\n case \"size_equals\":\n code += emit`\n if(${g.input}.size<${check.size}){\n ${tooSmall(g, check.size, \"set\", true, { exact: true, message: check.message })}\n }else if(${g.input}.size>${check.size}){\n ${tooBig(g, check.size, \"set\", true, { exact: true, message: check.message })}\n }`;\n break;\n }\n }\n }\n\n code += `}`;\n return `${code}\\n`;\n}\n\nexport function fastSet(ir: SetIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`${x} instanceof Set`];\n\n // Size checks\n if (ir.checks) {\n for (const check of [...ir.checks].sort(checkPriority)) {\n switch (check.kind) {\n case \"min_size\":\n parts.push(`${x}.size>=${check.minimum}`);\n break;\n case \"max_size\":\n parts.push(`${x}.size<=${check.maximum}`);\n break;\n case \"size_equals\":\n parts.push(`${x}.size===${check.size}`);\n break;\n }\n }\n }\n\n // Element validation via preamble helper (Set has no .every()).\n // Fresh scope: the helper is its own function, size-gated independently.\n const elemVar = g.temp(\"sv\");\n const elemGen = g.scoped(elemVar);\n const elemCheck = elemGen.visit(ir.valueType);\n if (elemCheck === null) return null;\n if (elemCheck !== \"true\") {\n const helperName = g.temp(\"se\");\n g.ctx.preamble.push(\n `function ${helperName}(s){${declareFastTemps(elemGen.scope)}for(var ${elemVar} of s){if(!(${elemCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":";;;;;AAOA,SAAgB,QAAQ,IAAgC,GAAoB;CAC1E,IAAI,OAAO,IAAI;WACN,EAAE,MAAM;QACX,YAAY,GAAG,KAAK,EAAE;QACtB,oBAAoB,GAAG,UAAU,CAAC,GAAG,GAAG,MAAM,EAAE;;CAQtD,MAAM,UAAU,YAAY,GAAG,SAAS;CACxC,MAAM,UAAU,EAAE,KAAK,OAAO;CAC9B,MAAM,aAAa,UAAU,EAAE,KAAK,OAAO,IAAI;CAC/C,IAAI,SACF,QAAQ,OAAO,WAAW;CAQ5B,QAAQ,IAAI;cACA,QAAQ,MAAM,EAAE,MAAM;QAC5B,EAAE,MAAM,GAAG,WAAW;EAAE,OAAO;EAAS,QAAQ;EAAS,MAAM,EAAE;CAAK,CAAC,EAAE;QACzE,UAAU,GAAG,WAAW,OAAO,QAAQ,MAAM,GAAG;;MAElD,UAAU,GAAG,EAAE,OAAO,GAAG,WAAW,KAAK;CAG7C,IAAI,GAAG,QACL,KAAK,MAAM,SAAS,GAAG,QACrB,QAAQ,MAAM,MAAd;EACE,KAAK;GACH,QAAQ,IAAI;iBACL,EAAE,MAAM,QAAQ,MAAM,QAAQ;gBAC/B,SAAS,GAAG,MAAM,SAAS,OAAO,MAAM,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;;GAE1E;EACF,KAAK;GACH,QAAQ,IAAI;iBACL,EAAE,MAAM,QAAQ,MAAM,QAAQ;gBAC/B,OAAO,GAAG,MAAM,SAAS,OAAO,MAAM,EAAE,SAAS,MAAM,QAAQ,CAAC,EAAE;;GAExE;EACF,KAAK;GACH,QAAQ,IAAI;iBACL,EAAE,MAAM,QAAQ,MAAM,KAAK;gBAC5B,SAAS,GAAG,MAAM,MAAM,OAAO,MAAM;IAAE,OAAO;IAAM,SAAS,MAAM;GAAQ,CAAC,EAAE;uBACvE,EAAE,MAAM,QAAQ,MAAM,KAAK;gBAClC,OAAO,GAAG,MAAM,MAAM,OAAO,MAAM;IAAE,OAAO;IAAM,SAAS,MAAM;GAAQ,CAAC,EAAE;;GAElF;CACJ;CAIJ,QAAQ;CACR,OAAO,GAAG,KAAK;AACjB;AAEA,SAAgB,QAAQ,IAAW,GAA2B;CAC5D,MAAM,IAAI,EAAE;CACZ,MAAM,QAAkB,CAAC,GAAG,EAAE,gBAAgB;CAG9C,IAAI,GAAG,QACL,KAAK,MAAM,SAAS,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC,KAAK,aAAa,GACnD,QAAQ,MAAM,MAAd;EACE,KAAK;GACH,MAAM,KAAK,GAAG,EAAE,SAAS,MAAM,SAAS;GACxC;EACF,KAAK;GACH,MAAM,KAAK,GAAG,EAAE,SAAS,MAAM,SAAS;GACxC;EACF,KAAK;GACH,MAAM,KAAK,GAAG,EAAE,UAAU,MAAM,MAAM;GACtC;CACJ;CAMJ,MAAM,UAAU,EAAE,KAAK,IAAI;CAC3B,MAAM,UAAU,EAAE,OAAO,OAAO;CAChC,MAAM,YAAY,QAAQ,MAAM,GAAG,SAAS;CAC5C,IAAI,cAAc,MAAM,OAAO;CAC/B,IAAI,cAAc,QAAQ;EACxB,MAAM,aAAa,EAAE,KAAK,IAAI;EAC9B,EAAE,IAAI,SAAS,KACb,YAAY,WAAW,MAAM,iBAAiB,QAAQ,KAAK,EAAE,UAAU,QAAQ,cAAc,UAAU,gCACzG;EACA,MAAM,KAAK,GAAG,WAAW,GAAG,EAAE,EAAE;CAClC;CAEA,OAAO,MAAM,KAAK,IAAI;AACxB"}
1
+ {"version":3,"file":"set.js","names":[],"sources":["../../../../src/core/codegen/schemas/set.ts"],"sourcesContent":["import type { SchemaIR, SetIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport { checkPriority, declareFastTemps, hasMutation } from \"../context.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\nimport { whenGatedSizeChecks } from \"./sizeable.js\";\n\nexport function slowSet(ir: SchemaIR & { type: \"set\" }, g: SlowGen): string {\n let code = emit`\n if(!(${g.input} instanceof Set)){\n ${invalidType(g, \"set\")}\n ${whenGatedSizeChecks(ir.checks ?? [], g, \"size\")}\n }else{`;\n\n // Validate each element BEFORE the size checks: Zod parses the elements\n // first and runs size checks afterward, so an invalid element surfaces ahead\n // of too_small/too_big when both fail. Mutating element schemas (coerce,\n // .trim(), url) rewrite the loop variable, which a Set cannot reflect —\n // rebuild into a fresh Set so the mutated values land in the output.\n const iterVar = g.temp(\"set_v\");\n // The element's path is the SET's own path, with no index segment: a Set has\n // no stable positional addressing, so zod's handleSetResult pushes each\n // element's issues into the set's payload UNPREFIXED (unlike an array, whose\n // handleArrayResult prefixes the index). Two bad elements therefore report at\n // the same path — that is zod's output, and an index we invented instead made\n // every set-element issue point somewhere zod never points.\n if (hasMutation(ir.valueType)) {\n const rebuiltVar = g.temp(\"set_n\");\n code += emit`\n var ${rebuiltVar}=new Set();\n for(var ${iterVar} of ${g.input}){\n ${g.visit(ir.valueType, { input: iterVar, output: iterVar, path: g.path })}\n ${rebuiltVar}.add(${iterVar});\n }\n ${g.output}=${rebuiltVar};`;\n } else {\n // An element that rewrites nothing can still hand back a REPLACEMENT — a\n // `__proto__`-scrubbed copy, a recursive element rebuilt by its own\n // validator — which zod's output Set holds in that element's place. Visited\n // with an output local of its own (see visitMember), the first replacement\n // starts the rebuilt Set: the elements before it, in order, then every\n // element's output from there on. A Set nothing replaces still comes back\n // by reference, and an element that never names its output costs nothing.\n const outVar = g.temp(\"set_o\");\n const element = g.visit(ir.valueType, { input: iterVar, output: outVar, path: g.path });\n if (!element.includes(outVar)) {\n code += emit`\n for(var ${iterVar} of ${g.input}){\n ${element}\n }`;\n } else {\n const rebuiltVar = g.temp(\"set_n\");\n const countVar = g.temp(\"set_c\");\n const skipVar = g.temp(\"set_j\");\n const earlierVar = g.temp(\"set_p\");\n code += emit`\n var ${rebuiltVar}=null;\n var ${countVar}=0;\n for(var ${iterVar} of ${g.input}){\n var ${outVar}=${iterVar};\n ${element}\n if(${rebuiltVar}!==null){\n ${rebuiltVar}.add(${outVar});\n }else if(${outVar}!==${iterVar}){\n ${rebuiltVar}=new Set();\n var ${skipVar}=0;\n for(var ${earlierVar} of ${g.input}){\n if(${skipVar}++===${countVar})break;\n ${rebuiltVar}.add(${earlierVar});\n }\n ${rebuiltVar}.add(${outVar});\n }\n ${countVar}++;\n }\n if(${rebuiltVar}!==null){${g.output}=${rebuiltVar};}`;\n }\n }\n\n // Size checks (run after element validation, mirroring Zod's check order).\n if (ir.checks) {\n for (const check of ir.checks) {\n switch (check.kind) {\n case \"min_size\":\n code += emit`\n if(${g.input}.size<${check.minimum}){\n ${tooSmall(g, check.minimum, \"set\", true, { message: check.message })}\n }`;\n break;\n case \"max_size\":\n code += emit`\n if(${g.input}.size>${check.maximum}){\n ${tooBig(g, check.maximum, \"set\", true, { message: check.message })}\n }`;\n break;\n case \"size_equals\":\n code += emit`\n if(${g.input}.size<${check.size}){\n ${tooSmall(g, check.size, \"set\", true, { exact: true, message: check.message })}\n }else if(${g.input}.size>${check.size}){\n ${tooBig(g, check.size, \"set\", true, { exact: true, message: check.message })}\n }`;\n break;\n }\n }\n }\n\n code += `}`;\n return `${code}\\n`;\n}\n\nexport function fastSet(ir: SetIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`${x} instanceof Set`];\n\n // Size checks\n if (ir.checks) {\n for (const check of [...ir.checks].sort(checkPriority)) {\n switch (check.kind) {\n case \"min_size\":\n parts.push(`${x}.size>=${check.minimum}`);\n break;\n case \"max_size\":\n parts.push(`${x}.size<=${check.maximum}`);\n break;\n case \"size_equals\":\n parts.push(`${x}.size===${check.size}`);\n break;\n }\n }\n }\n\n // Element validation via preamble helper (Set has no .every()).\n // Fresh scope: the helper is its own function, size-gated independently.\n const elemVar = g.temp(\"sv\");\n const elemGen = g.scoped(elemVar);\n const elemCheck = elemGen.visit(ir.valueType);\n if (elemCheck === null) return null;\n if (elemCheck !== \"true\") {\n const helperName = g.temp(\"se\");\n g.ctx.preamble.push(\n `function ${helperName}(s){${declareFastTemps(elemGen.scope)}for(var ${elemVar} of s){if(!(${elemCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x})`);\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
+ import { ZC_CPL_DECL, ZC_LENGTH_ORIGIN_DECL, ZC_SIZE_ORIGIN_DECL } from "../issue-decls.js";
1
2
  import { emitRuntimeHelper } from "../context.js";
2
3
  import { emit } from "../emit.js";
3
4
  import { tooBig, tooSmall } from "../emit-issue.js";
4
- import { ZC_CPL_DECL, ZC_LENGTH_ORIGIN_DECL, ZC_SIZE_ORIGIN_DECL } from "../issue-decls.js";
5
5
  //#region src/core/codegen/schemas/sizeable.ts
6
6
  /**
7
7
  * The UTF-16 unit count from which a string is CERTAINLY at least `min` code
@@ -1,8 +1,8 @@
1
+ import { ZC_EMAIL_DECL } from "../issue-decls.js";
1
2
  import { EMAIL_REGEX_SOURCE, fastTestSource, isDefaultEmailPattern } from "../well-known-regex.js";
2
3
  import { checkPriority, emitEffectFn, emitRegex, emitRegexSourceString, emitRuntimeHelper, escapeString } from "../context.js";
3
4
  import { emit } from "../emit.js";
4
5
  import { invalidFormat, invalidType, tooBig, tooSmall } from "../emit-issue.js";
5
- import { ZC_EMAIL_DECL } from "../issue-decls.js";
6
6
  import { fastRefineTest, refineCheck, superRefineCheck, superRefineFastTest } from "./effect.js";
7
7
  import { stringLengthTests, whenGatedSizeChecks } from "./sizeable.js";
8
8
  //#region src/core/codegen/schemas/string.ts
@@ -1 +1 @@
1
- {"version":3,"file":"tuple.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/tuple.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBA4DgB,UAAU,IAAI;EAAa;GAAiB,GAAG;iBAmI/C,UAAU,IAAI,SAAS,GAAG"}
1
+ {"version":3,"file":"tuple.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/tuple.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;iBA6DgB,UAAU,IAAI;EAAa;GAAiB,GAAG;iBA6I/C,UAAU,IAAI,SAAS,GAAG"}
@@ -1,4 +1,4 @@
1
- import { declareFastTemps, extendPath, extendStaticPathIndex, hasMutation, outputAlwaysDefined, tupleRewritesShortInput } from "../context.js";
1
+ import { declareFastTemps, extendPath, extendStaticPathIndex, hasMutation, outputAlwaysDefined, tupleRewritesShortInput, visitMember } from "../context.js";
2
2
  import { emit } from "../emit.js";
3
3
  import { invalidType, tooBig, tooSmall } from "../emit-issue.js";
4
4
  import { orderByRuntimeCost } from "../fast-size.js";
@@ -52,11 +52,12 @@ function slowTuple(ir, g) {
52
52
  for (let i = 0; i < len; i++) {
53
53
  const itemIR = ir.items[i];
54
54
  const elemExpr = `${x}[${i}]`;
55
- const elemPath = extendStaticPathIndex(g.path, i);
56
- const itemCode = g.visit(itemIR, {
57
- input: elemExpr,
58
- output: elemExpr,
59
- path: elemPath,
55
+ const itemCode = visitMember(g, itemIR, {
56
+ container: x,
57
+ original: g.input,
58
+ copy: `${x}.slice()`,
59
+ key: String(i),
60
+ path: extendStaticPathIndex(g.ctx, g.path, i),
60
61
  issues: itemIssues
61
62
  });
62
63
  const absent = `${i}>=${lenVar}`;
@@ -90,15 +91,17 @@ function slowTuple(ir, g) {
90
91
  }
91
92
  if (ir.rest !== null) {
92
93
  const idxVar = g.temp("ti");
93
- const restExpr = `${x}[${idxVar}]`;
94
- const restPath = extendPath(g.path, idxVar);
94
+ const restCode = visitMember(g, ir.rest, {
95
+ container: x,
96
+ original: g.input,
97
+ copy: `${x}.slice()`,
98
+ key: idxVar,
99
+ path: extendPath(g.ctx, g.path, idxVar),
100
+ issues: g.issues
101
+ });
95
102
  itemsCode += emit`
96
103
  for(var ${idxVar}=${len};${idxVar}<${x}.length;${idxVar}++){
97
- ${g.visit(ir.rest, {
98
- input: restExpr,
99
- output: restExpr,
100
- path: restPath
101
- })}
104
+ ${restCode}
102
105
  }`;
103
106
  const flushVar = g.temp("tqj");
104
107
  itemsCode += `for(var ${flushVar}=0;${flushVar}<${itemIssues}.length;${flushVar}++){${g.issues}.push(${itemIssues}[${flushVar}]);}`;
@@ -1 +1 @@
1
- {"version":3,"file":"tuple.js","names":[],"sources":["../../../../src/core/codegen/schemas/tuple.ts"],"sourcesContent":["import type { SchemaIR, TupleIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n declareFastTemps,\n extendPath,\n extendStaticPathIndex,\n hasMutation,\n outputAlwaysDefined,\n tupleRewritesShortInput,\n} from \"../context.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\n\n/**\n * What an ABSENT slot (index at or past the input's length) does to the output,\n * per zod's `handleTupleResults`:\n *\n * - `present`: can never be absent — below `optStart` without a rest element,\n * where a shorter input is already `too_small`.\n * - `skip`: at or past `optoutStart` and on the \"optional\" rung of `optin`.\n * The output ends here; the item is not consulted and nothing after it runs.\n * - `tail`: at or past `optoutStart` on any other rung. The item runs on\n * `undefined`; a failure ends the output here with its issues dropped, a\n * success is written back and may be trimmed later if it is `undefined`.\n * - `pad`: below `optoutStart`, so a later slot has to keep its index. The\n * item runs on `undefined`, its issues count, and its result — an own\n * `undefined` at the least — is written back.\n */\ntype SlotKind = \"present\" | \"skip\" | \"tail\" | \"pad\";\n\nfunction slotKinds(ir: TupleIR): SlotKind[] {\n const len = ir.items.length;\n const optoutStart = ir.optoutStart ?? len;\n const optionalIn = new Set(ir.optionalIn ?? []);\n const absentFrom = ir.rest === null ? ir.optStart : 0;\n return ir.items.map((_, i) => {\n if (i < absentFrom) return \"present\";\n if (i < optoutStart) return \"pad\";\n return optionalIn.has(i) ? \"skip\" : \"tail\";\n });\n}\n\n/**\n * Mirrors $ZodTuple. Without rest, an input shorter than `optStart` is a single\n * `too_small` (`minimum: optStart`, `inclusive: true`) that skips item\n * validation, and a longer one a single `too_big` that does NOT — zod pushes it\n * and runs the items anyway, so their issues follow it. Both are created by\n * the tuple node (schema error applies) and both share the `code, minimum |\n * maximum, inclusive, origin` key order that check-created size issues do not.\n *\n * Every item then runs, absent slots included, and the output is shaped by\n * {@link slotKinds}. The generated code keeps zod's invariant that the output\n * grows one slot at a time from the input's length: a slot that is about to be\n * handled as absent is exactly the output's current length, and once a `skip`\n * or a failed `tail` ends the output, every later absent slot sees a shorter\n * array and falls through. Ending the output at slot `i` needs no truncation\n * beyond what the failed item may have written, because nothing past `i` was\n * ever assigned.\n */\nexport function slowTuple(ir: SchemaIR & { type: \"tuple\" }, g: SlowGen): string {\n const len = ir.items.length;\n const kinds = slotKinds(ir);\n const optoutStart = ir.optoutStart ?? len;\n\n // Every read and write goes through ONE binding, seeded from the input and\n // re-pointed by each copy, with the result written to `g.output` at the end.\n // Reading `g.input` and writing `g.output` directly only worked while the two\n // were the same identifier — true at every `createSlowGen` root, but NOT under\n // `z.preprocess()`, which visits with `{ input: valueVar, output: g.output }`\n // (see slowEffect). There a copy landed in `g.output` while the item writes\n // went on hitting the original, so the output kept the pristine short array\n // and the caller's array collected the padding instead.\n const x = g.temp(\"ta\");\n\n // With a rest element the fixed items' issues are BUFFERED and flushed after\n // the rest loop, because that is the order zod reports them in: `$ZodTuple`\n // collects the fixed items into `itemResults` WITHOUT touching the payload,\n // runs the rest loop (which pushes through `handleTupleResult`), and only\n // then calls `handleTupleResults`, which pushes what it buffered. So\n // `z.tuple([z.string()]).rest(z.number())` on `[1,\"b\"]` reports the rest\n // element's issue first. `ZodError.message` is `JSON.stringify(issues)`, so\n // the order is user-visible, not just an array detail.\n const itemIssues = ir.rest === null ? g.issues : g.temp(\"tqi\");\n\n let code = emit`\n if(!Array.isArray(${g.input})){\n ${invalidType(g, \"tuple\")}\n }else{\n var ${x}=${g.input};\n ${ir.rest === null ? \"\" : `var ${itemIssues}=[];`}`;\n\n let itemsCode = \"\";\n const mutates = ir.items.some(hasMutation) || (ir.rest !== null && hasMutation(ir.rest));\n if (mutates) {\n itemsCode += `${x}=${x}.slice();`;\n }\n\n // The input's length, read once: absent slots are written back and would\n // otherwise shift the presence test for the slots after them.\n const lenVar = kinds.some((k) => k !== \"present\") ? g.temp(\"tl\") : \"\";\n if (lenVar) itemsCode += `var ${lenVar}=${x}.length;`;\n // A short input gains slots, so it is copied before the first write — the\n // caller's array must not grow. Guarded on the length so a well-formed input\n // never allocates; a mutating item has already paid for the copy.\n if (!mutates && tupleRewritesShortInput(ir)) {\n itemsCode += `if(${lenVar}<${len}){${x}=${x}.slice();}`;\n }\n\n for (let i = 0; i < len; i++) {\n const itemIR = ir.items[i] as SchemaIR;\n const elemExpr = `${x}[${i}]`;\n const elemPath = extendStaticPathIndex(g.path, i);\n const itemCode = g.visit(itemIR, {\n input: elemExpr,\n output: elemExpr,\n path: elemPath,\n issues: itemIssues,\n });\n // One copy of the item code per slot: an absent slot is materialized as an\n // own `undefined` first (`x[i] = undefined`, which is also what extends the\n // copied array), then validated exactly as a present one would be.\n const absent = `${i}>=${lenVar}`;\n switch (kinds[i]) {\n case \"present\":\n itemsCode += itemCode;\n break;\n case \"skip\":\n itemsCode += emit`if(${i}<${lenVar}){${itemCode}}`;\n break;\n case \"tail\": {\n const beforeVar = g.temp(\"tb\");\n itemsCode += emit`\n if(${i}<${lenVar}||${x}.length===${i}){\n var ${beforeVar}=${itemIssues}.length;\n if(${absent}){${elemExpr}=undefined;}\n ${itemCode}\n if(${absent}&&${itemIssues}.length>${beforeVar}){${itemIssues}.length=${beforeVar};${x}.length=${i};}\n }`;\n break;\n }\n case \"pad\":\n itemsCode += emit`if(${absent}){${elemExpr}=undefined;}${itemCode}`;\n break;\n }\n }\n\n // zod's trailing trim: absent slots that produced `undefined` are dropped\n // from the end while the item is optional-out. Only a `tail` slot can leave\n // one behind (a `pad` slot sits below `optoutStart`, a `skip` slot writes\n // nothing), so the loop is emitted only when some tail item might.\n if (kinds.some((k, i) => k === \"tail\" && !outputAlwaysDefined(ir.items[i] as SchemaIR))) {\n const tVar = g.temp(\"tt\");\n const floor = optoutStart > 0 ? `${tVar}>=${optoutStart}&&` : \"\";\n itemsCode += `for(var ${tVar}=${x}.length-1;${floor}${tVar}>=${lenVar}&&${x}[${tVar}]===undefined;${tVar}--){${x}.length=${tVar};}`;\n }\n\n if (ir.rest !== null) {\n const idxVar = g.temp(\"ti\");\n const restExpr = `${x}[${idxVar}]`;\n const restPath = extendPath(g.path, idxVar);\n itemsCode += emit`\n for(var ${idxVar}=${len};${idxVar}<${x}.length;${idxVar}++){\n ${g.visit(ir.rest, { input: restExpr, output: restExpr, path: restPath })}\n }`;\n const flushVar = g.temp(\"tqj\");\n itemsCode += `for(var ${flushVar}=0;${flushVar}<${itemIssues}.length;${flushVar}++){${g.issues}.push(${itemIssues}[${flushVar}]);}`;\n itemsCode += `${g.output}=${x};`;\n code += itemsCode;\n } else {\n const body = emit`\n if(${x}.length>${len}){\n ${tooBig(g, len, \"array\", true, { layout: \"tuple\", aborts: true })}\n }\n ${itemsCode}\n ${g.output}=${x};`;\n code +=\n ir.optStart > 0\n ? emit`\n if(${x}.length<${ir.optStart}){\n ${tooSmall(g, ir.optStart, \"array\", true, { layout: \"tuple\", aborts: true })}\n }else{\n ${body}\n }`\n : body;\n }\n\n code += `}\\n`;\n return code;\n}\n\nexport function fastTuple(ir: TupleIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`Array.isArray(${x})`];\n const kinds = slotKinds(ir);\n\n if (ir.rest === null) {\n if (ir.optStart === ir.items.length) {\n parts.push(`${x}.length===${ir.items.length}`);\n } else {\n if (ir.optStart > 0) parts.push(`${x}.length>=${ir.optStart}`);\n parts.push(`${x}.length<=${ir.items.length}`);\n }\n }\n\n // Per-index checks, cheapest-first: positions are independent, so the emitted\n // order only decides which one a reject stops on (see estimateRuntimeCost).\n // The Array.isArray + length conjuncts above stay in front — the element\n // reads are only meaningful once they hold.\n const indexed = ir.items.flatMap((itemIR, index) => (itemIR ? [{ index, itemIR }] : []));\n for (const { index, itemIR } of orderByRuntimeCost(indexed, (e) => e.itemIR, g.ctx)) {\n const itemCheck = g.visit(itemIR, { input: `${x}[${index}]` });\n if (itemCheck === null) return null;\n const kind = kinds[index];\n // The fast check answers true only where the output IS the input (see\n // fastResultIsInput), so a slot that would be written back when absent —\n // `pad` and `tail` alike — must be present here; the slow walk builds the\n // longer output. A `skip` slot is the reverse: absent, it is accepted\n // whatever its item says, since zod ends the output there without\n // consulting it.\n if (kind === \"pad\" || kind === \"tail\") {\n parts.push(\n itemCheck === \"true\" ? `${x}.length>${index}` : `${x}.length>${index}&&${itemCheck}`,\n );\n } else if (itemCheck === \"true\") {\n continue;\n } else {\n parts.push(kind === \"skip\" ? `(${x}.length<=${index}||${itemCheck})` : itemCheck);\n }\n }\n\n // Rest element validation via preamble helper (avoids .slice().every()\n // allocation). Fresh scope: the helper is its own function, size-gated\n // independently. (Fixed items above stay inline in the caller's && chain.)\n if (ir.rest !== null) {\n const rv = g.temp(\"tr\");\n const restGen = g.scoped(rv);\n const restCheck = restGen.visit(ir.rest);\n if (restCheck === null) return null;\n if (restCheck !== \"true\") {\n const helperName = g.temp(\"te\");\n g.ctx.preamble.push(\n `function ${helperName}(a,s){${declareFastTemps(restGen.scope)}for(var ${rv},i=s;i<a.length;i++){${rv}=a[i];if(!(${restCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x},${ir.items.length})`);\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tuple.js","names":[],"sources":["../../../../src/core/codegen/schemas/tuple.ts"],"sourcesContent":["import type { SchemaIR, TupleIR } from \"../../types.js\";\nimport type { FastGen, SlowGen } from \"../context.js\";\nimport {\n declareFastTemps,\n extendPath,\n extendStaticPathIndex,\n hasMutation,\n outputAlwaysDefined,\n tupleRewritesShortInput,\n visitMember,\n} from \"../context.js\";\nimport { orderByRuntimeCost } from \"../fast-size.js\";\nimport { emit } from \"../emit.js\";\nimport { invalidType, tooBig, tooSmall } from \"../emit-issue.js\";\n\n/**\n * What an ABSENT slot (index at or past the input's length) does to the output,\n * per zod's `handleTupleResults`:\n *\n * - `present`: can never be absent — below `optStart` without a rest element,\n * where a shorter input is already `too_small`.\n * - `skip`: at or past `optoutStart` and on the \"optional\" rung of `optin`.\n * The output ends here; the item is not consulted and nothing after it runs.\n * - `tail`: at or past `optoutStart` on any other rung. The item runs on\n * `undefined`; a failure ends the output here with its issues dropped, a\n * success is written back and may be trimmed later if it is `undefined`.\n * - `pad`: below `optoutStart`, so a later slot has to keep its index. The\n * item runs on `undefined`, its issues count, and its result — an own\n * `undefined` at the least — is written back.\n */\ntype SlotKind = \"present\" | \"skip\" | \"tail\" | \"pad\";\n\nfunction slotKinds(ir: TupleIR): SlotKind[] {\n const len = ir.items.length;\n const optoutStart = ir.optoutStart ?? len;\n const optionalIn = new Set(ir.optionalIn ?? []);\n const absentFrom = ir.rest === null ? ir.optStart : 0;\n return ir.items.map((_, i) => {\n if (i < absentFrom) return \"present\";\n if (i < optoutStart) return \"pad\";\n return optionalIn.has(i) ? \"skip\" : \"tail\";\n });\n}\n\n/**\n * Mirrors $ZodTuple. Without rest, an input shorter than `optStart` is a single\n * `too_small` (`minimum: optStart`, `inclusive: true`) that skips item\n * validation, and a longer one a single `too_big` that does NOT — zod pushes it\n * and runs the items anyway, so their issues follow it. Both are created by\n * the tuple node (schema error applies) and both share the `code, minimum |\n * maximum, inclusive, origin` key order that check-created size issues do not.\n *\n * Every item then runs, absent slots included, and the output is shaped by\n * {@link slotKinds}. The generated code keeps zod's invariant that the output\n * grows one slot at a time from the input's length: a slot that is about to be\n * handled as absent is exactly the output's current length, and once a `skip`\n * or a failed `tail` ends the output, every later absent slot sees a shorter\n * array and falls through. Ending the output at slot `i` needs no truncation\n * beyond what the failed item may have written, because nothing past `i` was\n * ever assigned.\n */\nexport function slowTuple(ir: SchemaIR & { type: \"tuple\" }, g: SlowGen): string {\n const len = ir.items.length;\n const kinds = slotKinds(ir);\n const optoutStart = ir.optoutStart ?? len;\n\n // Every read and write goes through ONE binding, seeded from the input and\n // re-pointed by each copy, with the result written to `g.output` at the end.\n // Reading `g.input` and writing `g.output` directly only works while the two\n // are the same identifier — true at every `createSlowGen` root, but not where\n // a parent hands over a separate local for each (an object's pass-through\n // property, a container member that rewrites nothing: see visitMember). There\n // a copy lands in `g.output` while the writes go on hitting the original, so\n // the output keeps the pristine array and the caller's array collects the\n // changes instead.\n const x = g.temp(\"ta\");\n\n // With a rest element the fixed items' issues are BUFFERED and flushed after\n // the rest loop, because that is the order zod reports them in: `$ZodTuple`\n // collects the fixed items into `itemResults` WITHOUT touching the payload,\n // runs the rest loop (which pushes through `handleTupleResult`), and only\n // then calls `handleTupleResults`, which pushes what it buffered. So\n // `z.tuple([z.string()]).rest(z.number())` on `[1,\"b\"]` reports the rest\n // element's issue first. `ZodError.message` is `JSON.stringify(issues)`, so\n // the order is user-visible, not just an array detail.\n const itemIssues = ir.rest === null ? g.issues : g.temp(\"tqi\");\n\n let code = emit`\n if(!Array.isArray(${g.input})){\n ${invalidType(g, \"tuple\")}\n }else{\n var ${x}=${g.input};\n ${ir.rest === null ? \"\" : `var ${itemIssues}=[];`}`;\n\n let itemsCode = \"\";\n const mutates = ir.items.some(hasMutation) || (ir.rest !== null && hasMutation(ir.rest));\n if (mutates) {\n itemsCode += `${x}=${x}.slice();`;\n }\n\n // The input's length, read once: absent slots are written back and would\n // otherwise shift the presence test for the slots after them.\n const lenVar = kinds.some((k) => k !== \"present\") ? g.temp(\"tl\") : \"\";\n if (lenVar) itemsCode += `var ${lenVar}=${x}.length;`;\n // A short input gains slots, so it is copied before the first write — the\n // caller's array must not grow. Guarded on the length so a well-formed input\n // never allocates; a mutating item has already paid for the copy.\n if (!mutates && tupleRewritesShortInput(ir)) {\n itemsCode += `if(${lenVar}<${len}){${x}=${x}.slice();}`;\n }\n\n for (let i = 0; i < len; i++) {\n const itemIR = ir.items[i] as SchemaIR;\n const elemExpr = `${x}[${i}]`;\n // Read into a local and handed back through visitMember, which lands a\n // replacement on a copy while `x` is still the caller's array.\n const itemCode = visitMember(g, itemIR, {\n container: x,\n original: g.input,\n copy: `${x}.slice()`,\n key: String(i),\n path: extendStaticPathIndex(g.ctx, g.path, i),\n issues: itemIssues,\n });\n // One copy of the item code per slot: an absent slot is materialized as an\n // own `undefined` first (`x[i] = undefined`, which is also what extends the\n // copied array), then validated exactly as a present one would be.\n const absent = `${i}>=${lenVar}`;\n switch (kinds[i]) {\n case \"present\":\n itemsCode += itemCode;\n break;\n case \"skip\":\n itemsCode += emit`if(${i}<${lenVar}){${itemCode}}`;\n break;\n case \"tail\": {\n const beforeVar = g.temp(\"tb\");\n itemsCode += emit`\n if(${i}<${lenVar}||${x}.length===${i}){\n var ${beforeVar}=${itemIssues}.length;\n if(${absent}){${elemExpr}=undefined;}\n ${itemCode}\n if(${absent}&&${itemIssues}.length>${beforeVar}){${itemIssues}.length=${beforeVar};${x}.length=${i};}\n }`;\n break;\n }\n case \"pad\":\n itemsCode += emit`if(${absent}){${elemExpr}=undefined;}${itemCode}`;\n break;\n }\n }\n\n // zod's trailing trim: absent slots that produced `undefined` are dropped\n // from the end while the item is optional-out. Only a `tail` slot can leave\n // one behind (a `pad` slot sits below `optoutStart`, a `skip` slot writes\n // nothing), so the loop is emitted only when some tail item might.\n if (kinds.some((k, i) => k === \"tail\" && !outputAlwaysDefined(ir.items[i] as SchemaIR))) {\n const tVar = g.temp(\"tt\");\n const floor = optoutStart > 0 ? `${tVar}>=${optoutStart}&&` : \"\";\n itemsCode += `for(var ${tVar}=${x}.length-1;${floor}${tVar}>=${lenVar}&&${x}[${tVar}]===undefined;${tVar}--){${x}.length=${tVar};}`;\n }\n\n if (ir.rest !== null) {\n const idxVar = g.temp(\"ti\");\n const restCode = visitMember(g, ir.rest, {\n container: x,\n original: g.input,\n copy: `${x}.slice()`,\n key: idxVar,\n path: extendPath(g.ctx, g.path, idxVar),\n issues: g.issues,\n });\n itemsCode += emit`\n for(var ${idxVar}=${len};${idxVar}<${x}.length;${idxVar}++){\n ${restCode}\n }`;\n const flushVar = g.temp(\"tqj\");\n itemsCode += `for(var ${flushVar}=0;${flushVar}<${itemIssues}.length;${flushVar}++){${g.issues}.push(${itemIssues}[${flushVar}]);}`;\n itemsCode += `${g.output}=${x};`;\n code += itemsCode;\n } else {\n const body = emit`\n if(${x}.length>${len}){\n ${tooBig(g, len, \"array\", true, { layout: \"tuple\", aborts: true })}\n }\n ${itemsCode}\n ${g.output}=${x};`;\n code +=\n ir.optStart > 0\n ? emit`\n if(${x}.length<${ir.optStart}){\n ${tooSmall(g, ir.optStart, \"array\", true, { layout: \"tuple\", aborts: true })}\n }else{\n ${body}\n }`\n : body;\n }\n\n code += `}\\n`;\n return code;\n}\n\nexport function fastTuple(ir: TupleIR, g: FastGen): string | null {\n const x = g.input;\n const parts: string[] = [`Array.isArray(${x})`];\n const kinds = slotKinds(ir);\n\n if (ir.rest === null) {\n if (ir.optStart === ir.items.length) {\n parts.push(`${x}.length===${ir.items.length}`);\n } else {\n if (ir.optStart > 0) parts.push(`${x}.length>=${ir.optStart}`);\n parts.push(`${x}.length<=${ir.items.length}`);\n }\n }\n\n // Per-index checks, cheapest-first: positions are independent, so the emitted\n // order only decides which one a reject stops on (see estimateRuntimeCost).\n // The Array.isArray + length conjuncts above stay in front — the element\n // reads are only meaningful once they hold.\n const indexed = ir.items.flatMap((itemIR, index) => (itemIR ? [{ index, itemIR }] : []));\n for (const { index, itemIR } of orderByRuntimeCost(indexed, (e) => e.itemIR, g.ctx)) {\n const itemCheck = g.visit(itemIR, { input: `${x}[${index}]` });\n if (itemCheck === null) return null;\n const kind = kinds[index];\n // The fast check answers true only where the output IS the input (see\n // fastResultIsInput), so a slot that would be written back when absent —\n // `pad` and `tail` alike — must be present here; the slow walk builds the\n // longer output. A `skip` slot is the reverse: absent, it is accepted\n // whatever its item says, since zod ends the output there without\n // consulting it.\n if (kind === \"pad\" || kind === \"tail\") {\n parts.push(\n itemCheck === \"true\" ? `${x}.length>${index}` : `${x}.length>${index}&&${itemCheck}`,\n );\n } else if (itemCheck === \"true\") {\n continue;\n } else {\n parts.push(kind === \"skip\" ? `(${x}.length<=${index}||${itemCheck})` : itemCheck);\n }\n }\n\n // Rest element validation via preamble helper (avoids .slice().every()\n // allocation). Fresh scope: the helper is its own function, size-gated\n // independently. (Fixed items above stay inline in the caller's && chain.)\n if (ir.rest !== null) {\n const rv = g.temp(\"tr\");\n const restGen = g.scoped(rv);\n const restCheck = restGen.visit(ir.rest);\n if (restCheck === null) return null;\n if (restCheck !== \"true\") {\n const helperName = g.temp(\"te\");\n g.ctx.preamble.push(\n `function ${helperName}(a,s){${declareFastTemps(restGen.scope)}for(var ${rv},i=s;i<a.length;i++){${rv}=a[i];if(!(${restCheck})){return false;}}return true;}`,\n );\n parts.push(`${helperName}(${x},${ir.items.length})`);\n }\n }\n\n return parts.join(\"&&\");\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"union.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/union.ts"],"mappings":";;;iBAQgB,UAAU,IAAI;EAAa;GAAiB,GAAG;iBA+I/C,UAAU,IAAI,SAAS,GAAG"}
1
+ {"version":3,"file":"union.d.ts","names":[],"sources":["../../../../src/core/codegen/schemas/union.ts"],"mappings":";;;iBAQgB,UAAU,IAAI;EAAa;GAAiB,GAAG;iBAiK/C,UAAU,IAAI,SAAS,GAAG"}