zod-compiler 1.23.0 → 1.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/cli/commands/check.d.ts +10 -7
- package/dist/cli/commands/check.d.ts.map +1 -1
- package/dist/cli/commands/check.js +125 -148
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +22 -19
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +102 -133
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/watch.d.ts +17 -15
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +126 -154
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/emitter.d.ts +19 -16
- package/dist/cli/emitter.d.ts.map +1 -1
- package/dist/cli/emitter.js +55 -71
- package/dist/cli/emitter.js.map +1 -1
- package/dist/cli/errors.d.ts +4 -1
- package/dist/cli/errors.d.ts.map +1 -1
- package/dist/cli/errors.js +6 -2
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/index.d.ts +1 -3
- package/dist/cli/index.js +147 -160
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/logger.d.ts +18 -15
- package/dist/cli/logger.d.ts.map +1 -1
- package/dist/cli/logger.js +38 -37
- package/dist/cli/logger.js.map +1 -1
- package/dist/core/codegen/build-path.d.ts +7 -41
- package/dist/core/codegen/build-path.d.ts.map +1 -1
- package/dist/core/codegen/build-path.js +481 -570
- package/dist/core/codegen/build-path.js.map +1 -1
- package/dist/core/codegen/context.d.ts +256 -253
- package/dist/core/codegen/context.d.ts.map +1 -1
- package/dist/core/codegen/context.js +363 -437
- package/dist/core/codegen/context.js.map +1 -1
- package/dist/core/codegen/dedupe.d.ts +22 -56
- package/dist/core/codegen/dedupe.d.ts.map +1 -1
- package/dist/core/codegen/dedupe.js +150 -242
- package/dist/core/codegen/dedupe.js.map +1 -1
- package/dist/core/codegen/emit-issue.d.ts +44 -68
- package/dist/core/codegen/emit-issue.d.ts.map +1 -1
- package/dist/core/codegen/emit-issue.js +76 -108
- package/dist/core/codegen/emit-issue.js.map +1 -1
- package/dist/core/codegen/emit.d.ts +4 -1
- package/dist/core/codegen/emit.d.ts.map +1 -1
- package/dist/core/codegen/emit.js +16 -13
- package/dist/core/codegen/emit.js.map +1 -1
- package/dist/core/codegen/fast-path.d.ts +7 -12
- package/dist/core/codegen/fast-path.d.ts.map +1 -1
- package/dist/core/codegen/fast-path.js +116 -145
- package/dist/core/codegen/fast-path.js.map +1 -1
- package/dist/core/codegen/fast-size.d.ts +12 -26
- package/dist/core/codegen/fast-size.d.ts.map +1 -1
- package/dist/core/codegen/fast-size.js +169 -244
- package/dist/core/codegen/fast-size.js.map +1 -1
- package/dist/core/codegen/index.d.ts +25 -23
- package/dist/core/codegen/index.d.ts.map +1 -1
- package/dist/core/codegen/index.js +239 -405
- package/dist/core/codegen/index.js.map +1 -1
- package/dist/core/codegen/issue-decls.d.ts +15 -12
- package/dist/core/codegen/issue-decls.d.ts.map +1 -1
- package/dist/core/codegen/issue-decls.js +131 -162
- package/dist/core/codegen/issue-decls.js.map +1 -1
- package/dist/core/codegen/regex-unroll.d.ts +4 -1
- package/dist/core/codegen/regex-unroll.d.ts.map +1 -1
- package/dist/core/codegen/regex-unroll.js +173 -197
- package/dist/core/codegen/regex-unroll.js.map +1 -1
- package/dist/core/codegen/schemas/any.d.ts +7 -4
- package/dist/core/codegen/schemas/any.d.ts.map +1 -1
- package/dist/core/codegen/schemas/any.js +8 -4
- package/dist/core/codegen/schemas/any.js.map +1 -1
- package/dist/core/codegen/schemas/array.d.ts +8 -5
- package/dist/core/codegen/schemas/array.d.ts.map +1 -1
- package/dist/core/codegen/schemas/array.js +77 -95
- package/dist/core/codegen/schemas/array.js.map +1 -1
- package/dist/core/codegen/schemas/bigint.d.ts +7 -4
- package/dist/core/codegen/schemas/bigint.d.ts.map +1 -1
- package/dist/core/codegen/schemas/bigint.js +44 -56
- package/dist/core/codegen/schemas/bigint.js.map +1 -1
- package/dist/core/codegen/schemas/boolean.d.ts +7 -4
- package/dist/core/codegen/schemas/boolean.d.ts.map +1 -1
- package/dist/core/codegen/schemas/boolean.js +12 -11
- package/dist/core/codegen/schemas/boolean.js.map +1 -1
- package/dist/core/codegen/schemas/catch.d.ts +8 -5
- package/dist/core/codegen/schemas/catch.d.ts.map +1 -1
- package/dist/core/codegen/schemas/catch.js +23 -23
- package/dist/core/codegen/schemas/catch.js.map +1 -1
- package/dist/core/codegen/schemas/date.d.ts +7 -4
- package/dist/core/codegen/schemas/date.d.ts.map +1 -1
- package/dist/core/codegen/schemas/date.js +49 -68
- package/dist/core/codegen/schemas/date.js.map +1 -1
- package/dist/core/codegen/schemas/default.d.ts +9 -6
- package/dist/core/codegen/schemas/default.d.ts.map +1 -1
- package/dist/core/codegen/schemas/default.js +29 -27
- package/dist/core/codegen/schemas/default.js.map +1 -1
- package/dist/core/codegen/schemas/discriminated-union.d.ts +12 -10
- package/dist/core/codegen/schemas/discriminated-union.d.ts.map +1 -1
- package/dist/core/codegen/schemas/discriminated-union.js +153 -178
- package/dist/core/codegen/schemas/discriminated-union.js.map +1 -1
- package/dist/core/codegen/schemas/effect.d.ts +9 -6
- package/dist/core/codegen/schemas/effect.d.ts.map +1 -1
- package/dist/core/codegen/schemas/effect.js +54 -67
- package/dist/core/codegen/schemas/effect.js.map +1 -1
- package/dist/core/codegen/schemas/enum.d.ts +7 -4
- package/dist/core/codegen/schemas/enum.d.ts.map +1 -1
- package/dist/core/codegen/schemas/enum.js +15 -21
- package/dist/core/codegen/schemas/enum.js.map +1 -1
- package/dist/core/codegen/schemas/fallback.d.ts +6 -3
- package/dist/core/codegen/schemas/fallback.d.ts.map +1 -1
- package/dist/core/codegen/schemas/fallback.js +14 -13
- package/dist/core/codegen/schemas/fallback.js.map +1 -1
- package/dist/core/codegen/schemas/file.d.ts +7 -4
- package/dist/core/codegen/schemas/file.d.ts.map +1 -1
- package/dist/core/codegen/schemas/file.js +51 -57
- package/dist/core/codegen/schemas/file.js.map +1 -1
- package/dist/core/codegen/schemas/intersection.d.ts +8 -5
- package/dist/core/codegen/schemas/intersection.d.ts.map +1 -1
- package/dist/core/codegen/schemas/intersection.js +16 -13
- package/dist/core/codegen/schemas/intersection.js.map +1 -1
- package/dist/core/codegen/schemas/literal.d.ts +7 -4
- package/dist/core/codegen/schemas/literal.d.ts.map +1 -1
- package/dist/core/codegen/schemas/literal.js +20 -23
- package/dist/core/codegen/schemas/literal.js.map +1 -1
- package/dist/core/codegen/schemas/map.d.ts +8 -5
- package/dist/core/codegen/schemas/map.d.ts.map +1 -1
- package/dist/core/codegen/schemas/map.js +61 -67
- package/dist/core/codegen/schemas/map.js.map +1 -1
- package/dist/core/codegen/schemas/nan.d.ts +7 -4
- package/dist/core/codegen/schemas/nan.d.ts.map +1 -1
- package/dist/core/codegen/schemas/nan.js +8 -4
- package/dist/core/codegen/schemas/nan.js.map +1 -1
- package/dist/core/codegen/schemas/never.d.ts +7 -4
- package/dist/core/codegen/schemas/never.d.ts.map +1 -1
- package/dist/core/codegen/schemas/never.js +8 -4
- package/dist/core/codegen/schemas/never.js.map +1 -1
- package/dist/core/codegen/schemas/null.d.ts +7 -4
- package/dist/core/codegen/schemas/null.d.ts.map +1 -1
- package/dist/core/codegen/schemas/null.js +8 -4
- package/dist/core/codegen/schemas/null.js.map +1 -1
- package/dist/core/codegen/schemas/nullable.d.ts +8 -5
- package/dist/core/codegen/schemas/nullable.d.ts.map +1 -1
- package/dist/core/codegen/schemas/nullable.js +8 -5
- package/dist/core/codegen/schemas/nullable.js.map +1 -1
- package/dist/core/codegen/schemas/number.d.ts +7 -4
- package/dist/core/codegen/schemas/number.d.ts.map +1 -1
- package/dist/core/codegen/schemas/number.js +120 -176
- package/dist/core/codegen/schemas/number.js.map +1 -1
- package/dist/core/codegen/schemas/object.d.ts +8 -5
- package/dist/core/codegen/schemas/object.d.ts.map +1 -1
- package/dist/core/codegen/schemas/object.js +144 -231
- package/dist/core/codegen/schemas/object.js.map +1 -1
- package/dist/core/codegen/schemas/optional.d.ts +9 -6
- package/dist/core/codegen/schemas/optional.d.ts.map +1 -1
- package/dist/core/codegen/schemas/optional.js +23 -31
- package/dist/core/codegen/schemas/optional.js.map +1 -1
- package/dist/core/codegen/schemas/pipe.d.ts +8 -5
- package/dist/core/codegen/schemas/pipe.d.ts.map +1 -1
- package/dist/core/codegen/schemas/pipe.js +20 -27
- package/dist/core/codegen/schemas/pipe.js.map +1 -1
- package/dist/core/codegen/schemas/readonly.d.ts +8 -5
- package/dist/core/codegen/schemas/readonly.d.ts.map +1 -1
- package/dist/core/codegen/schemas/readonly.js +8 -5
- package/dist/core/codegen/schemas/readonly.js.map +1 -1
- package/dist/core/codegen/schemas/record.d.ts +8 -5
- package/dist/core/codegen/schemas/record.d.ts.map +1 -1
- package/dist/core/codegen/schemas/record.js +52 -65
- package/dist/core/codegen/schemas/record.js.map +1 -1
- package/dist/core/codegen/schemas/recursive-ref.d.ts +9 -6
- package/dist/core/codegen/schemas/recursive-ref.d.ts.map +1 -1
- package/dist/core/codegen/schemas/recursive-ref.js +44 -44
- package/dist/core/codegen/schemas/recursive-ref.js.map +1 -1
- package/dist/core/codegen/schemas/set.d.ts +8 -5
- package/dist/core/codegen/schemas/set.d.ts.map +1 -1
- package/dist/core/codegen/schemas/set.js +61 -73
- package/dist/core/codegen/schemas/set.js.map +1 -1
- package/dist/core/codegen/schemas/string-bool.d.ts +6 -3
- package/dist/core/codegen/schemas/string-bool.d.ts.map +1 -1
- package/dist/core/codegen/schemas/string-bool.js +22 -23
- package/dist/core/codegen/schemas/string-bool.js.map +1 -1
- package/dist/core/codegen/schemas/string.d.ts +8 -5
- package/dist/core/codegen/schemas/string.d.ts.map +1 -1
- package/dist/core/codegen/schemas/string.js +168 -207
- package/dist/core/codegen/schemas/string.js.map +1 -1
- package/dist/core/codegen/schemas/symbol.d.ts +7 -4
- package/dist/core/codegen/schemas/symbol.d.ts.map +1 -1
- package/dist/core/codegen/schemas/symbol.js +8 -4
- package/dist/core/codegen/schemas/symbol.js.map +1 -1
- package/dist/core/codegen/schemas/template-literal.d.ts +7 -4
- package/dist/core/codegen/schemas/template-literal.d.ts.map +1 -1
- package/dist/core/codegen/schemas/template-literal.js +12 -13
- package/dist/core/codegen/schemas/template-literal.js.map +1 -1
- package/dist/core/codegen/schemas/tuple.d.ts +8 -5
- package/dist/core/codegen/schemas/tuple.d.ts.map +1 -1
- package/dist/core/codegen/schemas/tuple.js +84 -94
- package/dist/core/codegen/schemas/tuple.js.map +1 -1
- package/dist/core/codegen/schemas/undefined.d.ts +7 -4
- package/dist/core/codegen/schemas/undefined.d.ts.map +1 -1
- package/dist/core/codegen/schemas/undefined.js +8 -4
- package/dist/core/codegen/schemas/undefined.js.map +1 -1
- package/dist/core/codegen/schemas/union.d.ts +8 -5
- package/dist/core/codegen/schemas/union.d.ts.map +1 -1
- package/dist/core/codegen/schemas/union.js +49 -69
- package/dist/core/codegen/schemas/union.js.map +1 -1
- package/dist/core/codegen/schemas/unknown.d.ts +7 -4
- package/dist/core/codegen/schemas/unknown.d.ts.map +1 -1
- package/dist/core/codegen/schemas/unknown.js +8 -4
- package/dist/core/codegen/schemas/unknown.js.map +1 -1
- package/dist/core/codegen/schemas/void.d.ts +7 -4
- package/dist/core/codegen/schemas/void.d.ts.map +1 -1
- package/dist/core/codegen/schemas/void.js +8 -4
- package/dist/core/codegen/schemas/void.js.map +1 -1
- package/dist/core/codegen/slow-path.d.ts +7 -4
- package/dist/core/codegen/slow-path.d.ts.map +1 -1
- package/dist/core/codegen/slow-path.js +71 -96
- package/dist/core/codegen/slow-path.js.map +1 -1
- package/dist/core/codegen/well-known-regex.d.ts +22 -19
- package/dist/core/codegen/well-known-regex.d.ts.map +1 -1
- package/dist/core/codegen/well-known-regex.js +127 -96
- package/dist/core/codegen/well-known-regex.js.map +1 -1
- package/dist/core/compile.d.ts +7 -4
- package/dist/core/compile.d.ts.map +1 -1
- package/dist/core/compile.js +48 -48
- package/dist/core/compile.js.map +1 -1
- package/dist/core/diagnostic.d.ts +38 -39
- package/dist/core/diagnostic.d.ts.map +1 -1
- package/dist/core/diagnostic.js +140 -164
- package/dist/core/diagnostic.js.map +1 -1
- package/dist/core/extract/checks.d.ts +18 -15
- package/dist/core/extract/checks.d.ts.map +1 -1
- package/dist/core/extract/checks.js +318 -311
- package/dist/core/extract/checks.js.map +1 -1
- package/dist/core/extract/effects.d.ts +13 -10
- package/dist/core/extract/effects.d.ts.map +1 -1
- package/dist/core/extract/effects.js +153 -222
- package/dist/core/extract/effects.js.map +1 -1
- package/dist/core/extract/extractors/any.d.ts +5 -2
- package/dist/core/extract/extractors/any.d.ts.map +1 -1
- package/dist/core/extract/extractors/any.js +5 -1
- package/dist/core/extract/extractors/any.js.map +1 -1
- package/dist/core/extract/extractors/array.d.ts +6 -3
- package/dist/core/extract/extractors/array.d.ts.map +1 -1
- package/dist/core/extract/extractors/array.js +25 -20
- package/dist/core/extract/extractors/array.js.map +1 -1
- package/dist/core/extract/extractors/bigint.d.ts +6 -3
- package/dist/core/extract/extractors/bigint.d.ts.map +1 -1
- package/dist/core/extract/extractors/bigint.js +66 -64
- package/dist/core/extract/extractors/bigint.js.map +1 -1
- package/dist/core/extract/extractors/boolean.d.ts +5 -2
- package/dist/core/extract/extractors/boolean.d.ts.map +1 -1
- package/dist/core/extract/extractors/boolean.js +7 -3
- package/dist/core/extract/extractors/boolean.js.map +1 -1
- package/dist/core/extract/extractors/catch.d.ts +6 -3
- package/dist/core/extract/extractors/catch.d.ts.map +1 -1
- package/dist/core/extract/extractors/catch.js +26 -17
- package/dist/core/extract/extractors/catch.js.map +1 -1
- package/dist/core/extract/extractors/date.d.ts +6 -3
- package/dist/core/extract/extractors/date.d.ts.map +1 -1
- package/dist/core/extract/extractors/date.js +42 -46
- package/dist/core/extract/extractors/date.js.map +1 -1
- package/dist/core/extract/extractors/default.d.ts +6 -3
- package/dist/core/extract/extractors/default.d.ts.map +1 -1
- package/dist/core/extract/extractors/default.js +20 -14
- package/dist/core/extract/extractors/default.js.map +1 -1
- package/dist/core/extract/extractors/enum.d.ts +5 -2
- package/dist/core/extract/extractors/enum.d.ts.map +1 -1
- package/dist/core/extract/extractors/enum.js +12 -13
- package/dist/core/extract/extractors/enum.js.map +1 -1
- package/dist/core/extract/extractors/file.d.ts +6 -3
- package/dist/core/extract/extractors/file.d.ts.map +1 -1
- package/dist/core/extract/extractors/file.js +34 -28
- package/dist/core/extract/extractors/file.js.map +1 -1
- package/dist/core/extract/extractors/intersection.d.ts +5 -2
- package/dist/core/extract/extractors/intersection.d.ts.map +1 -1
- package/dist/core/extract/extractors/intersection.js +13 -11
- package/dist/core/extract/extractors/intersection.js.map +1 -1
- package/dist/core/extract/extractors/lazy.d.ts +6 -3
- package/dist/core/extract/extractors/lazy.d.ts.map +1 -1
- package/dist/core/extract/extractors/lazy.js +21 -30
- package/dist/core/extract/extractors/lazy.js.map +1 -1
- package/dist/core/extract/extractors/literal.d.ts +5 -2
- package/dist/core/extract/extractors/literal.d.ts.map +1 -1
- package/dist/core/extract/extractors/literal.js +8 -1
- package/dist/core/extract/extractors/literal.js.map +1 -1
- package/dist/core/extract/extractors/map.d.ts +6 -3
- package/dist/core/extract/extractors/map.d.ts.map +1 -1
- package/dist/core/extract/extractors/map.js +10 -4
- package/dist/core/extract/extractors/map.js.map +1 -1
- package/dist/core/extract/extractors/nan.d.ts +5 -2
- package/dist/core/extract/extractors/nan.d.ts.map +1 -1
- package/dist/core/extract/extractors/nan.js +5 -1
- package/dist/core/extract/extractors/nan.js.map +1 -1
- package/dist/core/extract/extractors/never.d.ts +5 -2
- package/dist/core/extract/extractors/never.d.ts.map +1 -1
- package/dist/core/extract/extractors/never.js +5 -1
- package/dist/core/extract/extractors/never.js.map +1 -1
- package/dist/core/extract/extractors/null.d.ts +5 -2
- package/dist/core/extract/extractors/null.d.ts.map +1 -1
- package/dist/core/extract/extractors/null.js +5 -1
- package/dist/core/extract/extractors/null.js.map +1 -1
- package/dist/core/extract/extractors/nullable.d.ts +5 -2
- package/dist/core/extract/extractors/nullable.d.ts.map +1 -1
- package/dist/core/extract/extractors/nullable.js +7 -3
- package/dist/core/extract/extractors/nullable.js.map +1 -1
- package/dist/core/extract/extractors/number.d.ts +6 -3
- package/dist/core/extract/extractors/number.d.ts.map +1 -1
- package/dist/core/extract/extractors/number.js +35 -35
- package/dist/core/extract/extractors/number.js.map +1 -1
- package/dist/core/extract/extractors/object.d.ts +6 -3
- package/dist/core/extract/extractors/object.d.ts.map +1 -1
- package/dist/core/extract/extractors/object.js +49 -76
- package/dist/core/extract/extractors/object.js.map +1 -1
- package/dist/core/extract/extractors/optional.d.ts +5 -2
- package/dist/core/extract/extractors/optional.d.ts.map +1 -1
- package/dist/core/extract/extractors/optional.js +10 -12
- package/dist/core/extract/extractors/optional.js.map +1 -1
- package/dist/core/extract/extractors/pipe.d.ts +6 -3
- package/dist/core/extract/extractors/pipe.d.ts.map +1 -1
- package/dist/core/extract/extractors/pipe.js +40 -41
- package/dist/core/extract/extractors/pipe.js.map +1 -1
- package/dist/core/extract/extractors/readonly.d.ts +5 -2
- package/dist/core/extract/extractors/readonly.d.ts.map +1 -1
- package/dist/core/extract/extractors/readonly.js +10 -6
- package/dist/core/extract/extractors/readonly.js.map +1 -1
- package/dist/core/extract/extractors/record.d.ts +6 -3
- package/dist/core/extract/extractors/record.d.ts.map +1 -1
- package/dist/core/extract/extractors/record.js +24 -35
- package/dist/core/extract/extractors/record.js.map +1 -1
- package/dist/core/extract/extractors/set.d.ts +6 -3
- package/dist/core/extract/extractors/set.d.ts.map +1 -1
- package/dist/core/extract/extractors/set.js +36 -30
- package/dist/core/extract/extractors/set.js.map +1 -1
- package/dist/core/extract/extractors/string-bool.d.ts +7 -4
- package/dist/core/extract/extractors/string-bool.d.ts.map +1 -1
- package/dist/core/extract/extractors/string-bool.js +66 -84
- package/dist/core/extract/extractors/string-bool.js.map +1 -1
- package/dist/core/extract/extractors/string.d.ts +6 -3
- package/dist/core/extract/extractors/string.d.ts.map +1 -1
- package/dist/core/extract/extractors/string.js +34 -37
- package/dist/core/extract/extractors/string.js.map +1 -1
- package/dist/core/extract/extractors/symbol.d.ts +5 -2
- package/dist/core/extract/extractors/symbol.d.ts.map +1 -1
- package/dist/core/extract/extractors/symbol.js +5 -1
- package/dist/core/extract/extractors/symbol.js.map +1 -1
- package/dist/core/extract/extractors/template-literal.d.ts +6 -3
- package/dist/core/extract/extractors/template-literal.d.ts.map +1 -1
- package/dist/core/extract/extractors/template-literal.js +11 -6
- package/dist/core/extract/extractors/template-literal.js.map +1 -1
- package/dist/core/extract/extractors/tuple.d.ts +6 -3
- package/dist/core/extract/extractors/tuple.d.ts.map +1 -1
- package/dist/core/extract/extractors/tuple.js +10 -4
- package/dist/core/extract/extractors/tuple.js.map +1 -1
- package/dist/core/extract/extractors/undefined.d.ts +5 -2
- package/dist/core/extract/extractors/undefined.d.ts.map +1 -1
- package/dist/core/extract/extractors/undefined.js +5 -1
- package/dist/core/extract/extractors/undefined.js.map +1 -1
- package/dist/core/extract/extractors/union.d.ts +6 -3
- package/dist/core/extract/extractors/union.d.ts.map +1 -1
- package/dist/core/extract/extractors/union.js +38 -64
- package/dist/core/extract/extractors/union.js.map +1 -1
- package/dist/core/extract/extractors/unknown.d.ts +5 -2
- package/dist/core/extract/extractors/unknown.d.ts.map +1 -1
- package/dist/core/extract/extractors/unknown.js +5 -1
- package/dist/core/extract/extractors/unknown.js.map +1 -1
- package/dist/core/extract/extractors/void.d.ts +5 -2
- package/dist/core/extract/extractors/void.d.ts.map +1 -1
- package/dist/core/extract/extractors/void.js +5 -1
- package/dist/core/extract/extractors/void.js.map +1 -1
- package/dist/core/extract/fallback.d.ts +6 -3
- package/dist/core/extract/fallback.d.ts.map +1 -1
- package/dist/core/extract/fallback.js +21 -7
- package/dist/core/extract/fallback.js.map +1 -1
- package/dist/core/extract/index.d.ts +6 -4
- package/dist/core/extract/index.d.ts.map +1 -1
- package/dist/core/extract/index.js +15 -15
- package/dist/core/extract/index.js.map +1 -1
- package/dist/core/extract/registry.d.ts +39 -36
- package/dist/core/extract/registry.d.ts.map +1 -1
- package/dist/core/extract/registry.js +96 -123
- package/dist/core/extract/registry.js.map +1 -1
- package/dist/core/extract/types.d.ts +124 -120
- package/dist/core/extract/types.d.ts.map +1 -1
- package/dist/core/extract/types.js +0 -1
- package/dist/core/iife.d.ts +14 -15
- package/dist/core/iife.d.ts.map +1 -1
- package/dist/core/iife.js +182 -206
- package/dist/core/iife.js.map +1 -1
- package/dist/core/pipeline.d.ts +33 -30
- package/dist/core/pipeline.d.ts.map +1 -1
- package/dist/core/pipeline.js +67 -74
- package/dist/core/pipeline.js.map +1 -1
- package/dist/core/types.d.ts +430 -427
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +0 -5
- package/dist/discovery.d.ts +8 -5
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +31 -32
- package/dist/discovery.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/jit.d.ts +15 -42
- package/dist/jit.d.ts.map +1 -1
- package/dist/jit.js +187 -216
- package/dist/jit.js.map +1 -1
- package/dist/loader.d.ts +14 -11
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +226 -258
- package/dist/loader.js.map +1 -1
- package/dist/static-filter.d.ts +4 -1
- package/dist/static-filter.d.ts.map +1 -1
- package/dist/static-filter.js +240 -367
- package/dist/static-filter.js.map +1 -1
- package/dist/swc.d.ts +38 -35
- package/dist/swc.d.ts.map +1 -1
- package/dist/swc.js +83 -76
- package/dist/swc.js.map +1 -1
- package/dist/unplugin/bun.d.ts +5 -2
- package/dist/unplugin/bun.d.ts.map +1 -1
- package/dist/unplugin/bun.js +5 -1
- package/dist/unplugin/bun.js.map +1 -1
- package/dist/unplugin/dep-graph.d.ts +10 -7
- package/dist/unplugin/dep-graph.d.ts.map +1 -1
- package/dist/unplugin/dep-graph.js +216 -252
- package/dist/unplugin/dep-graph.js.map +1 -1
- package/dist/unplugin/disk-cache.d.ts +121 -92
- package/dist/unplugin/disk-cache.d.ts.map +1 -1
- package/dist/unplugin/disk-cache.js +425 -444
- package/dist/unplugin/disk-cache.js.map +1 -1
- package/dist/unplugin/edits.d.ts +15 -12
- package/dist/unplugin/edits.d.ts.map +1 -1
- package/dist/unplugin/edits.js +24 -37
- package/dist/unplugin/edits.js.map +1 -1
- package/dist/unplugin/esbuild.d.ts +5 -2
- package/dist/unplugin/esbuild.d.ts.map +1 -1
- package/dist/unplugin/esbuild.js +5 -1
- package/dist/unplugin/esbuild.js.map +1 -1
- package/dist/unplugin/farm.d.ts +5 -2
- package/dist/unplugin/farm.d.ts.map +1 -1
- package/dist/unplugin/farm.js +5 -1
- package/dist/unplugin/farm.js.map +1 -1
- package/dist/unplugin/hoist-compile.d.ts +14 -42
- package/dist/unplugin/hoist-compile.d.ts.map +1 -1
- package/dist/unplugin/hoist-compile.js +67 -112
- package/dist/unplugin/hoist-compile.js.map +1 -1
- package/dist/unplugin/hoist.d.ts +56 -54
- package/dist/unplugin/hoist.d.ts.map +1 -1
- package/dist/unplugin/hoist.js +945 -1170
- package/dist/unplugin/hoist.js.map +1 -1
- package/dist/unplugin/index.d.ts +5 -3
- package/dist/unplugin/index.d.ts.map +1 -1
- package/dist/unplugin/index.js +175 -250
- package/dist/unplugin/index.js.map +1 -1
- package/dist/unplugin/rolldown.d.ts +5 -2
- package/dist/unplugin/rolldown.d.ts.map +1 -1
- package/dist/unplugin/rolldown.js +5 -1
- package/dist/unplugin/rolldown.js.map +1 -1
- package/dist/unplugin/rollup.d.ts +5 -2
- package/dist/unplugin/rollup.d.ts.map +1 -1
- package/dist/unplugin/rollup.js +5 -1
- package/dist/unplugin/rollup.js.map +1 -1
- package/dist/unplugin/rsbuild.d.ts +6 -3
- package/dist/unplugin/rsbuild.d.ts.map +1 -1
- package/dist/unplugin/rsbuild.js +15 -11
- package/dist/unplugin/rsbuild.js.map +1 -1
- package/dist/unplugin/rspack.d.ts +5 -2
- package/dist/unplugin/rspack.d.ts.map +1 -1
- package/dist/unplugin/rspack.js +5 -1
- package/dist/unplugin/rspack.js.map +1 -1
- package/dist/unplugin/transform.d.ts +30 -27
- package/dist/unplugin/transform.d.ts.map +1 -1
- package/dist/unplugin/transform.js +433 -620
- package/dist/unplugin/transform.js.map +1 -1
- package/dist/unplugin/types.d.ts +189 -184
- package/dist/unplugin/types.d.ts.map +1 -1
- package/dist/unplugin/types.js +22 -18
- package/dist/unplugin/types.js.map +1 -1
- package/dist/unplugin/virtual.d.ts +11 -8
- package/dist/unplugin/virtual.d.ts.map +1 -1
- package/dist/unplugin/virtual.js +65 -83
- package/dist/unplugin/virtual.js.map +1 -1
- package/dist/unplugin/vite.d.ts +5 -2
- package/dist/unplugin/vite.d.ts.map +1 -1
- package/dist/unplugin/vite.js +5 -1
- package/dist/unplugin/vite.js.map +1 -1
- package/dist/unplugin/webpack.d.ts +5 -2
- package/dist/unplugin/webpack.d.ts.map +1 -1
- package/dist/unplugin/webpack.js +5 -1
- package/dist/unplugin/webpack.js.map +1 -1
- package/package.json +23 -14
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/core/extract/types.js.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/unplugin/hoist.js
CHANGED
|
@@ -1,1242 +1,1017 @@
|
|
|
1
|
-
import { Parser } from "acorn";
|
|
2
1
|
import { applyEdits } from "./edits.js";
|
|
2
|
+
import { Parser } from "acorn";
|
|
3
|
+
//#region src/unplugin/hoist.ts
|
|
3
4
|
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
5
|
+
* Hoist Zod schema construction out of functions to module scope —
|
|
6
|
+
* equivalent of babel-plugin-zod-hoist.
|
|
7
|
+
*
|
|
8
|
+
* Schemas built inside function bodies are re-constructed on every call:
|
|
9
|
+
*
|
|
10
|
+
* function getSchema() {
|
|
11
|
+
* return z.object({ name: z.string() }); // rebuilt per call
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* becomes
|
|
15
|
+
*
|
|
16
|
+
* const _zh_94b7f5c1 = z.object({ name: z.string() });
|
|
17
|
+
* function getSchema() {
|
|
18
|
+
* return _zh_94b7f5c1; // built once
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* Safety rules (babel-plugin-zod-hoist's `canSafelyHoist`, hardened for
|
|
22
|
+
* lexical analysis):
|
|
23
|
+
* - A free identifier must be an import or a KNOWN_GLOBALS member, and must
|
|
24
|
+
* never be bound anywhere in the file (function params, locals, catch
|
|
25
|
+
* clauses, class names, module-level const/let/var — hoisting above those
|
|
26
|
+
* would change meaning or hit the TDZ). The babel plugin additionally
|
|
27
|
+
* allows arbitrary unbound identifiers because it has real scope
|
|
28
|
+
* information; this port's binding collector is lexical, so an unknown
|
|
29
|
+
* bare name is treated as a possibly-missed binding rather than a global
|
|
30
|
+
* (a wrong guess crashes at module load with a ReferenceError).
|
|
31
|
+
* `this`/`super` disqualify anywhere. Eager `await`/`yield` also
|
|
32
|
+
* disqualify (stricter than the babel plugin, which never encounters
|
|
33
|
+
* them: hoisting one would emit top-level await / orphaned yield).
|
|
34
|
+
* - Eligible roots: any binding imported from zod, an imported identifier
|
|
35
|
+
* matching /ZodSchema$/, or an imported identifier whose chain contains
|
|
36
|
+
* an inline z.* reference (e.g. `Base.extend({ a: z.string() })`).
|
|
37
|
+
* - Nesting (babel's `isNestedInZodCall`): the interior of a zod-rooted
|
|
38
|
+
* chain never hoists separately — it goes with the outer schema or not at
|
|
39
|
+
* all. Chains rooted elsewhere (`sql.type(...)`, `api.get(...)`) do NOT
|
|
40
|
+
* suppress their arguments: when the outer chain is rejected, an inner
|
|
41
|
+
* `z.object({...})` still hoists on its own.
|
|
42
|
+
* - Declarations are inserted at the top of the module (after shebang and
|
|
43
|
+
* directive prologue). Imports are initialized before module code runs,
|
|
44
|
+
* so referencing them from above their textual position is safe.
|
|
45
|
+
* - Names are content-hashed, so identical schemas dedupe to one binding.
|
|
46
|
+
*
|
|
47
|
+
* The source is TypeScript, which acorn cannot fully parse — candidates are
|
|
48
|
+
* located with a string/comment/depth-aware scanner and extracted with
|
|
49
|
+
* parseExpressionAt (the same technique as the autoDiscover rewrite).
|
|
50
|
+
* Anything unparseable (TS generics, `as` casts) is skipped: a miss leaves
|
|
51
|
+
* the schema unhoisted, never breaks the code.
|
|
52
|
+
*/
|
|
52
53
|
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
* Imported identifiers matching this pattern are treated as schema roots.
|
|
55
|
+
*
|
|
56
|
+
* The default must keep implying a "Zod" substring: it is one of the three
|
|
57
|
+
* triggers the transform hook's `code` filter (ZOD_MENTION in transform.ts)
|
|
58
|
+
* is a superset of. A default that matched, say, `/Schema$/` would make
|
|
59
|
+
* hoistable files without any "zod" mention invisible to bundlers with native
|
|
60
|
+
* hook filters. (A *user-supplied* pattern is handled — it drops the filter.)
|
|
61
|
+
*/
|
|
62
|
+
const SCHEMA_NAME_PATTERN = /ZodSchema$/;
|
|
62
63
|
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
* Module specifiers whose bindings count as the zod namespace. Every entry
|
|
65
|
+
* must contain "zod" for the same reason as SCHEMA_NAME_PATTERN above; both
|
|
66
|
+
* are pinned by `describe("code filter soundness")` in the transform tests.
|
|
67
|
+
*/
|
|
68
|
+
const ZOD_MODULES = /* @__PURE__ */ new Set([
|
|
69
|
+
"zod",
|
|
70
|
+
"zod/v3",
|
|
71
|
+
"zod/v4",
|
|
72
|
+
"zod/mini",
|
|
73
|
+
"zod/v4/mini"
|
|
74
|
+
]);
|
|
68
75
|
/**
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
76
|
+
* Collect runtime import bindings with a regex over import statements.
|
|
77
|
+
* Type-only imports and `type` specifiers are excluded — they cannot be
|
|
78
|
+
* referenced at runtime, so excluding them keeps the capture rule sound.
|
|
79
|
+
*/
|
|
80
|
+
function collectImportBindings(code) {
|
|
81
|
+
const all = /* @__PURE__ */ new Set();
|
|
82
|
+
const zod = /* @__PURE__ */ new Set();
|
|
83
|
+
const details = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const match of code.matchAll(/import\s+(type\s+)?([^'";]+?)\s+from\s*["']([^"']+)["']/g)) {
|
|
85
|
+
const [, typeOnly, clause, specifier] = match;
|
|
86
|
+
if (typeOnly || clause === void 0 || specifier === void 0) continue;
|
|
87
|
+
const isZod = ZOD_MODULES.has(specifier);
|
|
88
|
+
for (const { local, imported } of parseImportClause(clause)) {
|
|
89
|
+
all.add(local);
|
|
90
|
+
if (isZod) zod.add(local);
|
|
91
|
+
details.set(local, {
|
|
92
|
+
specifier,
|
|
93
|
+
imported
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
all,
|
|
99
|
+
zod,
|
|
100
|
+
details
|
|
101
|
+
};
|
|
91
102
|
}
|
|
92
103
|
/** Extract local binding names (with their source export) from an import clause. */
|
|
93
104
|
function parseImportClause(clause) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
105
|
+
const names = [];
|
|
106
|
+
const namedStart = clause.indexOf("{");
|
|
107
|
+
const head = namedStart === -1 ? clause : clause.slice(0, namedStart);
|
|
108
|
+
for (const part of head.split(",")) {
|
|
109
|
+
const trimmed = part.trim();
|
|
110
|
+
if (!trimmed) continue;
|
|
111
|
+
const ns = trimmed.match(/^\*\s*as\s+([A-Za-z_$][\w$]*)$/);
|
|
112
|
+
if (ns?.[1]) names.push({
|
|
113
|
+
local: ns[1],
|
|
114
|
+
imported: "*"
|
|
115
|
+
});
|
|
116
|
+
else if (/^[A-Za-z_$][\w$]*$/.test(trimmed)) names.push({
|
|
117
|
+
local: trimmed,
|
|
118
|
+
imported: "default"
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (namedStart !== -1) {
|
|
122
|
+
const namedEnd = clause.indexOf("}", namedStart);
|
|
123
|
+
const inner = clause.slice(namedStart + 1, namedEnd === -1 ? void 0 : namedEnd);
|
|
124
|
+
for (const part of inner.split(",")) {
|
|
125
|
+
const spec = part.trim();
|
|
126
|
+
if (!spec || spec.startsWith("type ")) continue;
|
|
127
|
+
const asMatch = spec.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
|
|
128
|
+
if (asMatch?.[1] && asMatch[2]) names.push({
|
|
129
|
+
local: asMatch[2],
|
|
130
|
+
imported: asMatch[1]
|
|
131
|
+
});
|
|
132
|
+
else if (/^[A-Za-z_$][\w$]*$/.test(spec)) names.push({
|
|
133
|
+
local: spec,
|
|
134
|
+
imported: spec
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return names;
|
|
128
139
|
}
|
|
129
140
|
/** Deterministic FNV-1a 32-bit hash, hex-encoded. */
|
|
130
141
|
function fnv1a(text) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
142
|
+
let hash = 2166136261;
|
|
143
|
+
for (let i = 0; i < text.length; i++) {
|
|
144
|
+
hash ^= text.charCodeAt(i);
|
|
145
|
+
hash = Math.imul(hash, 16777619);
|
|
146
|
+
}
|
|
147
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
137
148
|
}
|
|
138
149
|
/**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
* Char-code identifier/whitespace classes for the scanner hot loops — a
|
|
151
|
+
* regex `.test()` per character dominated scan time once the acorn parses
|
|
152
|
+
* were gone. The ident classes are deliberately ASCII-only (`[A-Za-z_$]` /
|
|
153
|
+
* `[\w$]`, matching the scanner's historical regexes); the space check falls
|
|
154
|
+
* back to `/\s/` for the rare non-ASCII code points it matches (NBSP, BOM,
|
|
155
|
+
* U+2028...).
|
|
156
|
+
*/
|
|
146
157
|
function isIdentStartCode(c) {
|
|
147
|
-
|
|
158
|
+
return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c === 95 || c === 36;
|
|
148
159
|
}
|
|
149
160
|
function isIdentPartCode(c) {
|
|
150
|
-
|
|
161
|
+
return c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36;
|
|
151
162
|
}
|
|
152
163
|
function isSpaceCode(c) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return c > 127 && /\s/.test(String.fromCharCode(c));
|
|
164
|
+
if (c === 32 || c >= 9 && c <= 13) return true;
|
|
165
|
+
return c > 127 && /\s/.test(String.fromCharCode(c));
|
|
156
166
|
}
|
|
157
167
|
/** After these tokens a `/` starts a regex literal, not division. */
|
|
158
|
-
const REGEX_PRECEDING_KEYWORDS = new Set([
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
const REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
|
|
169
|
+
"return",
|
|
170
|
+
"typeof",
|
|
171
|
+
"instanceof",
|
|
172
|
+
"in",
|
|
173
|
+
"of",
|
|
174
|
+
"new",
|
|
175
|
+
"delete",
|
|
176
|
+
"void",
|
|
177
|
+
"throw",
|
|
178
|
+
"do",
|
|
179
|
+
"else",
|
|
180
|
+
"case",
|
|
181
|
+
"yield",
|
|
182
|
+
"await"
|
|
173
183
|
]);
|
|
174
184
|
/** Is `/` after this token division (true) or a regex literal (false)? */
|
|
175
185
|
function isDivisionContext(lastToken) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (/^[\w$]+$/.test(lastToken))
|
|
181
|
-
return !REGEX_PRECEDING_KEYWORDS.has(lastToken);
|
|
182
|
-
return false;
|
|
186
|
+
if (lastToken === ")" || lastToken === "]") return true;
|
|
187
|
+
if (/^["'`]$/.test(lastToken)) return true;
|
|
188
|
+
if (/^[\w$]+$/.test(lastToken)) return !REGEX_PRECEDING_KEYWORDS.has(lastToken);
|
|
189
|
+
return false;
|
|
183
190
|
}
|
|
184
191
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
192
|
+
* Scan the source for candidate root identifiers (`z`, `FooZodSchema`, ...)
|
|
193
|
+
* followed by a `.`, tracking string/template/comment state and nesting
|
|
194
|
+
* depth. Depth 0 candidates are top-level initializers — already evaluated
|
|
195
|
+
* once — and are recorded only so their extents mask nested candidates.
|
|
196
|
+
*/
|
|
190
197
|
function scanSource(code, roots) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
let out = "";
|
|
299
|
-
let prev = 0;
|
|
300
|
-
for (let r = 0; r < maskRanges.length; r += 2) {
|
|
301
|
-
const from = maskRanges[r];
|
|
302
|
-
const to = maskRanges[r + 1];
|
|
303
|
-
out += code.slice(prev, from) + code.slice(from, to).replace(/[^\n]/g, " ");
|
|
304
|
-
prev = to;
|
|
305
|
-
}
|
|
306
|
-
return out + code.slice(prev);
|
|
307
|
-
};
|
|
308
|
-
return { candidates, stripped };
|
|
198
|
+
const candidates = [];
|
|
199
|
+
const maskRanges = [];
|
|
200
|
+
const mask = (from, to) => {
|
|
201
|
+
maskRanges.push(from, to);
|
|
202
|
+
};
|
|
203
|
+
let depth = 0;
|
|
204
|
+
const templateStack = [];
|
|
205
|
+
let lastToken = "";
|
|
206
|
+
let i = 0;
|
|
207
|
+
while (i < code.length) {
|
|
208
|
+
const ch = code[i];
|
|
209
|
+
const next = code[i + 1];
|
|
210
|
+
if (ch === "/" && next === "/") {
|
|
211
|
+
const nl = code.indexOf("\n", i);
|
|
212
|
+
const end = nl === -1 ? code.length : nl + 1;
|
|
213
|
+
mask(i, end);
|
|
214
|
+
i = end;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
if (ch === "/" && next === "*") {
|
|
218
|
+
const close = code.indexOf("*/", i + 2);
|
|
219
|
+
const end = close === -1 ? code.length : close + 2;
|
|
220
|
+
mask(i, end);
|
|
221
|
+
i = end;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (ch === "/") {
|
|
225
|
+
if (!isDivisionContext(lastToken)) {
|
|
226
|
+
const end = skipRegexLiteral(code, i);
|
|
227
|
+
mask(i, end);
|
|
228
|
+
i = end;
|
|
229
|
+
lastToken = ")";
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
lastToken = ch;
|
|
233
|
+
i++;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (ch === "\"" || ch === "'") {
|
|
237
|
+
const end = skipString(code, i, ch);
|
|
238
|
+
mask(i, end);
|
|
239
|
+
i = end;
|
|
240
|
+
lastToken = ch;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (ch === "`") {
|
|
244
|
+
const end = skipTemplateChunk(code, i + 1, templateStack, depth);
|
|
245
|
+
mask(i, end);
|
|
246
|
+
i = end;
|
|
247
|
+
lastToken = "`";
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (templateStack.length > 0 && ch === "}" && depth === templateStack[templateStack.length - 1]) {
|
|
251
|
+
templateStack.pop();
|
|
252
|
+
const end = skipTemplateChunk(code, i + 1, templateStack, depth);
|
|
253
|
+
mask(i, end);
|
|
254
|
+
i = end;
|
|
255
|
+
lastToken = "`";
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (ch === "(" || ch === "[" || ch === "{") {
|
|
259
|
+
depth++;
|
|
260
|
+
lastToken = ch;
|
|
261
|
+
i++;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (ch === ")" || ch === "]" || ch === "}") {
|
|
265
|
+
depth--;
|
|
266
|
+
lastToken = ch;
|
|
267
|
+
i++;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
|
|
271
|
+
let j = i + 1;
|
|
272
|
+
while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;
|
|
273
|
+
const word = code.slice(i, j);
|
|
274
|
+
let k = j;
|
|
275
|
+
while (k < code.length && isSpaceCode(code.charCodeAt(k))) k++;
|
|
276
|
+
if (roots.has(word) && code[k] === "." && lastToken !== ".") candidates.push({
|
|
277
|
+
index: i,
|
|
278
|
+
depth,
|
|
279
|
+
name: word,
|
|
280
|
+
afterArrow: lastToken === "=>"
|
|
281
|
+
});
|
|
282
|
+
lastToken = word;
|
|
283
|
+
i = j;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (!isSpaceCode(code.charCodeAt(i))) lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
|
|
287
|
+
i++;
|
|
288
|
+
}
|
|
289
|
+
const stripped = () => {
|
|
290
|
+
if (maskRanges.length === 0) return code;
|
|
291
|
+
let out = "";
|
|
292
|
+
let prev = 0;
|
|
293
|
+
for (let r = 0; r < maskRanges.length; r += 2) {
|
|
294
|
+
const from = maskRanges[r];
|
|
295
|
+
const to = maskRanges[r + 1];
|
|
296
|
+
out += code.slice(prev, from) + code.slice(from, to).replace(/[^\n]/g, " ");
|
|
297
|
+
prev = to;
|
|
298
|
+
}
|
|
299
|
+
return out + code.slice(prev);
|
|
300
|
+
};
|
|
301
|
+
return {
|
|
302
|
+
candidates,
|
|
303
|
+
stripped
|
|
304
|
+
};
|
|
309
305
|
}
|
|
310
306
|
function skipString(code, start, quote) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
else if (code[i] === quote || code[i] === "\n") {
|
|
316
|
-
return i + 1;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return code.length;
|
|
307
|
+
for (let i = start + 1; i < code.length; i++) if (code[i] === "\\") i++;
|
|
308
|
+
else if (code[i] === quote || code[i] === "\n") return i + 1;
|
|
309
|
+
return code.length;
|
|
320
310
|
}
|
|
321
311
|
/**
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
312
|
+
* Skip a template string chunk; returns the offset after the closing
|
|
313
|
+
* `` ` `` or after a `${`, recording the current depth so the scanner can
|
|
314
|
+
* recognize the matching `}` later.
|
|
315
|
+
*/
|
|
326
316
|
function skipTemplateChunk(code, start, templateStack, depth) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
else if (code[i] === "$" && code[i + 1] === "{") {
|
|
335
|
-
templateStack.push(depth);
|
|
336
|
-
return i + 2;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
return code.length;
|
|
317
|
+
for (let i = start; i < code.length; i++) if (code[i] === "\\") i++;
|
|
318
|
+
else if (code[i] === "`") return i + 1;
|
|
319
|
+
else if (code[i] === "$" && code[i + 1] === "{") {
|
|
320
|
+
templateStack.push(depth);
|
|
321
|
+
return i + 2;
|
|
322
|
+
}
|
|
323
|
+
return code.length;
|
|
340
324
|
}
|
|
341
325
|
function skipRegexLiteral(code, start) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
inClass = false;
|
|
353
|
-
}
|
|
354
|
-
else if (ch === "/" && !inClass) {
|
|
355
|
-
return i + 1;
|
|
356
|
-
}
|
|
357
|
-
else if (ch === "\n") {
|
|
358
|
-
// Not a regex after all (unterminated) — treat as division
|
|
359
|
-
return start + 1;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return code.length;
|
|
326
|
+
let inClass = false;
|
|
327
|
+
for (let i = start + 1; i < code.length; i++) {
|
|
328
|
+
const ch = code[i];
|
|
329
|
+
if (ch === "\\") i++;
|
|
330
|
+
else if (ch === "[") inClass = true;
|
|
331
|
+
else if (ch === "]") inClass = false;
|
|
332
|
+
else if (ch === "/" && !inClass) return i + 1;
|
|
333
|
+
else if (ch === "\n") return start + 1;
|
|
334
|
+
}
|
|
335
|
+
return code.length;
|
|
363
336
|
}
|
|
364
337
|
/**
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
338
|
+
* Cheap chain-extent scan: from a root identifier, advance past the longest
|
|
339
|
+
* member/call/tagged-template chain (`.x`, `?.x`, `!`, `(...)`, `[...]`,
|
|
340
|
+
* `` `...` ``). Used to mask the interior of depth-0 chains WITHOUT an acorn
|
|
341
|
+
* parse: schema modules are mostly top-level declarations, and parsing each
|
|
342
|
+
* one only to discard it under the depth-0 rule dominated cold hoist cost in
|
|
343
|
+
* a field report (hoist 37–46s vs discover 12–16s across ~7k transforms).
|
|
344
|
+
* May overshoot an AST-exact end only across TS-only syntax (postfix `!`);
|
|
345
|
+
* stops at anything else it does not recognize (`<` generics, operators) —
|
|
346
|
+
* an undershoot leaves interior candidates to their own depth-0/eligibility
|
|
347
|
+
* rules, an overshoot only widens the mask over an expression that already
|
|
348
|
+
* evaluates once at module scope.
|
|
349
|
+
*/
|
|
377
350
|
function findChainEnd(code, identStart) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
if (ch === "." || (ch === "?" && code[i + 1] === ".")) {
|
|
481
|
-
i += ch === "." ? 1 : 2;
|
|
482
|
-
skipTrivia();
|
|
483
|
-
while (i < code.length && isIdentPartCode(code.charCodeAt(i)))
|
|
484
|
-
i++;
|
|
485
|
-
continue;
|
|
486
|
-
}
|
|
487
|
-
if (ch === "!") {
|
|
488
|
-
i++;
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
|
-
if (ch === "(" || ch === "[" || ch === "`") {
|
|
492
|
-
skipNested();
|
|
493
|
-
continue;
|
|
494
|
-
}
|
|
495
|
-
return i;
|
|
496
|
-
}
|
|
351
|
+
let i = identStart;
|
|
352
|
+
while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;
|
|
353
|
+
const skipTrivia = () => {
|
|
354
|
+
for (;;) {
|
|
355
|
+
while (i < code.length && isSpaceCode(code.charCodeAt(i))) i++;
|
|
356
|
+
if (code[i] === "/" && code[i + 1] === "/") {
|
|
357
|
+
const nl = code.indexOf("\n", i);
|
|
358
|
+
i = nl === -1 ? code.length : nl + 1;
|
|
359
|
+
} else if (code[i] === "/" && code[i + 1] === "*") {
|
|
360
|
+
const close = code.indexOf("*/", i + 2);
|
|
361
|
+
i = close === -1 ? code.length : close + 2;
|
|
362
|
+
} else return;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const skipNested = () => {
|
|
366
|
+
let depth = 0;
|
|
367
|
+
const templateStack = [];
|
|
368
|
+
let lastToken = "";
|
|
369
|
+
while (i < code.length) {
|
|
370
|
+
const ch = code[i];
|
|
371
|
+
const next = code[i + 1];
|
|
372
|
+
if (ch === "/" && next === "/") {
|
|
373
|
+
const nl = code.indexOf("\n", i);
|
|
374
|
+
i = nl === -1 ? code.length : nl + 1;
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
if (ch === "/" && next === "*") {
|
|
378
|
+
const close = code.indexOf("*/", i + 2);
|
|
379
|
+
i = close === -1 ? code.length : close + 2;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (ch === "/") {
|
|
383
|
+
if (!isDivisionContext(lastToken)) {
|
|
384
|
+
i = skipRegexLiteral(code, i);
|
|
385
|
+
lastToken = ")";
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
lastToken = ch;
|
|
389
|
+
i++;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (ch === "\"" || ch === "'") {
|
|
393
|
+
i = skipString(code, i, ch);
|
|
394
|
+
lastToken = ch;
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
if (ch === "`") {
|
|
398
|
+
i = skipTemplateChunk(code, i + 1, templateStack, depth);
|
|
399
|
+
lastToken = "`";
|
|
400
|
+
if (depth === 0 && templateStack.length === 0) return;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (templateStack.length > 0 && ch === "}" && depth === templateStack[templateStack.length - 1]) {
|
|
404
|
+
templateStack.pop();
|
|
405
|
+
i = skipTemplateChunk(code, i + 1, templateStack, depth);
|
|
406
|
+
lastToken = "`";
|
|
407
|
+
if (depth === 0 && templateStack.length === 0) return;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
if (ch === "(" || ch === "[" || ch === "{") {
|
|
411
|
+
depth++;
|
|
412
|
+
lastToken = ch;
|
|
413
|
+
i++;
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (ch === ")" || ch === "]" || ch === "}") {
|
|
417
|
+
depth--;
|
|
418
|
+
lastToken = ch;
|
|
419
|
+
i++;
|
|
420
|
+
if (depth === 0 && templateStack.length === 0) return;
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
if (isIdentStartCode(code.charCodeAt(i)) && !isIdentPartCode(code.charCodeAt(i - 1))) {
|
|
424
|
+
let j = i + 1;
|
|
425
|
+
while (j < code.length && isIdentPartCode(code.charCodeAt(j))) j++;
|
|
426
|
+
lastToken = code.slice(i, j);
|
|
427
|
+
i = j;
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
if (!isSpaceCode(code.charCodeAt(i))) lastToken = ch === ">" && lastToken === "=" ? "=>" : ch;
|
|
431
|
+
i++;
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
for (;;) {
|
|
435
|
+
skipTrivia();
|
|
436
|
+
const ch = code[i];
|
|
437
|
+
if (ch === "." || ch === "?" && code[i + 1] === ".") {
|
|
438
|
+
i += ch === "." ? 1 : 2;
|
|
439
|
+
skipTrivia();
|
|
440
|
+
while (i < code.length && isIdentPartCode(code.charCodeAt(i))) i++;
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
if (ch === "!") {
|
|
444
|
+
i++;
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
if (ch === "(" || ch === "[" || ch === "`") {
|
|
448
|
+
skipNested();
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
return i;
|
|
452
|
+
}
|
|
497
453
|
}
|
|
498
454
|
/**
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
455
|
+
* Parse a single assignment-level expression at `pos` — the same entry point
|
|
456
|
+
* acorn's own parseExpressionAt uses, one precedence level down. At
|
|
457
|
+
* expression level a trailing comma in an argument position
|
|
458
|
+
* (`sql.type(z.object({...}),\n)`) starts a sequence-expression parse that
|
|
459
|
+
* throws on the surrounding `)`; assignment level treats the comma as
|
|
460
|
+
* trailing garbage and stops cleanly. parseMaybeAssign is the entry point
|
|
461
|
+
* the acorn plugin ecosystem overrides — stable across versions.
|
|
462
|
+
*/
|
|
507
463
|
function parseAssignmentAt(code, pos) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
464
|
+
const parser = new Parser({
|
|
465
|
+
ecmaVersion: "latest",
|
|
466
|
+
sourceType: "module"
|
|
467
|
+
}, code, pos);
|
|
468
|
+
parser.nextToken();
|
|
469
|
+
return parser.parseMaybeAssign();
|
|
511
470
|
}
|
|
512
471
|
/**
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
472
|
+
* Narrow a parsed expression to the largest call chain starting at `start`.
|
|
473
|
+
* The parse can overshoot into surrounding operators
|
|
474
|
+
* (`z.string().min(1) || fallback` parses as a LogicalExpression) — descend
|
|
475
|
+
* through same-start children until a CallExpression is found.
|
|
476
|
+
*/
|
|
518
477
|
function narrowToCallChain(node, start) {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
return null;
|
|
478
|
+
let current = node;
|
|
479
|
+
while (current.start === start) {
|
|
480
|
+
if (current.type === "CallExpression") return current;
|
|
481
|
+
const child = sameStartChild(current, start);
|
|
482
|
+
if (!child) return null;
|
|
483
|
+
current = child;
|
|
484
|
+
}
|
|
485
|
+
return null;
|
|
529
486
|
}
|
|
530
487
|
function sameStartChild(node, start) {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
488
|
+
const record = node;
|
|
489
|
+
for (const key of [
|
|
490
|
+
"left",
|
|
491
|
+
"object",
|
|
492
|
+
"callee",
|
|
493
|
+
"test",
|
|
494
|
+
"tag",
|
|
495
|
+
"expression",
|
|
496
|
+
"expressions"
|
|
497
|
+
]) {
|
|
498
|
+
const value = record[key];
|
|
499
|
+
const child = Array.isArray(value) ? value[0] : value;
|
|
500
|
+
if (typeof child === "object" && child !== null && child.start === start && typeof child.type === "string") return child;
|
|
501
|
+
}
|
|
502
|
+
return null;
|
|
543
503
|
}
|
|
544
504
|
/**
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
505
|
+
* Walk a member/call chain down to its base identifier, collecting the
|
|
506
|
+
* non-computed method names along the spine. Computed members
|
|
507
|
+
* (`base[name]()`) are unanalyzable — the chain is rejected.
|
|
508
|
+
*/
|
|
549
509
|
function describeChain(node) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
else if (current.type === "Identifier") {
|
|
563
|
-
return { root: current.name, methods };
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
return null;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
510
|
+
const methods = [];
|
|
511
|
+
let current = node;
|
|
512
|
+
while (true) if (current.type === "CallExpression") current = current.callee;
|
|
513
|
+
else if (current.type === "MemberExpression") {
|
|
514
|
+
if (current.computed || current.property.type !== "Identifier") return null;
|
|
515
|
+
methods.push(current.property.name);
|
|
516
|
+
current = current.object;
|
|
517
|
+
} else if (current.type === "Identifier") return {
|
|
518
|
+
root: current.name,
|
|
519
|
+
methods
|
|
520
|
+
};
|
|
521
|
+
else return null;
|
|
569
522
|
}
|
|
570
523
|
/**
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
const COMBINATOR_METHODS = new Set([
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
524
|
+
* Combinators eligible on non-z chain bases (babel-plugin-zod-hoist's
|
|
525
|
+
* SCHEMA_COMBINATOR_METHODS, verbatim) — `Base.extend({...})`,
|
|
526
|
+
* `Base.pick({...})`, `UserZodSchema.optional()`, ...
|
|
527
|
+
*/
|
|
528
|
+
const COMBINATOR_METHODS = /* @__PURE__ */ new Set([
|
|
529
|
+
"and",
|
|
530
|
+
"array",
|
|
531
|
+
"brand",
|
|
532
|
+
"catchall",
|
|
533
|
+
"deepPartial",
|
|
534
|
+
"describe",
|
|
535
|
+
"extend",
|
|
536
|
+
"merge",
|
|
537
|
+
"nullable",
|
|
538
|
+
"nullish",
|
|
539
|
+
"omit",
|
|
540
|
+
"optional",
|
|
541
|
+
"or",
|
|
542
|
+
"partial",
|
|
543
|
+
"passthrough",
|
|
544
|
+
"pick",
|
|
545
|
+
"readonly",
|
|
546
|
+
"refine",
|
|
547
|
+
"required",
|
|
548
|
+
"strict",
|
|
549
|
+
"strip",
|
|
550
|
+
"superRefine",
|
|
551
|
+
"transform"
|
|
599
552
|
]);
|
|
600
553
|
/**
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const PARSE_METHODS = new Set([
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
554
|
+
* Methods that evaluate data rather than construct schemas. Hoisting one
|
|
555
|
+
* would move the evaluation (and any throw) to module load.
|
|
556
|
+
*/
|
|
557
|
+
const PARSE_METHODS = /* @__PURE__ */ new Set([
|
|
558
|
+
"parse",
|
|
559
|
+
"safeParse",
|
|
560
|
+
"parseAsync",
|
|
561
|
+
"safeParseAsync",
|
|
562
|
+
"decode",
|
|
563
|
+
"encode",
|
|
564
|
+
"decodeAsync",
|
|
565
|
+
"encodeAsync"
|
|
613
566
|
]);
|
|
614
567
|
/**
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
const KNOWN_GLOBALS = new Set([
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
568
|
+
* Standard globals a hoisted expression may reference (eager or deferred —
|
|
569
|
+
* babel-parity behaviors like hoisting `z.date().default(new Date())` rely
|
|
570
|
+
* on Date/Math being recognized).
|
|
571
|
+
*
|
|
572
|
+
* The babel plugin allows ANY unbound identifier because it has real scope
|
|
573
|
+
* information; this port's binding collector is a lexical approximation, so
|
|
574
|
+
* an unknown bare name must be assumed to be a binding the collector missed
|
|
575
|
+
* — hoisting it would crash at module load with
|
|
576
|
+
* `ReferenceError: <name> is not defined`. A fixed allowlist converts that
|
|
577
|
+
* failure mode into a missed optimization.
|
|
578
|
+
*/
|
|
579
|
+
const KNOWN_GLOBALS = /* @__PURE__ */ new Set([
|
|
580
|
+
"globalThis",
|
|
581
|
+
"NaN",
|
|
582
|
+
"Infinity",
|
|
583
|
+
"Math",
|
|
584
|
+
"Number",
|
|
585
|
+
"String",
|
|
586
|
+
"Boolean",
|
|
587
|
+
"Array",
|
|
588
|
+
"Object",
|
|
589
|
+
"JSON",
|
|
590
|
+
"Date",
|
|
591
|
+
"RegExp",
|
|
592
|
+
"BigInt",
|
|
593
|
+
"Symbol",
|
|
594
|
+
"Map",
|
|
595
|
+
"Set",
|
|
596
|
+
"WeakMap",
|
|
597
|
+
"WeakSet",
|
|
598
|
+
"Promise",
|
|
599
|
+
"Proxy",
|
|
600
|
+
"Reflect",
|
|
601
|
+
"Intl",
|
|
602
|
+
"Error",
|
|
603
|
+
"TypeError",
|
|
604
|
+
"RangeError",
|
|
605
|
+
"SyntaxError",
|
|
606
|
+
"EvalError",
|
|
607
|
+
"URIError",
|
|
608
|
+
"AggregateError",
|
|
609
|
+
"ArrayBuffer",
|
|
610
|
+
"Uint8Array",
|
|
611
|
+
"parseInt",
|
|
612
|
+
"parseFloat",
|
|
613
|
+
"isNaN",
|
|
614
|
+
"isFinite",
|
|
615
|
+
"encodeURI",
|
|
616
|
+
"decodeURI",
|
|
617
|
+
"encodeURIComponent",
|
|
618
|
+
"decodeURIComponent",
|
|
619
|
+
"structuredClone",
|
|
620
|
+
"URL",
|
|
621
|
+
"URLSearchParams",
|
|
622
|
+
"TextEncoder",
|
|
623
|
+
"TextDecoder",
|
|
624
|
+
"atob",
|
|
625
|
+
"btoa",
|
|
626
|
+
"crypto",
|
|
627
|
+
"console",
|
|
628
|
+
"process",
|
|
629
|
+
"Buffer"
|
|
677
630
|
]);
|
|
678
631
|
/**
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
632
|
+
* Scope-aware free-variable analysis of an expression. Nested function
|
|
633
|
+
* params and local declarations are bound names, not captures — so
|
|
634
|
+
* `z.string().refine((v) => v.length > 0)` has no free variables beyond `z`.
|
|
635
|
+
* References inside nested function bodies are tracked separately: they
|
|
636
|
+
* evaluate per call even after hoisting, so safe globals are allowed there.
|
|
637
|
+
*/
|
|
685
638
|
function analyzeCaptures(expr) {
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
// (Stricter than the babel plugin, whose suite never exercises
|
|
773
|
-
// these.) Deferred occurrences run per call — fine to move.
|
|
774
|
-
if (!deferred) {
|
|
775
|
-
impure = true;
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
break;
|
|
779
|
-
case "MemberExpression":
|
|
780
|
-
visit(node.object, scopes, deferred);
|
|
781
|
-
if (node.computed)
|
|
782
|
-
visit(node.property, scopes, deferred);
|
|
783
|
-
return;
|
|
784
|
-
case "Property":
|
|
785
|
-
if (node.computed)
|
|
786
|
-
visit(node.key, scopes, deferred);
|
|
787
|
-
visit(node.value, scopes, deferred);
|
|
788
|
-
return;
|
|
789
|
-
case "FunctionExpression":
|
|
790
|
-
case "ArrowFunctionExpression": {
|
|
791
|
-
const scope = new Set();
|
|
792
|
-
for (const param of node.params)
|
|
793
|
-
patternNames(param, scope);
|
|
794
|
-
if (node.type === "FunctionExpression" && node.id)
|
|
795
|
-
scope.add(node.id.name);
|
|
796
|
-
collectFunctionScope(node.body, scope);
|
|
797
|
-
visit(node.body, [...scopes, scope], true);
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
default:
|
|
801
|
-
break;
|
|
802
|
-
}
|
|
803
|
-
for (const value of Object.values(node)) {
|
|
804
|
-
if (Array.isArray(value)) {
|
|
805
|
-
for (const item of value) {
|
|
806
|
-
if (typeof item === "object" && item !== null && "type" in item) {
|
|
807
|
-
visit(item, scopes, deferred);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
else if (typeof value === "object" && value !== null && "type" in value) {
|
|
812
|
-
visit(value, scopes, deferred);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
visit(expr, [], false);
|
|
817
|
-
return { eagerFree, deferredFree, impure };
|
|
639
|
+
const eagerFree = /* @__PURE__ */ new Set();
|
|
640
|
+
const deferredFree = /* @__PURE__ */ new Set();
|
|
641
|
+
let impure = false;
|
|
642
|
+
function patternNames(node, into) {
|
|
643
|
+
switch (node.type) {
|
|
644
|
+
case "Identifier":
|
|
645
|
+
into.add(node.name);
|
|
646
|
+
return;
|
|
647
|
+
case "ObjectPattern":
|
|
648
|
+
for (const prop of node.properties) if (prop.type === "Property") patternNames(prop.value, into);
|
|
649
|
+
else patternNames(prop.argument, into);
|
|
650
|
+
return;
|
|
651
|
+
case "ArrayPattern":
|
|
652
|
+
for (const el of node.elements) if (el) patternNames(el, into);
|
|
653
|
+
return;
|
|
654
|
+
case "AssignmentPattern":
|
|
655
|
+
patternNames(node.left, into);
|
|
656
|
+
return;
|
|
657
|
+
case "RestElement":
|
|
658
|
+
patternNames(node.argument, into);
|
|
659
|
+
return;
|
|
660
|
+
default: return;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
function collectFunctionScope(body, into) {
|
|
664
|
+
const stack = [body];
|
|
665
|
+
while (stack.length > 0) {
|
|
666
|
+
const node = stack.pop();
|
|
667
|
+
if (!node || typeof node !== "object") continue;
|
|
668
|
+
if (node.type === "VariableDeclaration") for (const decl of node.declarations) patternNames(decl.id, into);
|
|
669
|
+
else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
|
|
670
|
+
if (node.id) into.add(node.id.name);
|
|
671
|
+
continue;
|
|
672
|
+
} else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") continue;
|
|
673
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) {
|
|
674
|
+
for (const item of value) if (typeof item === "object" && item !== null && "type" in item) stack.push(item);
|
|
675
|
+
} else if (typeof value === "object" && value !== null && "type" in value) stack.push(value);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function visit(node, scopes, deferred) {
|
|
679
|
+
switch (node.type) {
|
|
680
|
+
case "Identifier": {
|
|
681
|
+
const name = node.name;
|
|
682
|
+
if (name !== "undefined" && !scopes.some((s) => s.has(name))) (deferred ? deferredFree : eagerFree).add(name);
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
case "ThisExpression":
|
|
686
|
+
case "Super":
|
|
687
|
+
impure = true;
|
|
688
|
+
return;
|
|
689
|
+
case "AwaitExpression":
|
|
690
|
+
case "YieldExpression":
|
|
691
|
+
if (!deferred) {
|
|
692
|
+
impure = true;
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
break;
|
|
696
|
+
case "MemberExpression":
|
|
697
|
+
visit(node.object, scopes, deferred);
|
|
698
|
+
if (node.computed) visit(node.property, scopes, deferred);
|
|
699
|
+
return;
|
|
700
|
+
case "Property":
|
|
701
|
+
if (node.computed) visit(node.key, scopes, deferred);
|
|
702
|
+
visit(node.value, scopes, deferred);
|
|
703
|
+
return;
|
|
704
|
+
case "FunctionExpression":
|
|
705
|
+
case "ArrowFunctionExpression": {
|
|
706
|
+
const scope = /* @__PURE__ */ new Set();
|
|
707
|
+
for (const param of node.params) patternNames(param, scope);
|
|
708
|
+
if (node.type === "FunctionExpression" && node.id) scope.add(node.id.name);
|
|
709
|
+
collectFunctionScope(node.body, scope);
|
|
710
|
+
visit(node.body, [...scopes, scope], true);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
default: break;
|
|
714
|
+
}
|
|
715
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) {
|
|
716
|
+
for (const item of value) if (typeof item === "object" && item !== null && "type" in item) visit(item, scopes, deferred);
|
|
717
|
+
} else if (typeof value === "object" && value !== null && "type" in value) visit(value, scopes, deferred);
|
|
718
|
+
}
|
|
719
|
+
visit(expr, [], false);
|
|
720
|
+
return {
|
|
721
|
+
eagerFree,
|
|
722
|
+
deferredFree,
|
|
723
|
+
impure
|
|
724
|
+
};
|
|
818
725
|
}
|
|
819
726
|
/** Offset after the shebang and directive prologue ("use client", ...). */
|
|
820
727
|
function insertionOffset(code) {
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
break;
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
const directive = code.slice(i).match(/^(["'])use [^"'\n]*\1\s*;?[^\S\n]*\n?/);
|
|
846
|
-
if (!directive)
|
|
847
|
-
return i;
|
|
848
|
-
i += directive[0].length;
|
|
849
|
-
}
|
|
728
|
+
let i = 0;
|
|
729
|
+
if (code.startsWith("#!")) {
|
|
730
|
+
const nl = code.indexOf("\n");
|
|
731
|
+
i = nl === -1 ? code.length : nl + 1;
|
|
732
|
+
}
|
|
733
|
+
while (true) {
|
|
734
|
+
while (i < code.length) {
|
|
735
|
+
const ch = code[i];
|
|
736
|
+
if (/\s/.test(ch)) i++;
|
|
737
|
+
else if (ch === "/" && code[i + 1] === "/") {
|
|
738
|
+
const nl = code.indexOf("\n", i);
|
|
739
|
+
i = nl === -1 ? code.length : nl + 1;
|
|
740
|
+
} else if (ch === "/" && code[i + 1] === "*") {
|
|
741
|
+
const end = code.indexOf("*/", i + 2);
|
|
742
|
+
i = end === -1 ? code.length : end + 2;
|
|
743
|
+
} else break;
|
|
744
|
+
}
|
|
745
|
+
const directive = code.slice(i).match(/^(["'])use [^"'\n]*\1\s*;?[^\S\n]*\n?/);
|
|
746
|
+
if (!directive) return i;
|
|
747
|
+
i += directive[0].length;
|
|
748
|
+
}
|
|
850
749
|
}
|
|
851
750
|
/** Keywords that precede `( ... ) {` without binding anything. */
|
|
852
751
|
const NON_BINDING_KEYWORDS = "if|for|while|switch|return|typeof|await|yield|new|do|else|case|in|of|delete|void";
|
|
853
752
|
/**
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
753
|
+
* Conservative shadow detection: collect every identifier appearing in a
|
|
754
|
+
* binding-like position — function/method/arrow parameter lists, catch
|
|
755
|
+
* clauses, class names, const/let/var declarator patterns. The scanner has
|
|
756
|
+
* no scope information, so an import referenced from a hoisted expression
|
|
757
|
+
* must resolve to that import everywhere; a name that is ever re-bound
|
|
758
|
+
* cannot be trusted and disqualifies hoists referencing it.
|
|
759
|
+
*
|
|
760
|
+
* Collection is depth-aware and multiline (balanced delimiter scanning, not
|
|
761
|
+
* line-bounded regexes): multiline destructuring declarations and parameter
|
|
762
|
+
* defaults containing calls are real production patterns whose bindings a
|
|
763
|
+
* line-based collector misses — and a missed binding here used to mean a
|
|
764
|
+
* hoist referencing it crashed at module load (`ReferenceError`).
|
|
765
|
+
* Over-collection (type names, destructuring default values, for-of
|
|
766
|
+
* iterables) is deliberate and safe: it can only suppress a hoist.
|
|
767
|
+
*/
|
|
869
768
|
function collectBoundNames(code) {
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
// method(a, b) { / method(a = call()): Ret { — excluding control flow.
|
|
974
|
-
// The balanced span must be directly followed by `{` (after an optional
|
|
975
|
-
// return type), which call expressions essentially never are.
|
|
976
|
-
const methodAnchor = new RegExp(String.raw `(?<![.\w$])(?!(?:${NON_BINDING_KEYWORDS})\b)[A-Za-z_$][\w$]*\s*\(`, "g");
|
|
977
|
-
for (const m of code.matchAll(methodAnchor)) {
|
|
978
|
-
const span = parenSpan(m.index + m[0].length - 1);
|
|
979
|
-
if (!span)
|
|
980
|
-
continue;
|
|
981
|
-
const after = code.slice(span.end + 1);
|
|
982
|
-
if (/^\s*(?::[^{};()]*)?\{/.test(after))
|
|
983
|
-
addBindingSegment(span.inner);
|
|
984
|
-
}
|
|
985
|
-
// catch (e)
|
|
986
|
-
for (const m of code.matchAll(/\bcatch\s*\(/g)) {
|
|
987
|
-
const span = parenSpan(m.index + m[0].length - 1);
|
|
988
|
-
if (span)
|
|
989
|
-
addBindingSegment(span.inner);
|
|
990
|
-
}
|
|
991
|
-
// class names are TDZ bindings (function declarations hoist, classes don't)
|
|
992
|
-
for (const m of code.matchAll(/\bclass\s+([A-Za-z_$][\w$]*)/g)) {
|
|
993
|
-
bound.add(m[1] ?? "");
|
|
994
|
-
}
|
|
995
|
-
// const/let/var declarator patterns — balanced + multiline. The span runs
|
|
996
|
-
// to the first top-level `;` (or an unbalanced closer: for-headers), so
|
|
997
|
-
// `const {\n inputSchema,\n} = getSchemas();` collects inputSchema.
|
|
998
|
-
for (const m of code.matchAll(/\b(?:const|let|var)\b/g)) {
|
|
999
|
-
const start = m.index + m[0].length;
|
|
1000
|
-
let depth = 0;
|
|
1001
|
-
let end = code.length;
|
|
1002
|
-
for (let i = start; i < code.length; i++) {
|
|
1003
|
-
const ch = code[i];
|
|
1004
|
-
if (ch === "(" || ch === "[" || ch === "{") {
|
|
1005
|
-
depth++;
|
|
1006
|
-
}
|
|
1007
|
-
else if (ch === ")" || ch === "]" || ch === "}") {
|
|
1008
|
-
depth--;
|
|
1009
|
-
if (depth < 0) {
|
|
1010
|
-
end = i;
|
|
1011
|
-
break;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
else if (depth === 0 && ch === ";") {
|
|
1015
|
-
end = i;
|
|
1016
|
-
break;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
addBindingSegment(code.slice(start, end));
|
|
1020
|
-
}
|
|
1021
|
-
return bound;
|
|
769
|
+
const bound = /* @__PURE__ */ new Set();
|
|
770
|
+
const addBindingSegment = (segment) => {
|
|
771
|
+
let depth = 0;
|
|
772
|
+
let pieceStart = 0;
|
|
773
|
+
let cut = -1;
|
|
774
|
+
const flush = (end) => {
|
|
775
|
+
const prefix = segment.slice(pieceStart, cut === -1 ? end : cut);
|
|
776
|
+
for (const id of prefix.matchAll(/[A-Za-z_$][\w$]*/g)) bound.add(id[0]);
|
|
777
|
+
cut = -1;
|
|
778
|
+
};
|
|
779
|
+
for (let i = 0; i < segment.length; i++) {
|
|
780
|
+
const ch = segment[i];
|
|
781
|
+
if (ch === "(" || ch === "[" || ch === "{") depth++;
|
|
782
|
+
else if (ch === ")" || ch === "]" || ch === "}") depth--;
|
|
783
|
+
else if (depth === 0 && ch === ",") {
|
|
784
|
+
flush(i);
|
|
785
|
+
pieceStart = i + 1;
|
|
786
|
+
} else if (depth === 0 && cut === -1 && (ch === ":" || ch === "=")) cut = i;
|
|
787
|
+
}
|
|
788
|
+
flush(segment.length);
|
|
789
|
+
};
|
|
790
|
+
/** Balanced `( ... )` span starting at `open` (must point at `(`). */
|
|
791
|
+
const parenSpan = (open) => {
|
|
792
|
+
let depth = 0;
|
|
793
|
+
for (let i = open; i < code.length; i++) {
|
|
794
|
+
const ch = code[i];
|
|
795
|
+
if (ch === "(") depth++;
|
|
796
|
+
else if (ch === ")") {
|
|
797
|
+
depth--;
|
|
798
|
+
if (depth === 0) return {
|
|
799
|
+
inner: code.slice(open + 1, i),
|
|
800
|
+
end: i
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return null;
|
|
805
|
+
};
|
|
806
|
+
for (const m of code.matchAll(/\bfunction\b/g)) {
|
|
807
|
+
let i = m.index + m[0].length;
|
|
808
|
+
while (i < code.length && code[i] !== "(" && code[i] !== "{" && code[i] !== ";") i++;
|
|
809
|
+
if (code[i] !== "(") continue;
|
|
810
|
+
const span = parenSpan(i);
|
|
811
|
+
if (span) addBindingSegment(span.inner);
|
|
812
|
+
}
|
|
813
|
+
for (const m of code.matchAll(/=>/g)) {
|
|
814
|
+
let i = m.index - 1;
|
|
815
|
+
while (i >= 0 && /\s/.test(code[i])) i--;
|
|
816
|
+
if (i < 0) continue;
|
|
817
|
+
let closeAt = -1;
|
|
818
|
+
if (code[i] === ")") closeAt = i;
|
|
819
|
+
else {
|
|
820
|
+
const before = code.slice(0, m.index);
|
|
821
|
+
const lastClose = before.lastIndexOf(")");
|
|
822
|
+
if (lastClose !== -1 && /^\s*:[^(){};]*$/.test(before.slice(lastClose + 1))) closeAt = lastClose;
|
|
823
|
+
}
|
|
824
|
+
if (closeAt === -1) continue;
|
|
825
|
+
let depth = 0;
|
|
826
|
+
for (let j = closeAt; j >= 0; j--) {
|
|
827
|
+
const ch = code[j];
|
|
828
|
+
if (ch === ")") depth++;
|
|
829
|
+
else if (ch === "(") {
|
|
830
|
+
depth--;
|
|
831
|
+
if (depth === 0) {
|
|
832
|
+
addBindingSegment(code.slice(j + 1, closeAt));
|
|
833
|
+
break;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
for (const m of code.matchAll(/([A-Za-z_$][\w$]*)\s*=>/g)) bound.add(m[1] ?? "");
|
|
839
|
+
const methodAnchor = new RegExp(String.raw`(?<![.\w$])(?!(?:${NON_BINDING_KEYWORDS})\b)[A-Za-z_$][\w$]*\s*\(`, "g");
|
|
840
|
+
for (const m of code.matchAll(methodAnchor)) {
|
|
841
|
+
const span = parenSpan(m.index + m[0].length - 1);
|
|
842
|
+
if (!span) continue;
|
|
843
|
+
const after = code.slice(span.end + 1);
|
|
844
|
+
if (/^\s*(?::[^{};()]*)?\{/.test(after)) addBindingSegment(span.inner);
|
|
845
|
+
}
|
|
846
|
+
for (const m of code.matchAll(/\bcatch\s*\(/g)) {
|
|
847
|
+
const span = parenSpan(m.index + m[0].length - 1);
|
|
848
|
+
if (span) addBindingSegment(span.inner);
|
|
849
|
+
}
|
|
850
|
+
for (const m of code.matchAll(/\bclass\s+([A-Za-z_$][\w$]*)/g)) bound.add(m[1] ?? "");
|
|
851
|
+
for (const m of code.matchAll(/\b(?:const|let|var)\b/g)) {
|
|
852
|
+
const start = m.index + m[0].length;
|
|
853
|
+
let depth = 0;
|
|
854
|
+
let end = code.length;
|
|
855
|
+
for (let i = start; i < code.length; i++) {
|
|
856
|
+
const ch = code[i];
|
|
857
|
+
if (ch === "(" || ch === "[" || ch === "{") depth++;
|
|
858
|
+
else if (ch === ")" || ch === "]" || ch === "}") {
|
|
859
|
+
depth--;
|
|
860
|
+
if (depth < 0) {
|
|
861
|
+
end = i;
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
} else if (depth === 0 && ch === ";") {
|
|
865
|
+
end = i;
|
|
866
|
+
break;
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
addBindingSegment(code.slice(start, end));
|
|
870
|
+
}
|
|
871
|
+
return bound;
|
|
1022
872
|
}
|
|
1023
873
|
/**
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
874
|
+
* Free-variable analysis of a hoisted expression's source text, for the
|
|
875
|
+
* build-time compile step. Returns null when the text does not parse (it
|
|
876
|
+
* always should — it was extracted by this module).
|
|
877
|
+
*/
|
|
878
|
+
function analyzeHoistedExpression(text) {
|
|
879
|
+
try {
|
|
880
|
+
const { eagerFree, deferredFree, impure } = analyzeCaptures(parseAssignmentAt(text, 0));
|
|
881
|
+
if (impure) return null;
|
|
882
|
+
return {
|
|
883
|
+
eagerFree,
|
|
884
|
+
deferredFree
|
|
885
|
+
};
|
|
886
|
+
} catch {
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
1039
889
|
}
|
|
1040
890
|
/**
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
891
|
+
* Hoist eligible Zod schema expressions to module scope.
|
|
892
|
+
* Returns the rewritten source, or null when nothing was hoisted.
|
|
893
|
+
*/
|
|
894
|
+
function hoistZodSchemas(code, options) {
|
|
895
|
+
return hoistZodSchemasMeta(code, options)?.code ?? null;
|
|
1046
896
|
}
|
|
1047
897
|
/**
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
if (!rootIsZod && (deepestMethod === undefined || !COMBINATOR_METHODS.has(deepestMethod))) {
|
|
1164
|
-
continue;
|
|
1165
|
-
}
|
|
1166
|
-
const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);
|
|
1167
|
-
if (impure)
|
|
1168
|
-
continue;
|
|
1169
|
-
// Capture rule (babel-plugin-zod-hoist's canSafelyHoist, hardened): a
|
|
1170
|
-
// free name is safe only when it is an import or a recognized standard
|
|
1171
|
-
// global, and is never re-bound anywhere in the file (no scope info, so
|
|
1172
|
-
// a name bound in ANY function cannot be trusted to mean the import —
|
|
1173
|
-
// over-rejection only costs a missed hoist). The babel plugin also
|
|
1174
|
-
// allows arbitrary unbound identifiers, but it has real scope analysis;
|
|
1175
|
-
// here an unknown bare name is more likely a binding the lexical
|
|
1176
|
-
// collector missed than a genuine global, and hoisting it would crash
|
|
1177
|
-
// at module load (`ReferenceError: <name> is not defined`).
|
|
1178
|
-
let eligible = true;
|
|
1179
|
-
for (const name of eagerFree) {
|
|
1180
|
-
if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {
|
|
1181
|
-
eligible = false;
|
|
1182
|
-
break;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
if (eligible) {
|
|
1186
|
-
for (const name of deferredFree) {
|
|
1187
|
-
if ((!imports.all.has(name) && !KNOWN_GLOBALS.has(name)) || isShadowed(name)) {
|
|
1188
|
-
eligible = false;
|
|
1189
|
-
break;
|
|
1190
|
-
}
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
if (!eligible)
|
|
1194
|
-
continue;
|
|
1195
|
-
// Non-zod, non-pattern roots qualify only when the chain itself
|
|
1196
|
-
// references a zod binding (`Base.extend({ a: z.string() })`).
|
|
1197
|
-
if (!rootIsZod && !rootMatchesPattern) {
|
|
1198
|
-
let referencesZod = false;
|
|
1199
|
-
for (const name of eagerFree) {
|
|
1200
|
-
if (imports.zod.has(name)) {
|
|
1201
|
-
referencesZod = true;
|
|
1202
|
-
break;
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
1205
|
-
for (const name of deferredFree) {
|
|
1206
|
-
if (imports.zod.has(name)) {
|
|
1207
|
-
referencesZod = true;
|
|
1208
|
-
break;
|
|
1209
|
-
}
|
|
1210
|
-
}
|
|
1211
|
-
if (!referencesZod)
|
|
1212
|
-
continue;
|
|
1213
|
-
}
|
|
1214
|
-
const text = code.slice(candidate.index, chain.end);
|
|
1215
|
-
let declName = declByText.get(text);
|
|
1216
|
-
if (!declName) {
|
|
1217
|
-
declName = `_zh_${fnv1a(text)}`;
|
|
1218
|
-
declByText.set(text, declName);
|
|
1219
|
-
}
|
|
1220
|
-
hoists.push({ start: candidate.index, end: chain.end, name: declName });
|
|
1221
|
-
// Non-zod-rooted chains mask their interior only on success — the inner
|
|
1222
|
-
// parts are consumed by this hoist's replacement.
|
|
1223
|
-
consumedUntil = Math.max(consumedUntil, chain.end);
|
|
1224
|
-
}
|
|
1225
|
-
if (hoists.length === 0)
|
|
1226
|
-
return null;
|
|
1227
|
-
const decls = [...declByText.entries()]
|
|
1228
|
-
.map(([text, name]) => `const ${name} = ${text};`)
|
|
1229
|
-
.join("\n");
|
|
1230
|
-
// The insertion offset is identical in input and output coordinates: the
|
|
1231
|
-
// directive prologue precedes every statement, and all hoist replacements
|
|
1232
|
-
// sit inside statements.
|
|
1233
|
-
const edits = hoists.map((h) => ({ start: h.start, end: h.end, text: h.name }));
|
|
1234
|
-
const insert = { offset: insertionOffset(code), text: `${decls}\n` };
|
|
1235
|
-
return {
|
|
1236
|
-
code: applyEdits(code, edits, insert),
|
|
1237
|
-
schemas: [...declByText.entries()].map(([text, name]) => ({ name, text })),
|
|
1238
|
-
edits,
|
|
1239
|
-
insert,
|
|
1240
|
-
};
|
|
898
|
+
* hoistZodSchemas + metadata about each hoisted declaration, so the
|
|
899
|
+
* transform can compile the hoisted schemas into optimized validators.
|
|
900
|
+
*/
|
|
901
|
+
function hoistZodSchemasMeta(code, options) {
|
|
902
|
+
if (/\bconst _zh_[0-9a-f]{8} = /.test(code)) return null;
|
|
903
|
+
const imports = collectImportBindings(code);
|
|
904
|
+
if (imports.all.size === 0) return null;
|
|
905
|
+
const rawPattern = options?.schemaNamePattern;
|
|
906
|
+
const namePattern = rawPattern === null ? null : rawPattern === void 0 ? SCHEMA_NAME_PATTERN : typeof rawPattern === "string" ? new RegExp(rawPattern) : rawPattern;
|
|
907
|
+
const roots = new Set(imports.zod);
|
|
908
|
+
if (namePattern) {
|
|
909
|
+
for (const name of imports.all) if (namePattern.test(name)) roots.add(name);
|
|
910
|
+
}
|
|
911
|
+
if (imports.zod.size > 0) for (const name of imports.all) roots.add(name);
|
|
912
|
+
if (roots.size === 0) return null;
|
|
913
|
+
options?.onScan?.();
|
|
914
|
+
const { candidates, stripped } = scanSource(code, roots);
|
|
915
|
+
if (candidates.length === 0) return null;
|
|
916
|
+
let boundNames;
|
|
917
|
+
function isShadowed(name) {
|
|
918
|
+
boundNames ??= collectBoundNames(stripped());
|
|
919
|
+
return boundNames.has(name);
|
|
920
|
+
}
|
|
921
|
+
const hoists = [];
|
|
922
|
+
const declByText = /* @__PURE__ */ new Map();
|
|
923
|
+
let consumedUntil = 0;
|
|
924
|
+
for (const candidate of candidates) {
|
|
925
|
+
if (candidate.index < consumedUntil) continue;
|
|
926
|
+
if (candidate.depth === 0 && !candidate.afterArrow) {
|
|
927
|
+
consumedUntil = findChainEnd(code, candidate.index);
|
|
928
|
+
continue;
|
|
929
|
+
}
|
|
930
|
+
let parsed;
|
|
931
|
+
try {
|
|
932
|
+
parsed = parseAssignmentAt(code, candidate.index);
|
|
933
|
+
} catch {
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
let chain = narrowToCallChain(parsed, candidate.index);
|
|
937
|
+
if (!chain) continue;
|
|
938
|
+
const rootIsZod = imports.zod.has(candidate.name);
|
|
939
|
+
if (rootIsZod) consumedUntil = chain.end;
|
|
940
|
+
let described = describeChain(chain);
|
|
941
|
+
while (chain !== null && described !== null && described.methods.length > 0 && PARSE_METHODS.has(described.methods[0])) {
|
|
942
|
+
const callee = chain.type === "CallExpression" ? chain.callee : null;
|
|
943
|
+
const inner = callee !== null && callee.type === "MemberExpression" ? callee.object : null;
|
|
944
|
+
chain = inner !== null && inner.type === "CallExpression" ? inner : null;
|
|
945
|
+
described = chain === null ? null : describeChain(chain);
|
|
946
|
+
}
|
|
947
|
+
if (chain === null || described === null) continue;
|
|
948
|
+
if (rootIsZod) consumedUntil = chain.end;
|
|
949
|
+
if (described.root !== candidate.name) continue;
|
|
950
|
+
if (described.methods.some((m) => PARSE_METHODS.has(m))) continue;
|
|
951
|
+
const rootMatchesPattern = namePattern?.test(candidate.name) === true;
|
|
952
|
+
const deepestMethod = described.methods[described.methods.length - 1];
|
|
953
|
+
if (!rootIsZod && (deepestMethod === void 0 || !COMBINATOR_METHODS.has(deepestMethod))) continue;
|
|
954
|
+
const { eagerFree, deferredFree, impure } = analyzeCaptures(chain);
|
|
955
|
+
if (impure) continue;
|
|
956
|
+
let eligible = true;
|
|
957
|
+
for (const name of eagerFree) if (!imports.all.has(name) && !KNOWN_GLOBALS.has(name) || isShadowed(name)) {
|
|
958
|
+
eligible = false;
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
if (eligible) {
|
|
962
|
+
for (const name of deferredFree) if (!imports.all.has(name) && !KNOWN_GLOBALS.has(name) || isShadowed(name)) {
|
|
963
|
+
eligible = false;
|
|
964
|
+
break;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (!eligible) continue;
|
|
968
|
+
if (!rootIsZod && !rootMatchesPattern) {
|
|
969
|
+
let referencesZod = false;
|
|
970
|
+
for (const name of eagerFree) if (imports.zod.has(name)) {
|
|
971
|
+
referencesZod = true;
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
for (const name of deferredFree) if (imports.zod.has(name)) {
|
|
975
|
+
referencesZod = true;
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
if (!referencesZod) continue;
|
|
979
|
+
}
|
|
980
|
+
const text = code.slice(candidate.index, chain.end);
|
|
981
|
+
let declName = declByText.get(text);
|
|
982
|
+
if (!declName) {
|
|
983
|
+
declName = `_zh_${fnv1a(text)}`;
|
|
984
|
+
declByText.set(text, declName);
|
|
985
|
+
}
|
|
986
|
+
hoists.push({
|
|
987
|
+
start: candidate.index,
|
|
988
|
+
end: chain.end,
|
|
989
|
+
name: declName
|
|
990
|
+
});
|
|
991
|
+
consumedUntil = Math.max(consumedUntil, chain.end);
|
|
992
|
+
}
|
|
993
|
+
if (hoists.length === 0) return null;
|
|
994
|
+
const decls = [...declByText.entries()].map(([text, name]) => `const ${name} = ${text};`).join("\n");
|
|
995
|
+
const edits = hoists.map((h) => ({
|
|
996
|
+
start: h.start,
|
|
997
|
+
end: h.end,
|
|
998
|
+
text: h.name
|
|
999
|
+
}));
|
|
1000
|
+
const insert = {
|
|
1001
|
+
offset: insertionOffset(code),
|
|
1002
|
+
text: `${decls}\n`
|
|
1003
|
+
};
|
|
1004
|
+
return {
|
|
1005
|
+
code: applyEdits(code, edits, insert),
|
|
1006
|
+
schemas: [...declByText.entries()].map(([text, name]) => ({
|
|
1007
|
+
name,
|
|
1008
|
+
text
|
|
1009
|
+
})),
|
|
1010
|
+
edits,
|
|
1011
|
+
insert
|
|
1012
|
+
};
|
|
1241
1013
|
}
|
|
1014
|
+
//#endregion
|
|
1015
|
+
export { SCHEMA_NAME_PATTERN, ZOD_MODULES, analyzeHoistedExpression, collectImportBindings, hoistZodSchemas, hoistZodSchemasMeta };
|
|
1016
|
+
|
|
1242
1017
|
//# sourceMappingURL=hoist.js.map
|