@scriptc/compiler 0.1.7 → 0.2.1
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/ambient/scriptc-node-fallback.d.ts +98 -39
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +15 -0
- package/dist/backend/build-cache.d.ts +1 -3
- package/dist/backend/build-cache.js +3 -22
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cache-root.d.ts +3 -0
- package/dist/backend/cache-root.js +23 -0
- package/dist/backend/cache-root.js.map +1 -0
- package/dist/backend/cycle-analysis.d.ts +15 -0
- package/dist/backend/cycle-analysis.js +108 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/executable-features.d.ts +4 -0
- package/dist/backend/executable-features.js +42 -0
- package/dist/backend/executable-features.js.map +1 -0
- package/dist/backend/external-c.d.ts +5 -27
- package/dist/backend/external-c.js +5 -40
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +2 -3
- package/dist/backend/ffi-callbacks.js +2 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.d.ts +4 -9
- package/dist/backend/library-identity-markers.js +11 -49
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +5 -0
- package/dist/backend/library-pack.js +123 -0
- package/dist/backend/library-pack.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +20 -0
- package/dist/backend/link-plan-core.js +18 -0
- package/dist/backend/link-plan-core.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +16 -17
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/link-trace.d.ts +2 -0
- package/dist/backend/link-trace.js +24 -0
- package/dist/backend/link-trace.js.map +1 -0
- package/dist/backend/linker.js +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.d.ts +9 -0
- package/dist/backend/literals.js +35 -0
- package/dist/backend/literals.js.map +1 -0
- package/dist/backend/literals.test.d.ts +1 -0
- package/dist/backend/literals.test.js +53 -0
- package/dist/backend/literals.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +2 -0
- package/dist/backend/llvm/blocks.js +9 -4
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.d.ts +1 -0
- package/dist/backend/llvm/blocks.test.js +91 -0
- package/dist/backend/llvm/blocks.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +14 -8
- package/dist/backend/llvm/classes.js +88 -30
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -7
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/debug-info.test.d.ts +1 -0
- package/dist/backend/llvm/debug-info.test.js +110 -0
- package/dist/backend/llvm/debug-info.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +21 -2
- package/dist/backend/llvm/dyn.js +647 -251
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +596 -1
- package/dist/backend/llvm/emitter.js +769 -425
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -2
- package/dist/backend/llvm/expr-bytes.js +60 -31
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +10 -6
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +78 -81
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +62 -31
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +54 -7
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +220 -131
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +30 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +2 -0
- package/dist/backend/llvm/lib-http2.js +215 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -0
- package/dist/backend/llvm/lib-lookup.d.ts +2 -0
- package/dist/backend/llvm/lib-lookup.js +39 -0
- package/dist/backend/llvm/lib-lookup.js.map +1 -0
- package/dist/backend/llvm/lib-network.js +25 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +44 -19
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +162 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +42 -131
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +12 -30
- package/dist/backend/native-toolchain.js +83 -233
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +77 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +73 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +103 -34
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +72 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +37 -7
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +5 -10
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +5 -6
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +16 -17
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +14 -0
- package/dist/executable/prepare.js +66 -0
- package/dist/executable/prepare.js.map +1 -0
- package/dist/ffi/ffi-manifest.d.ts +11 -4
- package/dist/ffi/ffi-manifest.js +170 -58
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.d.ts +1 -0
- package/dist/ffi/ffi-manifest.test.js +111 -0
- package/dist/ffi/ffi-manifest.test.js.map +1 -0
- package/dist/format-integer.d.ts +3 -0
- package/dist/format-integer.js +14 -0
- package/dist/format-integer.js.map +1 -0
- package/dist/frontend/analysis.d.ts +5 -0
- package/dist/frontend/analysis.js +88 -0
- package/dist/frontend/analysis.js.map +1 -0
- package/dist/frontend/arguments-usage.d.ts +1 -3
- package/dist/frontend/arguments-usage.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-lexer.d.ts +4 -25
- package/dist/frontend/cjs-lexer.js +6 -806
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/cjs-resolve.d.ts +5 -0
- package/dist/frontend/cjs-resolve.js +429 -0
- package/dist/frontend/cjs-resolve.js.map +1 -0
- package/dist/frontend/cjs-syntax.d.ts +26 -0
- package/dist/frontend/cjs-syntax.js +806 -0
- package/dist/frontend/cjs-syntax.js.map +1 -0
- package/dist/frontend/comptime-node.d.ts +4 -0
- package/dist/frontend/comptime-node.js +16 -0
- package/dist/frontend/comptime-node.js.map +1 -0
- package/dist/frontend/comptime-node.test.d.ts +1 -0
- package/dist/frontend/comptime-node.test.js +37 -0
- package/dist/frontend/comptime-node.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +3 -4
- package/dist/frontend/dts-paths.js +15 -8
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +2 -2
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/helper-tokens.d.ts +1 -0
- package/dist/frontend/helper-tokens.js +147 -0
- package/dist/frontend/helper-tokens.js.map +1 -0
- package/dist/frontend/helper-tokens.test.d.ts +1 -0
- package/dist/frontend/helper-tokens.test.js +35 -0
- package/dist/frontend/helper-tokens.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
- package/dist/frontend/inferred-js-diagnostics.js +69 -0
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +5 -2
- package/dist/frontend/input-tracker.js +24 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +23 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +32 -24
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.d.ts +4 -0
- package/dist/frontend/literal-values.js +21 -0
- package/dist/frontend/literal-values.js.map +1 -0
- package/dist/frontend/literal-values.test.d.ts +1 -0
- package/dist/frontend/literal-values.test.js +91 -0
- package/dist/frontend/literal-values.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
- package/dist/frontend/lowering/abstract-equality.js +3 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -1
- package/dist/frontend/lowering/array-values.js +43 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
- package/dist/frontend/lowering/class-callbacks.js +74 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-construction.d.ts +12 -0
- package/dist/frontend/lowering/class-construction.js +156 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +10 -0
- package/dist/frontend/lowering/class-descriptors.js +114 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +51 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1158 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +93 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +67 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +13 -0
- package/dist/frontend/lowering/class-method-values.js +235 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +19 -0
- package/dist/frontend/lowering/class-prototypes.js +242 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +66 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +208 -163
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +58 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +14 -0
- package/dist/frontend/lowering/error-methods.js +177 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +51 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +132 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +509 -183
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +88 -24
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +101 -0
- package/dist/frontend/lowering/function-context.js +109 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +143 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +4 -1
- package/dist/frontend/lowering/lib-boundary.js +112 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtin-values.js +249 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +33 -46
- package/dist/frontend/lowering/lower-builtins.js +676 -365
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +28 -22
- package/dist/frontend/lowering/lower-calls.js +1660 -412
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +95 -57
- package/dist/frontend/lowering/lower-classes.js +1491 -404
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +36 -32
- package/dist/frontend/lowering/lower-containers.js +925 -181
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +37 -13
- package/dist/frontend/lowering/lower-exprs.js +2163 -863
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +88 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -8
- package/dist/frontend/lowering/lower-island.js +66 -33
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +445 -39
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +39 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +17 -17
- package/dist/frontend/lowering/lower-stmts.js +855 -514
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +20 -11
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +140 -190
- package/dist/frontend/lowering/lowerer.js +1193 -712
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +172 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +10 -3
- package/dist/frontend/lowering/surfaces.js +86 -37
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +12 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +82 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +121 -38
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +9 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +39 -20
- package/dist/frontend/program.js +393 -189
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +105 -2
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/provenance-core.d.ts +9 -0
- package/dist/frontend/provenance-core.js +435 -0
- package/dist/frontend/provenance-core.js.map +1 -0
- package/dist/frontend/provenance.d.ts +0 -4
- package/dist/frontend/provenance.js +4 -459
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +3 -1
- package/dist/frontend/resolve.js +6 -3
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +4 -3
- package/dist/frontend/runtime-resolve.js +22 -18
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +53 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.d.ts +5 -0
- package/dist/frontend/services-node.js +19 -0
- package/dist/frontend/services-node.js.map +1 -0
- package/dist/frontend/services-node.test.d.ts +1 -0
- package/dist/frontend/services-node.test.js +70 -0
- package/dist/frontend/services-node.test.js.map +1 -0
- package/dist/frontend/services.d.ts +44 -0
- package/dist/frontend/services.js +90 -0
- package/dist/frontend/services.js.map +1 -0
- package/dist/frontend/services.test.d.ts +1 -0
- package/dist/frontend/services.test.js +174 -0
- package/dist/frontend/services.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +3 -3
- package/dist/frontend/ts7/adapter.js +14 -31
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/api.d.ts +16 -0
- package/dist/frontend/ts7/api.js +24 -0
- package/dist/frontend/ts7/api.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
- package/dist/frontend/ts7/ast-bytes.js +137 -0
- package/dist/frontend/ts7/ast-bytes.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-bytes.test.js +73 -0
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
- package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-guards.test.js +43 -0
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +194 -0
- package/dist/frontend/ts7/ast-node.js +448 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -0
- package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-node.test.js +266 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -0
- package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
- package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
- package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-text.d.ts +6 -0
- package/dist/frontend/ts7/ast-text.js +124 -0
- package/dist/frontend/ts7/ast-text.js.map +1 -0
- package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-text.test.js +38 -0
- package/dist/frontend/ts7/ast-text.test.js.map +1 -0
- package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
- package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
- package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.d.ts +42 -0
- package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
- package/dist/frontend/ts7/ast-types.generated.js +5 -0
- package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.js +3 -0
- package/dist/frontend/ts7/ast-types.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +58 -0
- package/dist/frontend/ts7/ast-wire.js +267 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire.test.js +151 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
- package/dist/frontend/ts7/ast.d.ts +14 -14
- package/dist/frontend/ts7/ast.js +25 -18
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +47 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +34 -18
- package/dist/frontend/type-mapper.js +552 -131
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +146 -2
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +16 -0
- package/dist/frontend/union-discriminants.js +98 -0
- package/dist/frontend/union-discriminants.js.map +1 -0
- package/dist/frontend/union-discriminants.test.d.ts +1 -0
- package/dist/frontend/union-discriminants.test.js +182 -0
- package/dist/frontend/union-discriminants.test.js.map +1 -0
- package/dist/index.d.ts +7 -198
- package/dist/index.js +369 -1572
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +23 -4
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.js +67 -49
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/control-flow.d.ts +6 -0
- package/dist/ir/control-flow.js +142 -0
- package/dist/ir/control-flow.js.map +1 -0
- package/dist/ir/control-flow.test.d.ts +1 -0
- package/dist/ir/control-flow.test.js +113 -0
- package/dist/ir/control-flow.test.js.map +1 -0
- package/dist/ir/integer-loops.js +7 -18
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.js +53 -27
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +334 -176
- package/dist/ir/ir.js +710 -903
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +162 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +33 -14
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +57 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +2018 -1498
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +536 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +137 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +94 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +85 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +107 -98
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -536
- package/dist/backend/c/c-emitter.js +0 -1932
- package/dist/backend/c/c-emitter.js.map +0 -1
- package/dist/backend/c/exprs.d.ts +0 -15
- package/dist/backend/c/exprs.js +0 -8847
- package/dist/backend/c/exprs.js.map +0 -1
- package/dist/backend/c/island.d.ts +0 -45
- package/dist/backend/c/island.js +0 -281
- package/dist/backend/c/island.js.map +0 -1
- package/dist/backend/c/may-throw.js.map +0 -1
- package/dist/backend/c/shapes.d.ts +0 -142
- package/dist/backend/c/shapes.js +0 -603
- package/dist/backend/c/shapes.js.map +0 -1
- package/dist/backend/c/stmts.d.ts +0 -76
- package/dist/backend/c/stmts.js +0 -1108
- package/dist/backend/c/stmts.js.map +0 -1
- package/dist/backend/c/types.d.ts +0 -71
- package/dist/backend/c/types.js +0 -459
- package/dist/backend/c/types.js.map +0 -1
- package/dist/backend/c/types.test.js +0 -32
- package/dist/backend/c/types.test.js.map +0 -1
- package/dist/backend/c/walkers.d.ts +0 -134
- package/dist/backend/c/walkers.js +0 -1772
- package/dist/backend/c/walkers.js.map +0 -1
- /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
package/dist/ir/validate.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { arrayOf, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, CHILDWRITER_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, ffiClassType, ffiSourceParamTypes, FILEHANDLE_T, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isJsonSafeType, isJsonStringifySafeType, isRefCounted, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, shapeHasAccessorSlots, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey,
|
|
1
|
+
import { arrayOf, BYTES_ELEMENT_NAME, BOOL, BYTES_U8, bytesOf, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canExitIslandToType, canMarshalIntoIsland, canMarshalTypedFuncIntoIsland, CHILD_T, CHILDSTREAM_T, CHILDWRITER_T, CRYPTOHASH_T, CRYPTOHMAC_T, DATE_T, DGRAMSOCK_T, DYN, DYN_HANDLE_KINDS, F64, ffiClassType, ffiSourceParamTypes, FILEHANDLE_T, FSWATCHER_T, HTTP2SESSION_T, HTTP2STREAM_T, HTTPCLIENTREQ_T, HTTPREQ_T, HTTPRES_T, islandPromisePayloadTag, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isJsonSafeType, isJsonStringifySafeType, isRefCounted, isSupportedArrayElem, isSupportedIndexValue, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, jsOpResultKind, JSVAL, NETSERVER_T, NETSOCKET_T, PROCSTREAM_T, REF_TRUTHY_KINDS, REGEX, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, SEARCH_PARAMS_T, SECURECTX_T, shapeHasAccessorSlots, SPAWNRES_T, STATS_T, STRING, SYMBOL_T, TESTCTX_T, typeEquals, typeKey, unionContainerArmsOk, URL_T, VOID } from "./ir.js";
|
|
2
2
|
import { BIGINT_T } from "./ir.js";
|
|
3
|
+
import { unionWideningTags } from "./analysis.js";
|
|
4
|
+
import { alwaysReturns } from "./control-flow.js";
|
|
3
5
|
/** Per-method signature for strIntrinsic: `argTypes` lists every argument
|
|
4
6
|
* position (optional ones included); `minArgs` is how many may be omitted
|
|
5
7
|
* from the end (backends fill the documented defaults). Exported for the
|
|
@@ -38,11 +40,14 @@ export const REGEX_INTRINSIC_SIGS = {
|
|
|
38
40
|
// VOID here is the process.envGet sentinel; the regexIntrinsic case
|
|
39
41
|
// checks the union's arms.
|
|
40
42
|
match: { receiver: STRING, argTypes: [REGEX], result: VOID },
|
|
43
|
+
exec: { receiver: STRING, argTypes: [REGEX], result: VOID },
|
|
44
|
+
lastIndex: { receiver: REGEX, argTypes: [], result: F64 },
|
|
41
45
|
matchAll: { receiver: STRING, argTypes: [REGEX], result: arrayOf(arrayOf(STRING)) },
|
|
42
46
|
matchAllInto: { receiver: STRING, argTypes: [REGEX, arrayOf(F64)], result: arrayOf(arrayOf(STRING)) },
|
|
43
47
|
search: { receiver: STRING, argTypes: [REGEX], result: F64 },
|
|
44
48
|
source: { receiver: REGEX, argTypes: [], result: STRING },
|
|
45
49
|
flags: { receiver: REGEX, argTypes: [], result: STRING },
|
|
50
|
+
toString: { receiver: REGEX, argTypes: [], result: STRING },
|
|
46
51
|
replace: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
|
|
47
52
|
replaceAll: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
|
|
48
53
|
split: { receiver: STRING, argTypes: [REGEX, F64], result: arrayOf(STRING) },
|
|
@@ -57,6 +62,11 @@ export const REGEX_INTRINSIC_SIGS = {
|
|
|
57
62
|
export const LIB_FN_SIGS = {
|
|
58
63
|
"fetch.start": { argTypes: [STRING, DYN], result: { kind: "promise", inner: DYN } },
|
|
59
64
|
"fetch.responseNew": { argTypes: [DYN, DYN], result: DYN },
|
|
65
|
+
"fetch.input": { argTypes: [DYN, DYN], result: { kind: "promise", inner: DYN } },
|
|
66
|
+
"fetch.function": { argTypes: [], result: DYN },
|
|
67
|
+
"fetch.requestNew": { argTypes: [DYN, DYN], result: DYN },
|
|
68
|
+
"fetch.headersNew": { argTypes: [DYN], result: DYN },
|
|
69
|
+
"fetch.responseArrayBuffer": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
|
|
60
70
|
"fetch.responseJson": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
|
|
61
71
|
"fetch.responseText": { argTypes: [DYN], result: { kind: "promise", inner: STRING } },
|
|
62
72
|
"fetch.responseBytes": { argTypes: [DYN], result: { kind: "promise", inner: BYTES_U8 } },
|
|
@@ -68,6 +78,8 @@ export const LIB_FN_SIGS = {
|
|
|
68
78
|
// Program-dependent iterable: typed arrays/bytes/string stay intact so
|
|
69
79
|
// the native stream can pull lazily; checked-dynamic values are the
|
|
70
80
|
// fallback. The libCall validator below checks the closed set.
|
|
81
|
+
"fetch.webIs": { argTypes: [DYN, STRING], result: BOOL },
|
|
82
|
+
"fetch.streamIs": { argTypes: [DYN], result: BOOL },
|
|
71
83
|
"fetch.streamFrom": { argTypes: [null], result: DYN },
|
|
72
84
|
// The chunk/result record depends on ReadableStream<T>; validated below.
|
|
73
85
|
"fetch.readerRead": { argTypes: [DYN], result: VOID },
|
|
@@ -78,13 +90,46 @@ export const LIB_FN_SIGS = {
|
|
|
78
90
|
// checked in the libCall case, like error.new.
|
|
79
91
|
"island.castFail": { argTypes: [JSVAL, STRING], result: VOID },
|
|
80
92
|
"json.parse": { argTypes: [STRING], result: DYN },
|
|
93
|
+
"json.parseReviver": { argTypes: [STRING, DYN], result: DYN },
|
|
94
|
+
"json.stringifyReplacer": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
95
|
+
"json.stringifyValue": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
81
96
|
"dyn.keySet": { argTypes: [DYN, STRING, DYN], result: VOID },
|
|
97
|
+
"dyn.keySetComputed": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
98
|
+
"dyn.keyDelete": { argTypes: [DYN, STRING, BOOL], result: VOID },
|
|
99
|
+
"dyn.keyDeleteComputed": { argTypes: [DYN, DYN, BOOL], result: VOID },
|
|
100
|
+
"dyn.hasKeyComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
101
|
+
"dyn.hasOwnComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
102
|
+
"dyn.propertyIsEnumerableComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
103
|
+
"dyn.globalSymbolGet": { argTypes: [SYMBOL_T], result: DYN },
|
|
104
|
+
"dyn.globalSymbolSet": { argTypes: [SYMBOL_T, DYN], result: VOID },
|
|
105
|
+
"dyn.globalSymbolHas": { argTypes: [SYMBOL_T], result: BOOL },
|
|
106
|
+
"dyn.globalSymbolDelete": { argTypes: [SYMBOL_T], result: VOID },
|
|
107
|
+
"dyn.typedRefIs": { argTypes: [DYN, STRING], result: BOOL },
|
|
108
|
+
"dyn.classIs": { argTypes: [DYN, STRING], result: BOOL },
|
|
82
109
|
"dyn.iterPack": { argTypes: [DYN, STRING], result: DYN },
|
|
110
|
+
"dyn.arrayFromIterator": { argTypes: [DYN], result: DYN },
|
|
111
|
+
"dyn.iterator": { argTypes: [DYN, STRING], result: DYN },
|
|
112
|
+
"dyn.iteratorResult": { argTypes: [DYN], result: DYN },
|
|
113
|
+
"dyn.mapSeedEntries": { argTypes: [DYN], result: DYN },
|
|
114
|
+
"dyn.mapSeedEntry": { argTypes: [DYN], result: DYN },
|
|
83
115
|
"dyn.arrLen": { argTypes: [DYN], result: F64 },
|
|
84
116
|
"dyn.arrAt": { argTypes: [DYN, F64], result: DYN },
|
|
85
117
|
"dyn.hasKey": { argTypes: [DYN, STRING], result: BOOL },
|
|
86
|
-
"dyn.
|
|
118
|
+
"dyn.freeze": { argTypes: [DYN], result: DYN },
|
|
119
|
+
"dyn.isFrozen": { argTypes: [DYN], result: BOOL },
|
|
120
|
+
"dyn.nativeSetNew": { argTypes: [DYN], result: DYN },
|
|
121
|
+
"dyn.nativeSetIs": { argTypes: [DYN], result: BOOL },
|
|
122
|
+
"dyn.nativeMapIs": { argTypes: [DYN], result: BOOL },
|
|
123
|
+
"dyn.nativeUrlIs": { argTypes: [DYN], result: BOOL },
|
|
124
|
+
"dyn.nativeDateIs": { argTypes: [DYN], result: BOOL },
|
|
125
|
+
"date.nativeNew": { argTypes: [DYN], result: DYN },
|
|
126
|
+
"date.checkedValue": { argTypes: [DYN], result: DATE_T },
|
|
127
|
+
"dyn.nativeRegexIs": { argTypes: [DYN], result: BOOL },
|
|
128
|
+
"dyn.toString": { argTypes: [DYN, DYN, STRING], result: STRING },
|
|
87
129
|
"dyn.defineProps": { argTypes: [DYN, DYN], result: DYN },
|
|
130
|
+
"dyn.defineProperty": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
131
|
+
"dyn.getOwnPropertyDescriptor": { argTypes: [DYN, DYN], result: DYN },
|
|
132
|
+
"dyn.arrayProtoCall": { argTypes: [DYN, STRING, DYN], result: DYN },
|
|
88
133
|
"dyn.typeof": { argTypes: [DYN], result: STRING },
|
|
89
134
|
"dyn.objectTag": { argTypes: [DYN], result: STRING },
|
|
90
135
|
"module.registryInit": { argTypes: [F64], result: VOID },
|
|
@@ -139,8 +184,8 @@ export const LIB_FN_SIGS = {
|
|
|
139
184
|
// Signal listeners are zero-param (the ambient shape); exit/stdin
|
|
140
185
|
// callbacks carry program-dependent one-param shapes — null slots, the
|
|
141
186
|
// libCall case checks them (child.onExit precedent).
|
|
142
|
-
"process.onSignal": { argTypes: [
|
|
143
|
-
"process.offSignal": { argTypes: [
|
|
187
|
+
"process.onSignal": { argTypes: [STRING, DYN, BOOL], result: VOID },
|
|
188
|
+
"process.offSignal": { argTypes: [STRING, DYN], result: VOID },
|
|
144
189
|
"process.onExit": { argTypes: [null, BOOL], result: VOID },
|
|
145
190
|
"process.offExit": { argTypes: [null], result: VOID },
|
|
146
191
|
"stdin.onData": { argTypes: [null, BOOL], result: VOID },
|
|
@@ -188,6 +233,7 @@ export const LIB_FN_SIGS = {
|
|
|
188
233
|
"net.getAutoSelTimeout": { argTypes: [], result: F64 },
|
|
189
234
|
"net.setAutoSelTimeout": { argTypes: [F64], result: VOID },
|
|
190
235
|
"fs.realpathSync": { argTypes: [STRING], result: STRING },
|
|
236
|
+
"fs.realpathNativeSync": { argTypes: [STRING], result: STRING },
|
|
191
237
|
"os.userName": { argTypes: [], result: STRING },
|
|
192
238
|
"os.userShell": { argTypes: [], result: STRING },
|
|
193
239
|
"os.userHomedir": { argTypes: [], result: STRING },
|
|
@@ -243,16 +289,19 @@ export const LIB_FN_SIGS = {
|
|
|
243
289
|
"str.btoa": { argTypes: [DYN], result: STRING },
|
|
244
290
|
"str.b64Missing": { argTypes: [], result: STRING },
|
|
245
291
|
"str.decodeUriComponent": { argTypes: [STRING], result: STRING },
|
|
292
|
+
"str.decodeUri": { argTypes: [STRING], result: STRING },
|
|
246
293
|
"str.encodeUri": { argTypes: [STRING], result: STRING },
|
|
247
294
|
"regexp.escape": { argTypes: [STRING], result: STRING },
|
|
248
295
|
"num.toExponential": { argTypes: [F64], result: STRING },
|
|
249
296
|
"num.toFixed0": { argTypes: [F64], result: STRING },
|
|
250
297
|
"num.toFixed": { argTypes: [F64, F64], result: STRING },
|
|
298
|
+
"num.toStringRadix": { argTypes: [F64, DYN], result: STRING },
|
|
251
299
|
"num.sameValue": { argTypes: [F64, F64], result: BOOL },
|
|
252
300
|
"intl.numFormatEnUs": { argTypes: [F64], result: STRING },
|
|
253
301
|
"sym.new": { argTypes: [STRING], result: SYMBOL_T },
|
|
254
302
|
"sym.newAnon": { argTypes: [], result: SYMBOL_T },
|
|
255
303
|
"sym.for": { argTypes: [STRING], result: SYMBOL_T },
|
|
304
|
+
"sym.wellKnown": { argTypes: [STRING], result: SYMBOL_T },
|
|
256
305
|
// Result is the interned `string | undefined` union — the libCall case
|
|
257
306
|
// checks the arms (the spawnRes.error pattern).
|
|
258
307
|
"sym.keyFor": { argTypes: [SYMBOL_T], result: VOID },
|
|
@@ -288,6 +337,7 @@ export const LIB_FN_SIGS = {
|
|
|
288
337
|
"bigint.dataViewGet": { argTypes: [BYTES_U8, F64, BOOL, BOOL], result: BIGINT_T },
|
|
289
338
|
"bigint.dataViewSet": { argTypes: [BYTES_U8, F64, BIGINT_T, BOOL], result: VOID },
|
|
290
339
|
"url.new": { argTypes: [STRING], result: URL_T },
|
|
340
|
+
"url.newBase": { argTypes: [STRING, STRING], result: URL_T },
|
|
291
341
|
"url.protocol": { argTypes: [URL_T], result: STRING },
|
|
292
342
|
"url.origin": { argTypes: [URL_T], result: STRING },
|
|
293
343
|
"url.username": { argTypes: [URL_T], result: STRING },
|
|
@@ -298,10 +348,13 @@ export const LIB_FN_SIGS = {
|
|
|
298
348
|
"url.pathname": { argTypes: [URL_T], result: STRING },
|
|
299
349
|
"url.href": { argTypes: [URL_T], result: STRING },
|
|
300
350
|
"url.fileURLToPathUrl": { argTypes: [URL_T], result: STRING },
|
|
351
|
+
"url.fileURLToPathChecked": { argTypes: [DYN], result: STRING },
|
|
301
352
|
"url.fileURLToPathStr": { argTypes: [STRING], result: STRING },
|
|
302
353
|
"url.pathToFileURL": { argTypes: [STRING], result: URL_T },
|
|
354
|
+
"url.pathToFileURLPlatform": { argTypes: [STRING, BOOL], result: URL_T },
|
|
303
355
|
"url.pathToFileURLWin32": { argTypes: [STRING], result: URL_T },
|
|
304
356
|
"sp.new": { argTypes: [], result: SEARCH_PARAMS_T },
|
|
357
|
+
"sp.newChecked": { argTypes: [DYN], result: SEARCH_PARAMS_T },
|
|
305
358
|
"sp.parse": { argTypes: [STRING], result: SEARCH_PARAMS_T },
|
|
306
359
|
"sp.copy": { argTypes: [SEARCH_PARAMS_T], result: SEARCH_PARAMS_T },
|
|
307
360
|
// The pairs argument is string[][] — checked structurally below (the
|
|
@@ -815,6 +868,8 @@ export const LIB_FN_SIGS = {
|
|
|
815
868
|
"child.disconnect": { argTypes: [CHILD_T], result: VOID },
|
|
816
869
|
"child.onMessage": { argTypes: [CHILD_T, null, BOOL], result: VOID },
|
|
817
870
|
"child.onDisconnect": { argTypes: [CHILD_T, null, BOOL], result: VOID },
|
|
871
|
+
"child.onSpawn": { argTypes: [CHILD_T, null], result: VOID },
|
|
872
|
+
"child.onDyn": { argTypes: [CHILD_T, STRING, DYN], result: VOID },
|
|
818
873
|
"process.connected": { argTypes: [], result: BOOL },
|
|
819
874
|
"process.send": { argTypes: [STRING], result: BOOL },
|
|
820
875
|
"process.sendCb": { argTypes: [STRING, null], result: BOOL },
|
|
@@ -829,6 +884,7 @@ export const LIB_FN_SIGS = {
|
|
|
829
884
|
argTypes: [STRING, arrayOf(STRING), F64, F64, F64, F64, F64, BOOL, BOOL, BOOL, arrayOf(STRING), STRING],
|
|
830
885
|
result: CHILD_T,
|
|
831
886
|
},
|
|
887
|
+
"cp.spawnDynamic": { argTypes: [STRING, arrayOf(STRING), DYN], result: CHILD_T },
|
|
832
888
|
// The callback's func type is program-dependent (zero params, or the
|
|
833
889
|
// `number | null` union / the %Error class) — the libCall case checks
|
|
834
890
|
// the shape; the slot here only pins arity and the child receiver.
|
|
@@ -880,6 +936,7 @@ export const LIB_FN_SIGS = {
|
|
|
880
936
|
"child.kill": { argTypes: [CHILD_T, STRING], result: BOOL },
|
|
881
937
|
"child.killNum": { argTypes: [CHILD_T, F64], result: BOOL },
|
|
882
938
|
"child.unref": { argTypes: [CHILD_T], result: VOID },
|
|
939
|
+
"child.ref": { argTypes: [CHILD_T], result: VOID },
|
|
883
940
|
"spawnRes.stdout": { argTypes: [SPAWNRES_T], result: STRING },
|
|
884
941
|
"spawnRes.stderr": { argTypes: [SPAWNRES_T], result: STRING },
|
|
885
942
|
"crypto.randomUUID": { argTypes: [], result: STRING },
|
|
@@ -887,6 +944,7 @@ export const LIB_FN_SIGS = {
|
|
|
887
944
|
"crypto.randomBytes": { argTypes: [F64], result: BYTES_U8 },
|
|
888
945
|
"crypto.hashDigestStr": { argTypes: [STRING, STRING, STRING], result: STRING },
|
|
889
946
|
"crypto.hashDigestBytes": { argTypes: [STRING, BYTES_U8, STRING], result: STRING },
|
|
947
|
+
"crypto.native": { argTypes: [], result: DYN },
|
|
890
948
|
"crypto.hashNew": { argTypes: [STRING], result: CRYPTOHASH_T },
|
|
891
949
|
"crypto.hmacNewStr": { argTypes: [STRING, STRING], result: CRYPTOHMAC_T },
|
|
892
950
|
"crypto.hmacNewBytes": { argTypes: [STRING, BYTES_U8], result: CRYPTOHMAC_T },
|
|
@@ -909,7 +967,10 @@ export const LIB_FN_SIGS = {
|
|
|
909
967
|
// The Buffer statics and the fs/zlib Buffer forms: fixed always-u8
|
|
910
968
|
// signatures (Buffer IS a Uint8Array — one bytes kind).
|
|
911
969
|
"buffer.fromStr": { argTypes: [STRING, STRING], result: BYTES_U8 },
|
|
970
|
+
"buffer.brand": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
971
|
+
"buffer.fromDyn": { argTypes: [DYN, STRING], result: BYTES_U8 },
|
|
912
972
|
"buffer.concat": { argTypes: [arrayOf(BYTES_U8)], result: BYTES_U8 },
|
|
973
|
+
"buffer.byteLenDyn": { argTypes: [DYN, STRING], result: F64 },
|
|
913
974
|
"buffer.byteLenStr": { argTypes: [STRING, STRING], result: F64 },
|
|
914
975
|
"buffer.isEncoding": { argTypes: [STRING], result: BOOL },
|
|
915
976
|
"buffer.concatLen": { argTypes: [arrayOf(BYTES_U8), F64], result: BYTES_U8 },
|
|
@@ -937,10 +998,12 @@ export const LIB_FN_SIGS = {
|
|
|
937
998
|
"emitter.setDefaultMaxChk": { argTypes: [DYN, STRING], result: VOID },
|
|
938
999
|
"fs.readFileSyncBytes": { argTypes: [STRING], result: BYTES_U8 },
|
|
939
1000
|
"fs.writeFileSyncBytes": { argTypes: [STRING, BYTES_U8], result: VOID },
|
|
1001
|
+
"fs.appendFileSyncBytes": { argTypes: [STRING, BYTES_U8], result: VOID },
|
|
940
1002
|
"fsp.readFileBytes": { argTypes: [STRING], result: { kind: "promise", inner: BYTES_U8 } },
|
|
941
1003
|
"zlib.deflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
942
1004
|
"zlib.inflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
943
1005
|
"zlib.deflateRawSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
1006
|
+
"zlib.deflateLevelSync": { argTypes: [BYTES_U8, F64, F64], result: BYTES_U8 },
|
|
944
1007
|
"zlib.inflateRawSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
945
1008
|
"zlib.gzipSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
946
1009
|
"zlib.gunzipSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
@@ -1006,30 +1069,63 @@ export const LIB_FN_SIGS = {
|
|
|
1006
1069
|
"process.cwd": { argTypes: [], result: STRING },
|
|
1007
1070
|
"process.pid": { argTypes: [], result: F64 },
|
|
1008
1071
|
"dyn.this": { argTypes: [], result: DYN },
|
|
1072
|
+
"dyn.generatorThis": { argTypes: [], result: DYN },
|
|
1009
1073
|
"process.getuid": { argTypes: [], result: F64 },
|
|
1010
1074
|
"process.getgid": { argTypes: [], result: F64 },
|
|
1011
1075
|
"process.execPath": { argTypes: [], result: STRING },
|
|
1012
1076
|
"process.arch": { argTypes: [], result: STRING },
|
|
1077
|
+
"process.versions": { argTypes: [], result: DYN },
|
|
1078
|
+
"process.builtinId": { argTypes: [DYN, arrayOf(STRING)], result: STRING },
|
|
1079
|
+
"process.builtinModule": { argTypes: [STRING, DYN], result: DYN },
|
|
1080
|
+
"process.builtinUnsupported": { argTypes: [STRING, STRING], result: DYN },
|
|
1081
|
+
"fs.callbackValue": { argTypes: [STRING], result: DYN },
|
|
1082
|
+
"fs.callbackCall": { argTypes: [STRING, DYN], result: DYN },
|
|
1083
|
+
"process.hrtimeValue": { argTypes: [], result: DYN },
|
|
1013
1084
|
"process.versionsNode": { argTypes: [], result: STRING },
|
|
1014
1085
|
"process.versionsOpenssl": { argTypes: [], result: STRING },
|
|
1015
1086
|
"process.kill": { argTypes: [F64, STRING], result: BOOL },
|
|
1016
1087
|
"process.killNum": { argTypes: [F64, F64], result: BOOL },
|
|
1017
1088
|
"process.stdoutWrite": { argTypes: [STRING], result: BOOL },
|
|
1089
|
+
"process.stdio": { argTypes: [F64], result: DYN },
|
|
1018
1090
|
"process.stderrWrite": { argTypes: [STRING], result: BOOL },
|
|
1019
1091
|
// error.new's result and the receiver slots are builtin-error classes —
|
|
1020
1092
|
// program-dependent object types, checked in the libCall case.
|
|
1021
1093
|
"error.new": { argTypes: [STRING], result: VOID },
|
|
1094
|
+
"error.newOptions": { argTypes: [DYN, DYN], result: VOID },
|
|
1095
|
+
"error.ctorOptions": { argTypes: [null, DYN, DYN], result: VOID },
|
|
1096
|
+
"error.cause": { argTypes: [null], result: DYN },
|
|
1097
|
+
"error.hasCause": { argTypes: [null], result: BOOL },
|
|
1098
|
+
"error.setCause": { argTypes: [null, DYN], result: VOID },
|
|
1099
|
+
"error.defineCause": { argTypes: [null, DYN], result: VOID },
|
|
1100
|
+
"error.deleteCause": { argTypes: [null], result: VOID },
|
|
1022
1101
|
"error.nodeThrow": { argTypes: [F64, STRING, STRING], result: VOID },
|
|
1023
1102
|
"dyn.toStringCoerce": { argTypes: [DYN], result: STRING },
|
|
1103
|
+
"dyn.stringConstructor": { argTypes: [DYN], result: STRING },
|
|
1104
|
+
"dyn.propertyKey": { argTypes: [DYN], result: DYN },
|
|
1105
|
+
"dyn.toNumeric": { argTypes: [DYN], result: DYN },
|
|
1106
|
+
"dyn.increment": { argTypes: [DYN, BOOL], result: DYN },
|
|
1107
|
+
"dyn.numberConstructor": { argTypes: [DYN], result: F64 },
|
|
1108
|
+
"dyn.bigintConstructor": { argTypes: [DYN], result: BIGINT_T },
|
|
1024
1109
|
"dyn.toNumberCoerce": { argTypes: [DYN], result: F64 },
|
|
1110
|
+
"dyn.add": { argTypes: [DYN, DYN], result: DYN },
|
|
1111
|
+
"dyn.arithmetic": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1112
|
+
"dyn.compare": { argTypes: [DYN, DYN, STRING], result: BOOL },
|
|
1113
|
+
"dyn.bitwise": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1114
|
+
"dyn.proxyNew": { argTypes: [DYN, DYN], result: DYN },
|
|
1025
1115
|
// Always throws; the result is the READ's declared type (a typed dummy
|
|
1026
1116
|
// the unwind abandons) — the libCall case skips the result check.
|
|
1027
1117
|
"global.undefRead": { argTypes: [STRING], result: VOID },
|
|
1118
|
+
"console.native": { argTypes: [], result: DYN },
|
|
1119
|
+
"global.native": { argTypes: [arrayOf(STRING)], result: DYN },
|
|
1028
1120
|
// `X.name` through a class value: the arg is a program-dependent
|
|
1029
1121
|
// classval (a null slot; the libCall case checks the kind).
|
|
1030
1122
|
"class.name": { argTypes: [null], result: STRING },
|
|
1031
1123
|
"error.ctor": { argTypes: [null, STRING], result: VOID },
|
|
1032
1124
|
"error.toString": { argTypes: [null], result: STRING },
|
|
1125
|
+
"dyn.sameValue": { argTypes: [DYN, DYN], result: BOOL },
|
|
1126
|
+
"error.stack": { argTypes: [null], result: STRING },
|
|
1127
|
+
"error.stackLimitGet": { argTypes: [], result: F64 },
|
|
1128
|
+
"error.stackLimitSet": { argTypes: [F64], result: VOID },
|
|
1033
1129
|
// Receiver (any error-hierarchy object) and the program-dependent
|
|
1034
1130
|
// `string | undefined` result are checked in the libCall case.
|
|
1035
1131
|
"error.code": { argTypes: [null], result: VOID },
|
|
@@ -1044,20 +1140,77 @@ export const LIB_FN_SIGS = {
|
|
|
1044
1140
|
"error.domCause": { argTypes: [null], result: DYN },
|
|
1045
1141
|
"error.domClone": { argTypes: [null, DYN], result: VOID },
|
|
1046
1142
|
"dyn.errInstanceof": { argTypes: [DYN, F64], result: BOOL },
|
|
1143
|
+
"weakMap.is": { argTypes: [DYN], result: BOOL },
|
|
1144
|
+
"weakSet.is": { argTypes: [DYN], result: BOOL },
|
|
1145
|
+
"weakMap.new": { argTypes: [DYN], result: DYN },
|
|
1146
|
+
"weakSet.new": { argTypes: [DYN], result: DYN },
|
|
1147
|
+
"dyn.fromEntries": { argTypes: [DYN], result: DYN },
|
|
1148
|
+
"bytes.constructor": { argTypes: [STRING], result: DYN },
|
|
1149
|
+
"bytes.instanceOf": { argTypes: [DYN, DYN], result: BOOL },
|
|
1150
|
+
"bytes.construct": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1151
|
+
"dyn.dataViewIs": { argTypes: [DYN], result: BOOL },
|
|
1152
|
+
"dyn.construct": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1153
|
+
"arrayBuffer.constructor": { argTypes: [], result: DYN },
|
|
1154
|
+
"arrayBuffer.new": { argTypes: [DYN], result: DYN },
|
|
1155
|
+
"ffi.argument": { argTypes: [DYN, STRING], result: DYN },
|
|
1156
|
+
"ffi.memoryModule": { argTypes: [DYN], result: DYN },
|
|
1157
|
+
"intl.segmenterNew": { argTypes: [], result: DYN },
|
|
1158
|
+
"arrayBuffer.is": { argTypes: [DYN], result: BOOL },
|
|
1159
|
+
"arrayBuffer.isView": { argTypes: [DYN], result: BOOL },
|
|
1160
|
+
"arrayBuffer.byteLengthGetter": { argTypes: [], result: F64 },
|
|
1161
|
+
"arrayBuffer.byteLengthDescriptor": { argTypes: [DYN], result: DYN },
|
|
1162
|
+
"arrayBuffer.viewU8C": { argTypes: [DYN, DYN, DYN], result: bytesOf("u8c") },
|
|
1163
|
+
"arrayBuffer.viewI8": { argTypes: [DYN, DYN, DYN], result: bytesOf("i8") },
|
|
1164
|
+
"arrayBuffer.viewU16": { argTypes: [DYN, DYN, DYN], result: bytesOf("u16") },
|
|
1165
|
+
"arrayBuffer.viewI16": { argTypes: [DYN, DYN, DYN], result: bytesOf("i16") },
|
|
1166
|
+
"arrayBuffer.viewU8": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
|
1167
|
+
"arrayBuffer.viewU32": { argTypes: [DYN, DYN, DYN], result: bytesOf("u32") },
|
|
1168
|
+
"arrayBuffer.viewI32": { argTypes: [DYN, DYN, DYN], result: bytesOf("i32") },
|
|
1169
|
+
"arrayBuffer.viewF32": { argTypes: [DYN, DYN, DYN], result: bytesOf("f32") },
|
|
1170
|
+
"arrayBuffer.viewF64": { argTypes: [DYN, DYN, DYN], result: bytesOf("f64") },
|
|
1171
|
+
"arrayBuffer.viewDV": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
|
1047
1172
|
"dyn.objKeys": { argTypes: [DYN], result: DYN },
|
|
1173
|
+
"dyn.forInKeys": { argTypes: [DYN], result: DYN },
|
|
1048
1174
|
"dyn.hasOwn": { argTypes: [DYN, STRING], result: BOOL },
|
|
1175
|
+
"dyn.propertyIsEnumerable": { argTypes: [DYN, STRING], result: BOOL },
|
|
1049
1176
|
"dyn.assign": { argTypes: [DYN, DYN], result: DYN },
|
|
1177
|
+
"dyn.copyDataProperties": { argTypes: [DYN, DYN], result: DYN },
|
|
1178
|
+
"dyn.objectRest": { argTypes: [DYN, DYN], result: DYN },
|
|
1050
1179
|
"dyn.packPush": { argTypes: [DYN, DYN], result: VOID },
|
|
1051
1180
|
"dyn.packPushSpread": { argTypes: [DYN, DYN, STRING], result: VOID },
|
|
1052
1181
|
"dyn.packPushSpreadIter": { argTypes: [DYN, DYN], result: VOID },
|
|
1182
|
+
"dyn.reflectApply": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
1053
1183
|
"dyn.assignAll": { argTypes: [DYN, DYN], result: DYN },
|
|
1054
1184
|
"dyn.objCreateNullProto": { argTypes: [], result: DYN },
|
|
1185
|
+
"dyn.arrayPrototype": { argTypes: [], result: DYN },
|
|
1186
|
+
"dyn.objectPrototype": { argTypes: [], result: DYN },
|
|
1187
|
+
"dyn.functionApply": { argTypes: [], result: DYN },
|
|
1188
|
+
"dyn.builtinMethod": { argTypes: [STRING, STRING], result: DYN },
|
|
1189
|
+
"dyn.classPrototype": { argTypes: [DYN, DYN], result: DYN },
|
|
1190
|
+
"dyn.classBasePrototype": { argTypes: [DYN], result: DYN },
|
|
1191
|
+
"dyn.classInherit": { argTypes: [DYN, DYN], result: DYN },
|
|
1192
|
+
"dyn.classSuper": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
1193
|
+
"dyn.assignPrototype": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
1194
|
+
"dyn.objCreate": { argTypes: [DYN], result: DYN },
|
|
1195
|
+
"dyn.objCreateWithProperties": { argTypes: [DYN, DYN], result: DYN },
|
|
1196
|
+
"dyn.getPrototype": { argTypes: [DYN], result: DYN },
|
|
1197
|
+
"dyn.setPrototype": { argTypes: [DYN, DYN], result: DYN },
|
|
1198
|
+
"dyn.getOwnPropertyNames": { argTypes: [DYN], result: DYN },
|
|
1199
|
+
"dyn.ownKeys": { argTypes: [DYN], result: DYN },
|
|
1200
|
+
"dyn.getOwnPropertySymbols": { argTypes: [DYN], result: DYN },
|
|
1201
|
+
"dyn.getOwnPropertyDescriptors": { argTypes: [DYN], result: DYN },
|
|
1202
|
+
"dyn.preventExtensions": { argTypes: [DYN], result: DYN },
|
|
1203
|
+
"dyn.isExtensible": { argTypes: [DYN], result: BOOL },
|
|
1204
|
+
"dyn.seal": { argTypes: [DYN], result: DYN },
|
|
1205
|
+
"dyn.isSealed": { argTypes: [DYN], result: BOOL },
|
|
1055
1206
|
"dyn.objValues": { argTypes: [DYN], result: DYN },
|
|
1056
1207
|
"dyn.objEntries": { argTypes: [DYN], result: DYN },
|
|
1057
1208
|
"dyn.structuredClone": { argTypes: [DYN, DYN], result: DYN },
|
|
1058
1209
|
"dyn.cloneMissing": { argTypes: [], result: DYN },
|
|
1059
1210
|
"dyn.cloneTransferFail": { argTypes: [], result: DYN },
|
|
1060
1211
|
"regex.new": { argTypes: [STRING, STRING], result: REGEX },
|
|
1212
|
+
"regex.resetLastIndex": { argTypes: [REGEX, F64], result: VOID },
|
|
1213
|
+
"regex.newChecked": { argTypes: [DYN, DYN], result: REGEX },
|
|
1061
1214
|
// node:events EventEmitter: receivers are emitter-hierarchy objects and
|
|
1062
1215
|
// the chaining forms (on/off/removeAll/setMax) return the receiver's
|
|
1063
1216
|
// own class — program-dependent object types, checked in the libCall
|
|
@@ -1082,6 +1235,7 @@ export const LIB_FN_SIGS = {
|
|
|
1082
1235
|
"emitter.emitError": { argTypes: [null, STRING, null], result: BOOL },
|
|
1083
1236
|
"emitter.count": { argTypes: [null, STRING], result: F64 },
|
|
1084
1237
|
"emitter.countFn": { argTypes: [null, STRING, null], result: F64 },
|
|
1238
|
+
"emitter.countDyn": { argTypes: [null, STRING, DYN], result: F64 },
|
|
1085
1239
|
"emitter.names": { argTypes: [null], result: VOID },
|
|
1086
1240
|
"emitter.listeners": { argTypes: [null, STRING], result: VOID },
|
|
1087
1241
|
"emitter.onData": { argTypes: [null, STRING, null, BOOL, BOOL], result: VOID },
|
|
@@ -1143,6 +1297,8 @@ export const LIB_FN_SIGS = {
|
|
|
1143
1297
|
"readable.pushDyn": { argTypes: [null, DYN], result: BOOL },
|
|
1144
1298
|
"readable.unshift": { argTypes: [null, BYTES_U8], result: VOID },
|
|
1145
1299
|
"readable.unshiftStr": { argTypes: [null, STRING], result: VOID },
|
|
1300
|
+
"stream.onDyn": { argTypes: [null, STRING, DYN, BOOL, BOOL], result: VOID },
|
|
1301
|
+
"readable.readDyn": { argTypes: [null, DYN], result: DYN },
|
|
1146
1302
|
"readable.read": { argTypes: [null, F64], result: VOID },
|
|
1147
1303
|
"readable.pause": { argTypes: [null], result: VOID },
|
|
1148
1304
|
"readable.setEncoding": { argTypes: [null, STRING], result: VOID },
|
|
@@ -1269,6 +1425,8 @@ export const LIB_FN_SIGS = {
|
|
|
1269
1425
|
"dc.tcTraceSync": { argTypes: [F64, DYN, DYN, DYN, DYN], result: DYN },
|
|
1270
1426
|
"dc.tcTraceCallback": { argTypes: [F64, DYN, F64, DYN, DYN, DYN], result: DYN },
|
|
1271
1427
|
"dc.tcTracePromise": { argTypes: [F64, DYN, DYN, DYN, DYN], result: { kind: "promise", inner: DYN } },
|
|
1428
|
+
"process.onUncaughtException": { argTypes: [DYN, BOOL, BOOL], result: VOID },
|
|
1429
|
+
"process.offUncaughtException": { argTypes: [DYN, BOOL], result: VOID },
|
|
1272
1430
|
"process.onUnhandledRejection": { argTypes: [DYN, BOOL], result: VOID },
|
|
1273
1431
|
"process.offUnhandledRejection": { argTypes: [DYN], result: VOID },
|
|
1274
1432
|
"process.onRejectionHandled": { argTypes: [DYN, BOOL], result: VOID },
|
|
@@ -1320,7 +1478,13 @@ export const LIB_FN_SIGS = {
|
|
|
1320
1478
|
"date.parseGetTime": { argTypes: [STRING], result: F64 },
|
|
1321
1479
|
"date.utc": { argTypes: [F64, F64, F64, F64, F64, F64, F64], result: F64 },
|
|
1322
1480
|
"text.decode": { argTypes: [BYTES_U8], result: STRING },
|
|
1481
|
+
"bytes.bufferSource": { argTypes: [DYN], result: BYTES_U8 },
|
|
1482
|
+
"text.decodeBufferSource": { argTypes: [DYN], result: STRING },
|
|
1483
|
+
"text.decodeOptions": { argTypes: [BYTES_U8, BOOL, BOOL], result: STRING },
|
|
1484
|
+
"text.decodeStream": { argTypes: [DYN, BYTES_U8, F64, BOOL, BOOL, BOOL], result: STRING },
|
|
1485
|
+
"text.decodeLegacyOptions": { argTypes: [BYTES_U8, F64, BOOL, BOOL], result: STRING },
|
|
1323
1486
|
"text.decodeLegacy": { argTypes: [BYTES_U8, F64], result: STRING },
|
|
1487
|
+
"text.decoderEncoding": { argTypes: [DYN], result: F64 },
|
|
1324
1488
|
"fs.mkdirRecursiveSync": { argTypes: [STRING], result: VOID },
|
|
1325
1489
|
"fs.rmOptsSync": { argTypes: [STRING, BOOL, BOOL], result: VOID },
|
|
1326
1490
|
"fs.rmRetrySync": { argTypes: [STRING, BOOL, BOOL, F64, F64], result: VOID },
|
|
@@ -1338,6 +1502,7 @@ export const LIB_FN_SIGS = {
|
|
|
1338
1502
|
// Arg 0 is a packed f64[] OR a bytes value (the spread-typed-array
|
|
1339
1503
|
// form) — checked in the libCall case.
|
|
1340
1504
|
"string.fromCharCode": { argTypes: [null], result: STRING },
|
|
1505
|
+
"string.fromCodePoint": { argTypes: [null], result: STRING },
|
|
1341
1506
|
"string.lastIndexOf": { argTypes: [STRING, STRING], result: F64 },
|
|
1342
1507
|
"string.lastIndexOfFrom": { argTypes: [STRING, STRING, F64], result: F64 },
|
|
1343
1508
|
"string.raw": { argTypes: [arrayOf(STRING), arrayOf(STRING)], result: STRING },
|
|
@@ -1386,6 +1551,30 @@ export function validateModule(mod) {
|
|
|
1386
1551
|
}
|
|
1387
1552
|
const retainedFfiCallbacks = new Map();
|
|
1388
1553
|
for (const entry of mod.ffiImports ?? []) {
|
|
1554
|
+
if (entry.callbackOperation !== undefined) {
|
|
1555
|
+
const fail = (detail) => { errors.push({ message: `FFI callback operation "${entry.name}" ${detail}`, loc: moduleLoc }); };
|
|
1556
|
+
if (!entry.library || entry.library.includes("\0"))
|
|
1557
|
+
fail("requires a library name");
|
|
1558
|
+
if (entry.callbackOperation === "register") {
|
|
1559
|
+
const param = entry.params[0];
|
|
1560
|
+
if (entry.params.length !== 1 || !param || !isFfiCallbackParam(param) ||
|
|
1561
|
+
param.callback.id !== "callback" || param.callback.lifetime !== "retained" || param.callback.invoke !== "script-thread" ||
|
|
1562
|
+
param.callback.params.some(p => typeof p !== "string" || ["cstring", "string", "bytes"].includes(p)) ||
|
|
1563
|
+
entry.returns !== "pointer" || entry.callbackTarget !== undefined)
|
|
1564
|
+
fail("has an invalid registration ABI");
|
|
1565
|
+
}
|
|
1566
|
+
else if (entry.callbackOperation === "release") {
|
|
1567
|
+
const target = entry.callbackTarget ? ffiByName.get(entry.callbackTarget) : undefined;
|
|
1568
|
+
if (entry.params.length !== 0 || entry.returns !== "void" || target?.callbackOperation !== "register" ||
|
|
1569
|
+
target.library !== entry.library)
|
|
1570
|
+
fail("has an invalid release target or ABI");
|
|
1571
|
+
}
|
|
1572
|
+
else
|
|
1573
|
+
fail("has an invalid operation");
|
|
1574
|
+
}
|
|
1575
|
+
else if (entry.callbackTarget !== undefined) {
|
|
1576
|
+
errors.push({ message: `FFI binding "${entry.name}" has a callback target without a release operation`, loc: moduleLoc });
|
|
1577
|
+
}
|
|
1389
1578
|
const ids = new Set();
|
|
1390
1579
|
for (const param of entry.params) {
|
|
1391
1580
|
if (!isFfiCallbackParam(param))
|
|
@@ -1398,6 +1587,9 @@ export function validateModule(mod) {
|
|
|
1398
1587
|
errors.push({ message: `FFI callback "${entry.name}:${param.callback.id}" has invalid invoke mode`, loc: moduleLoc });
|
|
1399
1588
|
}
|
|
1400
1589
|
if (param.callback.invoke === "foreign") {
|
|
1590
|
+
if (param.callback.params.some((p) => p === "i64" || p === "u64" || p === "pointer")) {
|
|
1591
|
+
errors.push({ message: `FFI foreign callback "${entry.name}:${param.callback.id}" has unsupported 64-bit or pointer arguments`, loc: moduleLoc });
|
|
1592
|
+
}
|
|
1401
1593
|
if (param.callback.lifetime !== "retained") {
|
|
1402
1594
|
errors.push({ message: `FFI foreign callback "${entry.name}:${param.callback.id}" is not retained`, loc: moduleLoc });
|
|
1403
1595
|
}
|
|
@@ -1535,6 +1727,50 @@ export function validateModule(mod) {
|
|
|
1535
1727
|
errors.push({ message: `duplicate class "${cls.name}"`, loc: cls.loc });
|
|
1536
1728
|
}
|
|
1537
1729
|
classesByName.set(cls.name, cls);
|
|
1730
|
+
if (cls.localCaptures !== undefined && (cls.runtime || cls.genericOf !== undefined)) {
|
|
1731
|
+
errors.push({ message: `class ${cls.name}: local class cannot use a runtime or generic family layout`, loc: cls.loc });
|
|
1732
|
+
}
|
|
1733
|
+
if (cls.localCaptures !== undefined) {
|
|
1734
|
+
const environment = cls.fields.find((field) => field.name === `%classEnvironment:${cls.name}`);
|
|
1735
|
+
if (environment?.type.kind !== "classval" || environment.type.className !== cls.name) {
|
|
1736
|
+
errors.push({ message: `class ${cls.name}: local class requires its constructor environment field`, loc: cls.loc });
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
if (cls.localBaseCapture !== undefined) {
|
|
1740
|
+
const base = cls.localCaptures?.[cls.localBaseCapture];
|
|
1741
|
+
if (!Number.isInteger(cls.localBaseCapture) || base?.type.kind !== "classval" || base.type.className !== cls.base) {
|
|
1742
|
+
errors.push({ message: `class ${cls.name}: invalid local base capture`, loc: cls.loc });
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
if (cls.baseValueGlobal !== undefined) {
|
|
1746
|
+
const global = mod.globals?.find((global) => global.id === cls.baseValueGlobal);
|
|
1747
|
+
if (cls.localBaseCapture !== undefined || !cls.base || global?.type.kind !== "classval" || global.type.className !== cls.base) {
|
|
1748
|
+
errors.push({ message: `class ${cls.name}: invalid computed base global`, loc: cls.loc });
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
if (cls.jsLength !== undefined && (!Number.isSafeInteger(cls.jsLength) || cls.jsLength < 0)) {
|
|
1752
|
+
errors.push({ message: `class ${cls.name}: invalid constructor length`, loc: cls.loc });
|
|
1753
|
+
}
|
|
1754
|
+
if (cls.prototypeDataHelper !== undefined) {
|
|
1755
|
+
const helper = functionsByName.get(cls.prototypeDataHelper);
|
|
1756
|
+
if (!helper || helper.params.length !== 0 || helper.returnType.kind !== "dyn" || helper.captures !== undefined || helper.classCaptures !== undefined) {
|
|
1757
|
+
errors.push({ message: `class ${cls.name}: prototype data helper must be a noncapturing () => dyn function`, loc: cls.loc });
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (cls.instancePrototypeHelper !== undefined) {
|
|
1761
|
+
const helper = functionsByName.get(cls.instancePrototypeHelper);
|
|
1762
|
+
const receiver = helper?.params[0]?.type;
|
|
1763
|
+
if (!helper || helper.params.length !== 1 || receiver?.kind !== "object" || receiver.className !== cls.name ||
|
|
1764
|
+
helper.returnType.kind !== "dyn" || helper.captures !== undefined || helper.classCaptures !== undefined) {
|
|
1765
|
+
errors.push({ message: `class ${cls.name}: instance prototype helper must be a noncapturing (instance) => dyn function`, loc: cls.loc });
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
for (const symbol of cls.symbolFields ?? []) {
|
|
1769
|
+
const global = mod.globals?.find((global) => global.id === symbol.globalId);
|
|
1770
|
+
if (global?.type.kind !== "symbol" || !cls.fields.some((field) => field.name === symbol.field)) {
|
|
1771
|
+
errors.push({ message: `class ${cls.name}: invalid symbol field metadata`, loc: cls.loc });
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1538
1774
|
const seen = new Set();
|
|
1539
1775
|
for (const f of cls.fields) {
|
|
1540
1776
|
if (seen.has(f.name)) {
|
|
@@ -1577,6 +1813,9 @@ export function validateModule(mod) {
|
|
|
1577
1813
|
errors.push({ message: `class ${cls.name}: undeclared base "${cls.base}"`, loc: cls.loc });
|
|
1578
1814
|
continue;
|
|
1579
1815
|
}
|
|
1816
|
+
if (base.localCaptures !== undefined && cls.localBaseCapture === undefined && cls.baseValueGlobal === undefined) {
|
|
1817
|
+
errors.push({ message: `class ${cls.name}: local base requires a captured constructor`, loc: cls.loc });
|
|
1818
|
+
}
|
|
1580
1819
|
const seen = new Set([cls.name]);
|
|
1581
1820
|
for (let c = base; c; c = c.base !== undefined ? classesByName.get(c.base) : undefined) {
|
|
1582
1821
|
if (seen.has(c.name)) {
|
|
@@ -1651,9 +1890,16 @@ export function validateModule(mod) {
|
|
|
1651
1890
|
// field count) — anything else has no honest index/JSON story.
|
|
1652
1891
|
if (rec.tuple) {
|
|
1653
1892
|
const names = new Set(rec.fields.map((f) => f.name));
|
|
1893
|
+
let positionsComplete = true;
|
|
1894
|
+
for (let i = 0; i < rec.fields.length; i++) {
|
|
1895
|
+
if (!names.has(String(i))) {
|
|
1896
|
+
positionsComplete = false;
|
|
1897
|
+
break;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1654
1900
|
if (rec.fields.length === 0 ||
|
|
1655
1901
|
names.size !== rec.fields.length ||
|
|
1656
|
-
|
|
1902
|
+
!positionsComplete) {
|
|
1657
1903
|
errors.push({ message: `record ${rec.id}: tuple fields are not "0".."${rec.fields.length - 1}"`, loc: noLoc });
|
|
1658
1904
|
}
|
|
1659
1905
|
if (rec.indexValue) {
|
|
@@ -1675,31 +1921,64 @@ export function validateModule(mod) {
|
|
|
1675
1921
|
errors.push({ message: `duplicate union "${u.id}"`, loc: noLoc });
|
|
1676
1922
|
}
|
|
1677
1923
|
unionsById.set(u.id, u);
|
|
1924
|
+
}
|
|
1925
|
+
for (const u of mod.unions ?? []) {
|
|
1678
1926
|
if (u.arms.length < 2) {
|
|
1679
1927
|
errors.push({ message: `union ${u.id}: fewer than 2 arms`, loc: noLoc });
|
|
1680
1928
|
}
|
|
1929
|
+
if (u.discriminant) {
|
|
1930
|
+
const { field, cases } = u.discriminant;
|
|
1931
|
+
const tags = new Set();
|
|
1932
|
+
const values = new Set();
|
|
1933
|
+
for (const candidate of cases) {
|
|
1934
|
+
const arm = u.arms[candidate.tag];
|
|
1935
|
+
const record = arm?.kind === "record" ? recordsById.get(arm.shapeId) : undefined;
|
|
1936
|
+
const member = record?.fields.find((entry) => entry.name === field);
|
|
1937
|
+
if (!Number.isInteger(candidate.tag) || candidate.tag < 0 || !member || tags.has(candidate.tag)) {
|
|
1938
|
+
errors.push({ message: `union ${u.id}: invalid discriminant tag ${candidate.tag}`, loc: noLoc });
|
|
1939
|
+
}
|
|
1940
|
+
tags.add(candidate.tag);
|
|
1941
|
+
if (candidate.values.length === 0) {
|
|
1942
|
+
errors.push({ message: `union ${u.id}: empty discriminant values for tag ${candidate.tag}`, loc: noLoc });
|
|
1943
|
+
}
|
|
1944
|
+
for (const value of candidate.values) {
|
|
1945
|
+
if (value === undefined) {
|
|
1946
|
+
errors.push({ message: `union ${u.id}: undefined discriminant value`, loc: noLoc });
|
|
1947
|
+
continue;
|
|
1948
|
+
}
|
|
1949
|
+
const fieldTypes = member?.type.kind === "union"
|
|
1950
|
+
? unionsById.get(member.type.unionId)?.arms ?? [] : member ? [member.type] : [];
|
|
1951
|
+
const valid = fieldTypes.some((type) => typeof value === "string" ? type.kind === "string"
|
|
1952
|
+
: typeof value === "boolean" ? type.kind === "bool"
|
|
1953
|
+
: typeof value === "number" && Number.isFinite(value) && type.kind === "f64");
|
|
1954
|
+
const key = typeof value + ":" + String(value);
|
|
1955
|
+
if (!valid || values.has(key)) {
|
|
1956
|
+
errors.push({ message: `union ${u.id}: invalid or repeated discriminant value ${key}`, loc: noLoc });
|
|
1957
|
+
}
|
|
1958
|
+
values.add(key);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
for (let tag = 0; tag < u.arms.length; tag++) {
|
|
1962
|
+
if (u.arms[tag].kind === "record" && !tags.has(tag)) {
|
|
1963
|
+
errors.push({ message: `union ${u.id}: missing discriminant for record arm ${tag}`, loc: noLoc });
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1681
1967
|
u.arms.forEach((arm, i) => {
|
|
1682
1968
|
// The unit kinds (undefinedT/nullT) are valid arms — union membership
|
|
1683
|
-
// is the ONLY place they may appear
|
|
1684
|
-
//
|
|
1685
|
-
//
|
|
1686
|
-
// sibling rules live in unionFuncSetArmsOk (shared with the frontend's
|
|
1687
|
-
// union builders): a func arm allows unit and FUNC siblings (the
|
|
1688
|
-
// nullable-callback shape, and the primitive-constructor tables where
|
|
1689
|
-
// closure pointer identity per tag is the narrowing); a set arm is
|
|
1690
|
-
// valid exactly when every other arm is a unit (the defaulted-Set-
|
|
1691
|
-
// param ABI); func/set-beside-data stays out.
|
|
1969
|
+
// is the ONLY place they may appear. Containers are valid beside
|
|
1970
|
+
// unit arms: tag tests distinguish absence while the reference
|
|
1971
|
+
// payload preserves identity. The shared rule refuses data siblings.
|
|
1692
1972
|
if (arm.kind === "void" ||
|
|
1693
1973
|
arm.kind === "union" ||
|
|
1694
|
-
arm.kind === "map" ||
|
|
1695
1974
|
arm.kind === "dyn" ||
|
|
1696
1975
|
arm.kind === "jsval" ||
|
|
1697
1976
|
arm.kind === "date" ||
|
|
1698
1977
|
arm.kind === "generator") {
|
|
1699
1978
|
errors.push({ message: `union ${u.id}: arm ${i} is ${arm.kind}`, loc: noLoc });
|
|
1700
1979
|
}
|
|
1701
|
-
if ((arm.kind === "
|
|
1702
|
-
!
|
|
1980
|
+
if ((arm.kind === "map" || arm.kind === "set" || arm.kind === "promise") &&
|
|
1981
|
+
!unionContainerArmsOk(u.arms)) {
|
|
1703
1982
|
errors.push({ message: `union ${u.id}: ${arm.kind} arm ${i} beside non-unit arms`, loc: noLoc });
|
|
1704
1983
|
}
|
|
1705
1984
|
if (arm.kind === "record" && !recordsById.has(arm.shapeId)) {
|
|
@@ -1791,6 +2070,9 @@ export function validateModule(mod) {
|
|
|
1791
2070
|
}
|
|
1792
2071
|
};
|
|
1793
2072
|
for (const g of mod.globals ?? []) {
|
|
2073
|
+
if (g.tdz && g.type.kind !== "record" && g.type.kind !== "func" && g.type.kind !== "dyn") {
|
|
2074
|
+
errors.push({ message: `TDZ global "${g.name}" must have record, function, or checked-value storage`, loc: noLoc });
|
|
2075
|
+
}
|
|
1794
2076
|
if (isUnitType(g.type)) {
|
|
1795
2077
|
errors.push({ message: `global "${g.name}" has bare unit type ${g.type.kind}`, loc: noLoc });
|
|
1796
2078
|
}
|
|
@@ -1890,15 +2172,16 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1890
2172
|
// Unit kinds live only inside unions: a bare-unit local, param, or
|
|
1891
2173
|
// return type is frontend breakage (mapType never produces them).
|
|
1892
2174
|
for (const l of fn.locals) {
|
|
2175
|
+
if (l.tdz && !l.boxed)
|
|
2176
|
+
err(`TDZ local "${l.name}" must be boxed`, fn.loc);
|
|
1893
2177
|
if (isUnitType(l.type))
|
|
1894
2178
|
err(`local "${l.name}" has bare unit type ${l.type.kind}`, fn.loc);
|
|
1895
2179
|
}
|
|
1896
2180
|
if (isUnitType(fn.returnType)) {
|
|
1897
2181
|
err(`return type is bare unit type ${fn.returnType.kind}`, fn.loc);
|
|
1898
2182
|
}
|
|
1899
|
-
//
|
|
1900
|
-
//
|
|
1901
|
-
// escape; a caught anywhere else is frontend breakage).
|
|
2183
|
+
// Exception snapshots may be captured, but are never public parameters
|
|
2184
|
+
// or return values. Their payload crosses those boundaries explicitly.
|
|
1902
2185
|
if (fn.returnType.kind === "caught")
|
|
1903
2186
|
err("return type is caught", fn.loc);
|
|
1904
2187
|
for (const p of fn.params) {
|
|
@@ -1908,14 +2191,27 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1908
2191
|
if (p.type.kind === "caught")
|
|
1909
2192
|
err(`param "${p.name}" is caught-typed`, fn.loc);
|
|
1910
2193
|
}
|
|
1911
|
-
for (const c of fn.captures ?? []) {
|
|
2194
|
+
for (const c of [...(fn.captures ?? []), ...(fn.classCaptures ?? [])]) {
|
|
1912
2195
|
const local = locals.get(c.localId);
|
|
1913
2196
|
if (!local)
|
|
1914
2197
|
err(`capture "${c.name}" has no local entry "${c.localId}"`, fn.loc);
|
|
1915
2198
|
else if (!local.boxed)
|
|
1916
2199
|
err(`capture local "${c.localId}" is not boxed`, fn.loc);
|
|
1917
|
-
if (c.type
|
|
1918
|
-
err(`capture "${c.
|
|
2200
|
+
else if (!typeEquals(local.type, c.type))
|
|
2201
|
+
err(`capture local "${c.localId}" has the wrong type`, fn.loc);
|
|
2202
|
+
}
|
|
2203
|
+
if (fn.classCaptures !== undefined) {
|
|
2204
|
+
const self = fn.params[0];
|
|
2205
|
+
const cls = self?.type.kind === "object" ? classes.get(self.type.className) : undefined;
|
|
2206
|
+
if (fn.captures !== undefined || cls?.localCaptures === undefined) {
|
|
2207
|
+
err("class captures require a local-class instance receiver and no closure environment", fn.loc);
|
|
2208
|
+
}
|
|
2209
|
+
for (const capture of fn.classCaptures) {
|
|
2210
|
+
const slot = cls?.localCaptures?.[capture.slot];
|
|
2211
|
+
if (!Number.isInteger(capture.slot) || !slot || !typeEquals(slot.type, capture.type)) {
|
|
2212
|
+
err(`class capture "${capture.name}" has an invalid slot or type`, fn.loc);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
1919
2215
|
}
|
|
1920
2216
|
const expectType = (expr, want, what) => {
|
|
1921
2217
|
if (!typeEquals(expr.type, want)) {
|
|
@@ -1957,12 +2253,218 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1957
2253
|
seen.add(type.unionId);
|
|
1958
2254
|
return unions.get(type.unionId)?.arms.some((arm) => liveDynRefEligible(arm, seen)) ?? false;
|
|
1959
2255
|
};
|
|
2256
|
+
function checkNullishOperands(e) {
|
|
2257
|
+
expectType(e.right, e.type, "nullish right operand");
|
|
2258
|
+
// The ISLAND form: `a ?? b` over an engine value — left, right,
|
|
2259
|
+
// and result are all handles (the emitters' jsval nullish arm).
|
|
2260
|
+
if (e.left.type.kind === "jsval") {
|
|
2261
|
+
if (e.type.kind !== "jsval")
|
|
2262
|
+
err("jsval nullish must answer jsval", e.loc);
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
// The CHECKED-DYNAMIC form: the runtime kind decides (the
|
|
2266
|
+
// emitters' scr_dyn_is_nullish arm) — left, right, and result
|
|
2267
|
+
// all live in the checked-dynamic tree.
|
|
2268
|
+
if (e.left.type.kind === "dyn") {
|
|
2269
|
+
if (e.type.kind !== "dyn")
|
|
2270
|
+
err("dyn nullish must answer dyn", e.loc);
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
if (e.left.type.kind !== "union") {
|
|
2274
|
+
err(`nullish left must be a union, got ${e.left.type.kind}`, e.loc);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
const def = unions.get(e.left.type.unionId);
|
|
2278
|
+
if (!def) {
|
|
2279
|
+
err(`nullish left references unknown union ${e.left.type.unionId}`, e.loc);
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
if (!def.arms.some(isUnitType)) {
|
|
2283
|
+
err("nullish left union has no unit arm (frontend must fence)", e.loc);
|
|
2284
|
+
}
|
|
2285
|
+
// Two shapes: pass-through (type === left's union) or narrowed
|
|
2286
|
+
// (type === the union's SINGLE non-unit arm).
|
|
2287
|
+
if (!typeEquals(e.type, e.left.type)) {
|
|
2288
|
+
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2289
|
+
if (rest.length !== 1 || !typeEquals(e.type, rest[0])) {
|
|
2290
|
+
err("nullish type must be the left union or its single non-unit arm", e.loc);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
function checkBranchingTree(root) {
|
|
2295
|
+
// Predicates and conditional dispatch can nest in either direction.
|
|
2296
|
+
// Preserve child-before-parent diagnostics with bounded native stack
|
|
2297
|
+
// use, including trees that mix the three branching operators.
|
|
2298
|
+
const pending = [{ expr: root, visited: false }];
|
|
2299
|
+
while (pending.length !== 0) {
|
|
2300
|
+
const task = pending.pop();
|
|
2301
|
+
const e = task.expr;
|
|
2302
|
+
if (!task.visited) {
|
|
2303
|
+
if (e.kind === "logical" || e.kind === "nullish") {
|
|
2304
|
+
pending.push({ expr: e, visited: true });
|
|
2305
|
+
pending.push({ expr: e.right, visited: false });
|
|
2306
|
+
pending.push({ expr: e.left, visited: false });
|
|
2307
|
+
}
|
|
2308
|
+
else if (e.kind === "ternary") {
|
|
2309
|
+
pending.push({ expr: e, visited: true });
|
|
2310
|
+
pending.push({ expr: e.else_, visited: false });
|
|
2311
|
+
pending.push({ expr: e.then, visited: false });
|
|
2312
|
+
pending.push({ expr: e.cond, visited: false });
|
|
2313
|
+
}
|
|
2314
|
+
else {
|
|
2315
|
+
checkExpr(e);
|
|
2316
|
+
}
|
|
2317
|
+
continue;
|
|
2318
|
+
}
|
|
2319
|
+
if (e.kind === "logical") {
|
|
2320
|
+
if (e.type.kind !== "f64" && e.type.kind !== "string" && e.type.kind !== "bool" &&
|
|
2321
|
+
e.type.kind !== "jsval" && e.type.kind !== "union" && e.type.kind !== "dyn") {
|
|
2322
|
+
err(`logical ${e.op} must be f64|string|bool|jsval|union|dyn, got ${e.type.kind}`, e.loc);
|
|
2323
|
+
}
|
|
2324
|
+
if (e.type.kind === "union")
|
|
2325
|
+
checkTruthyUnion(e.type.unionId, e.loc);
|
|
2326
|
+
expectType(e.left, e.type, `logical ${e.op} left`);
|
|
2327
|
+
expectType(e.right, e.type, `logical ${e.op} right`);
|
|
2328
|
+
}
|
|
2329
|
+
else if (e.kind === "nullish") {
|
|
2330
|
+
checkNullishOperands(e);
|
|
2331
|
+
}
|
|
2332
|
+
else if (e.kind === "ternary") {
|
|
2333
|
+
expectType(e.cond, BOOL, "ternary condition");
|
|
2334
|
+
expectType(e.then, e.type, "ternary then-branch");
|
|
2335
|
+
expectType(e.else_, e.type, "ternary else-branch");
|
|
2336
|
+
if (e.type.kind === "void")
|
|
2337
|
+
err("ternary must not be void", e.loc);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
// Keep expression families in separate functions so native bootstrap builds
|
|
2342
|
+
// do not feed LLVM a single control-flow graph containing every IR check.
|
|
1960
2343
|
function checkExpr(e) {
|
|
2344
|
+
switch (e.kind) {
|
|
2345
|
+
case "numLit":
|
|
2346
|
+
case "strLit":
|
|
2347
|
+
case "moduleNsRef":
|
|
2348
|
+
case "boolLit":
|
|
2349
|
+
case "unitLit":
|
|
2350
|
+
case "varRef":
|
|
2351
|
+
case "bin":
|
|
2352
|
+
case "unary":
|
|
2353
|
+
case "incDec":
|
|
2354
|
+
case "fieldIncDec":
|
|
2355
|
+
case "assignExpr":
|
|
2356
|
+
case "seqExpr":
|
|
2357
|
+
case "dynDestrCheck":
|
|
2358
|
+
case "dynIterN":
|
|
2359
|
+
case "toBool":
|
|
2360
|
+
case "logical":
|
|
2361
|
+
case "nullish":
|
|
2362
|
+
case "ternary":
|
|
2363
|
+
case "unionEq":
|
|
2364
|
+
case "unionFuncEq":
|
|
2365
|
+
return checkScalarExpr(e);
|
|
2366
|
+
case "strConcat":
|
|
2367
|
+
case "strEq":
|
|
2368
|
+
case "strCmp":
|
|
2369
|
+
case "optChain":
|
|
2370
|
+
case "chainRecv":
|
|
2371
|
+
case "orDefault":
|
|
2372
|
+
case "toString":
|
|
2373
|
+
case "strIntrinsic":
|
|
2374
|
+
case "regexLit":
|
|
2375
|
+
case "templateStrings":
|
|
2376
|
+
case "regexIntrinsic":
|
|
2377
|
+
return checkStringExpr(e);
|
|
2378
|
+
case "arrayLit":
|
|
2379
|
+
case "arrayNewLen":
|
|
2380
|
+
case "arrayGet":
|
|
2381
|
+
case "arrayHas":
|
|
2382
|
+
case "arrayState":
|
|
2383
|
+
case "bytesNew":
|
|
2384
|
+
case "bytesIntrinsic":
|
|
2385
|
+
case "arrIntrinsic":
|
|
2386
|
+
return checkArrayExpr(e);
|
|
2387
|
+
case "mapNew":
|
|
2388
|
+
case "mapIntrinsic":
|
|
2389
|
+
case "setNew":
|
|
2390
|
+
case "setIntrinsic":
|
|
2391
|
+
return checkCollectionExpr(e);
|
|
2392
|
+
case "call":
|
|
2393
|
+
case "ffiCall":
|
|
2394
|
+
case "closure":
|
|
2395
|
+
case "callValue":
|
|
2396
|
+
return checkCallExpr(e);
|
|
2397
|
+
case "selfRef":
|
|
2398
|
+
case "new":
|
|
2399
|
+
case "fieldGet":
|
|
2400
|
+
case "promiseVoidWiden":
|
|
2401
|
+
case "upcast":
|
|
2402
|
+
case "downcast":
|
|
2403
|
+
case "classRef":
|
|
2404
|
+
case "newValue":
|
|
2405
|
+
case "instanceOfValue":
|
|
2406
|
+
case "instanceOf":
|
|
2407
|
+
case "virtualCall":
|
|
2408
|
+
return checkClassExpr(e);
|
|
2409
|
+
case "recordLit":
|
|
2410
|
+
case "recordClone":
|
|
2411
|
+
case "recordGet":
|
|
2412
|
+
case "recordKeyGet":
|
|
2413
|
+
case "recordOvfHas":
|
|
2414
|
+
case "recordOvfKeys":
|
|
2415
|
+
return checkRecordExpr(e);
|
|
2416
|
+
case "dynFrom":
|
|
2417
|
+
case "dynFromJsval":
|
|
2418
|
+
case "dynCall":
|
|
2419
|
+
case "dynInvoke":
|
|
2420
|
+
case "dynObjLit":
|
|
2421
|
+
case "dynArrLit":
|
|
2422
|
+
case "unionWrap":
|
|
2423
|
+
case "dynTest":
|
|
2424
|
+
case "dynKeyGet":
|
|
2425
|
+
case "dynHasKey":
|
|
2426
|
+
case "dynScalarEq":
|
|
2427
|
+
case "caughtTest":
|
|
2428
|
+
case "caughtCheck":
|
|
2429
|
+
case "caughtToDyn":
|
|
2430
|
+
case "caughtNarrow":
|
|
2431
|
+
return checkDynamicExpr(e);
|
|
2432
|
+
case "unionNarrow":
|
|
2433
|
+
case "unionDisc":
|
|
2434
|
+
case "unionKeyGet":
|
|
2435
|
+
case "unionIsTag":
|
|
2436
|
+
return checkUnionExpr(e);
|
|
2437
|
+
case "intrinsic":
|
|
2438
|
+
return checkIntrinsicExpr(e);
|
|
2439
|
+
case "libCall":
|
|
2440
|
+
return checkLibCall(e);
|
|
2441
|
+
case "jsonStringify":
|
|
2442
|
+
case "dynCheck":
|
|
2443
|
+
return checkConversionExpr(e);
|
|
2444
|
+
case "awaitExpr":
|
|
2445
|
+
case "yieldExpr":
|
|
2446
|
+
case "genResume":
|
|
2447
|
+
case "awaitUnionExpr":
|
|
2448
|
+
case "newPromise":
|
|
2449
|
+
case "promiseWithResolvers":
|
|
2450
|
+
return checkAsyncExpr(e);
|
|
2451
|
+
case "jsMarshal":
|
|
2452
|
+
case "jsOp":
|
|
2453
|
+
case "jsExit":
|
|
2454
|
+
case "jsBridgePromise":
|
|
2455
|
+
return checkIslandExpr(e);
|
|
2456
|
+
default: {
|
|
2457
|
+
const _exhaustive = e;
|
|
2458
|
+
void _exhaustive;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
function checkScalarExpr(e) {
|
|
1961
2463
|
switch (e.kind) {
|
|
1962
2464
|
case "numLit":
|
|
1963
2465
|
// ±Infinity and NaN are real literals (the globals
|
|
1964
|
-
// `Infinity`/`NaN`, Number constants) —
|
|
1965
|
-
// (
|
|
2466
|
+
// `Infinity`/`NaN`, Number constants) — the backend spells them
|
|
2467
|
+
// (bit-encoded f64 in LLVM).
|
|
1966
2468
|
// procStream is the ONE non-f64 numLit: process.stdout/stderr as
|
|
1967
2469
|
// first-class values mint the stream's fd (1/2) as the scalar —
|
|
1968
2470
|
// the prefixStream idiom.
|
|
@@ -2026,6 +2528,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2026
2528
|
(e.left.type.kind === "array" ||
|
|
2027
2529
|
e.left.type.kind === "map" ||
|
|
2028
2530
|
e.left.type.kind === "set" ||
|
|
2531
|
+
e.left.type.kind === "regex" ||
|
|
2532
|
+
e.left.type.kind === "url" ||
|
|
2029
2533
|
e.left.type.kind === "object" ||
|
|
2030
2534
|
e.left.type.kind === "record" ||
|
|
2031
2535
|
// Symbol identity IS pointer identity (the frontend's rule).
|
|
@@ -2129,12 +2633,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2129
2633
|
// Statements in an expression cannot jump out of the expression,
|
|
2130
2634
|
// but a local state branch is valid: optional array stores must
|
|
2131
2635
|
// choose ARRAY_VALUE versus ARRAY_UNDEFINED before the final result
|
|
2132
|
-
// is evaluated.
|
|
2133
|
-
|
|
2636
|
+
// is evaluated. Delegation also needs a local loop. Nested control
|
|
2637
|
+
// flow is checked recursively; jumps still cannot leave the region.
|
|
2638
|
+
const allowed = new Set(["varDecl", "assign", "exprStmt", "fieldSet", "recordSet", "recordKeySet", "arraySet", "arraySetLength", "arraySetUndefined", "arrayDelete", "bytesSet", "block", "if", "while"]);
|
|
2639
|
+
if (e.generatorDelegate) {
|
|
2640
|
+
if (!fn.generator || fn.async)
|
|
2641
|
+
err("delegation sequence outside a synchronous generator", e.loc);
|
|
2642
|
+
allowed.add("return");
|
|
2643
|
+
allowed.add("throw");
|
|
2644
|
+
allowed.add("runtimeFence");
|
|
2645
|
+
}
|
|
2134
2646
|
const flat = (ss) => {
|
|
2135
2647
|
for (const s of ss) {
|
|
2136
2648
|
if (!allowed.has(s.kind)) {
|
|
2137
|
-
err(`seqExpr statement kind "${s.kind}"
|
|
2649
|
+
err(`seqExpr statement kind "${s.kind}" can leave the expression`, s.loc);
|
|
2138
2650
|
continue;
|
|
2139
2651
|
}
|
|
2140
2652
|
if (s.kind === "block") {
|
|
@@ -2148,6 +2660,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2148
2660
|
checkExpr(s.cond);
|
|
2149
2661
|
continue;
|
|
2150
2662
|
}
|
|
2663
|
+
if (s.kind === "while") {
|
|
2664
|
+
expectType(s.cond, BOOL, "seqExpr while condition");
|
|
2665
|
+
checkExpr(s.cond);
|
|
2666
|
+
flat(s.body);
|
|
2667
|
+
continue;
|
|
2668
|
+
}
|
|
2151
2669
|
checkStmt(s);
|
|
2152
2670
|
}
|
|
2153
2671
|
};
|
|
@@ -2190,16 +2708,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2190
2708
|
err("toBool must be bool", e.loc);
|
|
2191
2709
|
break;
|
|
2192
2710
|
case "logical":
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
e.type.kind !== "jsval" && e.type.kind !== "union" && e.type.kind !== "dyn") {
|
|
2197
|
-
err(`logical ${e.op} must be f64|string|bool|jsval|union|dyn, got ${e.type.kind}`, e.loc);
|
|
2198
|
-
}
|
|
2199
|
-
if (e.type.kind === "union")
|
|
2200
|
-
checkTruthyUnion(e.type.unionId, e.loc);
|
|
2201
|
-
expectType(e.left, e.type, `logical ${e.op} left`);
|
|
2202
|
-
expectType(e.right, e.type, `logical ${e.op} right`);
|
|
2711
|
+
case "nullish":
|
|
2712
|
+
case "ternary":
|
|
2713
|
+
checkBranchingTree(e);
|
|
2203
2714
|
break;
|
|
2204
2715
|
case "unionEq": {
|
|
2205
2716
|
checkExpr(e.left);
|
|
@@ -2233,6 +2744,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2233
2744
|
err("unionFuncEq must be bool", e.loc);
|
|
2234
2745
|
break;
|
|
2235
2746
|
}
|
|
2747
|
+
default: {
|
|
2748
|
+
const _exhaustive = e;
|
|
2749
|
+
void _exhaustive;
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
function checkStringExpr(e) {
|
|
2754
|
+
switch (e.kind) {
|
|
2236
2755
|
case "strConcat":
|
|
2237
2756
|
checkExpr(e.left);
|
|
2238
2757
|
checkExpr(e.right);
|
|
@@ -2250,16 +2769,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2250
2769
|
if (e.type.kind !== "bool")
|
|
2251
2770
|
err(`${e.kind} must be bool`, e.loc);
|
|
2252
2771
|
break;
|
|
2253
|
-
case "ternary":
|
|
2254
|
-
checkExpr(e.cond);
|
|
2255
|
-
checkExpr(e.then);
|
|
2256
|
-
checkExpr(e.else_);
|
|
2257
|
-
expectType(e.cond, BOOL, "ternary condition");
|
|
2258
|
-
expectType(e.then, e.type, "ternary then-branch");
|
|
2259
|
-
expectType(e.else_, e.type, "ternary else-branch");
|
|
2260
|
-
if (e.type.kind === "void")
|
|
2261
|
-
err("ternary must not be void", e.loc);
|
|
2262
|
-
break;
|
|
2263
2772
|
case "optChain": {
|
|
2264
2773
|
checkExpr(e.receiver);
|
|
2265
2774
|
// An island-handle chain (`x?.y` on 'any'): the nullish test is a
|
|
@@ -2312,13 +2821,13 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2312
2821
|
break;
|
|
2313
2822
|
}
|
|
2314
2823
|
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2315
|
-
if (rest.length
|
|
2316
|
-
err("optChain receiver must have unit arms and
|
|
2824
|
+
if (rest.length === 0 || rest.length === def.arms.length) {
|
|
2825
|
+
err("optChain receiver must have unit arms and at least one non-unit arm", e.loc);
|
|
2317
2826
|
break;
|
|
2318
2827
|
}
|
|
2319
2828
|
if (activeChains.has(e.id))
|
|
2320
2829
|
err(`optChain id "${e.id}" shadows an active chain`, e.loc);
|
|
2321
|
-
activeChains.set(e.id, rest[0]);
|
|
2830
|
+
activeChains.set(e.id, rest.length === 1 ? rest[0] : e.receiver.type);
|
|
2322
2831
|
checkExpr(e.body);
|
|
2323
2832
|
activeChains.delete(e.id);
|
|
2324
2833
|
if (e.type.kind === "void") {
|
|
@@ -2347,47 +2856,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2347
2856
|
expectType(e, bound, "chainRecv");
|
|
2348
2857
|
break;
|
|
2349
2858
|
}
|
|
2350
|
-
case "nullish": {
|
|
2351
|
-
checkExpr(e.left);
|
|
2352
|
-
checkExpr(e.right);
|
|
2353
|
-
expectType(e.right, e.type, "nullish right operand");
|
|
2354
|
-
// The ISLAND form: `a ?? b` over an engine value — left, right,
|
|
2355
|
-
// and result are all handles (the emitters' jsval nullish arm).
|
|
2356
|
-
if (e.left.type.kind === "jsval") {
|
|
2357
|
-
if (e.type.kind !== "jsval")
|
|
2358
|
-
err("jsval nullish must answer jsval", e.loc);
|
|
2359
|
-
break;
|
|
2360
|
-
}
|
|
2361
|
-
// The CHECKED-DYNAMIC form: the runtime kind decides (the
|
|
2362
|
-
// emitters' scr_dyn_is_nullish arm) — left, right, and result
|
|
2363
|
-
// all live in the checked-dynamic tree.
|
|
2364
|
-
if (e.left.type.kind === "dyn") {
|
|
2365
|
-
if (e.type.kind !== "dyn")
|
|
2366
|
-
err("dyn nullish must answer dyn", e.loc);
|
|
2367
|
-
break;
|
|
2368
|
-
}
|
|
2369
|
-
if (e.left.type.kind !== "union") {
|
|
2370
|
-
err(`nullish left must be a union, got ${e.left.type.kind}`, e.loc);
|
|
2371
|
-
break;
|
|
2372
|
-
}
|
|
2373
|
-
const def = unions.get(e.left.type.unionId);
|
|
2374
|
-
if (!def) {
|
|
2375
|
-
err(`nullish left references unknown union ${e.left.type.unionId}`, e.loc);
|
|
2376
|
-
break;
|
|
2377
|
-
}
|
|
2378
|
-
if (!def.arms.some(isUnitType)) {
|
|
2379
|
-
err("nullish left union has no unit arm (frontend must fence)", e.loc);
|
|
2380
|
-
}
|
|
2381
|
-
// Two shapes: pass-through (type === left's union) or narrowed
|
|
2382
|
-
// (type === the union's SINGLE non-unit arm).
|
|
2383
|
-
if (!typeEquals(e.type, e.left.type)) {
|
|
2384
|
-
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2385
|
-
if (rest.length !== 1 || !typeEquals(e.type, rest[0])) {
|
|
2386
|
-
err("nullish type must be the left union or its single non-unit arm", e.loc);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
break;
|
|
2390
|
-
}
|
|
2391
2859
|
case "orDefault": {
|
|
2392
2860
|
checkExpr(e.left);
|
|
2393
2861
|
checkExpr(e.right);
|
|
@@ -2434,7 +2902,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2434
2902
|
err(`toString of unknown union ${e.operand.type.unionId}`, e.loc);
|
|
2435
2903
|
}
|
|
2436
2904
|
else if (!def.arms.every((a) => a.kind === "undefinedT" || a.kind === "nullT" ||
|
|
2437
|
-
a.kind === "string" || a.kind === "f64" || a.kind === "bool" ||
|
|
2905
|
+
a.kind === "string" || a.kind === "f64" || a.kind === "bigint" || a.kind === "bool" ||
|
|
2438
2906
|
(a.kind === "bytes" && a.elem === "u8"))) {
|
|
2439
2907
|
err("toString union operand has a non-stringable arm (frontend must fence)", e.loc);
|
|
2440
2908
|
}
|
|
@@ -2504,7 +2972,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2504
2972
|
if (want)
|
|
2505
2973
|
expectType(a, want, `regexIntrinsic ${e.method} arg ${i}`);
|
|
2506
2974
|
});
|
|
2507
|
-
if (e.method === "match") {
|
|
2975
|
+
if (e.method === "match" || e.method === "exec") {
|
|
2508
2976
|
// The `string[] | null` union (program-dependent id) — checked
|
|
2509
2977
|
// by arms, like the libCall case checks process.envGet.
|
|
2510
2978
|
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
@@ -2521,6 +2989,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2521
2989
|
}
|
|
2522
2990
|
break;
|
|
2523
2991
|
}
|
|
2992
|
+
default: {
|
|
2993
|
+
const _exhaustive = e;
|
|
2994
|
+
void _exhaustive;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
function checkArrayExpr(e) {
|
|
2999
|
+
switch (e.kind) {
|
|
2524
3000
|
case "arrayLit": {
|
|
2525
3001
|
if (e.type.kind !== "array") {
|
|
2526
3002
|
err(`arrayLit must be array-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -2602,21 +3078,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2602
3078
|
if (e.source) {
|
|
2603
3079
|
checkExpr(e.source);
|
|
2604
3080
|
const sk = e.source.type;
|
|
2605
|
-
if (sk.kind === "
|
|
2606
|
-
// Same-elem copies only (cross-kind construction is fenced).
|
|
2607
|
-
if (!typeEquals(sk, e.type)) {
|
|
2608
|
-
err(`bytesNew copy source elem mismatch`, e.loc);
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
else if (sk.kind === "array") {
|
|
3081
|
+
if (sk.kind === "array") {
|
|
2612
3082
|
if (sk.elem.kind !== "f64") {
|
|
2613
3083
|
err(`bytesNew array source must hold f64, got ${sk.elem.kind}`, e.loc);
|
|
2614
3084
|
}
|
|
2615
3085
|
}
|
|
2616
|
-
else if (sk.kind !== "f64") {
|
|
3086
|
+
else if (sk.kind !== "f64" && sk.kind !== "bytes" && sk.kind !== "dyn") {
|
|
2617
3087
|
err(`bytesNew source of kind ${sk.kind}`, e.loc);
|
|
2618
3088
|
}
|
|
2619
3089
|
}
|
|
3090
|
+
if (e.from && e.source?.type.kind !== "dyn")
|
|
3091
|
+
err("bytesNew from requires a dyn source", e.loc);
|
|
2620
3092
|
break;
|
|
2621
3093
|
}
|
|
2622
3094
|
case "bytesIntrinsic": {
|
|
@@ -2652,6 +3124,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2652
3124
|
err(`bytesIntrinsic ${e.method} args[1] must be a strLit encoding`, e.loc);
|
|
2653
3125
|
}
|
|
2654
3126
|
const EXTRA_SIGS = {
|
|
3127
|
+
buffer: { argTypes: [], minArgs: 0, result: DYN },
|
|
3128
|
+
setFromDyn: { argTypes: [DYN, F64], minArgs: 1, result: VOID },
|
|
3129
|
+
copyWithin: { argTypes: [F64, F64, F64], minArgs: 3, result: bytesOf(recv.elem) },
|
|
2655
3130
|
equals: { argTypes: [BYTES_U8], minArgs: 1, result: BOOL },
|
|
2656
3131
|
compareBuf: { argTypes: [BYTES_U8, F64, F64, F64, F64], minArgs: 1, result: F64 },
|
|
2657
3132
|
// [needle, align, byteOffset?] — an OMITTED byteOffset is Node's
|
|
@@ -2691,7 +3166,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2691
3166
|
: e.method === "toArray"
|
|
2692
3167
|
? { argTypes: [], minArgs: 0, result: arrayOf(F64) }
|
|
2693
3168
|
: e.method === "setFrom"
|
|
2694
|
-
? { argTypes: [bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
|
|
3169
|
+
? { argTypes: [e.args[0]?.type.kind === "bytes" ? e.args[0].type : bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
|
|
2695
3170
|
: e.method === "toString" || e.method === "toStringVar"
|
|
2696
3171
|
? { argTypes: [STRING, F64, F64], minArgs: 1, result: STRING }
|
|
2697
3172
|
: e.method === "readNum"
|
|
@@ -2803,7 +3278,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2803
3278
|
// misjudge JS ===; the frontend fences these.
|
|
2804
3279
|
err(`arrIntrinsic ${e.method} on union elements (frontend must reject)`, e.loc);
|
|
2805
3280
|
}
|
|
2806
|
-
if (e.method === "shift" || e.method === "pop") {
|
|
3281
|
+
if ((e.method === "shift" || e.method === "pop") && !(elem.kind === "dyn" && e.type.kind === "dyn")) {
|
|
2807
3282
|
const rdef = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
2808
3283
|
if (!rdef ||
|
|
2809
3284
|
!rdef.arms.some((arm) => arm.kind === "undefinedT") ||
|
|
@@ -2829,12 +3304,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2829
3304
|
}
|
|
2830
3305
|
break;
|
|
2831
3306
|
}
|
|
3307
|
+
default: {
|
|
3308
|
+
const _exhaustive = e;
|
|
3309
|
+
void _exhaustive;
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
function checkCollectionExpr(e) {
|
|
3314
|
+
switch (e.kind) {
|
|
2832
3315
|
case "mapNew": {
|
|
2833
3316
|
if (e.type.kind !== "map") {
|
|
2834
3317
|
err(`mapNew must be map-typed, got ${e.type.kind}`, e.loc);
|
|
2835
3318
|
break;
|
|
2836
3319
|
}
|
|
2837
|
-
if (!isSupportedMapKey(e.type.key)) {
|
|
3320
|
+
if (!isSupportedMapKey(e.type.key, e.type.key.kind === "union" ? unions.get(e.type.key.unionId)?.arms : undefined)) {
|
|
2838
3321
|
err(`mapNew key kind ${e.type.key.kind} (frontend must fence)`, e.loc);
|
|
2839
3322
|
}
|
|
2840
3323
|
if (!isSupportedMapValue(e.type.value)) {
|
|
@@ -2868,6 +3351,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2868
3351
|
}
|
|
2869
3352
|
checkExpr(e.args[0]);
|
|
2870
3353
|
expectType(e.args[0], key, "mapIntrinsic get key");
|
|
3354
|
+
if (value.kind === "dyn") {
|
|
3355
|
+
expectType(e, DYN, "mapIntrinsic get result");
|
|
3356
|
+
break;
|
|
3357
|
+
}
|
|
2871
3358
|
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
2872
3359
|
const rest = def ? def.arms.filter((a) => a.kind !== "undefinedT") : [];
|
|
2873
3360
|
// When V is itself a union its own undefined arm (if any) folds
|
|
@@ -2917,7 +3404,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2917
3404
|
err(`setNew must be set-typed, got ${e.type.kind}`, e.loc);
|
|
2918
3405
|
break;
|
|
2919
3406
|
}
|
|
2920
|
-
if (!isSupportedSetElem(e.type.elem)) {
|
|
3407
|
+
if (!isSupportedSetElem(e.type.elem, e.type.elem.kind === "union" ? unions.get(e.type.elem.unionId)?.arms : undefined)) {
|
|
2921
3408
|
err(`setNew element kind ${e.type.elem.kind} (frontend must fence)`, e.loc);
|
|
2922
3409
|
}
|
|
2923
3410
|
// The seed is one T[]-typed expression (T = the element type).
|
|
@@ -2961,6 +3448,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2961
3448
|
}
|
|
2962
3449
|
break;
|
|
2963
3450
|
}
|
|
3451
|
+
default: {
|
|
3452
|
+
const _exhaustive = e;
|
|
3453
|
+
void _exhaustive;
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
function checkCallExpr(e) {
|
|
3458
|
+
switch (e.kind) {
|
|
2964
3459
|
case "call": {
|
|
2965
3460
|
for (const a of e.args)
|
|
2966
3461
|
checkExpr(a);
|
|
@@ -3060,6 +3555,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3060
3555
|
}
|
|
3061
3556
|
case "callValue": {
|
|
3062
3557
|
checkExpr(e.callee);
|
|
3558
|
+
if (e.receiver !== undefined) {
|
|
3559
|
+
checkExpr(e.receiver);
|
|
3560
|
+
expectType(e.receiver, DYN, "callValue receiver");
|
|
3561
|
+
}
|
|
3063
3562
|
for (const a of e.args)
|
|
3064
3563
|
checkExpr(a);
|
|
3065
3564
|
if (e.callee.type.kind !== "func") {
|
|
@@ -3080,6 +3579,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3080
3579
|
}
|
|
3081
3580
|
break;
|
|
3082
3581
|
}
|
|
3582
|
+
default: {
|
|
3583
|
+
const _exhaustive = e;
|
|
3584
|
+
void _exhaustive;
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
function checkClassExpr(e) {
|
|
3589
|
+
switch (e.kind) {
|
|
3083
3590
|
case "selfRef":
|
|
3084
3591
|
if (fn.captures === undefined) {
|
|
3085
3592
|
err("selfRef outside a lifted function", e.loc);
|
|
@@ -3096,6 +3603,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3096
3603
|
break;
|
|
3097
3604
|
}
|
|
3098
3605
|
const ctor = functions.get(`%${e.className}.constructor`);
|
|
3606
|
+
if (cls.localCaptures !== undefined)
|
|
3607
|
+
err(`new ${e.className}: local class requires a class value`, e.loc);
|
|
3099
3608
|
if (!ctor) {
|
|
3100
3609
|
err(`new ${e.className}: missing constructor function`, e.loc);
|
|
3101
3610
|
break;
|
|
@@ -3205,6 +3714,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3205
3714
|
if (!typeEquals(e.type, { kind: "classval", className: e.className })) {
|
|
3206
3715
|
err(`classRef to "${e.className}" must have that classval type`, e.loc);
|
|
3207
3716
|
}
|
|
3717
|
+
if ((e.captures === undefined) !== (cls.localCaptures === undefined) ||
|
|
3718
|
+
(e.captures?.length ?? 0) !== (cls.localCaptures?.length ?? 0)) {
|
|
3719
|
+
err(`classRef to "${e.className}" must supply its class captures`, e.loc);
|
|
3720
|
+
}
|
|
3721
|
+
(e.captures ?? []).forEach((id, index) => {
|
|
3722
|
+
const local = locals.get(id);
|
|
3723
|
+
const wanted = cls.localCaptures?.[index];
|
|
3724
|
+
if (!local?.boxed || (wanted && !typeEquals(local.type, wanted.type))) {
|
|
3725
|
+
err(`classRef capture "${id}" must name a box with the declared type`, e.loc);
|
|
3726
|
+
}
|
|
3727
|
+
});
|
|
3208
3728
|
break;
|
|
3209
3729
|
}
|
|
3210
3730
|
case "newValue": {
|
|
@@ -3248,6 +3768,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3248
3768
|
// Both sides must be hierarchy members: the operand needs a vt
|
|
3249
3769
|
// word to read; a standalone target class has one possible value
|
|
3250
3770
|
// and the frontend folds it statically.
|
|
3771
|
+
if (classes.get(e.classValue.type.className)?.localCaptures !== undefined &&
|
|
3772
|
+
e.value.type.kind === "object" && classes.get(e.value.type.className)?.localCaptures !== undefined)
|
|
3773
|
+
break;
|
|
3251
3774
|
if (!hierarchy.has(e.classValue.type.className)) {
|
|
3252
3775
|
err(`instanceOfValue against standalone class "${e.classValue.type.className}"`, e.loc);
|
|
3253
3776
|
}
|
|
@@ -3325,6 +3848,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3325
3848
|
}
|
|
3326
3849
|
break;
|
|
3327
3850
|
}
|
|
3851
|
+
default: {
|
|
3852
|
+
const _exhaustive = e;
|
|
3853
|
+
void _exhaustive;
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3857
|
+
function checkRecordExpr(e) {
|
|
3858
|
+
switch (e.kind) {
|
|
3328
3859
|
case "recordLit": {
|
|
3329
3860
|
if (e.type.kind !== "record") {
|
|
3330
3861
|
err(`recordLit must be record-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3444,8 +3975,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3444
3975
|
// literal key naming no declared field) skip the declared check
|
|
3445
3976
|
// and require the overflow to exist.
|
|
3446
3977
|
const surfaces = (t) => typeEquals(t, e.type) ||
|
|
3447
|
-
(e.type.kind === "union" &&
|
|
3448
|
-
|
|
3978
|
+
(e.type.kind === "union" && (() => {
|
|
3979
|
+
const result = unions.get(e.type.unionId);
|
|
3980
|
+
const source = t.kind === "union" ? unions.get(t.unionId) : undefined;
|
|
3981
|
+
return !!result && (result.arms.some((a) => typeEquals(a, t)) ||
|
|
3982
|
+
(!!source && unionWideningTags(source.arms, result.arms) !== null));
|
|
3983
|
+
})()) ||
|
|
3449
3984
|
e.type.kind === "dyn";
|
|
3450
3985
|
if (e.overflowOnly && !shape.indexValue) {
|
|
3451
3986
|
err(`recordKeyGet on ${e.shapeId}: overflowOnly read of a shape without an index signature`, e.loc);
|
|
@@ -3461,6 +3996,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3461
3996
|
}
|
|
3462
3997
|
break;
|
|
3463
3998
|
}
|
|
3999
|
+
case "recordOvfHas": {
|
|
4000
|
+
checkExpr(e.obj);
|
|
4001
|
+
checkExpr(e.key);
|
|
4002
|
+
const shape = records.get(e.shapeId);
|
|
4003
|
+
if (!shape)
|
|
4004
|
+
err(`recordOvfHas on undeclared shape "${e.shapeId}"`, e.loc);
|
|
4005
|
+
else if (!shape.indexValue || shape.tuple)
|
|
4006
|
+
err(`recordOvfHas on ${e.shapeId}: requires an index-signature record`, e.loc);
|
|
4007
|
+
expectType(e.obj, { kind: "record", shapeId: e.shapeId }, "recordOvfHas receiver");
|
|
4008
|
+
expectType(e.key, STRING, "recordOvfHas key");
|
|
4009
|
+
if (e.type.kind !== "bool")
|
|
4010
|
+
err("recordOvfHas must be bool", e.loc);
|
|
4011
|
+
break;
|
|
4012
|
+
}
|
|
3464
4013
|
case "recordOvfKeys": {
|
|
3465
4014
|
checkExpr(e.obj);
|
|
3466
4015
|
const shape = records.get(e.shapeId);
|
|
@@ -3476,6 +4025,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3476
4025
|
}
|
|
3477
4026
|
break;
|
|
3478
4027
|
}
|
|
4028
|
+
default: {
|
|
4029
|
+
const _exhaustive = e;
|
|
4030
|
+
void _exhaustive;
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
}
|
|
4034
|
+
function checkDynamicExpr(e) {
|
|
4035
|
+
switch (e.kind) {
|
|
3479
4036
|
case "dynFrom": {
|
|
3480
4037
|
if (e.type.kind !== "dyn")
|
|
3481
4038
|
err(`dynFrom must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3517,6 +4074,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3517
4074
|
}
|
|
3518
4075
|
case "dynCall": {
|
|
3519
4076
|
checkExpr(e.callee);
|
|
4077
|
+
if (e.receiver !== undefined) {
|
|
4078
|
+
checkExpr(e.receiver);
|
|
4079
|
+
expectType(e.receiver, DYN, "dynCall receiver");
|
|
4080
|
+
}
|
|
3520
4081
|
expectType(e.callee, DYN, "dynCall callee");
|
|
3521
4082
|
if (e.type.kind !== "dyn")
|
|
3522
4083
|
err(`dynCall must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3559,8 +4120,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3559
4120
|
err(`dynObjLit must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
3560
4121
|
for (const f of e.fields ?? []) {
|
|
3561
4122
|
checkExpr(f.key);
|
|
3562
|
-
if (f.key.type.kind !== "string")
|
|
3563
|
-
err(`dynObjLit key of kind ${f.key.type.kind} (must be string)`, e.loc);
|
|
4123
|
+
if (f.key.type.kind !== "string" && f.key.type.kind !== "dyn")
|
|
4124
|
+
err(`dynObjLit key of kind ${f.key.type.kind} (must be string or dyn)`, e.loc);
|
|
3564
4125
|
checkExpr(f.value);
|
|
3565
4126
|
if (f.value.type.kind !== "dyn")
|
|
3566
4127
|
err(`dynObjLit field value of kind ${f.value.type.kind} (must be dyn)`, e.loc);
|
|
@@ -3622,14 +4183,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3622
4183
|
expectType(e.value, { kind: "dyn" }, "dynTest operand");
|
|
3623
4184
|
if (e.type.kind !== "bool")
|
|
3624
4185
|
err("dynTest must be bool", e.loc);
|
|
4186
|
+
if (e.bytesElem !== undefined && (e.test !== "bytes" || !Object.hasOwn(BYTES_ELEMENT_NAME, e.bytesElem))) {
|
|
4187
|
+
err("dynTest bytesElem requires a valid bytes test", e.loc);
|
|
4188
|
+
}
|
|
3625
4189
|
break;
|
|
3626
4190
|
}
|
|
3627
4191
|
case "dynKeyGet": {
|
|
3628
4192
|
checkExpr(e.value);
|
|
3629
4193
|
checkExpr(e.key);
|
|
3630
4194
|
expectType(e.value, { kind: "dyn" }, "dynKeyGet operand");
|
|
3631
|
-
if (e.key.type.kind !== "string")
|
|
3632
|
-
err(`dynKeyGet key is ${e.key.type.kind}, not string`, e.loc);
|
|
4195
|
+
if (e.key.type.kind !== "string" && e.key.type.kind !== "dyn")
|
|
4196
|
+
err(`dynKeyGet key is ${e.key.type.kind}, not string or dyn`, e.loc);
|
|
3633
4197
|
if (e.type.kind !== "dyn")
|
|
3634
4198
|
err("dynKeyGet must be dyn", e.loc);
|
|
3635
4199
|
break;
|
|
@@ -3704,6 +4268,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3704
4268
|
}
|
|
3705
4269
|
break;
|
|
3706
4270
|
}
|
|
4271
|
+
default: {
|
|
4272
|
+
const _exhaustive = e;
|
|
4273
|
+
void _exhaustive;
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
function checkUnionExpr(e) {
|
|
4278
|
+
switch (e.kind) {
|
|
3707
4279
|
case "unionNarrow": {
|
|
3708
4280
|
checkExpr(e.value);
|
|
3709
4281
|
const def = unions.get(e.unionId);
|
|
@@ -3777,7 +4349,11 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3777
4349
|
// non-unit arms have no keyed read at all. Number keys read ARRAY
|
|
3778
4350
|
// arms; string keys read RECORD arms.
|
|
3779
4351
|
const resultUnion = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
3780
|
-
const surfaces = (t) => typeEquals(t, e.type) || !!resultUnion?.arms.some((a) => typeEquals(a, t))
|
|
4352
|
+
const surfaces = (t) => typeEquals(t, e.type) || !!resultUnion?.arms.some((a) => typeEquals(a, t)) ||
|
|
4353
|
+
(t.kind === "union" && !!resultUnion && (() => {
|
|
4354
|
+
const source = unions.get(t.unionId);
|
|
4355
|
+
return !!source && unionWideningTags(source.arms, resultUnion.arms) !== null;
|
|
4356
|
+
})());
|
|
3781
4357
|
def.arms.forEach((arm, i) => {
|
|
3782
4358
|
if (arm.kind === "undefinedT" || arm.kind === "nullT") {
|
|
3783
4359
|
if (!resultUnion?.arms.some((a) => a.kind === "undefinedT")) {
|
|
@@ -3832,1296 +4408,1351 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3832
4408
|
err("unionIsTag must be bool", e.loc);
|
|
3833
4409
|
break;
|
|
3834
4410
|
}
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
}
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
}
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
if (
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4411
|
+
default: {
|
|
4412
|
+
const _exhaustive = e;
|
|
4413
|
+
void _exhaustive;
|
|
4414
|
+
}
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
function checkIntrinsicExpr(e) {
|
|
4418
|
+
if (e.name === "module.await") {
|
|
4419
|
+
if (e.args.length !== 1)
|
|
4420
|
+
err("module.await takes exactly one argument", e.loc);
|
|
4421
|
+
for (const a of e.args) {
|
|
4422
|
+
checkExpr(a);
|
|
4423
|
+
if (a.type.kind !== "promise" || a.type.inner.kind !== "void") {
|
|
4424
|
+
err(`${typeKey(a.type)} argument to module.await (needs promise<void>)`, a.loc);
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
if (e.type.kind !== "void")
|
|
4428
|
+
err("module.await must be void", e.loc);
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
4431
|
+
if (e.name === "promise.all") {
|
|
4432
|
+
// ONE argument: an array of promises whose inner type is the
|
|
4433
|
+
// result's array element (or void, collapsing to promise<void>).
|
|
4434
|
+
// The exact-inner-type rule is the frontend's fence; the coarse
|
|
4435
|
+
// shape keeps hand-written IR honest.
|
|
4436
|
+
if (e.args.length !== 1)
|
|
4437
|
+
err("promise.all takes exactly one argument", e.loc);
|
|
4438
|
+
for (const a of e.args) {
|
|
4439
|
+
checkExpr(a);
|
|
4440
|
+
if (a.type.kind !== "array" || a.type.elem.kind !== "promise") {
|
|
4441
|
+
err(`${a.type.kind} argument to promise.all (needs an array of promises)`, a.loc);
|
|
4442
|
+
}
|
|
4443
|
+
}
|
|
4444
|
+
if (e.type.kind !== "promise")
|
|
4445
|
+
err("promise.all must be promise-typed", e.loc);
|
|
4446
|
+
else if (e.type.inner.kind !== "array" && e.type.inner.kind !== "void") {
|
|
4447
|
+
err("promise.all result must be a promise of an array (or void)", e.loc);
|
|
4448
|
+
}
|
|
4449
|
+
return;
|
|
4450
|
+
}
|
|
4451
|
+
if (e.name === "promise.reject") {
|
|
4452
|
+
// ONE argument: the %Error-rooted reason object (the rejection
|
|
4453
|
+
// payload shares the thrown-Error representation — the
|
|
4454
|
+
// frontend's fence pins the hierarchy; the coarse object shape
|
|
4455
|
+
// keeps hand-written IR honest) or a checked-dynamic reason
|
|
4456
|
+
// (the thrown-dyn representation — identity flows to catch and
|
|
4457
|
+
// unhandledRejection observers). The result is the
|
|
4458
|
+
// context-named promise.
|
|
4459
|
+
if (e.args.length !== 1)
|
|
4460
|
+
err("promise.reject takes exactly one argument", e.loc);
|
|
4461
|
+
for (const a of e.args) {
|
|
4462
|
+
checkExpr(a);
|
|
4463
|
+
if (a.type.kind !== "object" && a.type.kind !== "dyn") {
|
|
4464
|
+
err(`${a.type.kind} argument to promise.reject (needs an Error object or a dyn reason)`, a.loc);
|
|
4465
|
+
}
|
|
4466
|
+
}
|
|
4467
|
+
if (e.type.kind !== "promise")
|
|
4468
|
+
err("promise.reject must be promise-typed", e.loc);
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
if (e.name === "promise.resolve") {
|
|
4472
|
+
// Zero args (Promise<void>) or one plain value of the result's
|
|
4473
|
+
// inner type — promise arguments never reach the intrinsic
|
|
4474
|
+
// (the frontend returns them as-is).
|
|
4475
|
+
if (e.args.length > 1)
|
|
4476
|
+
err("promise.resolve takes at most one argument", e.loc);
|
|
4477
|
+
for (const a of e.args) {
|
|
4478
|
+
checkExpr(a);
|
|
4479
|
+
if (a.type.kind === "promise") {
|
|
4480
|
+
err("promise argument to promise.resolve (identity belongs in the frontend)", a.loc);
|
|
4481
|
+
}
|
|
4482
|
+
}
|
|
4483
|
+
if (e.type.kind !== "promise")
|
|
4484
|
+
err("promise.resolve must be promise-typed", e.loc);
|
|
4485
|
+
else if (e.args.length === 0 && e.type.inner.kind !== "void") {
|
|
4486
|
+
err("zero-argument promise.resolve must be promise<void>", e.loc);
|
|
4487
|
+
}
|
|
4488
|
+
else if (e.args.length === 1 && !typeEquals(e.args[0].type, e.type.inner)) {
|
|
4489
|
+
err("promise.resolve argument must be the result's inner type", e.loc);
|
|
4490
|
+
}
|
|
4491
|
+
return;
|
|
4492
|
+
}
|
|
4493
|
+
if (e.name === "promise.race") {
|
|
4494
|
+
// Entries are promises; the result is the combined promise. The
|
|
4495
|
+
// per-entry inner-type compatibility (equal to the result inner,
|
|
4496
|
+
// one of its union arms, or a sub-union of it) is the frontend's
|
|
4497
|
+
// fence; here the coarse shape keeps hand-written IR honest.
|
|
4498
|
+
if (e.args.length === 0)
|
|
4499
|
+
err("promise.race with no entries", e.loc);
|
|
4500
|
+
for (const a of e.args) {
|
|
4501
|
+
checkExpr(a);
|
|
4502
|
+
if (a.type.kind !== "promise") {
|
|
4503
|
+
err(`${a.type.kind} entry in promise.race`, a.loc);
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
if (e.type.kind !== "promise")
|
|
4507
|
+
err("promise.race must be promise-typed", e.loc);
|
|
4508
|
+
return;
|
|
4509
|
+
}
|
|
4510
|
+
for (const a of e.args) {
|
|
4511
|
+
checkExpr(a);
|
|
4512
|
+
// Arrays/functions/records/unions stay out of console.log (and
|
|
4513
|
+
// its stderr twin console.error) by design (the ambient signature
|
|
4514
|
+
// accepts number|string|boolean; a union of those satisfies it,
|
|
4515
|
+
// so the frontend rejects union args explicitly) — inspect
|
|
4516
|
+
// formatting is unimplemented, so the backend must never see one.
|
|
4517
|
+
if (a.type.kind !== "f64" && a.type.kind !== "string" && a.type.kind !== "bool") {
|
|
4518
|
+
err(`${a.type.kind} argument to ${e.name}`, a.loc);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
if (e.type.kind !== "void")
|
|
4522
|
+
err(`${e.name} must be void`, e.loc);
|
|
4523
|
+
}
|
|
4524
|
+
function checkLibCall(e) {
|
|
4525
|
+
const sig = LIB_FN_SIGS[e.fn];
|
|
4526
|
+
if (!sig) {
|
|
4527
|
+
err(`libCall of unknown library function "${e.fn}"`, e.loc);
|
|
4528
|
+
return;
|
|
4529
|
+
}
|
|
4530
|
+
// emitter.emit is variadic: (recv, name) plus the event's tuple.
|
|
4531
|
+
// The stream constructors (trailing option callbacks), write/end
|
|
4532
|
+
// (the optional chunk/cb tail), and unpipe (the optional
|
|
4533
|
+
// destination) admit a longer list the same way.
|
|
4534
|
+
const variadic = e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" ||
|
|
4535
|
+
e.fn === "readable.new" || e.fn === "writable.new" ||
|
|
4536
|
+
e.fn === "duplex.new" || e.fn === "transform.new" ||
|
|
4537
|
+
e.fn === "passthrough.new" ||
|
|
4538
|
+
e.fn === "readable.init" || e.fn === "writable.init" ||
|
|
4539
|
+
e.fn === "duplex.init" || e.fn === "transform.init" ||
|
|
4540
|
+
e.fn === "passthrough.init" ||
|
|
4541
|
+
e.fn === "readable.initDyn" || e.fn === "writable.initDyn" ||
|
|
4542
|
+
e.fn === "duplex.initDyn" || e.fn === "transform.initDyn" ||
|
|
4543
|
+
e.fn === "passthrough.initDyn" ||
|
|
4544
|
+
e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn" ||
|
|
4545
|
+
e.fn === "sp.pipeline" ||
|
|
4546
|
+
e.fn === "writable.write" ||
|
|
4547
|
+
e.fn === "writable.writeStr" || e.fn === "writable.writeU" ||
|
|
4548
|
+
e.fn === "writable.end" ||
|
|
4549
|
+
e.fn === "readable.unpipe";
|
|
4550
|
+
if (variadic
|
|
4551
|
+
? e.args.length < sig.argTypes.length
|
|
4552
|
+
: e.args.length !== sig.argTypes.length) {
|
|
4553
|
+
err(`libCall ${e.fn}: ${e.args.length} args, expected ${sig.argTypes.length}`, e.loc);
|
|
4554
|
+
}
|
|
4555
|
+
e.args.forEach((a, i) => {
|
|
4556
|
+
checkExpr(a);
|
|
4557
|
+
const want = sig.argTypes[i];
|
|
4558
|
+
if (want)
|
|
4559
|
+
expectType(a, want, `libCall ${e.fn} arg ${i}`);
|
|
4560
|
+
});
|
|
4561
|
+
if (checkLibValueCall(e))
|
|
4562
|
+
return;
|
|
4563
|
+
if (checkLibNetworkCall(e))
|
|
4564
|
+
return;
|
|
4565
|
+
if (checkLibFileCall(e))
|
|
4566
|
+
return;
|
|
4567
|
+
if (checkLibProcessCall(e))
|
|
4568
|
+
return;
|
|
4569
|
+
if (checkLibSpecialCall(e))
|
|
4570
|
+
return;
|
|
4571
|
+
if (checkLibStreamCall(e, sig.argTypes.length, sig.result))
|
|
4572
|
+
return;
|
|
4573
|
+
if (checkLibEmitterCall(e, sig.result))
|
|
4574
|
+
return;
|
|
4575
|
+
if (e.fn === "error.stack" || e.fn === "error.cause" || e.fn === "error.hasCause" || e.fn === "error.setCause" || e.fn === "error.defineCause" || e.fn === "error.deleteCause") {
|
|
4576
|
+
const recv = e.args[0];
|
|
4577
|
+
let cls = recv?.type.kind === "object" ? classes.get(recv.type.className) : undefined;
|
|
4578
|
+
while (cls?.base)
|
|
4579
|
+
cls = classes.get(cls.base);
|
|
4580
|
+
if (cls?.name !== "%Error")
|
|
4581
|
+
err(`libCall ${e.fn} receiver must be an error object`, e.loc);
|
|
4582
|
+
}
|
|
4583
|
+
if (e.fn === "error.ctor" || e.fn === "error.ctorOptions" || e.fn === "error.toString") {
|
|
4584
|
+
const recv = e.args[0];
|
|
4585
|
+
const wantErrorRoot = e.fn === "error.toString";
|
|
4586
|
+
const ok = recv &&
|
|
4587
|
+
isBuiltinErrorObject(recv.type) &&
|
|
4588
|
+
(!wantErrorRoot || (recv.type.kind === "object" && recv.type.className === "%Error"));
|
|
4589
|
+
if (!ok) {
|
|
4590
|
+
err(`libCall ${e.fn} receiver must be ${wantErrorRoot ? "'%Error'" : "a builtin error class"}`, e.loc);
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
if (!typeEquals(e.type, sig.result)) {
|
|
4594
|
+
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
function checkLibValueCall(e) {
|
|
4598
|
+
if (e.fn === "fileHandle.read" || e.fn === "fileHandle.writeBytes" || e.fn === "fileHandle.writeStr") {
|
|
4599
|
+
const inner = e.type.kind === "promise" ? e.type.inner : undefined;
|
|
4600
|
+
const shape = inner?.kind === "record" ? records.get(inner.shapeId) : undefined;
|
|
4601
|
+
const countName = e.fn === "fileHandle.read" ? "bytesRead" : "bytesWritten";
|
|
4602
|
+
const payload = e.args[1]?.type;
|
|
4603
|
+
const count = shape?.fields.find((f) => f.name === countName);
|
|
4604
|
+
const buffer = shape?.fields.find((f) => f.name === "buffer");
|
|
4605
|
+
const ok = shape !== undefined && !shape.tuple && shape.indexValue === undefined && shape.fields.length === 2 &&
|
|
4606
|
+
count?.type.kind === "f64" && payload !== undefined && buffer !== undefined &&
|
|
4607
|
+
typeEquals(buffer.type, payload);
|
|
4608
|
+
if (!ok) {
|
|
4609
|
+
err(`libCall ${e.fn} must return a promise of { ${countName}: number, buffer }`, e.loc);
|
|
4610
|
+
}
|
|
4611
|
+
return true;
|
|
4612
|
+
}
|
|
4613
|
+
if (e.fn === "fetch.streamFrom") {
|
|
4614
|
+
const t = e.args[0]?.type;
|
|
4615
|
+
const ok = t?.kind === "string" ||
|
|
4616
|
+
(t?.kind === "bytes" && t.elem === "u8") ||
|
|
4617
|
+
(t?.kind === "array" &&
|
|
4618
|
+
canConvertToDyn(t.elem, (id) => records.get(id), (id) => unions.get(id))) ||
|
|
4619
|
+
t?.kind === "dyn";
|
|
4620
|
+
if (!ok) {
|
|
4621
|
+
err(`libCall fetch.streamFrom arg 0: expected a supported iterable, got ${t?.kind}`, e.loc);
|
|
4622
|
+
}
|
|
4623
|
+
return true;
|
|
4624
|
+
}
|
|
4625
|
+
if (e.fn === "fetch.readerRead") {
|
|
4626
|
+
if (e.type.kind !== "promise" || e.type.inner.kind !== "record") {
|
|
4627
|
+
err(`libCall fetch.readerRead must return a promise of a read-result record`, e.loc);
|
|
4628
|
+
}
|
|
4629
|
+
return true;
|
|
4630
|
+
}
|
|
4631
|
+
if (e.fn === "fetch.responseText" || e.fn === "fetch.responseBytes") {
|
|
4632
|
+
const valueType = e.fn === "fetch.responseText" ? STRING : BYTES_U8;
|
|
4633
|
+
const inner = e.type.kind === "promise" ? e.type.inner : null;
|
|
4634
|
+
const union = inner?.kind === "union" ? unions.get(inner.unionId) : undefined;
|
|
4635
|
+
if (inner === null ||
|
|
4636
|
+
(!typeEquals(inner, valueType) &&
|
|
4637
|
+
!union?.arms.some((arm) => typeEquals(arm, valueType)))) {
|
|
4638
|
+
err(`libCall ${e.fn} must return a promise whose value includes ${valueType.kind}`, e.loc);
|
|
4639
|
+
}
|
|
4640
|
+
return true;
|
|
4641
|
+
}
|
|
4642
|
+
if (e.fn === "string.fromCharCode" || e.fn === "string.fromCodePoint") {
|
|
4643
|
+
// One packed f64[] or one bytes value (the spread form).
|
|
4644
|
+
const t = e.args[0]?.type;
|
|
4645
|
+
const ok = t && ((t.kind === "array" && t.elem.kind === "f64") || t.kind === "bytes");
|
|
4646
|
+
if (!ok) {
|
|
4647
|
+
err(`libCall ${e.fn} arg 0: expected number[] or bytes, got ${t?.kind}`, e.loc);
|
|
4648
|
+
}
|
|
4649
|
+
return true;
|
|
4650
|
+
}
|
|
4651
|
+
if (e.fn === "process.envGet") {
|
|
4652
|
+
// Result is the module's interned `string | undefined` union.
|
|
4653
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4654
|
+
const ok = def &&
|
|
4655
|
+
def.arms.length === 2 &&
|
|
4656
|
+
def.arms[0].kind === "string" &&
|
|
4657
|
+
def.arms[1].kind === "undefinedT";
|
|
4658
|
+
if (!ok) {
|
|
4659
|
+
err(`libCall process.envGet must return the 'string | undefined' union`, e.loc);
|
|
4660
|
+
}
|
|
4661
|
+
return true;
|
|
4662
|
+
}
|
|
4663
|
+
if (e.fn === "process.columns" || e.fn === "process.rows") {
|
|
4664
|
+
// Result is the module's interned `number | undefined` union.
|
|
4665
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4666
|
+
const ok = def &&
|
|
4667
|
+
def.arms.length === 2 &&
|
|
4668
|
+
def.arms[0].kind === "f64" &&
|
|
4669
|
+
def.arms[1].kind === "undefinedT";
|
|
4670
|
+
if (!ok) {
|
|
4671
|
+
err(`libCall ${e.fn} must return the 'number | undefined' union`, e.loc);
|
|
4672
|
+
}
|
|
4673
|
+
return true;
|
|
4674
|
+
}
|
|
4675
|
+
return false;
|
|
4676
|
+
}
|
|
4677
|
+
function checkLibNetworkCall(e) {
|
|
4678
|
+
if (e.fn === "http.createServer" || e.fn === "http2.createServerReq") {
|
|
4679
|
+
// The request handler: void, at most (req, res) in order.
|
|
4680
|
+
const cbT = e.args[0]?.type;
|
|
4681
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4682
|
+
if (ok && cbT?.kind === "func") {
|
|
4683
|
+
const [p0, p1] = cbT.params;
|
|
4684
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4685
|
+
ok = false;
|
|
4686
|
+
if (p1 !== undefined && p1.kind !== "httpRes")
|
|
4687
|
+
ok = false;
|
|
4688
|
+
}
|
|
4689
|
+
if (!ok) {
|
|
4690
|
+
err(`libCall ${e.fn} handler shape (frontend must fence)`, e.loc);
|
|
4691
|
+
}
|
|
4692
|
+
return true;
|
|
4693
|
+
}
|
|
4694
|
+
if (e.fn === "http.serverOnRequest") {
|
|
4695
|
+
// The 'request' listener: the same shape as http.createServer's
|
|
4696
|
+
// handler — void, at most (req, res) in order.
|
|
4697
|
+
const cbT = e.args[1]?.type;
|
|
4698
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4699
|
+
if (ok && cbT?.kind === "func") {
|
|
4700
|
+
const [p0, p1] = cbT.params;
|
|
4701
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4702
|
+
ok = false;
|
|
4703
|
+
if (p1 !== undefined && p1.kind !== "httpRes")
|
|
4704
|
+
ok = false;
|
|
4705
|
+
}
|
|
4706
|
+
if (!ok) {
|
|
4707
|
+
err(`libCall http.serverOnRequest handler shape (frontend must fence)`, e.loc);
|
|
4708
|
+
}
|
|
4709
|
+
return true;
|
|
4710
|
+
}
|
|
4711
|
+
if (e.fn === "http2.serverOnSessionError") {
|
|
4712
|
+
const cbT = e.args[1]?.type;
|
|
4713
|
+
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" &&
|
|
4714
|
+
cbT.params.length <= 2 &&
|
|
4715
|
+
(cbT.params[0] === undefined ||
|
|
4716
|
+
(cbT.params[0].kind === "object" && cbT.params[0].className === "%Error")) &&
|
|
4717
|
+
(cbT.params[1] === undefined || cbT.params[1].kind === "http2Session");
|
|
4718
|
+
if (!ok) {
|
|
4719
|
+
err(`libCall http2.serverOnSessionError callback shape (frontend must fence)`, e.loc);
|
|
4720
|
+
}
|
|
4721
|
+
return true;
|
|
4722
|
+
}
|
|
4723
|
+
if (e.fn === "http.reqOnData") {
|
|
4724
|
+
const cbT = e.args[1]?.type;
|
|
4725
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4726
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4727
|
+
const p = cbT.params[0];
|
|
4728
|
+
// dyn = the checked-dynamic listener's adapter (the chunk
|
|
4729
|
+
// boxes Buffer-flavored in the runtime data thunk).
|
|
4730
|
+
ok = (p.kind === "bytes" && p.elem === "u8") || p.kind === "dyn";
|
|
4731
|
+
}
|
|
4732
|
+
if (!ok) {
|
|
4733
|
+
err(`libCall http.reqOnData callback shape (frontend must fence)`, e.loc);
|
|
4734
|
+
}
|
|
4735
|
+
return true;
|
|
4736
|
+
}
|
|
4737
|
+
if (e.fn === "http.reqStatusCode") {
|
|
4738
|
+
// Result is the module's interned `number | undefined` union.
|
|
4739
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4740
|
+
const ok = def &&
|
|
4741
|
+
def.arms.length === 2 &&
|
|
4742
|
+
def.arms[0].kind === "f64" &&
|
|
4743
|
+
def.arms[1].kind === "undefinedT";
|
|
4744
|
+
if (!ok) {
|
|
4745
|
+
err(`libCall http.reqStatusCode must return the 'number | undefined' union`, e.loc);
|
|
4746
|
+
}
|
|
4747
|
+
return true;
|
|
4748
|
+
}
|
|
4749
|
+
if (e.fn === "net.sockRemoteAddress") {
|
|
4750
|
+
// Result is the interned `string | undefined` union (envGet's).
|
|
4751
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4752
|
+
const ok = def &&
|
|
4753
|
+
def.arms.length === 2 &&
|
|
4754
|
+
def.arms[0].kind === "string" &&
|
|
4755
|
+
def.arms[1].kind === "undefinedT";
|
|
4756
|
+
if (!ok) {
|
|
4757
|
+
err(`libCall net.sockRemoteAddress must return the 'string | undefined' union`, e.loc);
|
|
4758
|
+
}
|
|
4759
|
+
return true;
|
|
4760
|
+
}
|
|
4761
|
+
if (e.fn === "net.sockEncrypted") {
|
|
4762
|
+
// Result is the interned `boolean | undefined` union.
|
|
4763
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4764
|
+
const ok = def &&
|
|
4765
|
+
def.arms.length === 2 &&
|
|
4766
|
+
def.arms[0].kind === "bool" &&
|
|
4767
|
+
def.arms[1].kind === "undefinedT";
|
|
4768
|
+
if (!ok) {
|
|
4769
|
+
err(`libCall net.sockEncrypted must return the 'boolean | undefined' union`, e.loc);
|
|
4770
|
+
}
|
|
4771
|
+
return true;
|
|
4772
|
+
}
|
|
4773
|
+
if (e.fn === "tls.sockAuthError") {
|
|
4774
|
+
// Result is the interned `string | null` union (Node's
|
|
4775
|
+
// authorizationError: the verify-failure code string, or null).
|
|
4776
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4777
|
+
const ok = def &&
|
|
4778
|
+
def.arms.length === 2 &&
|
|
4779
|
+
def.arms[0].kind === "string" &&
|
|
4780
|
+
def.arms[1].kind === "nullT";
|
|
4781
|
+
if (!ok) {
|
|
4782
|
+
err(`libCall tls.sockAuthError must return the 'string | null' union`, e.loc);
|
|
4783
|
+
}
|
|
4784
|
+
return true;
|
|
4785
|
+
}
|
|
4786
|
+
if (e.fn === "http.requestCb" || e.fn === "https.requestCb" ||
|
|
4787
|
+
e.fn === "http.requestUrlCb" || e.fn === "http.clientOnResponse" ||
|
|
4788
|
+
e.fn === "http.requestAgentCb" || e.fn === "https.requestAgentCb" ||
|
|
4789
|
+
e.fn === "https.requestUrlCb") {
|
|
4790
|
+
// The response listener: void, no params or exactly (res: httpReq).
|
|
4791
|
+
const cbT = e.args[e.fn === "http.requestCb" ? 7
|
|
4792
|
+
: e.fn === "https.requestCb" ? 9
|
|
4793
|
+
: e.fn === "http.requestUrlCb" || e.fn === "https.requestUrlCb" ? 3
|
|
4794
|
+
: e.fn === "http.requestAgentCb" ? 8
|
|
4795
|
+
: e.fn === "https.requestAgentCb" ? 10
|
|
4796
|
+
: 1]?.type;
|
|
4797
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4798
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4799
|
+
ok = cbT.params[0].kind === "httpReq";
|
|
4800
|
+
}
|
|
4801
|
+
if (!ok) {
|
|
4802
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4803
|
+
}
|
|
4804
|
+
return true;
|
|
4805
|
+
}
|
|
4806
|
+
if (e.fn === "http.reqOnError" || e.fn === "http.clientOnError") {
|
|
4807
|
+
// The error listener: void, no params or exactly (err: %Error).
|
|
4808
|
+
const cbT = e.args[1]?.type;
|
|
4809
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4810
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4811
|
+
const p = cbT.params[0];
|
|
4812
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4813
|
+
}
|
|
4814
|
+
if (!ok) {
|
|
4815
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4816
|
+
}
|
|
4817
|
+
return true;
|
|
4818
|
+
}
|
|
4819
|
+
if (e.fn === "net.sockRead") {
|
|
4820
|
+
// Result is the interned `Buffer | null` union.
|
|
4821
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4822
|
+
const ok = def &&
|
|
4823
|
+
def.arms.length === 2 &&
|
|
4824
|
+
def.arms.some((a) => a.kind === "bytes" && a.elem === "u8") &&
|
|
4825
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
4826
|
+
if (!ok) {
|
|
4827
|
+
err(`libCall net.sockRead must return the 'Buffer | null' union`, e.loc);
|
|
4828
|
+
}
|
|
4829
|
+
return true;
|
|
4830
|
+
}
|
|
4831
|
+
if (e.fn === "http.serverOnUpgrade" || e.fn === "http.clientOnUpgrade" ||
|
|
4832
|
+
e.fn === "http.serverOnConnect") {
|
|
4833
|
+
// (req, socket, head) or any shorter prefix, void return. The
|
|
4834
|
+
// 'connect' registration additionally admits a socket slot
|
|
4835
|
+
// that is a UNION carrying a netSocket arm (the h2 compat
|
|
4836
|
+
// listener — the emitted adapter wraps the socket there).
|
|
4837
|
+
const cbT = e.args[1]?.type;
|
|
4838
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 3;
|
|
4839
|
+
if (ok && cbT?.kind === "func") {
|
|
4840
|
+
const [p0, p1, p2] = cbT.params;
|
|
4841
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4842
|
+
ok = false;
|
|
4843
|
+
if (p1 !== undefined && p1.kind !== "netSocket") {
|
|
4844
|
+
if (e.fn === "http.serverOnConnect" && p1?.kind === "union") {
|
|
4845
|
+
const def = unions.get(p1.unionId);
|
|
4846
|
+
if (!def || !def.arms.some((a) => a.kind === "netSocket"))
|
|
4232
4847
|
ok = false;
|
|
4233
4848
|
}
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
}
|
|
4237
|
-
break;
|
|
4238
|
-
}
|
|
4239
|
-
if (e.fn === "net.listenOptsCb" || e.fn === "net.listenOptsReusePortCb") {
|
|
4240
|
-
const cbIndex = e.fn === "net.listenOptsReusePortCb" ? 5 : 4;
|
|
4241
|
-
const t = e.args[cbIndex]?.type;
|
|
4242
|
-
const funcOk = (x) => x?.kind === "func" && x.params.length === 0 && x.ret.kind === "void";
|
|
4243
|
-
let ok = funcOk(t);
|
|
4244
|
-
if (!ok && t?.kind === "union") {
|
|
4245
|
-
const def = unions.get(t.unionId);
|
|
4246
|
-
ok = !!def && def.arms.length === 2 && def.arms.some((a) => funcOk(a)) &&
|
|
4247
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4248
|
-
}
|
|
4249
|
-
if (!ok) {
|
|
4250
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4251
|
-
}
|
|
4252
|
-
break;
|
|
4253
|
-
}
|
|
4254
|
-
if (e.fn === "net.connectLookup") {
|
|
4255
|
-
// The caller's resolver: (hostname: string, options: unknown,
|
|
4256
|
-
// callback: (err: <union>, addresses: <record[]>) => void) =>
|
|
4257
|
-
// void — the emitter synthesizes the answer thunk from these
|
|
4258
|
-
// types, so the structure must hold.
|
|
4259
|
-
const t = e.args[2]?.type;
|
|
4260
|
-
let ok = t?.kind === "func" && t.ret.kind === "void" && t.params.length === 3 &&
|
|
4261
|
-
t.params[0].kind === "string" && t.params[1].kind === "dyn";
|
|
4262
|
-
if (ok && t?.kind === "func") {
|
|
4263
|
-
const cbT = t.params[2];
|
|
4264
|
-
ok = cbT.kind === "func" && cbT.ret.kind === "void" && cbT.params.length === 2 &&
|
|
4265
|
-
cbT.params[0].kind === "union" &&
|
|
4266
|
-
cbT.params[1].kind === "array" && cbT.params[1].elem.kind === "record";
|
|
4267
|
-
}
|
|
4268
|
-
if (!ok) {
|
|
4269
|
-
err(`libCall net.connectLookup resolver shape (frontend must fence)`, e.loc);
|
|
4270
|
-
}
|
|
4271
|
-
break;
|
|
4272
|
-
}
|
|
4273
|
-
if (e.fn === "http.requestConn" || e.fn === "http.requestConnCb") {
|
|
4274
|
-
const dialT = e.args[0]?.type;
|
|
4275
|
-
if (!(dialT?.kind === "func" && dialT.params.length === 0 && dialT.ret.kind === "netSocket")) {
|
|
4276
|
-
err(`libCall ${e.fn} dialer shape (frontend must fence)`, e.loc);
|
|
4277
|
-
break;
|
|
4278
|
-
}
|
|
4279
|
-
if (e.fn === "http.requestConnCb") {
|
|
4280
|
-
const cbT = e.args[6]?.type;
|
|
4281
|
-
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1 &&
|
|
4282
|
-
(cbT.params[0] === undefined || cbT.params[0].kind === "httpReq");
|
|
4283
|
-
if (!ok)
|
|
4284
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4285
|
-
}
|
|
4286
|
-
break;
|
|
4287
|
-
}
|
|
4288
|
-
if (e.fn === "http.reqStatusMessage" || e.fn === "http.resStatusMsgGet") {
|
|
4289
|
-
// Result is the interned `string | undefined` union (reqHeader's).
|
|
4290
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4291
|
-
const ok = def &&
|
|
4292
|
-
def.arms.length === 2 &&
|
|
4293
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4294
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4295
|
-
if (!ok) {
|
|
4296
|
-
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4849
|
+
else {
|
|
4850
|
+
ok = false;
|
|
4297
4851
|
}
|
|
4298
|
-
break;
|
|
4299
4852
|
}
|
|
4300
|
-
if (
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4853
|
+
if (p2 !== undefined && !(p2.kind === "bytes" && p2.elem === "u8"))
|
|
4854
|
+
ok = false;
|
|
4855
|
+
}
|
|
4856
|
+
if (!ok) {
|
|
4857
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4858
|
+
}
|
|
4859
|
+
return true;
|
|
4860
|
+
}
|
|
4861
|
+
if (e.fn === "net.listenOptsCb" || e.fn === "net.listenOptsReusePortCb") {
|
|
4862
|
+
const cbIndex = e.fn === "net.listenOptsReusePortCb" ? 5 : 4;
|
|
4863
|
+
const t = e.args[cbIndex]?.type;
|
|
4864
|
+
const funcOk = (x) => x?.kind === "func" && x.params.length === 0 && x.ret.kind === "void";
|
|
4865
|
+
let ok = funcOk(t);
|
|
4866
|
+
if (!ok && t?.kind === "union") {
|
|
4867
|
+
const def = unions.get(t.unionId);
|
|
4868
|
+
ok = !!def && def.arms.length === 2 && def.arms.some((a) => funcOk(a)) &&
|
|
4869
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4870
|
+
}
|
|
4871
|
+
if (!ok) {
|
|
4872
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4873
|
+
}
|
|
4874
|
+
return true;
|
|
4875
|
+
}
|
|
4876
|
+
if (e.fn === "net.connectLookup") {
|
|
4877
|
+
// The caller's resolver: (hostname: string, options: unknown,
|
|
4878
|
+
// callback: (err: <union>, addresses: <record[]>) => void) =>
|
|
4879
|
+
// void — the emitter synthesizes the answer thunk from these
|
|
4880
|
+
// types, so the structure must hold.
|
|
4881
|
+
const t = e.args[2]?.type;
|
|
4882
|
+
let ok = t?.kind === "func" && t.ret.kind === "void" && t.params.length === 3 &&
|
|
4883
|
+
t.params[0].kind === "string" && t.params[1].kind === "dyn";
|
|
4884
|
+
if (ok && t?.kind === "func") {
|
|
4885
|
+
const cbT = t.params[2];
|
|
4886
|
+
ok = cbT.kind === "func" && cbT.ret.kind === "void" && cbT.params.length === 2 &&
|
|
4887
|
+
cbT.params[0].kind === "union" &&
|
|
4888
|
+
cbT.params[1].kind === "array" && cbT.params[1].elem.kind === "record";
|
|
4889
|
+
}
|
|
4890
|
+
if (!ok) {
|
|
4891
|
+
err(`libCall net.connectLookup resolver shape (frontend must fence)`, e.loc);
|
|
4892
|
+
}
|
|
4893
|
+
return true;
|
|
4894
|
+
}
|
|
4895
|
+
if (e.fn === "http.requestConn" || e.fn === "http.requestConnCb") {
|
|
4896
|
+
const dialT = e.args[0]?.type;
|
|
4897
|
+
if (!(dialT?.kind === "func" && dialT.params.length === 0 && dialT.ret.kind === "netSocket")) {
|
|
4898
|
+
err(`libCall ${e.fn} dialer shape (frontend must fence)`, e.loc);
|
|
4899
|
+
return true;
|
|
4900
|
+
}
|
|
4901
|
+
if (e.fn === "http.requestConnCb") {
|
|
4902
|
+
const cbT = e.args[6]?.type;
|
|
4903
|
+
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1 &&
|
|
4904
|
+
(cbT.params[0] === undefined || cbT.params[0].kind === "httpReq");
|
|
4905
|
+
if (!ok)
|
|
4906
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4907
|
+
}
|
|
4908
|
+
return true;
|
|
4909
|
+
}
|
|
4910
|
+
if (e.fn === "http.reqStatusMessage" || e.fn === "http.resStatusMsgGet") {
|
|
4911
|
+
// Result is the interned `string | undefined` union (reqHeader's).
|
|
4912
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4913
|
+
const ok = def &&
|
|
4914
|
+
def.arms.length === 2 &&
|
|
4915
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
4916
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4917
|
+
if (!ok) {
|
|
4918
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4919
|
+
}
|
|
4920
|
+
return true;
|
|
4921
|
+
}
|
|
4922
|
+
if (e.fn === "http.resSocket") {
|
|
4923
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4924
|
+
const ok = def && def.arms.length === 2 &&
|
|
4925
|
+
def.arms.some((a) => a.kind === "netSocket") &&
|
|
4926
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
4927
|
+
if (!ok)
|
|
4928
|
+
err(`libCall http.resSocket must return the 'Socket | null' union`, e.loc);
|
|
4929
|
+
return true;
|
|
4930
|
+
}
|
|
4931
|
+
if (e.fn === "http.reqH2Stream") {
|
|
4932
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4933
|
+
const ok = def && def.arms.length === 2 &&
|
|
4934
|
+
def.arms.some((a) => a.kind === "http2Stream") &&
|
|
4935
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4936
|
+
if (!ok)
|
|
4937
|
+
err(`libCall http.reqH2Stream must return the 'Http2Stream | undefined' union`, e.loc);
|
|
4938
|
+
return true;
|
|
4939
|
+
}
|
|
4940
|
+
if (e.fn === "http.reqHeader" || e.fn === "http.reqTrailer" || e.fn === "http.resGetHeader" || e.fn === "http.clientGetHeader") {
|
|
4941
|
+
// Result is the interned `string | undefined` union (envGet's).
|
|
4942
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4943
|
+
const ok = def &&
|
|
4944
|
+
def.arms.length === 2 &&
|
|
4945
|
+
def.arms[0].kind === "string" &&
|
|
4946
|
+
def.arms[1].kind === "undefinedT";
|
|
4947
|
+
if (!ok) {
|
|
4948
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4949
|
+
}
|
|
4950
|
+
return true;
|
|
4951
|
+
}
|
|
4952
|
+
if (e.fn === "http.reqHeaderValues" || e.fn === "http.reqTrailerValues") {
|
|
4953
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4954
|
+
const ok = def && def.arms.length === 2 &&
|
|
4955
|
+
def.arms[0].kind === "array" && def.arms[0].elem.kind === "string" &&
|
|
4956
|
+
def.arms[1].kind === "undefinedT";
|
|
4957
|
+
if (!ok)
|
|
4958
|
+
err(`libCall ${e.fn} must return the 'string[] | undefined' union`, e.loc);
|
|
4959
|
+
return true;
|
|
4960
|
+
}
|
|
4961
|
+
if (e.fn === "net.createServerCb" || e.fn === "net.serverOnConnection" ||
|
|
4962
|
+
e.fn === "net.serverOnSecureConnection" ||
|
|
4963
|
+
e.fn === "http.serverSetTimeoutCb" || e.fn === "http.serverOnTimeout" ||
|
|
4964
|
+
e.fn === "http.clientOnSocket" ||
|
|
4965
|
+
e.fn === "net.sockOnData" || e.fn === "net.serverOnError" ||
|
|
4966
|
+
e.fn === "net.sockOnError") {
|
|
4967
|
+
// The program-dependent listener shapes: a void closure with no
|
|
4968
|
+
// params, or exactly the one supported parameter per event
|
|
4969
|
+
// (socket handle / data chunk bytes / error %Error). The
|
|
4970
|
+
// callback slot is arg 0 for createServerCb, arg 1 otherwise.
|
|
4971
|
+
const cbT = e.args[e.fn === "net.createServerCb" ? 0 : e.fn === "http.serverSetTimeoutCb" ? 2 : 1]?.type;
|
|
4972
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4973
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4974
|
+
const p = cbT.params[0];
|
|
4975
|
+
if (e.fn === "net.sockOnData")
|
|
4976
|
+
ok = (p.kind === "bytes" && p.elem === "u8") || p.kind === "dyn";
|
|
4977
|
+
else if (e.fn === "net.serverOnError" || e.fn === "net.sockOnError") {
|
|
4978
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4979
|
+
}
|
|
4980
|
+
else
|
|
4981
|
+
ok = p.kind === "netSocket";
|
|
4982
|
+
}
|
|
4983
|
+
if (!ok) {
|
|
4984
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4985
|
+
}
|
|
4986
|
+
return true;
|
|
4987
|
+
}
|
|
4988
|
+
if (e.fn === "http2.createSecureServerSni") {
|
|
4989
|
+
// The SNI callback: (servername: string, cb: (err, ctx?) => void)
|
|
4990
|
+
// => void — as a bare func, or the `| undefined` union from the
|
|
4991
|
+
// conditional-spread spelling (exactly two arms: the func and
|
|
4992
|
+
// undefined). The cb's own params are program-interned unions
|
|
4993
|
+
// (Error|null, SecureContext|undefined) whose arms the emitted
|
|
4994
|
+
// answer thunk decodes; here the structural func shape is what
|
|
4995
|
+
// the validator can pin.
|
|
4996
|
+
const sniOk = (t) => t?.kind === "func" && t.ret.kind === "void" && t.params.length === 2 &&
|
|
4997
|
+
t.params[0].kind === "string" && t.params[1].kind === "func";
|
|
4998
|
+
const argT = e.args[2]?.type;
|
|
4999
|
+
let ok = sniOk(argT);
|
|
5000
|
+
if (!ok && argT?.kind === "union") {
|
|
5001
|
+
const def = unions.get(argT.unionId);
|
|
5002
|
+
ok = def !== undefined && def.arms.length === 2 &&
|
|
5003
|
+
def.arms.some((a) => a.kind === "undefinedT") &&
|
|
5004
|
+
def.arms.some((a) => sniOk(a));
|
|
5005
|
+
}
|
|
5006
|
+
if (!ok) {
|
|
5007
|
+
err(`libCall ${e.fn} SNI callback shape (frontend must fence)`, e.loc);
|
|
5008
|
+
}
|
|
5009
|
+
return true;
|
|
5010
|
+
}
|
|
5011
|
+
if (e.fn === "dgram.onMessage" || e.fn === "dgram.onError") {
|
|
5012
|
+
// The dgram listener shapes: a void closure with no params, or
|
|
5013
|
+
// the per-event parameter shapes — message takes (msg: bytes<u8>
|
|
5014
|
+
// [, rinfo: record]), error the one %Error param.
|
|
5015
|
+
const cbT = e.args[1]?.type;
|
|
5016
|
+
const maxParams = e.fn === "dgram.onMessage" ? 2 : 1;
|
|
5017
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
5018
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5019
|
+
if (e.fn === "dgram.onMessage") {
|
|
5020
|
+
const p0 = cbT.params[0];
|
|
5021
|
+
ok = p0.kind === "bytes" && p0.elem === "u8";
|
|
5022
|
+
const p1 = cbT.params[1];
|
|
5023
|
+
if (ok && p1 !== undefined)
|
|
5024
|
+
ok = p1.kind === "record";
|
|
4308
5025
|
}
|
|
4309
|
-
|
|
4310
|
-
const
|
|
4311
|
-
|
|
4312
|
-
def.arms.some((a) => a.kind === "http2Stream") &&
|
|
4313
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4314
|
-
if (!ok)
|
|
4315
|
-
err(`libCall http.reqH2Stream must return the 'Http2Stream | undefined' union`, e.loc);
|
|
4316
|
-
break;
|
|
5026
|
+
else {
|
|
5027
|
+
const p = cbT.params[0];
|
|
5028
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4317
5029
|
}
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
5030
|
+
}
|
|
5031
|
+
if (!ok) {
|
|
5032
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5033
|
+
}
|
|
5034
|
+
return true;
|
|
5035
|
+
}
|
|
5036
|
+
if (e.fn === "dns.lookup") {
|
|
5037
|
+
// The callback: void, at most (err: Error | null, address:
|
|
5038
|
+
// string, family: number).
|
|
5039
|
+
const cbT = e.args[2]?.type;
|
|
5040
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 3;
|
|
5041
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5042
|
+
const p0 = cbT.params[0];
|
|
5043
|
+
const def = p0.kind === "union" ? unions.get(p0.unionId) : undefined;
|
|
5044
|
+
ok =
|
|
5045
|
+
def !== undefined &&
|
|
4322
5046
|
def.arms.length === 2 &&
|
|
4323
|
-
def.arms
|
|
4324
|
-
def.arms
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
5047
|
+
def.arms.some((a) => a.kind === "nullT") &&
|
|
5048
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error");
|
|
5049
|
+
const p1 = cbT.params[1];
|
|
5050
|
+
if (ok && p1 !== undefined)
|
|
5051
|
+
ok = p1.kind === "string";
|
|
5052
|
+
const p2 = cbT.params[2];
|
|
5053
|
+
if (ok && p2 !== undefined)
|
|
5054
|
+
ok = p2.kind === "f64";
|
|
5055
|
+
}
|
|
5056
|
+
if (!ok) {
|
|
5057
|
+
err(`libCall dns.lookup callback shape (frontend must fence)`, e.loc);
|
|
5058
|
+
}
|
|
5059
|
+
return true;
|
|
5060
|
+
}
|
|
5061
|
+
return false;
|
|
5062
|
+
}
|
|
5063
|
+
function checkLibFileCall(e) {
|
|
5064
|
+
if (e.fn === "zlib.deflateCb" || e.fn === "zlib.inflateCb" ||
|
|
5065
|
+
e.fn === "zlib.deflateRawCb" || e.fn === "zlib.inflateRawCb" ||
|
|
5066
|
+
e.fn === "zlib.gzipCb" || e.fn === "zlib.gunzipCb" || e.fn === "zlib.unzipCb") {
|
|
5067
|
+
const cbT = e.args[1]?.type;
|
|
5068
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
5069
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5070
|
+
const error = cbT.params[0];
|
|
5071
|
+
if (error.kind !== "dyn") {
|
|
5072
|
+
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
5073
|
+
ok = def !== undefined &&
|
|
5074
|
+
def.arms.some((arm) => arm.kind === "nullT") &&
|
|
5075
|
+
def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error") &&
|
|
5076
|
+
def.arms.every((arm) => arm.kind === "nullT" || arm.kind === "undefinedT" ||
|
|
5077
|
+
(arm.kind === "object" && arm.className === "%Error"));
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 2) {
|
|
5081
|
+
const value = cbT.params[1];
|
|
5082
|
+
ok = value.kind === "dyn" || (value.kind === "bytes" && value.elem === "u8");
|
|
5083
|
+
}
|
|
5084
|
+
if (!ok)
|
|
5085
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5086
|
+
return true;
|
|
5087
|
+
}
|
|
5088
|
+
if (e.fn === "fs.renameCb" ||
|
|
5089
|
+
e.fn === "process.stdoutWriteBytesCb" ||
|
|
5090
|
+
e.fn === "process.stderrWriteBytesCb") {
|
|
5091
|
+
// The callback is void and accepts either no parameters, one
|
|
5092
|
+
// checked-dynamic error slot (JS), or Error | null (optionally
|
|
5093
|
+
// including undefined for an explicitly optional parameter).
|
|
5094
|
+
const cbT = e.args[2]?.type;
|
|
5095
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
5096
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5097
|
+
const p = cbT.params[0];
|
|
5098
|
+
if (p.kind === "dyn") {
|
|
5099
|
+
ok = true;
|
|
4329
5100
|
}
|
|
4330
|
-
|
|
4331
|
-
const def =
|
|
4332
|
-
|
|
4333
|
-
def
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
5101
|
+
else {
|
|
5102
|
+
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
5103
|
+
ok =
|
|
5104
|
+
def !== undefined &&
|
|
5105
|
+
def.arms.some((a) => a.kind === "nullT") &&
|
|
5106
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
5107
|
+
def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
|
|
5108
|
+
(a.kind === "object" && a.className === "%Error"));
|
|
4338
5109
|
}
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
5110
|
+
}
|
|
5111
|
+
if (!ok) {
|
|
5112
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5113
|
+
}
|
|
5114
|
+
return true;
|
|
5115
|
+
}
|
|
5116
|
+
if (e.fn === "net.serverAddress") {
|
|
5117
|
+
// Result is the {address, family, port} record (dgram.address's
|
|
5118
|
+
// check, another receiver).
|
|
5119
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5120
|
+
const ok = shape !== undefined &&
|
|
5121
|
+
shape.fields.length === 3 &&
|
|
5122
|
+
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
5123
|
+
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
5124
|
+
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
5125
|
+
if (!ok) {
|
|
5126
|
+
err(`libCall net.serverAddress must return the {address, family, port} record`, e.loc);
|
|
5127
|
+
}
|
|
5128
|
+
return true;
|
|
5129
|
+
}
|
|
5130
|
+
if (e.fn === "dgram.address") {
|
|
5131
|
+
// Result is the {address, family, port} record.
|
|
5132
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5133
|
+
const ok = shape !== undefined &&
|
|
5134
|
+
shape.fields.length === 3 &&
|
|
5135
|
+
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
5136
|
+
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
5137
|
+
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
5138
|
+
if (!ok) {
|
|
5139
|
+
err(`libCall dgram.address must return the {address, family, port} record`, e.loc);
|
|
5140
|
+
}
|
|
5141
|
+
return true;
|
|
5142
|
+
}
|
|
5143
|
+
if (e.fn === "fs.readdirTypesSync" || e.fn === "fsp.readdirTypes") {
|
|
5144
|
+
// Result: the interned Dirent record array — {%dtype: f64,
|
|
5145
|
+
// name: string, parentPath: string} rows (canonical field
|
|
5146
|
+
// order; the structure lowerFsReaddirTypesCall pinned).
|
|
5147
|
+
const result = e.fn === "fsp.readdirTypes"
|
|
5148
|
+
? e.type.kind === "promise" ? e.type.inner : undefined
|
|
5149
|
+
: e.type;
|
|
5150
|
+
const shape = result?.kind === "array" && result.elem.kind === "record"
|
|
5151
|
+
? records.get(result.elem.shapeId)
|
|
5152
|
+
: undefined;
|
|
5153
|
+
const ok = shape !== undefined &&
|
|
5154
|
+
!shape.tuple &&
|
|
5155
|
+
shape.indexValue === undefined &&
|
|
5156
|
+
shape.fields.length === 3 &&
|
|
5157
|
+
shape.fields[0].name === "%dtype" && shape.fields[0].type.kind === "f64" &&
|
|
5158
|
+
shape.fields[1].name === "name" && shape.fields[1].type.kind === "string" &&
|
|
5159
|
+
shape.fields[2].name === "parentPath" && shape.fields[2].type.kind === "string";
|
|
5160
|
+
if (!ok) {
|
|
5161
|
+
err(`libCall ${e.fn} must return ${e.fn === "fsp.readdirTypes" ? "a promise of " : ""}the Dirent record array`, e.loc);
|
|
5162
|
+
}
|
|
5163
|
+
return true;
|
|
5164
|
+
}
|
|
5165
|
+
if (e.fn === "os.networkInterfaces") {
|
|
5166
|
+
// Result: a pure index-signature record whose value is
|
|
5167
|
+
// `Info[] | undefined`, Info a two-record union (one arm's
|
|
5168
|
+
// scopeid f64, the other's `number | undefined`) — the structure
|
|
5169
|
+
// lowerOsNetworkInterfacesCall pinned.
|
|
5170
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5171
|
+
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
5172
|
+
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
5173
|
+
const arrArm = ivDef?.arms.find((a) => a.kind === "array");
|
|
5174
|
+
ok = ok && ivDef !== undefined && ivDef.arms.length === 2 && arrArm !== undefined && ivDef.arms.some((a) => a.kind === "undefinedT");
|
|
5175
|
+
const infoDef = ok && arrArm.kind === "array" && arrArm.elem.kind === "union" ? unions.get(arrArm.elem.unionId) : undefined;
|
|
5176
|
+
ok = ok && infoDef !== undefined && infoDef.arms.length === 2 && infoDef.arms.every((a) => a.kind === "record");
|
|
5177
|
+
if (!ok) {
|
|
5178
|
+
err(`libCall os.networkInterfaces must return the NetworkInterfaceInfo dictionary record`, e.loc);
|
|
5179
|
+
}
|
|
5180
|
+
return true;
|
|
5181
|
+
}
|
|
5182
|
+
if (e.fn === "qs.parse") {
|
|
5183
|
+
// Result: a pure index-signature record whose value union
|
|
5184
|
+
// carries a string arm and a string[] arm (undefined tolerated
|
|
5185
|
+
// — @types/node's Dict — and f64 too: the header-family
|
|
5186
|
+
// canonicalization interns every such dictionary with the
|
|
5187
|
+
// number arm, type-level only) — the structure
|
|
5188
|
+
// lowerQuerystringParseCall pinned.
|
|
5189
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5190
|
+
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
5191
|
+
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
5192
|
+
ok = ok && ivDef !== undefined &&
|
|
5193
|
+
ivDef.arms.some((a) => a.kind === "string") &&
|
|
5194
|
+
ivDef.arms.some((a) => a.kind === "array" && a.elem.kind === "string") &&
|
|
5195
|
+
ivDef.arms.every((a) => a.kind === "string" || a.kind === "array" || a.kind === "undefinedT" || a.kind === "f64");
|
|
5196
|
+
if (!ok) {
|
|
5197
|
+
err(`libCall qs.parse must return the ParsedUrlQuery dictionary record`, e.loc);
|
|
5198
|
+
}
|
|
5199
|
+
return true;
|
|
5200
|
+
}
|
|
5201
|
+
return false;
|
|
5202
|
+
}
|
|
5203
|
+
function checkLibProcessCall(e) {
|
|
5204
|
+
if (e.fn === "cp.execFile") {
|
|
5205
|
+
const cb = e.args[2]?.type;
|
|
5206
|
+
if (cb?.kind !== "func" || cb.rest === true || cb.params.length > 3 || cb.ret.kind !== "void") {
|
|
5207
|
+
err(`libCall cp.execFile callback must be a non-rest void function with at most three parameters`, e.loc);
|
|
5208
|
+
}
|
|
5209
|
+
else {
|
|
5210
|
+
const error = cb.params[0];
|
|
5211
|
+
if (error !== undefined) {
|
|
5212
|
+
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
5213
|
+
if (!def || def.arms.length !== 2 ||
|
|
5214
|
+
!def.arms.some((arm) => arm.kind === "nullT") ||
|
|
5215
|
+
!def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error")) {
|
|
5216
|
+
err(`libCall cp.execFile callback error parameter must be Error | null`, e.loc);
|
|
4363
5217
|
}
|
|
4364
|
-
break;
|
|
4365
5218
|
}
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
// conditional-spread spelling (exactly two arms: the func and
|
|
4370
|
-
// undefined). The cb's own params are program-interned unions
|
|
4371
|
-
// (Error|null, SecureContext|undefined) whose arms the emitted
|
|
4372
|
-
// answer thunk decodes; here the structural func shape is what
|
|
4373
|
-
// the validator can pin.
|
|
4374
|
-
const sniOk = (t) => t?.kind === "func" && t.ret.kind === "void" && t.params.length === 2 &&
|
|
4375
|
-
t.params[0].kind === "string" && t.params[1].kind === "func";
|
|
4376
|
-
const argT = e.args[2]?.type;
|
|
4377
|
-
let ok = sniOk(argT);
|
|
4378
|
-
if (!ok && argT?.kind === "union") {
|
|
4379
|
-
const def = unions.get(argT.unionId);
|
|
4380
|
-
ok = def !== undefined && def.arms.length === 2 &&
|
|
4381
|
-
def.arms.some((a) => a.kind === "undefinedT") &&
|
|
4382
|
-
def.arms.some((a) => sniOk(a));
|
|
4383
|
-
}
|
|
4384
|
-
if (!ok) {
|
|
4385
|
-
err(`libCall ${e.fn} SNI callback shape (frontend must fence)`, e.loc);
|
|
4386
|
-
}
|
|
4387
|
-
break;
|
|
5219
|
+
const stdout = cb.params[1];
|
|
5220
|
+
if (stdout !== undefined && stdout.kind !== "string") {
|
|
5221
|
+
err(`libCall cp.execFile callback stdout parameter must be string`, e.loc);
|
|
4388
5222
|
}
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
// [, rinfo: record]), error the one %Error param.
|
|
4393
|
-
const cbT = e.args[1]?.type;
|
|
4394
|
-
const maxParams = e.fn === "dgram.onMessage" ? 2 : 1;
|
|
4395
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4396
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4397
|
-
if (e.fn === "dgram.onMessage") {
|
|
4398
|
-
const p0 = cbT.params[0];
|
|
4399
|
-
ok = p0.kind === "bytes" && p0.elem === "u8";
|
|
4400
|
-
const p1 = cbT.params[1];
|
|
4401
|
-
if (ok && p1 !== undefined)
|
|
4402
|
-
ok = p1.kind === "record";
|
|
4403
|
-
}
|
|
4404
|
-
else {
|
|
4405
|
-
const p = cbT.params[0];
|
|
4406
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4407
|
-
}
|
|
4408
|
-
}
|
|
4409
|
-
if (!ok) {
|
|
4410
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4411
|
-
}
|
|
4412
|
-
break;
|
|
5223
|
+
const stderr = cb.params[2];
|
|
5224
|
+
if (stderr !== undefined && stderr.kind !== "string") {
|
|
5225
|
+
err(`libCall cp.execFile callback stderr parameter must be string`, e.loc);
|
|
4413
5226
|
}
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
5227
|
+
}
|
|
5228
|
+
}
|
|
5229
|
+
if (e.fn === "child.onSpawn") {
|
|
5230
|
+
const cb = e.args[1];
|
|
5231
|
+
if (!cb || cb.type.kind !== "func" || cb.type.params.length !== 0 || cb.type.ret.kind !== "void")
|
|
5232
|
+
err("child.onSpawn callback must be () => void", e.loc);
|
|
5233
|
+
}
|
|
5234
|
+
if (e.fn === "child.onExit" || e.fn === "child.onClose" || e.fn === "child.onError") {
|
|
5235
|
+
// The listener: a closure with no params, or exactly the
|
|
5236
|
+
// supported parameter shapes per event — exit takes (code:
|
|
5237
|
+
// number | null) with an optional (signal: string | null)
|
|
5238
|
+
// second parameter, error exactly (err: %Error).
|
|
5239
|
+
const cb = e.args[1];
|
|
5240
|
+
const cbT = cb?.type;
|
|
5241
|
+
const maxParams = e.fn === "child.onError" ? 1 : 2;
|
|
5242
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
5243
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5244
|
+
const p = cbT.params[0];
|
|
5245
|
+
if (e.fn === "child.onExit" || e.fn === "child.onClose") {
|
|
5246
|
+
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
5247
|
+
ok =
|
|
5248
|
+
def !== undefined &&
|
|
5249
|
+
def.arms.length === 2 &&
|
|
5250
|
+
def.arms[0].kind === "f64" &&
|
|
5251
|
+
def.arms[1].kind === "nullT";
|
|
5252
|
+
if (ok && cbT.params.length === 2) {
|
|
5253
|
+
const s = cbT.params[1];
|
|
5254
|
+
const sdef = s.kind === "union" ? unions.get(s.unionId) : undefined;
|
|
4422
5255
|
ok =
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
const p1 = cbT.params[1];
|
|
4428
|
-
if (ok && p1 !== undefined)
|
|
4429
|
-
ok = p1.kind === "string";
|
|
4430
|
-
const p2 = cbT.params[2];
|
|
4431
|
-
if (ok && p2 !== undefined)
|
|
4432
|
-
ok = p2.kind === "f64";
|
|
4433
|
-
}
|
|
4434
|
-
if (!ok) {
|
|
4435
|
-
err(`libCall dns.lookup callback shape (frontend must fence)`, e.loc);
|
|
4436
|
-
}
|
|
4437
|
-
break;
|
|
4438
|
-
}
|
|
4439
|
-
if (e.fn === "zlib.deflateCb" || e.fn === "zlib.inflateCb" ||
|
|
4440
|
-
e.fn === "zlib.deflateRawCb" || e.fn === "zlib.inflateRawCb" ||
|
|
4441
|
-
e.fn === "zlib.gzipCb" || e.fn === "zlib.gunzipCb" || e.fn === "zlib.unzipCb") {
|
|
4442
|
-
const cbT = e.args[1]?.type;
|
|
4443
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4444
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4445
|
-
const error = cbT.params[0];
|
|
4446
|
-
if (error.kind !== "dyn") {
|
|
4447
|
-
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
4448
|
-
ok = def !== undefined &&
|
|
4449
|
-
def.arms.some((arm) => arm.kind === "nullT") &&
|
|
4450
|
-
def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error") &&
|
|
4451
|
-
def.arms.every((arm) => arm.kind === "nullT" || arm.kind === "undefinedT" ||
|
|
4452
|
-
(arm.kind === "object" && arm.className === "%Error"));
|
|
4453
|
-
}
|
|
4454
|
-
}
|
|
4455
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 2) {
|
|
4456
|
-
const value = cbT.params[1];
|
|
4457
|
-
ok = value.kind === "dyn" || (value.kind === "bytes" && value.elem === "u8");
|
|
4458
|
-
}
|
|
4459
|
-
if (!ok)
|
|
4460
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4461
|
-
break;
|
|
4462
|
-
}
|
|
4463
|
-
if (e.fn === "fs.renameCb" ||
|
|
4464
|
-
e.fn === "process.stdoutWriteBytesCb" ||
|
|
4465
|
-
e.fn === "process.stderrWriteBytesCb") {
|
|
4466
|
-
// The callback is void and accepts either no parameters, one
|
|
4467
|
-
// checked-dynamic error slot (JS), or Error | null (optionally
|
|
4468
|
-
// including undefined for an explicitly optional parameter).
|
|
4469
|
-
const cbT = e.args[2]?.type;
|
|
4470
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4471
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4472
|
-
const p = cbT.params[0];
|
|
4473
|
-
if (p.kind === "dyn") {
|
|
4474
|
-
ok = true;
|
|
4475
|
-
}
|
|
4476
|
-
else {
|
|
4477
|
-
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
4478
|
-
ok =
|
|
4479
|
-
def !== undefined &&
|
|
4480
|
-
def.arms.some((a) => a.kind === "nullT") &&
|
|
4481
|
-
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
4482
|
-
def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
|
|
4483
|
-
(a.kind === "object" && a.className === "%Error"));
|
|
4484
|
-
}
|
|
4485
|
-
}
|
|
4486
|
-
if (!ok) {
|
|
4487
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4488
|
-
}
|
|
4489
|
-
break;
|
|
4490
|
-
}
|
|
4491
|
-
if (e.fn === "net.serverAddress") {
|
|
4492
|
-
// Result is the {address, family, port} record (dgram.address's
|
|
4493
|
-
// check, another receiver).
|
|
4494
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4495
|
-
const ok = shape !== undefined &&
|
|
4496
|
-
shape.fields.length === 3 &&
|
|
4497
|
-
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
4498
|
-
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
4499
|
-
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
4500
|
-
if (!ok) {
|
|
4501
|
-
err(`libCall net.serverAddress must return the {address, family, port} record`, e.loc);
|
|
4502
|
-
}
|
|
4503
|
-
break;
|
|
4504
|
-
}
|
|
4505
|
-
if (e.fn === "dgram.address") {
|
|
4506
|
-
// Result is the {address, family, port} record.
|
|
4507
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4508
|
-
const ok = shape !== undefined &&
|
|
4509
|
-
shape.fields.length === 3 &&
|
|
4510
|
-
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
4511
|
-
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
4512
|
-
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
4513
|
-
if (!ok) {
|
|
4514
|
-
err(`libCall dgram.address must return the {address, family, port} record`, e.loc);
|
|
4515
|
-
}
|
|
4516
|
-
break;
|
|
4517
|
-
}
|
|
4518
|
-
if (e.fn === "fs.readdirTypesSync" || e.fn === "fsp.readdirTypes") {
|
|
4519
|
-
// Result: the interned Dirent record array — {%dtype: f64,
|
|
4520
|
-
// name: string, parentPath: string} rows (canonical field
|
|
4521
|
-
// order; the structure lowerFsReaddirTypesCall pinned).
|
|
4522
|
-
const result = e.fn === "fsp.readdirTypes"
|
|
4523
|
-
? e.type.kind === "promise" ? e.type.inner : undefined
|
|
4524
|
-
: e.type;
|
|
4525
|
-
const shape = result?.kind === "array" && result.elem.kind === "record"
|
|
4526
|
-
? records.get(result.elem.shapeId)
|
|
4527
|
-
: undefined;
|
|
4528
|
-
const ok = shape !== undefined &&
|
|
4529
|
-
!shape.tuple &&
|
|
4530
|
-
shape.indexValue === undefined &&
|
|
4531
|
-
shape.fields.length === 3 &&
|
|
4532
|
-
shape.fields[0].name === "%dtype" && shape.fields[0].type.kind === "f64" &&
|
|
4533
|
-
shape.fields[1].name === "name" && shape.fields[1].type.kind === "string" &&
|
|
4534
|
-
shape.fields[2].name === "parentPath" && shape.fields[2].type.kind === "string";
|
|
4535
|
-
if (!ok) {
|
|
4536
|
-
err(`libCall ${e.fn} must return ${e.fn === "fsp.readdirTypes" ? "a promise of " : ""}the Dirent record array`, e.loc);
|
|
4537
|
-
}
|
|
4538
|
-
break;
|
|
4539
|
-
}
|
|
4540
|
-
if (e.fn === "os.networkInterfaces") {
|
|
4541
|
-
// Result: a pure index-signature record whose value is
|
|
4542
|
-
// `Info[] | undefined`, Info a two-record union (one arm's
|
|
4543
|
-
// scopeid f64, the other's `number | undefined`) — the structure
|
|
4544
|
-
// lowerOsNetworkInterfacesCall pinned.
|
|
4545
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4546
|
-
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
4547
|
-
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
4548
|
-
const arrArm = ivDef?.arms.find((a) => a.kind === "array");
|
|
4549
|
-
ok = ok && ivDef !== undefined && ivDef.arms.length === 2 && arrArm !== undefined && ivDef.arms.some((a) => a.kind === "undefinedT");
|
|
4550
|
-
const infoDef = ok && arrArm.kind === "array" && arrArm.elem.kind === "union" ? unions.get(arrArm.elem.unionId) : undefined;
|
|
4551
|
-
ok = ok && infoDef !== undefined && infoDef.arms.length === 2 && infoDef.arms.every((a) => a.kind === "record");
|
|
4552
|
-
if (!ok) {
|
|
4553
|
-
err(`libCall os.networkInterfaces must return the NetworkInterfaceInfo dictionary record`, e.loc);
|
|
4554
|
-
}
|
|
4555
|
-
break;
|
|
4556
|
-
}
|
|
4557
|
-
if (e.fn === "qs.parse") {
|
|
4558
|
-
// Result: a pure index-signature record whose value union
|
|
4559
|
-
// carries a string arm and a string[] arm (undefined tolerated
|
|
4560
|
-
// — @types/node's Dict — and f64 too: the header-family
|
|
4561
|
-
// canonicalization interns every such dictionary with the
|
|
4562
|
-
// number arm, type-level only) — the structure
|
|
4563
|
-
// lowerQuerystringParseCall pinned.
|
|
4564
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4565
|
-
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
4566
|
-
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
4567
|
-
ok = ok && ivDef !== undefined &&
|
|
4568
|
-
ivDef.arms.some((a) => a.kind === "string") &&
|
|
4569
|
-
ivDef.arms.some((a) => a.kind === "array" && a.elem.kind === "string") &&
|
|
4570
|
-
ivDef.arms.every((a) => a.kind === "string" || a.kind === "array" || a.kind === "undefinedT" || a.kind === "f64");
|
|
4571
|
-
if (!ok) {
|
|
4572
|
-
err(`libCall qs.parse must return the ParsedUrlQuery dictionary record`, e.loc);
|
|
5256
|
+
sdef !== undefined &&
|
|
5257
|
+
sdef.arms.length === 2 &&
|
|
5258
|
+
sdef.arms.some((a) => a.kind === "string") &&
|
|
5259
|
+
sdef.arms.some((a) => a.kind === "nullT");
|
|
4573
5260
|
}
|
|
4574
|
-
break;
|
|
4575
|
-
}
|
|
4576
|
-
if (e.fn === "cp.execFile") {
|
|
4577
|
-
const cb = e.args[2]?.type;
|
|
4578
|
-
if (cb?.kind !== "func" || cb.rest === true || cb.params.length > 3 || cb.ret.kind !== "void") {
|
|
4579
|
-
err(`libCall cp.execFile callback must be a non-rest void function with at most three parameters`, e.loc);
|
|
4580
|
-
}
|
|
4581
|
-
else {
|
|
4582
|
-
const error = cb.params[0];
|
|
4583
|
-
if (error !== undefined) {
|
|
4584
|
-
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
4585
|
-
if (!def || def.arms.length !== 2 ||
|
|
4586
|
-
!def.arms.some((arm) => arm.kind === "nullT") ||
|
|
4587
|
-
!def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error")) {
|
|
4588
|
-
err(`libCall cp.execFile callback error parameter must be Error | null`, e.loc);
|
|
4589
|
-
}
|
|
4590
|
-
}
|
|
4591
|
-
const stdout = cb.params[1];
|
|
4592
|
-
if (stdout !== undefined && stdout.kind !== "string") {
|
|
4593
|
-
err(`libCall cp.execFile callback stdout parameter must be string`, e.loc);
|
|
4594
|
-
}
|
|
4595
|
-
const stderr = cb.params[2];
|
|
4596
|
-
if (stderr !== undefined && stderr.kind !== "string") {
|
|
4597
|
-
err(`libCall cp.execFile callback stderr parameter must be string`, e.loc);
|
|
4598
|
-
}
|
|
4599
|
-
}
|
|
4600
|
-
}
|
|
4601
|
-
if (e.fn === "child.onExit" || e.fn === "child.onClose" || e.fn === "child.onError") {
|
|
4602
|
-
// The listener: a closure with no params, or exactly the
|
|
4603
|
-
// supported parameter shapes per event — exit takes (code:
|
|
4604
|
-
// number | null) with an optional (signal: string | null)
|
|
4605
|
-
// second parameter, error exactly (err: %Error).
|
|
4606
|
-
const cb = e.args[1];
|
|
4607
|
-
const cbT = cb?.type;
|
|
4608
|
-
const maxParams = e.fn === "child.onError" ? 1 : 2;
|
|
4609
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4610
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4611
|
-
const p = cbT.params[0];
|
|
4612
|
-
if (e.fn === "child.onExit" || e.fn === "child.onClose") {
|
|
4613
|
-
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
4614
|
-
ok =
|
|
4615
|
-
def !== undefined &&
|
|
4616
|
-
def.arms.length === 2 &&
|
|
4617
|
-
def.arms[0].kind === "f64" &&
|
|
4618
|
-
def.arms[1].kind === "nullT";
|
|
4619
|
-
if (ok && cbT.params.length === 2) {
|
|
4620
|
-
const s = cbT.params[1];
|
|
4621
|
-
const sdef = s.kind === "union" ? unions.get(s.unionId) : undefined;
|
|
4622
|
-
ok =
|
|
4623
|
-
sdef !== undefined &&
|
|
4624
|
-
sdef.arms.length === 2 &&
|
|
4625
|
-
sdef.arms.some((a) => a.kind === "string") &&
|
|
4626
|
-
sdef.arms.some((a) => a.kind === "nullT");
|
|
4627
|
-
}
|
|
4628
|
-
}
|
|
4629
|
-
else {
|
|
4630
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4631
|
-
}
|
|
4632
|
-
}
|
|
4633
|
-
if (!ok) {
|
|
4634
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4635
|
-
}
|
|
4636
|
-
break;
|
|
4637
|
-
}
|
|
4638
|
-
if (e.fn === "writer.onDrain" || e.fn === "writer.onFinish" || e.fn === "writer.onError") {
|
|
4639
|
-
const cbT = e.args[1]?.type;
|
|
4640
|
-
const maxParams = e.fn === "writer.onError" ? 1 : 0;
|
|
4641
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4642
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4643
|
-
const p = cbT.params[0];
|
|
4644
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4645
|
-
}
|
|
4646
|
-
if (!ok)
|
|
4647
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4648
|
-
break;
|
|
4649
5261
|
}
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
// The listener: a void closure with no params, or exactly the
|
|
4653
|
-
// one supported parameter shape per event (code number / data
|
|
4654
|
-
// chunk bytes / error %Error).
|
|
4655
|
-
const cbT = e.args[0]?.type;
|
|
4656
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4657
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4658
|
-
const p = cbT.params[0];
|
|
4659
|
-
if (e.fn === "stdin.onData")
|
|
4660
|
-
ok = p.kind === "bytes" && p.elem === "u8";
|
|
4661
|
-
else if (e.fn === "stdin.onError")
|
|
4662
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4663
|
-
else
|
|
4664
|
-
ok = p.kind === "f64";
|
|
4665
|
-
}
|
|
4666
|
-
if (!ok) {
|
|
4667
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4668
|
-
}
|
|
4669
|
-
break;
|
|
4670
|
-
}
|
|
4671
|
-
if (e.fn === "spawnRes.status") {
|
|
4672
|
-
// Result is the module's interned `number | null` union.
|
|
4673
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4674
|
-
const ok = def &&
|
|
4675
|
-
def.arms.length === 2 &&
|
|
4676
|
-
def.arms[0].kind === "f64" &&
|
|
4677
|
-
def.arms[1].kind === "nullT";
|
|
4678
|
-
if (!ok) {
|
|
4679
|
-
err(`libCall spawnRes.status must return the 'number | null' union`, e.loc);
|
|
4680
|
-
}
|
|
4681
|
-
break;
|
|
5262
|
+
else {
|
|
5263
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4682
5264
|
}
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
5265
|
+
}
|
|
5266
|
+
if (!ok) {
|
|
5267
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5268
|
+
}
|
|
5269
|
+
return true;
|
|
5270
|
+
}
|
|
5271
|
+
if (e.fn === "writer.onDrain" || e.fn === "writer.onFinish" || e.fn === "writer.onError") {
|
|
5272
|
+
const cbT = e.args[1]?.type;
|
|
5273
|
+
const maxParams = e.fn === "writer.onError" ? 1 : 0;
|
|
5274
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
5275
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5276
|
+
const p = cbT.params[0];
|
|
5277
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
5278
|
+
}
|
|
5279
|
+
if (!ok)
|
|
5280
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5281
|
+
return true;
|
|
5282
|
+
}
|
|
5283
|
+
if (e.fn === "process.onExit" || e.fn === "process.offExit" ||
|
|
5284
|
+
e.fn === "stdin.onData" || e.fn === "stdin.onError") {
|
|
5285
|
+
// The listener: a void closure with no params, or exactly the
|
|
5286
|
+
// one supported parameter shape per event (code number / data
|
|
5287
|
+
// chunk bytes / error %Error).
|
|
5288
|
+
const cbT = e.args[0]?.type;
|
|
5289
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
5290
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5291
|
+
const p = cbT.params[0];
|
|
5292
|
+
if (e.fn === "stdin.onData")
|
|
5293
|
+
ok = p.kind === "bytes" && p.elem === "u8";
|
|
5294
|
+
else if (e.fn === "stdin.onError")
|
|
5295
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
5296
|
+
else
|
|
5297
|
+
ok = p.kind === "f64";
|
|
5298
|
+
}
|
|
5299
|
+
if (!ok) {
|
|
5300
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5301
|
+
}
|
|
5302
|
+
return true;
|
|
5303
|
+
}
|
|
5304
|
+
if (e.fn === "spawnRes.status") {
|
|
5305
|
+
// Result is the module's interned `number | null` union.
|
|
5306
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5307
|
+
const ok = def &&
|
|
5308
|
+
def.arms.length === 2 &&
|
|
5309
|
+
def.arms[0].kind === "f64" &&
|
|
5310
|
+
def.arms[1].kind === "nullT";
|
|
5311
|
+
if (!ok) {
|
|
5312
|
+
err(`libCall spawnRes.status must return the 'number | null' union`, e.loc);
|
|
5313
|
+
}
|
|
5314
|
+
return true;
|
|
5315
|
+
}
|
|
5316
|
+
if (e.fn === "spawnRes.signal") {
|
|
5317
|
+
// Result is the module's interned `string | null` union.
|
|
5318
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5319
|
+
const ok = def &&
|
|
5320
|
+
def.arms.length === 2 &&
|
|
5321
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5322
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5323
|
+
if (!ok) {
|
|
5324
|
+
err(`libCall spawnRes.signal must return the 'string | null' union`, e.loc);
|
|
5325
|
+
}
|
|
5326
|
+
return true;
|
|
5327
|
+
}
|
|
5328
|
+
if (e.fn === "sp.get") {
|
|
5329
|
+
// Result is the interned `string | null` union (the runtime
|
|
5330
|
+
// answers +1-or-NULL; the backend builds the arms).
|
|
5331
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5332
|
+
const ok = def &&
|
|
5333
|
+
def.arms.length === 2 &&
|
|
5334
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5335
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5336
|
+
if (!ok) {
|
|
5337
|
+
err(`libCall sp.get must return the 'string | null' union`, e.loc);
|
|
5338
|
+
}
|
|
5339
|
+
return true;
|
|
5340
|
+
}
|
|
5341
|
+
if (e.fn === "sp.fromPairs") {
|
|
5342
|
+
const t = e.args[0]?.type;
|
|
5343
|
+
const ok = t && t.kind === "array" && t.elem.kind === "array" && t.elem.elem.kind === "string";
|
|
5344
|
+
if (!ok) {
|
|
5345
|
+
err(`libCall sp.fromPairs arg 0: expected string[][], got ${t?.kind}`, e.loc);
|
|
5346
|
+
}
|
|
5347
|
+
return true;
|
|
5348
|
+
}
|
|
5349
|
+
if (e.fn === "sym.desc" || e.fn === "sym.keyFor") {
|
|
5350
|
+
// Result is the interned `string | undefined` union (the
|
|
5351
|
+
// runtime answers +1-or-NULL; the backend builds the arms).
|
|
5352
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5353
|
+
const ok = def &&
|
|
5354
|
+
def.arms.length === 2 &&
|
|
5355
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5356
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5357
|
+
if (!ok) {
|
|
5358
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
5359
|
+
}
|
|
5360
|
+
return true;
|
|
5361
|
+
}
|
|
5362
|
+
if (e.fn === "spawnRes.error") {
|
|
5363
|
+
// Result is the interned `%Error | undefined` union.
|
|
5364
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5365
|
+
const ok = def &&
|
|
5366
|
+
def.arms.length === 2 &&
|
|
5367
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
5368
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5369
|
+
if (!ok) {
|
|
5370
|
+
err(`libCall spawnRes.error must return the 'Error | undefined' union`, e.loc);
|
|
5371
|
+
}
|
|
5372
|
+
return true;
|
|
5373
|
+
}
|
|
5374
|
+
if (e.fn === "child.pid" || e.fn === "child.exitCode") {
|
|
5375
|
+
// pid: the interned `number | undefined`; exitCode: `number | null`.
|
|
5376
|
+
const wantUnit = e.fn === "child.pid" ? "undefinedT" : "nullT";
|
|
5377
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5378
|
+
const ok = def &&
|
|
5379
|
+
def.arms.length === 2 &&
|
|
5380
|
+
def.arms[0].kind === "f64" &&
|
|
5381
|
+
def.arms[1].kind === wantUnit;
|
|
5382
|
+
if (!ok) {
|
|
5383
|
+
err(`libCall ${e.fn} must return the 'number | ${wantUnit === "nullT" ? "null" : "undefined"}' union`, e.loc);
|
|
5384
|
+
}
|
|
5385
|
+
return true;
|
|
5386
|
+
}
|
|
5387
|
+
if (e.fn === "net.serverCloseBind") {
|
|
5388
|
+
// The bound close: (cbUnion) => netServer, cbUnion carrying a
|
|
5389
|
+
// void-returning func arm (≤1 param) and the undefined arm.
|
|
5390
|
+
const t = e.type;
|
|
5391
|
+
const cbU = t.kind === "func" && t.params.length === 1 ? t.params[0] : null;
|
|
5392
|
+
const def = cbU?.kind === "union" ? unions.get(cbU.unionId) : undefined;
|
|
5393
|
+
const ok = t.kind === "func" && (t.ret.kind === "netServer" || t.ret.kind === "void") &&
|
|
5394
|
+
def &&
|
|
5395
|
+
def.arms.some((a) => a.kind === "func" && a.params.length <= 1 && a.ret.kind === "void") &&
|
|
5396
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5397
|
+
if (!ok) {
|
|
5398
|
+
err(`libCall net.serverCloseBind must produce the bound-close func type`, e.loc);
|
|
5399
|
+
}
|
|
5400
|
+
return true;
|
|
5401
|
+
}
|
|
5402
|
+
if (e.fn === "child.stdin" || e.fn === "child.stdout" || e.fn === "child.stderr") {
|
|
5403
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5404
|
+
const handleKind = e.fn === "child.stdin" ? "childWriter" : "childStream";
|
|
5405
|
+
const ok = def &&
|
|
5406
|
+
def.arms.length === 2 &&
|
|
5407
|
+
def.arms.some((a) => a.kind === handleKind) &&
|
|
5408
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5409
|
+
if (!ok) {
|
|
5410
|
+
err(`libCall ${e.fn} must return the '${e.fn === "child.stdin" ? "Writable" : "Readable"} | null' union`, e.loc);
|
|
5411
|
+
}
|
|
5412
|
+
return true;
|
|
5413
|
+
}
|
|
5414
|
+
return false;
|
|
5415
|
+
}
|
|
5416
|
+
function checkLibSpecialCall(e) {
|
|
5417
|
+
if (e.fn === "island.castFail") {
|
|
5418
|
+
// The deferred boundary failure's typed dummy: a promise (the
|
|
5419
|
+
// only cast shape the frontend defers).
|
|
5420
|
+
if (e.type.kind !== "promise") {
|
|
5421
|
+
err(`libCall island.castFail must return a promise type, got ${e.type.kind}`, e.loc);
|
|
5422
|
+
}
|
|
5423
|
+
return true;
|
|
5424
|
+
}
|
|
5425
|
+
if (e.fn === "global.undefRead") {
|
|
5426
|
+
// Always throws — the result type is whatever the declared type
|
|
5427
|
+
// of the undefined global mapped to (never materialized).
|
|
5428
|
+
return true;
|
|
5429
|
+
}
|
|
5430
|
+
if (e.fn === "error.nodeThrow" || e.fn === "error.argTypeThrow" || e.fn === "error.propTypeThrow" ||
|
|
5431
|
+
e.fn === "fs.mkdtempChk" || e.fn === "fs.readFileChk" ||
|
|
5432
|
+
e.fn === "fs.opendirChk" || e.fn === "fs.watchFileChk" || e.fn === "fs.lchmodChk" ||
|
|
5433
|
+
e.fn === "fs.readChk" || e.fn === "fs.streamOptsChk" || e.fn === "net.connectOptsChk" ||
|
|
5434
|
+
e.fn === "tls.caCertsChk") {
|
|
5435
|
+
// Always throws — the result type is the replaced expression's
|
|
5436
|
+
// own (never materialized; the global.undefRead pattern). The
|
|
5437
|
+
// fs Chk ladders qualify: every validation failure throws
|
|
5438
|
+
// Node's typed error, and a full pass throws the trailing
|
|
5439
|
+
// compiler-rendered fence.
|
|
5440
|
+
return true;
|
|
5441
|
+
}
|
|
5442
|
+
if (e.fn === "error.new" || e.fn === "error.newOptions") {
|
|
5443
|
+
// Which builtin the runtime constructs is named by the result type.
|
|
5444
|
+
if (!isBuiltinErrorObject(e.type)) {
|
|
5445
|
+
err(`libCall ${e.fn} must return a builtin error class, got ${e.type.kind}`, e.loc);
|
|
5446
|
+
}
|
|
5447
|
+
return true;
|
|
5448
|
+
}
|
|
5449
|
+
if (e.fn === "error.newDom") {
|
|
5450
|
+
if (e.type.kind !== "object" || e.type.className !== "%DOMException") {
|
|
5451
|
+
err(`libCall error.newDom must return %DOMException, got ${e.type.kind}`, e.loc);
|
|
5452
|
+
}
|
|
5453
|
+
return true;
|
|
5454
|
+
}
|
|
5455
|
+
if (e.fn === "error.domCode" || e.fn === "error.domHasCause" || e.fn === "error.domCause" || e.fn === "error.domClone") {
|
|
5456
|
+
// Receiver: exactly %DOMException (subclassing is fenced — the
|
|
5457
|
+
// hidden runtime slots admit no other layout).
|
|
5458
|
+
const recv = e.args[0];
|
|
5459
|
+
if (!recv || recv.type.kind !== "object" || recv.type.className !== "%DOMException") {
|
|
5460
|
+
err(`libCall ${e.fn} receiver must be %DOMException`, e.loc);
|
|
5461
|
+
}
|
|
5462
|
+
return true;
|
|
5463
|
+
}
|
|
5464
|
+
if (e.fn === "class.name") {
|
|
5465
|
+
// The arg is any class value (program-dependent classval).
|
|
5466
|
+
if (e.args[0]?.type.kind !== "classval") {
|
|
5467
|
+
err(`libCall class.name takes a class value`, e.loc);
|
|
5468
|
+
}
|
|
5469
|
+
if (e.type.kind !== "string") {
|
|
5470
|
+
err(`libCall class.name must return string`, e.loc);
|
|
5471
|
+
}
|
|
5472
|
+
return true;
|
|
5473
|
+
}
|
|
5474
|
+
if (e.fn === "assert.refEqBytes" || e.fn === "assert.bytesDeepEq") {
|
|
5475
|
+
// Both value slots: ONE static bytes type (the frontend's
|
|
5476
|
+
// same-static-type gate — a u8/u32 mix would memcmp garbage).
|
|
5477
|
+
const a = e.args[0]?.type;
|
|
5478
|
+
const b = e.args[1]?.type;
|
|
5479
|
+
if (a?.kind !== "bytes" || b === undefined || !typeEquals(a, b)) {
|
|
5480
|
+
err(`libCall ${e.fn} takes two same-typed bytes values`, e.loc);
|
|
5481
|
+
}
|
|
5482
|
+
return true;
|
|
5483
|
+
}
|
|
5484
|
+
if (e.fn === "assert.refEqFn") {
|
|
5485
|
+
// ANY two function signatures: the compare is pointer identity.
|
|
5486
|
+
if (e.args[0]?.type.kind !== "func" || e.args[1]?.type.kind !== "func") {
|
|
5487
|
+
err(`libCall assert.refEqFn takes two function values`, e.loc);
|
|
5488
|
+
}
|
|
5489
|
+
return true;
|
|
5490
|
+
}
|
|
5491
|
+
if (e.fn === "error.code") {
|
|
5492
|
+
// Receiver: any error-hierarchy object (a user subclass embeds
|
|
5493
|
+
// the code slot in its prefix); result: the interned
|
|
5494
|
+
// `string | undefined` union (the process.envGet pattern).
|
|
5495
|
+
const recv = e.args[0];
|
|
5496
|
+
if (!recv || recv.type.kind !== "object") {
|
|
5497
|
+
err(`libCall error.code receiver must be an error object`, e.loc);
|
|
5498
|
+
return true;
|
|
5499
|
+
}
|
|
5500
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5501
|
+
const ok = def &&
|
|
5502
|
+
def.arms.length === 2 &&
|
|
5503
|
+
def.arms[0].kind === "string" &&
|
|
5504
|
+
def.arms[1].kind === "undefinedT";
|
|
5505
|
+
if (!ok) {
|
|
5506
|
+
err(`libCall error.code must return the 'string | undefined' union`, e.loc);
|
|
5507
|
+
}
|
|
5508
|
+
return true;
|
|
5509
|
+
}
|
|
5510
|
+
return false;
|
|
5511
|
+
}
|
|
5512
|
+
function checkLibStreamCall(e, fixedArgs, result) {
|
|
5513
|
+
if (e.fn.startsWith("readable.") || e.fn.startsWith("writable.") ||
|
|
5514
|
+
e.fn.startsWith("duplex.") || e.fn.startsWith("transform.") ||
|
|
5515
|
+
e.fn.startsWith("passthrough.") || e.fn === "stream.destroy" ||
|
|
5516
|
+
e.fn === "stream.destroyErr" || e.fn === "stream.iteratorClose" || e.fn === "stream.prop" ||
|
|
5517
|
+
e.fn === "stream.errored" || e.fn === "stream.finished" ||
|
|
5518
|
+
e.fn === "stream.finishedDyn" || e.fn === "stream.pipeline" ||
|
|
5519
|
+
e.fn === "stream.pipelineDyn") {
|
|
5520
|
+
// Receiver/result: stream-hierarchy objects (a class whose base
|
|
5521
|
+
// chain reaches a runtime stream class). Constructors have no
|
|
5522
|
+
// receiver — their RESULT names the class; chaining forms
|
|
5523
|
+
// return the receiver's static type; pipe returns its
|
|
5524
|
+
// destination's.
|
|
5525
|
+
const isStreamObject = (t) => {
|
|
5526
|
+
if (t?.kind !== "object")
|
|
5527
|
+
return false;
|
|
5528
|
+
let name = t.className;
|
|
5529
|
+
while (name !== undefined) {
|
|
5530
|
+
if (RUNTIME_STREAM_CLASSES.has(name))
|
|
5531
|
+
return true;
|
|
5532
|
+
name = classes.get(name)?.base;
|
|
5533
|
+
}
|
|
5534
|
+
return false;
|
|
5535
|
+
};
|
|
5536
|
+
if (e.fn.endsWith(".new")) {
|
|
5537
|
+
if (!isStreamObject(e.type)) {
|
|
5538
|
+
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
5539
|
+
}
|
|
5540
|
+
for (let i = fixedArgs; i < e.args.length; i++) {
|
|
5541
|
+
if (e.args[i].type.kind !== "func") {
|
|
5542
|
+
err(`libCall ${e.fn} option callback ${i} must be a func`, e.loc);
|
|
4692
5543
|
}
|
|
4693
|
-
break;
|
|
4694
5544
|
}
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4702
|
-
def.arms.some((a) => a.kind === "nullT");
|
|
4703
|
-
if (!ok) {
|
|
4704
|
-
err(`libCall sp.get must return the 'string | null' union`, e.loc);
|
|
4705
|
-
}
|
|
4706
|
-
break;
|
|
5545
|
+
return true;
|
|
5546
|
+
}
|
|
5547
|
+
if (e.fn.endsWith(".newDyn")) {
|
|
5548
|
+
// The dyn-options constructor: (optsDyn) → the stream class.
|
|
5549
|
+
if (!isStreamObject(e.type)) {
|
|
5550
|
+
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4707
5551
|
}
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
}
|
|
4714
|
-
break;
|
|
5552
|
+
return true;
|
|
5553
|
+
}
|
|
5554
|
+
if (e.fn.endsWith(".initDyn")) {
|
|
5555
|
+
// (recv, optsDyn, flags, ...fallback wrapper closures).
|
|
5556
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5557
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4715
5558
|
}
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4720
|
-
const ok = def &&
|
|
4721
|
-
def.arms.length === 2 &&
|
|
4722
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4723
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4724
|
-
if (!ok) {
|
|
4725
|
-
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
5559
|
+
for (let i = fixedArgs; i < e.args.length; i++) {
|
|
5560
|
+
if (e.args[i].type.kind !== "func") {
|
|
5561
|
+
err(`libCall ${e.fn} fallback callback ${i} must be a func`, e.loc);
|
|
4726
5562
|
}
|
|
4727
|
-
break;
|
|
4728
5563
|
}
|
|
4729
|
-
if (e.
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
err(`libCall spawnRes.error must return the 'Error | undefined' union`, e.loc);
|
|
4738
|
-
}
|
|
4739
|
-
break;
|
|
5564
|
+
if (e.type.kind !== "void")
|
|
5565
|
+
err(`libCall ${e.fn} must be void`, e.loc);
|
|
5566
|
+
return true;
|
|
5567
|
+
}
|
|
5568
|
+
if (e.fn === "stream.finished" || e.fn === "stream.finishedDyn") {
|
|
5569
|
+
// (recv, cb) → the cleanup closure.
|
|
5570
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5571
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4740
5572
|
}
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4745
|
-
const ok = def &&
|
|
4746
|
-
def.arms.length === 2 &&
|
|
4747
|
-
def.arms[0].kind === "f64" &&
|
|
4748
|
-
def.arms[1].kind === wantUnit;
|
|
4749
|
-
if (!ok) {
|
|
4750
|
-
err(`libCall ${e.fn} must return the 'number | ${wantUnit === "nullT" ? "null" : "undefined"}' union`, e.loc);
|
|
4751
|
-
}
|
|
4752
|
-
break;
|
|
5573
|
+
const cbK = e.args[1]?.type.kind;
|
|
5574
|
+
if (e.fn === "stream.finished" ? cbK !== "func" : cbK !== "dyn") {
|
|
5575
|
+
err(`libCall ${e.fn} callback must be ${e.fn === "stream.finished" ? "a func" : "dyn"}`, e.loc);
|
|
4753
5576
|
}
|
|
4754
|
-
if (e.
|
|
4755
|
-
|
|
4756
|
-
// void-returning func arm (≤1 param) and the undefined arm.
|
|
4757
|
-
const t = e.type;
|
|
4758
|
-
const cbU = t.kind === "func" && t.params.length === 1 ? t.params[0] : null;
|
|
4759
|
-
const def = cbU?.kind === "union" ? unions.get(cbU.unionId) : undefined;
|
|
4760
|
-
const ok = t.kind === "func" && (t.ret.kind === "netServer" || t.ret.kind === "void") &&
|
|
4761
|
-
def &&
|
|
4762
|
-
def.arms.some((a) => a.kind === "func" && a.params.length <= 1 && a.ret.kind === "void") &&
|
|
4763
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4764
|
-
if (!ok) {
|
|
4765
|
-
err(`libCall net.serverCloseBind must produce the bound-close func type`, e.loc);
|
|
4766
|
-
}
|
|
4767
|
-
break;
|
|
5577
|
+
if (e.type.kind !== "func") {
|
|
5578
|
+
err(`libCall ${e.fn} must return the cleanup closure, got ${e.type.kind}`, e.loc);
|
|
4768
5579
|
}
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
}
|
|
4779
|
-
break;
|
|
5580
|
+
return true;
|
|
5581
|
+
}
|
|
5582
|
+
if (e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn") {
|
|
5583
|
+
// (count, s1..sn, cb) → the destination's type.
|
|
5584
|
+
const count = e.args[0];
|
|
5585
|
+
const n = count?.kind === "numLit" ? count.value : -1;
|
|
5586
|
+
if (n < 2 || e.args.length !== n + 2) {
|
|
5587
|
+
err(`libCall ${e.fn} count/arity mismatch`, e.loc);
|
|
5588
|
+
return true;
|
|
4780
5589
|
}
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
if (e.type.kind !== "promise") {
|
|
4785
|
-
err(`libCall island.castFail must return a promise type, got ${e.type.kind}`, e.loc);
|
|
5590
|
+
for (let i = 1; i <= n; i++) {
|
|
5591
|
+
if (!isStreamObject(e.args[i]?.type)) {
|
|
5592
|
+
err(`libCall ${e.fn} stage ${i} must be a stream-hierarchy object`, e.loc);
|
|
4786
5593
|
}
|
|
4787
|
-
break;
|
|
4788
5594
|
}
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
break;
|
|
5595
|
+
const cbK = e.args[n + 1]?.type.kind;
|
|
5596
|
+
if (e.fn === "stream.pipeline" ? cbK !== "func" : cbK !== "dyn") {
|
|
5597
|
+
err(`libCall ${e.fn} callback must be ${e.fn === "stream.pipeline" ? "a func" : "dyn"}`, e.loc);
|
|
4793
5598
|
}
|
|
4794
|
-
if (e.
|
|
4795
|
-
e.fn
|
|
4796
|
-
e.fn === "fs.opendirChk" || e.fn === "fs.watchFileChk" || e.fn === "fs.lchmodChk" ||
|
|
4797
|
-
e.fn === "fs.readChk" || e.fn === "fs.streamOptsChk" || e.fn === "net.connectOptsChk" ||
|
|
4798
|
-
e.fn === "tls.caCertsChk") {
|
|
4799
|
-
// Always throws — the result type is the replaced expression's
|
|
4800
|
-
// own (never materialized; the global.undefRead pattern). The
|
|
4801
|
-
// fs Chk ladders qualify: every validation failure throws
|
|
4802
|
-
// Node's typed error, and a full pass throws the trailing
|
|
4803
|
-
// compiler-rendered fence.
|
|
4804
|
-
break;
|
|
5599
|
+
if (!typeEquals(e.type, e.args[n].type)) {
|
|
5600
|
+
err(`libCall ${e.fn} must return its destination's type`, e.loc);
|
|
4805
5601
|
}
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
5602
|
+
return true;
|
|
5603
|
+
}
|
|
5604
|
+
if (e.fn === "readable.fromArr") {
|
|
5605
|
+
// No receiver: the seed array leads; the result is the class.
|
|
5606
|
+
if (e.args[0]?.type.kind !== "array" || !isStreamObject(e.type)) {
|
|
5607
|
+
err(`libCall readable.fromArr must take an array and return a stream class`, e.loc);
|
|
4812
5608
|
}
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
5609
|
+
return true;
|
|
5610
|
+
}
|
|
5611
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5612
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
5613
|
+
return true;
|
|
5614
|
+
}
|
|
5615
|
+
if (e.fn === "readable.nextChunk" || e.fn === "readable.nextChunkDyn") {
|
|
5616
|
+
if (e.type.kind !== "promise") {
|
|
5617
|
+
err(`libCall ${e.fn} must return a promise, got ${e.type.kind}`, e.loc);
|
|
4818
5618
|
}
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
5619
|
+
return true;
|
|
5620
|
+
}
|
|
5621
|
+
if (e.fn === "readable.pause" || e.fn === "readable.resume" ||
|
|
5622
|
+
e.fn === "readable.unpipe" || e.fn === "writable.end" ||
|
|
5623
|
+
e.fn === "readable.setEncoding" || e.fn === "readable.pushEncoding" ||
|
|
5624
|
+
e.fn === "stream.destroy" || e.fn === "stream.destroyErr" ||
|
|
5625
|
+
e.fn === "stream.iteratorClose") {
|
|
5626
|
+
if (!typeEquals(e.type, e.args[0].type)) {
|
|
5627
|
+
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
4827
5628
|
}
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
if (e.type.kind !== "string") {
|
|
4834
|
-
err(`libCall class.name must return string`, e.loc);
|
|
4835
|
-
}
|
|
4836
|
-
break;
|
|
5629
|
+
return true;
|
|
5630
|
+
}
|
|
5631
|
+
if (e.fn === "readable.pipe") {
|
|
5632
|
+
if (!isStreamObject(e.args[1]?.type) || !typeEquals(e.type, e.args[1].type)) {
|
|
5633
|
+
err(`libCall readable.pipe must return its destination's type`, e.loc);
|
|
4837
5634
|
}
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
5635
|
+
return true;
|
|
5636
|
+
}
|
|
5637
|
+
if (e.fn === "readable.read" || e.fn === "readable.flowing" || e.fn === "stream.errored") {
|
|
5638
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5639
|
+
const wantArm = (t) => e.fn === "readable.read" ? t.kind === "bytes" :
|
|
5640
|
+
e.fn === "readable.flowing" ? t.kind === "bool" :
|
|
5641
|
+
t.kind === "object";
|
|
5642
|
+
const ok = def && def.arms.length === 2 &&
|
|
5643
|
+
def.arms.some(wantArm) && def.arms.some((a) => a.kind === "nullT");
|
|
5644
|
+
if (!ok)
|
|
5645
|
+
err(`libCall ${e.fn} must return its nullable union`, e.loc);
|
|
5646
|
+
return true;
|
|
5647
|
+
}
|
|
5648
|
+
if (e.fn === "stream.prop") {
|
|
5649
|
+
if (e.type.kind !== "bool" && e.type.kind !== "f64") {
|
|
5650
|
+
err(`libCall stream.prop must be bool or f64, got ${e.type.kind}`, e.loc);
|
|
4847
5651
|
}
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
5652
|
+
return true;
|
|
5653
|
+
}
|
|
5654
|
+
if (!typeEquals(e.type, result)) {
|
|
5655
|
+
err(`libCall ${e.fn} must be ${result.kind}, got ${e.type.kind}`, e.loc);
|
|
5656
|
+
}
|
|
5657
|
+
return true;
|
|
5658
|
+
}
|
|
5659
|
+
return false;
|
|
5660
|
+
}
|
|
5661
|
+
function checkLibEmitterCall(e, result) {
|
|
5662
|
+
if ((e.fn.startsWith("emitter.") || e.fn === "stream.onDyn") && e.fn !== "emitter.setDefaultMax" &&
|
|
5663
|
+
e.fn !== "emitter.setDefaultMaxChk" &&
|
|
5664
|
+
e.fn !== "emitter.getDefaultMax" && e.fn !== "emitter.checkListener") {
|
|
5665
|
+
// Receiver: an emitter-hierarchy object (the %EventEmitter class
|
|
5666
|
+
// itself, or a class whose base chain reaches it). emitter.new
|
|
5667
|
+
// has no receiver — its RESULT is the bare emitter class.
|
|
5668
|
+
const isEmitterObject = (t) => {
|
|
5669
|
+
if (t?.kind !== "object")
|
|
5670
|
+
return false;
|
|
5671
|
+
let name = t.className;
|
|
5672
|
+
while (name !== undefined) {
|
|
5673
|
+
if (name === RUNTIME_EMITTER_CLASS)
|
|
5674
|
+
return true;
|
|
5675
|
+
name = classes.get(name)?.base;
|
|
5676
|
+
}
|
|
5677
|
+
return false;
|
|
5678
|
+
};
|
|
5679
|
+
if (e.fn === "emitter.new") {
|
|
5680
|
+
if (e.type.kind !== "object" || e.type.className !== RUNTIME_EMITTER_CLASS) {
|
|
5681
|
+
err(`libCall emitter.new must return '%EventEmitter', got ${e.type.kind}`, e.loc);
|
|
4854
5682
|
}
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
if (!ok) {
|
|
4870
|
-
err(`libCall error.code must return the 'string | undefined' union`, e.loc);
|
|
4871
|
-
}
|
|
4872
|
-
break;
|
|
5683
|
+
return true;
|
|
5684
|
+
}
|
|
5685
|
+
if (!isEmitterObject(e.args[0]?.type)) {
|
|
5686
|
+
err(`libCall ${e.fn} receiver must be an emitter-hierarchy object`, e.loc);
|
|
5687
|
+
return true;
|
|
5688
|
+
}
|
|
5689
|
+
// The chaining forms return the receiver's own static class.
|
|
5690
|
+
if (e.fn === "emitter.on" || e.fn === "emitter.off" ||
|
|
5691
|
+
e.fn === "emitter.onDyn" || (e.fn === "emitter.onFlex" || e.fn === "stream.onDyn") || e.fn === "emitter.offDyn" ||
|
|
5692
|
+
e.fn === "emitter.onData" || e.fn === "emitter.onDataDyn" ||
|
|
5693
|
+
e.fn === "emitter.removeAll" || e.fn === "emitter.setMax" ||
|
|
5694
|
+
e.fn === "emitter.setMaxChk") {
|
|
5695
|
+
if (!typeEquals(e.type, e.args[0].type)) {
|
|
5696
|
+
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
4873
5697
|
}
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
e.fn
|
|
4878
|
-
e.fn === "stream.errored" || e.fn === "stream.finished" ||
|
|
4879
|
-
e.fn === "stream.finishedDyn" || e.fn === "stream.pipeline" ||
|
|
4880
|
-
e.fn === "stream.pipelineDyn") {
|
|
4881
|
-
// Receiver/result: stream-hierarchy objects (a class whose base
|
|
4882
|
-
// chain reaches a runtime stream class). Constructors have no
|
|
4883
|
-
// receiver — their RESULT names the class; chaining forms
|
|
4884
|
-
// return the receiver's static type; pipe returns its
|
|
4885
|
-
// destination's.
|
|
4886
|
-
const isStreamObject = (t) => {
|
|
4887
|
-
if (t?.kind !== "object")
|
|
4888
|
-
return false;
|
|
4889
|
-
let name = t.className;
|
|
4890
|
-
while (name !== undefined) {
|
|
4891
|
-
if (RUNTIME_STREAM_CLASSES.has(name))
|
|
4892
|
-
return true;
|
|
4893
|
-
name = classes.get(name)?.base;
|
|
4894
|
-
}
|
|
4895
|
-
return false;
|
|
4896
|
-
};
|
|
4897
|
-
if (e.fn.endsWith(".new")) {
|
|
4898
|
-
if (!isStreamObject(e.type)) {
|
|
4899
|
-
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4900
|
-
}
|
|
4901
|
-
for (let i = sig.argTypes.length; i < e.args.length; i++) {
|
|
4902
|
-
if (e.args[i].type.kind !== "func") {
|
|
4903
|
-
err(`libCall ${e.fn} option callback ${i} must be a func`, e.loc);
|
|
4904
|
-
}
|
|
4905
|
-
}
|
|
4906
|
-
break;
|
|
4907
|
-
}
|
|
4908
|
-
if (e.fn.endsWith(".newDyn")) {
|
|
4909
|
-
// The dyn-options constructor: (optsDyn) → the stream class.
|
|
4910
|
-
if (!isStreamObject(e.type)) {
|
|
4911
|
-
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4912
|
-
}
|
|
4913
|
-
break;
|
|
4914
|
-
}
|
|
4915
|
-
if (e.fn.endsWith(".initDyn")) {
|
|
4916
|
-
// (recv, optsDyn, flags, ...fallback wrapper closures).
|
|
4917
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4918
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4919
|
-
}
|
|
4920
|
-
for (let i = sig.argTypes.length; i < e.args.length; i++) {
|
|
4921
|
-
if (e.args[i].type.kind !== "func") {
|
|
4922
|
-
err(`libCall ${e.fn} fallback callback ${i} must be a func`, e.loc);
|
|
4923
|
-
}
|
|
4924
|
-
}
|
|
4925
|
-
if (e.type.kind !== "void")
|
|
4926
|
-
err(`libCall ${e.fn} must be void`, e.loc);
|
|
4927
|
-
break;
|
|
4928
|
-
}
|
|
4929
|
-
if (e.fn === "stream.finished" || e.fn === "stream.finishedDyn") {
|
|
4930
|
-
// (recv, cb) → the cleanup closure.
|
|
4931
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4932
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4933
|
-
}
|
|
4934
|
-
const cbK = e.args[1]?.type.kind;
|
|
4935
|
-
if (e.fn === "stream.finished" ? cbK !== "func" : cbK !== "dyn") {
|
|
4936
|
-
err(`libCall ${e.fn} callback must be ${e.fn === "stream.finished" ? "a func" : "dyn"}`, e.loc);
|
|
4937
|
-
}
|
|
4938
|
-
if (e.type.kind !== "func") {
|
|
4939
|
-
err(`libCall ${e.fn} must return the cleanup closure, got ${e.type.kind}`, e.loc);
|
|
4940
|
-
}
|
|
4941
|
-
break;
|
|
4942
|
-
}
|
|
4943
|
-
if (e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn") {
|
|
4944
|
-
// (count, s1..sn, cb) → the destination's type.
|
|
4945
|
-
const count = e.args[0];
|
|
4946
|
-
const n = count?.kind === "numLit" ? count.value : -1;
|
|
4947
|
-
if (n < 2 || e.args.length !== n + 2) {
|
|
4948
|
-
err(`libCall ${e.fn} count/arity mismatch`, e.loc);
|
|
4949
|
-
break;
|
|
4950
|
-
}
|
|
4951
|
-
for (let i = 1; i <= n; i++) {
|
|
4952
|
-
if (!isStreamObject(e.args[i]?.type)) {
|
|
4953
|
-
err(`libCall ${e.fn} stage ${i} must be a stream-hierarchy object`, e.loc);
|
|
4954
|
-
}
|
|
4955
|
-
}
|
|
4956
|
-
const cbK = e.args[n + 1]?.type.kind;
|
|
4957
|
-
if (e.fn === "stream.pipeline" ? cbK !== "func" : cbK !== "dyn") {
|
|
4958
|
-
err(`libCall ${e.fn} callback must be ${e.fn === "stream.pipeline" ? "a func" : "dyn"}`, e.loc);
|
|
4959
|
-
}
|
|
4960
|
-
if (!typeEquals(e.type, e.args[n].type)) {
|
|
4961
|
-
err(`libCall ${e.fn} must return its destination's type`, e.loc);
|
|
4962
|
-
}
|
|
4963
|
-
break;
|
|
4964
|
-
}
|
|
4965
|
-
if (e.fn === "readable.fromArr") {
|
|
4966
|
-
// No receiver: the seed array leads; the result is the class.
|
|
4967
|
-
if (e.args[0]?.type.kind !== "array" || !isStreamObject(e.type)) {
|
|
4968
|
-
err(`libCall readable.fromArr must take an array and return a stream class`, e.loc);
|
|
4969
|
-
}
|
|
4970
|
-
break;
|
|
4971
|
-
}
|
|
4972
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4973
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4974
|
-
break;
|
|
4975
|
-
}
|
|
4976
|
-
if (e.fn === "readable.nextChunk" || e.fn === "readable.nextChunkDyn") {
|
|
4977
|
-
if (e.type.kind !== "promise") {
|
|
4978
|
-
err(`libCall ${e.fn} must return a promise, got ${e.type.kind}`, e.loc);
|
|
4979
|
-
}
|
|
4980
|
-
break;
|
|
4981
|
-
}
|
|
4982
|
-
if (e.fn === "readable.pause" || e.fn === "readable.resume" ||
|
|
4983
|
-
e.fn === "readable.unpipe" || e.fn === "writable.end" ||
|
|
4984
|
-
e.fn === "readable.setEncoding" || e.fn === "readable.pushEncoding" ||
|
|
4985
|
-
e.fn === "stream.destroy" || e.fn === "stream.destroyErr" ||
|
|
4986
|
-
e.fn === "stream.iteratorClose") {
|
|
4987
|
-
if (!typeEquals(e.type, e.args[0].type)) {
|
|
4988
|
-
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
4989
|
-
}
|
|
4990
|
-
break;
|
|
4991
|
-
}
|
|
4992
|
-
if (e.fn === "readable.pipe") {
|
|
4993
|
-
if (!isStreamObject(e.args[1]?.type) || !typeEquals(e.type, e.args[1].type)) {
|
|
4994
|
-
err(`libCall readable.pipe must return its destination's type`, e.loc);
|
|
4995
|
-
}
|
|
4996
|
-
break;
|
|
4997
|
-
}
|
|
4998
|
-
if (e.fn === "readable.read" || e.fn === "readable.flowing" || e.fn === "stream.errored") {
|
|
4999
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5000
|
-
const wantArm = (t) => e.fn === "readable.read" ? t.kind === "bytes" :
|
|
5001
|
-
e.fn === "readable.flowing" ? t.kind === "bool" :
|
|
5002
|
-
t.kind === "object";
|
|
5003
|
-
const ok = def && def.arms.length === 2 &&
|
|
5004
|
-
def.arms.some(wantArm) && def.arms.some((a) => a.kind === "nullT");
|
|
5005
|
-
if (!ok)
|
|
5006
|
-
err(`libCall ${e.fn} must return its nullable union`, e.loc);
|
|
5007
|
-
break;
|
|
5008
|
-
}
|
|
5009
|
-
if (e.fn === "stream.prop") {
|
|
5010
|
-
if (e.type.kind !== "bool" && e.type.kind !== "f64") {
|
|
5011
|
-
err(`libCall stream.prop must be bool or f64, got ${e.type.kind}`, e.loc);
|
|
5012
|
-
}
|
|
5013
|
-
break;
|
|
5014
|
-
}
|
|
5015
|
-
if (!typeEquals(e.type, sig.result)) {
|
|
5016
|
-
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
5017
|
-
}
|
|
5018
|
-
break;
|
|
5698
|
+
// The listener slots carry closures (the dyn family's checked-
|
|
5699
|
+
// dynamic listener is table-checked; its adapter is a func).
|
|
5700
|
+
if ((e.fn === "emitter.on" || e.fn === "emitter.off" || e.fn === "emitter.onData") && e.args[2]?.type.kind !== "func") {
|
|
5701
|
+
err(`libCall ${e.fn} listener must be a func`, e.loc);
|
|
5019
5702
|
}
|
|
5020
|
-
if (e.fn.
|
|
5021
|
-
e.fn
|
|
5022
|
-
e.fn !== "emitter.getDefaultMax" && e.fn !== "emitter.checkListener") {
|
|
5023
|
-
// Receiver: an emitter-hierarchy object (the %EventEmitter class
|
|
5024
|
-
// itself, or a class whose base chain reaches it). emitter.new
|
|
5025
|
-
// has no receiver — its RESULT is the bare emitter class.
|
|
5026
|
-
const isEmitterObject = (t) => {
|
|
5027
|
-
if (t?.kind !== "object")
|
|
5028
|
-
return false;
|
|
5029
|
-
let name = t.className;
|
|
5030
|
-
while (name !== undefined) {
|
|
5031
|
-
if (name === RUNTIME_EMITTER_CLASS)
|
|
5032
|
-
return true;
|
|
5033
|
-
name = classes.get(name)?.base;
|
|
5034
|
-
}
|
|
5035
|
-
return false;
|
|
5036
|
-
};
|
|
5037
|
-
if (e.fn === "emitter.new") {
|
|
5038
|
-
if (e.type.kind !== "object" || e.type.className !== RUNTIME_EMITTER_CLASS) {
|
|
5039
|
-
err(`libCall emitter.new must return '%EventEmitter', got ${e.type.kind}`, e.loc);
|
|
5040
|
-
}
|
|
5041
|
-
break;
|
|
5042
|
-
}
|
|
5043
|
-
if (!isEmitterObject(e.args[0]?.type)) {
|
|
5044
|
-
err(`libCall ${e.fn} receiver must be an emitter-hierarchy object`, e.loc);
|
|
5045
|
-
break;
|
|
5046
|
-
}
|
|
5047
|
-
// The chaining forms return the receiver's own static class.
|
|
5048
|
-
if (e.fn === "emitter.on" || e.fn === "emitter.off" ||
|
|
5049
|
-
e.fn === "emitter.onDyn" || e.fn === "emitter.onFlex" || e.fn === "emitter.offDyn" ||
|
|
5050
|
-
e.fn === "emitter.onData" || e.fn === "emitter.onDataDyn" ||
|
|
5051
|
-
e.fn === "emitter.removeAll" || e.fn === "emitter.setMax" ||
|
|
5052
|
-
e.fn === "emitter.setMaxChk") {
|
|
5053
|
-
if (!typeEquals(e.type, e.args[0].type)) {
|
|
5054
|
-
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
5055
|
-
}
|
|
5056
|
-
// The listener slots carry closures (the dyn family's checked-
|
|
5057
|
-
// dynamic listener is table-checked; its adapter is a func).
|
|
5058
|
-
if ((e.fn === "emitter.on" || e.fn === "emitter.off" || e.fn === "emitter.onData") && e.args[2]?.type.kind !== "func") {
|
|
5059
|
-
err(`libCall ${e.fn} listener must be a func`, e.loc);
|
|
5060
|
-
}
|
|
5061
|
-
if ((e.fn === "emitter.onDyn" || e.fn === "emitter.onDataDyn") && e.args[3]?.type.kind !== "func") {
|
|
5062
|
-
err(`libCall ${e.fn} adapter must be a func`, e.loc);
|
|
5063
|
-
}
|
|
5064
|
-
break;
|
|
5065
|
-
}
|
|
5066
|
-
if (e.fn === "emitter.emitData") {
|
|
5067
|
-
const chunkT = e.args[2]?.type;
|
|
5068
|
-
const ok = chunkT !== undefined &&
|
|
5069
|
-
((chunkT.kind === "bytes" && chunkT.elem === "u8") || chunkT.kind === "string");
|
|
5070
|
-
if (!ok)
|
|
5071
|
-
err(`libCall emitter.emitData chunk must be bytes<u8> or string`, e.loc);
|
|
5072
|
-
if (e.type.kind !== "bool")
|
|
5073
|
-
err(`libCall emitter.emitData must be bool`, e.loc);
|
|
5074
|
-
break;
|
|
5075
|
-
}
|
|
5076
|
-
if (e.fn === "emitter.countFn" && e.args[2]?.type.kind !== "func") {
|
|
5077
|
-
err(`libCall emitter.countFn listener must be a func`, e.loc);
|
|
5078
|
-
break;
|
|
5079
|
-
}
|
|
5080
|
-
if (e.fn === "emitter.emitError" && e.args[2]?.type.kind !== "object") {
|
|
5081
|
-
err(`libCall emitter.emitError payload must be an error-hierarchy object`, e.loc);
|
|
5082
|
-
break;
|
|
5083
|
-
}
|
|
5084
|
-
if (e.fn === "emitter.names") {
|
|
5085
|
-
const ok = e.type.kind === "array" && e.type.elem.kind === "string";
|
|
5086
|
-
if (!ok)
|
|
5087
|
-
err(`libCall emitter.names must return string[]`, e.loc);
|
|
5088
|
-
break;
|
|
5089
|
-
}
|
|
5090
|
-
if (e.fn === "emitter.listeners") {
|
|
5091
|
-
const ok = e.type.kind === "array" && e.type.elem.kind === "func";
|
|
5092
|
-
if (!ok)
|
|
5093
|
-
err(`libCall emitter.listeners must return a func array`, e.loc);
|
|
5094
|
-
break;
|
|
5095
|
-
}
|
|
5096
|
-
if (e.fn === "emitter.emitFlex") {
|
|
5097
|
-
if (e.args.slice(2).some((arg) => arg.type.kind !== "dyn")) {
|
|
5098
|
-
err("libCall emitter.emitFlex payloads must be checked-dynamic", e.loc);
|
|
5099
|
-
}
|
|
5100
|
-
}
|
|
5101
|
-
if (e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" || e.fn === "emitter.count" ||
|
|
5102
|
-
e.fn === "emitter.getMax" || e.fn === "emitter.ctor" ||
|
|
5103
|
-
e.fn === "emitter.countFn" || e.fn === "emitter.emitError") {
|
|
5104
|
-
if (!typeEquals(e.type, sig.result)) {
|
|
5105
|
-
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
5106
|
-
}
|
|
5107
|
-
break;
|
|
5108
|
-
}
|
|
5703
|
+
if ((e.fn === "emitter.onDyn" || e.fn === "emitter.onDataDyn") && e.args[3]?.type.kind !== "func") {
|
|
5704
|
+
err(`libCall ${e.fn} adapter must be a func`, e.loc);
|
|
5109
5705
|
}
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5706
|
+
return true;
|
|
5707
|
+
}
|
|
5708
|
+
if (e.fn === "emitter.emitData") {
|
|
5709
|
+
const chunkT = e.args[2]?.type;
|
|
5710
|
+
const ok = chunkT !== undefined &&
|
|
5711
|
+
((chunkT.kind === "bytes" && chunkT.elem === "u8") || chunkT.kind === "string");
|
|
5712
|
+
if (!ok)
|
|
5713
|
+
err(`libCall emitter.emitData chunk must be bytes<u8> or string`, e.loc);
|
|
5714
|
+
if (e.type.kind !== "bool")
|
|
5715
|
+
err(`libCall emitter.emitData must be bool`, e.loc);
|
|
5716
|
+
return true;
|
|
5717
|
+
}
|
|
5718
|
+
if (e.fn === "emitter.countFn" && e.args[2]?.type.kind !== "func") {
|
|
5719
|
+
err(`libCall emitter.countFn listener must be a func`, e.loc);
|
|
5720
|
+
return true;
|
|
5721
|
+
}
|
|
5722
|
+
if (e.fn === "emitter.emitError" && e.args[2]?.type.kind !== "object") {
|
|
5723
|
+
err(`libCall emitter.emitError payload must be an error-hierarchy object`, e.loc);
|
|
5724
|
+
return true;
|
|
5725
|
+
}
|
|
5726
|
+
if (e.fn === "emitter.names") {
|
|
5727
|
+
const ok = e.type.kind === "array" && e.type.elem.kind === "string";
|
|
5728
|
+
if (!ok)
|
|
5729
|
+
err(`libCall emitter.names must return string[]`, e.loc);
|
|
5730
|
+
return true;
|
|
5731
|
+
}
|
|
5732
|
+
if (e.fn === "emitter.listeners") {
|
|
5733
|
+
const ok = e.type.kind === "array" && e.type.elem.kind === "func";
|
|
5734
|
+
if (!ok)
|
|
5735
|
+
err(`libCall emitter.listeners must return a func array`, e.loc);
|
|
5736
|
+
return true;
|
|
5737
|
+
}
|
|
5738
|
+
if (e.fn === "emitter.emitFlex") {
|
|
5739
|
+
if (e.args.slice(2).some((arg) => arg.type.kind !== "dyn")) {
|
|
5740
|
+
err("libCall emitter.emitFlex payloads must be checked-dynamic", e.loc);
|
|
5119
5741
|
}
|
|
5120
|
-
|
|
5121
|
-
|
|
5742
|
+
}
|
|
5743
|
+
if (e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" || e.fn === "emitter.count" ||
|
|
5744
|
+
e.fn === "emitter.getMax" || e.fn === "emitter.ctor" ||
|
|
5745
|
+
e.fn === "emitter.countFn" || e.fn === "emitter.countDyn" || e.fn === "emitter.emitError") {
|
|
5746
|
+
if (!typeEquals(e.type, result)) {
|
|
5747
|
+
err(`libCall ${e.fn} must be ${result.kind}, got ${e.type.kind}`, e.loc);
|
|
5122
5748
|
}
|
|
5123
|
-
|
|
5749
|
+
return true;
|
|
5124
5750
|
}
|
|
5751
|
+
}
|
|
5752
|
+
return false;
|
|
5753
|
+
}
|
|
5754
|
+
function checkConversionExpr(e) {
|
|
5755
|
+
switch (e.kind) {
|
|
5125
5756
|
case "jsonStringify": {
|
|
5126
5757
|
checkExpr(e.value);
|
|
5127
5758
|
if (e.type.kind !== "string") {
|
|
@@ -5166,11 +5797,19 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5166
5797
|
// Runtime HANDLE targets unwrap the checked-dynamic tree's handle kind by tag (a
|
|
5167
5798
|
// retained reference, no copy — DYN_HANDLE_KINDS).
|
|
5168
5799
|
const handleOk = DYN_HANDLE_KINDS.has(e.type.kind);
|
|
5169
|
-
if (!
|
|
5800
|
+
if (!canDynCheckTo(e.type, (id) => records.get(id), (id) => unions.get(id)) && !undefArmedOk && !bytesOk && !errorOk && !classOk && !funcOk && !handleOk) {
|
|
5170
5801
|
err(`dynCheck against non-JSON-representable type ${e.type.kind}`, e.loc);
|
|
5171
5802
|
}
|
|
5172
5803
|
break;
|
|
5173
5804
|
}
|
|
5805
|
+
default: {
|
|
5806
|
+
const _exhaustive = e;
|
|
5807
|
+
void _exhaustive;
|
|
5808
|
+
}
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
function checkAsyncExpr(e) {
|
|
5812
|
+
switch (e.kind) {
|
|
5174
5813
|
case "awaitExpr": {
|
|
5175
5814
|
checkExpr(e.value);
|
|
5176
5815
|
if (e.value.type.kind !== "promise") {
|
|
@@ -5198,7 +5837,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5198
5837
|
}
|
|
5199
5838
|
// The undefined next-channel has no C value form: such yields are
|
|
5200
5839
|
// void-typed (statement position only — the frontend fences reads).
|
|
5201
|
-
if (
|
|
5840
|
+
if (e.captureCompletion) {
|
|
5841
|
+
if (fn.async || e.type.kind !== "dyn" || !typeEquals(e.captureCompletion.returnType, fn.returnType)) {
|
|
5842
|
+
err("invalid captured generator completion", e.loc);
|
|
5843
|
+
}
|
|
5844
|
+
}
|
|
5845
|
+
else if (fn.generator.nextT.kind === "undefinedT") {
|
|
5202
5846
|
if (e.type.kind !== "void")
|
|
5203
5847
|
err("yield result must be void on an undefined next-channel", e.loc);
|
|
5204
5848
|
}
|
|
@@ -5239,7 +5883,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5239
5883
|
err("genResume throw with no payload", e.loc);
|
|
5240
5884
|
}
|
|
5241
5885
|
else if (e.arg.type.kind === "void" ||
|
|
5242
|
-
e.arg.type.kind === "dyn" ||
|
|
5243
5886
|
e.arg.type.kind === "caught" ||
|
|
5244
5887
|
e.arg.type.kind === "date") {
|
|
5245
5888
|
err(`genResume throw of a ${e.arg.type.kind} value`, e.loc);
|
|
@@ -5377,6 +6020,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5377
6020
|
}
|
|
5378
6021
|
break;
|
|
5379
6022
|
}
|
|
6023
|
+
default: {
|
|
6024
|
+
const _exhaustive = e;
|
|
6025
|
+
void _exhaustive;
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
}
|
|
6029
|
+
function checkIslandExpr(e) {
|
|
6030
|
+
switch (e.kind) {
|
|
5380
6031
|
case "jsMarshal": {
|
|
5381
6032
|
checkExpr(e.value);
|
|
5382
6033
|
if (e.type.kind !== "jsval")
|
|
@@ -5530,6 +6181,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5530
6181
|
}
|
|
5531
6182
|
case "assign": {
|
|
5532
6183
|
const binding = locals.get(s.localId) ?? globals.get(s.localId);
|
|
6184
|
+
if (s.initializes && !binding?.tdz) {
|
|
6185
|
+
err(`initializing assign requires a TDZ binding "${s.localId}"`, s.loc);
|
|
6186
|
+
}
|
|
5533
6187
|
if (!binding)
|
|
5534
6188
|
err(`assign to undeclared local/global "${s.localId}"`, s.loc);
|
|
5535
6189
|
// Global initialization happens via assign inside %init functions,
|
|
@@ -5538,7 +6192,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5538
6192
|
// emits the init-time one. Locals keep the strict check — except a
|
|
5539
6193
|
// TDZ const, whose source declaration IS an assign into the
|
|
5540
6194
|
// scope-entry box (tsc rejects user reassignment there too).
|
|
5541
|
-
else if (!binding.mutable && locals.has(s.localId) && !(
|
|
6195
|
+
else if (!binding.mutable && locals.has(s.localId) && !locals.get(s.localId)?.tdz) {
|
|
5542
6196
|
err(`assign to immutable local "${binding.name}"`, s.loc);
|
|
5543
6197
|
}
|
|
5544
6198
|
if (binding?.type.kind === "caught") {
|
|
@@ -5849,138 +6503,4 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5849
6503
|
err(`non-void function may complete without returning`, fn.loc);
|
|
5850
6504
|
}
|
|
5851
6505
|
}
|
|
5852
|
-
/** Conservative "all paths return" — mirrors what tsc already guarantees. */
|
|
5853
|
-
function alwaysReturns(stmts, unions) {
|
|
5854
|
-
for (const s of stmts) {
|
|
5855
|
-
switch (s.kind) {
|
|
5856
|
-
case "return":
|
|
5857
|
-
return true;
|
|
5858
|
-
case "throw":
|
|
5859
|
-
case "rethrow":
|
|
5860
|
-
case "runtimeFence":
|
|
5861
|
-
// Terminates the path like return: control unwinds (to a handler or
|
|
5862
|
-
// out of the function), never falling off the end. tsc agrees —
|
|
5863
|
-
// `function f(): T { throw x; }` typechecks without a return.
|
|
5864
|
-
return true;
|
|
5865
|
-
case "exprStmt":
|
|
5866
|
-
// process.exit never returns (fflush + _Exit): the path terminates
|
|
5867
|
-
// like a throw. Mirrors tsc's own never-based reachability, which
|
|
5868
|
-
// accepted the function without a trailing return — the
|
|
5869
|
-
// parseAsync().catch entry handler ends exactly this way.
|
|
5870
|
-
if (s.expr.kind === "libCall" && s.expr.fn === "process.exit")
|
|
5871
|
-
return true;
|
|
5872
|
-
break;
|
|
5873
|
-
case "tryCatch":
|
|
5874
|
-
// Normal completion requires the try body to complete normally (and
|
|
5875
|
-
// the catch, when the try raised) — if both always terminate, so
|
|
5876
|
-
// does the whole statement. Without a catch, an exception keeps
|
|
5877
|
-
// propagating (never a normal completion), so the try body alone
|
|
5878
|
-
// decides. A finally that always terminates (throw) also decides.
|
|
5879
|
-
if (alwaysReturns(s.tryBody, unions) &&
|
|
5880
|
-
(s.catchBody === null || alwaysReturns(s.catchBody, unions))) {
|
|
5881
|
-
return true;
|
|
5882
|
-
}
|
|
5883
|
-
if (s.finallyBody && alwaysReturns(s.finallyBody, unions))
|
|
5884
|
-
return true;
|
|
5885
|
-
break;
|
|
5886
|
-
case "if":
|
|
5887
|
-
if (s.else_ && alwaysReturns(s.then, unions) && alwaysReturns(s.else_, unions))
|
|
5888
|
-
return true;
|
|
5889
|
-
break;
|
|
5890
|
-
case "while":
|
|
5891
|
-
// `while (true)` with no break never completes normally (tsc treats
|
|
5892
|
-
// it the same way), so anything after it is unreachable.
|
|
5893
|
-
if (s.cond.kind === "boolLit" && s.cond.value && !containsBreak(s.body))
|
|
5894
|
-
return true;
|
|
5895
|
-
break;
|
|
5896
|
-
case "for":
|
|
5897
|
-
// `for (;;)` — no condition, or a literal-true one — with no break
|
|
5898
|
-
// never completes normally either (the walk-up-until-root idiom:
|
|
5899
|
-
// every exit is a return).
|
|
5900
|
-
if ((s.cond === null || (s.cond.kind === "boolLit" && s.cond.value)) &&
|
|
5901
|
-
!containsBreak(s.body)) {
|
|
5902
|
-
return true;
|
|
5903
|
-
}
|
|
5904
|
-
break;
|
|
5905
|
-
case "block":
|
|
5906
|
-
if (alwaysReturns(s.body, unions))
|
|
5907
|
-
return true;
|
|
5908
|
-
break;
|
|
5909
|
-
case "doWhile":
|
|
5910
|
-
// The body runs at least once: if it returns on all paths, so does
|
|
5911
|
-
// the loop. `do {} while (true)` with no break never completes.
|
|
5912
|
-
if (alwaysReturns(s.body, unions))
|
|
5913
|
-
return true;
|
|
5914
|
-
if (s.cond.kind === "boolLit" && s.cond.value && !containsBreak(s.body))
|
|
5915
|
-
return true;
|
|
5916
|
-
break;
|
|
5917
|
-
case "switch": {
|
|
5918
|
-
// A switch always returns when no case body ever breaks out, every
|
|
5919
|
-
// possible entry point (any case) reaches a return, and dispatch
|
|
5920
|
-
// cannot miss every case: either a default exists, or the switch is
|
|
5921
|
-
// an EXHAUSTIVE discriminant switch — the discriminant is a
|
|
5922
|
-
// `unionDisc` over a union with N arms, every test is a distinct
|
|
5923
|
-
// literal, and there are at least N of them. (At least: several
|
|
5924
|
-
// discriminant VALUES can share one deduped IR arm, e.g.
|
|
5925
|
-
// `{op: 0; a} | {op: 2; a}` is one record shape.) The real
|
|
5926
|
-
// exhaustiveness guarantee is tsc's — it accepted the function
|
|
5927
|
-
// without a trailing return (trust-the-checker, like narrowing
|
|
5928
|
-
// itself); this condition only keeps hand-written IR conservative.
|
|
5929
|
-
// With no switch-level breaks, execution from case i runs bodies
|
|
5930
|
-
// i..end as a straight line — check that flattened suffix.
|
|
5931
|
-
const hasDefault = s.cases.some((c) => c.test === null);
|
|
5932
|
-
const literalTests = s.cases.map((c) => c.test).filter((t) => t !== null && (t.kind === "numLit" || t.kind === "strLit" || t.kind === "boolLit"));
|
|
5933
|
-
const distinct = new Set(literalTests.map((t) => `${t.kind}:${String(t.value)}`));
|
|
5934
|
-
const exhaustive = !hasDefault &&
|
|
5935
|
-
s.disc.kind === "unionDisc" &&
|
|
5936
|
-
literalTests.length === s.cases.length &&
|
|
5937
|
-
distinct.size === s.cases.length &&
|
|
5938
|
-
s.cases.length >= (unions.get(s.disc.unionId)?.arms.length ?? Infinity);
|
|
5939
|
-
if (!hasDefault && !exhaustive)
|
|
5940
|
-
break;
|
|
5941
|
-
if (s.cases.some((c) => containsBreak(c.body)))
|
|
5942
|
-
break;
|
|
5943
|
-
const bodies = s.cases.map((c) => c.body);
|
|
5944
|
-
const everyEntryReturns = bodies.every((_, i) => alwaysReturns(bodies.slice(i).flat(), unions));
|
|
5945
|
-
if (everyEntryReturns)
|
|
5946
|
-
return true;
|
|
5947
|
-
break;
|
|
5948
|
-
}
|
|
5949
|
-
default:
|
|
5950
|
-
break;
|
|
5951
|
-
}
|
|
5952
|
-
}
|
|
5953
|
-
return false;
|
|
5954
|
-
}
|
|
5955
|
-
/** Break at this level (not inside a nested loop or switch, whose bodies
|
|
5956
|
-
* own their breaks). */
|
|
5957
|
-
function containsBreak(stmts) {
|
|
5958
|
-
for (const s of stmts) {
|
|
5959
|
-
switch (s.kind) {
|
|
5960
|
-
case "break":
|
|
5961
|
-
return true;
|
|
5962
|
-
case "if":
|
|
5963
|
-
if (containsBreak(s.then) || (s.else_ && containsBreak(s.else_)))
|
|
5964
|
-
return true;
|
|
5965
|
-
break;
|
|
5966
|
-
case "block":
|
|
5967
|
-
if (containsBreak(s.body))
|
|
5968
|
-
return true;
|
|
5969
|
-
break;
|
|
5970
|
-
case "tryCatch":
|
|
5971
|
-
// Plain try/catch does not capture breaks — a break inside binds to
|
|
5972
|
-
// the enclosing loop/switch (finally-crossing jumps are rejected
|
|
5973
|
-
// upstream, so reachable IR only has these in plain try/catch).
|
|
5974
|
-
if (containsBreak(s.tryBody) ||
|
|
5975
|
-
(s.catchBody !== null && containsBreak(s.catchBody)) ||
|
|
5976
|
-
(s.finallyBody !== null && containsBreak(s.finallyBody))) {
|
|
5977
|
-
return true;
|
|
5978
|
-
}
|
|
5979
|
-
break;
|
|
5980
|
-
default:
|
|
5981
|
-
break; // while/for/doWhile/switch bodies own their breaks
|
|
5982
|
-
}
|
|
5983
|
-
}
|
|
5984
|
-
return false;
|
|
5985
|
-
}
|
|
5986
6506
|
//# sourceMappingURL=validate.js.map
|