@scriptc/compiler 0.1.6 → 0.2.0
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 +73 -25
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +28 -5
- 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 +107 -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/debug-symbols.d.ts +8 -0
- package/dist/backend/debug-symbols.js +52 -0
- package/dist/backend/debug-symbols.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 +2 -1
- package/dist/backend/link-plan.js +18 -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 +9 -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 +4 -0
- package/dist/backend/llvm/blocks.js +25 -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 +70 -28
- 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.d.ts +32 -0
- package/dist/backend/llvm/debug-info.js +198 -0
- package/dist/backend/llvm/debug-info.js.map +1 -0
- 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 +16 -2
- package/dist/backend/llvm/dyn.js +498 -175
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +598 -1
- package/dist/backend/llvm/emitter.js +739 -409
- 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 +1 -1
- package/dist/backend/llvm/expr-bytes.js +32 -14
- 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 +9 -5
- 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 +72 -74
- 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 +51 -30
- 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 +43 -4
- 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 +102 -121
- 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 +59 -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 +21 -16
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +125 -1
- 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 +35 -130
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.js +4 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +26 -1
- package/dist/backend/llvm/split.test.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 +10 -25
- package/dist/backend/native-toolchain.js +89 -219
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +15 -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 +70 -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/source-locations.d.ts +12 -0
- package/dist/backend/source-locations.js +32 -0
- package/dist/backend/source-locations.js.map +1 -0
- package/dist/backend/source-locations.test.d.ts +1 -0
- package/dist/backend/source-locations.test.js +16 -0
- package/dist/backend/source-locations.test.js.map +1 -0
- 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 +95 -30
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +65 -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 +3 -3
- 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.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js +15 -3
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +33 -10
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +38 -16
- 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 +4 -0
- package/dist/frontend/arguments-usage.js +40 -0
- package/dist/frontend/arguments-usage.js.map +1 -0
- package/dist/frontend/binding-source.d.ts +4 -0
- package/dist/frontend/binding-source.js +18 -0
- package/dist/frontend/binding-source.js.map +1 -0
- 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 +63 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
- package/dist/frontend/lowering/class-descriptors.js +73 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -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 +92 -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 +64 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +10 -0
- package/dist/frontend/lowering/class-method-values.js +170 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
- package/dist/frontend/lowering/class-prototypes.js +134 -0
- package/dist/frontend/lowering/class-prototypes.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 +164 -155
- 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 +39 -16
- 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 +11 -0
- package/dist/frontend/lowering/error-methods.js +78 -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 +49 -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 +124 -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 +485 -185
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
- package/dist/frontend/lowering/expressions/optional-chains.js +27 -14
- 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 +93 -0
- package/dist/frontend/lowering/function-context.js +103 -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 +10 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
- package/dist/frontend/lowering/lib-boundary.js +59 -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 +12 -0
- package/dist/frontend/lowering/lower-builtin-values.js +139 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
- package/dist/frontend/lowering/lower-builtins.js +553 -346
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +22 -26
- package/dist/frontend/lowering/lower-calls.js +1373 -380
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +83 -45
- package/dist/frontend/lowering/lower-classes.js +952 -339
- 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 +27 -32
- package/dist/frontend/lowering/lower-containers.js +796 -151
- 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.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 +35 -11
- package/dist/frontend/lowering/lower-exprs.js +1785 -790
- 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 +77 -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 +5 -8
- package/dist/frontend/lowering/lower-island.js +34 -23
- 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 +252 -38
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- 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 +10 -14
- package/dist/frontend/lowering/lower-stmts.js +731 -532
- 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 +19 -10
- 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 +113 -189
- package/dist/frontend/lowering/lowerer.js +1033 -663
- 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 +26 -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 +9 -4
- package/dist/frontend/lowering/surfaces.js +98 -35
- 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 +10 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +77 -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 +5 -4
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +1 -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 +43 -19
- package/dist/frontend/program.js +556 -197
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.d.ts +1 -0
- package/dist/frontend/program.test.js +202 -0
- package/dist/frontend/program.test.js.map +1 -0
- 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 +21 -15
- 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 +52 -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 +29 -19
- package/dist/frontend/type-mapper.js +713 -306
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.d.ts +1 -0
- package/dist/frontend/type-mapper.test.js +207 -0
- package/dist/frontend/type-mapper.test.js.map +1 -0
- 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 -197
- package/dist/index.js +369 -1567
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +25 -6
- 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 +309 -164
- package/dist/ir/ir.js +588 -879
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +127 -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 +19 -12
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +53 -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 +1956 -1496
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +476 -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/compiler-self-identity.d.ts +1 -1
- package/dist/library/compiler-self-identity.js +31 -15
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/compiler-self-identity.test.d.ts +1 -0
- package/dist/library/compiler-self-identity.test.js +93 -0
- package/dist/library/compiler-self-identity.test.js.map +1 -0
- 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 +135 -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 +74 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +33 -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 +171 -18
- 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 -531
- package/dist/backend/c/c-emitter.js +0 -1917
- 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 -8803
- 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 -1084
- 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 -1773
- 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
|
|
@@ -43,6 +45,7 @@ export const REGEX_INTRINSIC_SIGS = {
|
|
|
43
45
|
search: { receiver: STRING, argTypes: [REGEX], result: F64 },
|
|
44
46
|
source: { receiver: REGEX, argTypes: [], result: STRING },
|
|
45
47
|
flags: { receiver: REGEX, argTypes: [], result: STRING },
|
|
48
|
+
toString: { receiver: REGEX, argTypes: [], result: STRING },
|
|
46
49
|
replace: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
|
|
47
50
|
replaceAll: { receiver: STRING, argTypes: [REGEX, STRING], result: STRING },
|
|
48
51
|
split: { receiver: STRING, argTypes: [REGEX, F64], result: arrayOf(STRING) },
|
|
@@ -57,6 +60,7 @@ export const REGEX_INTRINSIC_SIGS = {
|
|
|
57
60
|
export const LIB_FN_SIGS = {
|
|
58
61
|
"fetch.start": { argTypes: [STRING, DYN], result: { kind: "promise", inner: DYN } },
|
|
59
62
|
"fetch.responseNew": { argTypes: [DYN, DYN], result: DYN },
|
|
63
|
+
"fetch.responseArrayBuffer": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
|
|
60
64
|
"fetch.responseJson": { argTypes: [DYN], result: { kind: "promise", inner: DYN } },
|
|
61
65
|
"fetch.responseText": { argTypes: [DYN], result: { kind: "promise", inner: STRING } },
|
|
62
66
|
"fetch.responseBytes": { argTypes: [DYN], result: { kind: "promise", inner: BYTES_U8 } },
|
|
@@ -78,13 +82,45 @@ export const LIB_FN_SIGS = {
|
|
|
78
82
|
// checked in the libCall case, like error.new.
|
|
79
83
|
"island.castFail": { argTypes: [JSVAL, STRING], result: VOID },
|
|
80
84
|
"json.parse": { argTypes: [STRING], result: DYN },
|
|
85
|
+
"json.parseReviver": { argTypes: [STRING, DYN], result: DYN },
|
|
86
|
+
"json.stringifyReplacer": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
87
|
+
"json.stringifyValue": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
81
88
|
"dyn.keySet": { argTypes: [DYN, STRING, DYN], result: VOID },
|
|
89
|
+
"dyn.keySetComputed": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
90
|
+
"dyn.keyDelete": { argTypes: [DYN, STRING, BOOL], result: VOID },
|
|
91
|
+
"dyn.keyDeleteComputed": { argTypes: [DYN, DYN, BOOL], result: VOID },
|
|
92
|
+
"dyn.hasKeyComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
93
|
+
"dyn.hasOwnComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
94
|
+
"dyn.propertyIsEnumerableComputed": { argTypes: [DYN, DYN], result: BOOL },
|
|
95
|
+
"dyn.globalSymbolGet": { argTypes: [SYMBOL_T], result: DYN },
|
|
96
|
+
"dyn.globalSymbolSet": { argTypes: [SYMBOL_T, DYN], result: VOID },
|
|
97
|
+
"dyn.globalSymbolHas": { argTypes: [SYMBOL_T], result: BOOL },
|
|
98
|
+
"dyn.globalSymbolDelete": { argTypes: [SYMBOL_T], result: VOID },
|
|
99
|
+
"dyn.typedRefIs": { argTypes: [DYN, STRING], result: BOOL },
|
|
82
100
|
"dyn.iterPack": { argTypes: [DYN, STRING], result: DYN },
|
|
101
|
+
"dyn.arrayFromIterator": { argTypes: [DYN], result: DYN },
|
|
102
|
+
"dyn.iterator": { argTypes: [DYN, STRING], result: DYN },
|
|
103
|
+
"dyn.iteratorResult": { argTypes: [DYN], result: DYN },
|
|
104
|
+
"dyn.mapSeedEntries": { argTypes: [DYN], result: DYN },
|
|
105
|
+
"dyn.mapSeedEntry": { argTypes: [DYN], result: DYN },
|
|
83
106
|
"dyn.arrLen": { argTypes: [DYN], result: F64 },
|
|
84
107
|
"dyn.arrAt": { argTypes: [DYN, F64], result: DYN },
|
|
85
108
|
"dyn.hasKey": { argTypes: [DYN, STRING], result: BOOL },
|
|
86
|
-
"dyn.
|
|
109
|
+
"dyn.freeze": { argTypes: [DYN], result: DYN },
|
|
110
|
+
"dyn.isFrozen": { argTypes: [DYN], result: BOOL },
|
|
111
|
+
"dyn.nativeSetNew": { argTypes: [DYN], result: DYN },
|
|
112
|
+
"dyn.nativeSetIs": { argTypes: [DYN], result: BOOL },
|
|
113
|
+
"dyn.nativeMapIs": { argTypes: [DYN], result: BOOL },
|
|
114
|
+
"dyn.nativeUrlIs": { argTypes: [DYN], result: BOOL },
|
|
115
|
+
"dyn.nativeDateIs": { argTypes: [DYN], result: BOOL },
|
|
116
|
+
"date.nativeNew": { argTypes: [DYN], result: DYN },
|
|
117
|
+
"date.checkedValue": { argTypes: [DYN], result: DATE_T },
|
|
118
|
+
"dyn.nativeRegexIs": { argTypes: [DYN], result: BOOL },
|
|
119
|
+
"dyn.toString": { argTypes: [DYN, DYN, STRING], result: STRING },
|
|
87
120
|
"dyn.defineProps": { argTypes: [DYN, DYN], result: DYN },
|
|
121
|
+
"dyn.defineProperty": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
122
|
+
"dyn.getOwnPropertyDescriptor": { argTypes: [DYN, DYN], result: DYN },
|
|
123
|
+
"dyn.arrayProtoCall": { argTypes: [DYN, STRING, DYN], result: DYN },
|
|
88
124
|
"dyn.typeof": { argTypes: [DYN], result: STRING },
|
|
89
125
|
"dyn.objectTag": { argTypes: [DYN], result: STRING },
|
|
90
126
|
"module.registryInit": { argTypes: [F64], result: VOID },
|
|
@@ -139,8 +175,8 @@ export const LIB_FN_SIGS = {
|
|
|
139
175
|
// Signal listeners are zero-param (the ambient shape); exit/stdin
|
|
140
176
|
// callbacks carry program-dependent one-param shapes — null slots, the
|
|
141
177
|
// libCall case checks them (child.onExit precedent).
|
|
142
|
-
"process.onSignal": { argTypes: [
|
|
143
|
-
"process.offSignal": { argTypes: [
|
|
178
|
+
"process.onSignal": { argTypes: [STRING, DYN, BOOL], result: VOID },
|
|
179
|
+
"process.offSignal": { argTypes: [STRING, DYN], result: VOID },
|
|
144
180
|
"process.onExit": { argTypes: [null, BOOL], result: VOID },
|
|
145
181
|
"process.offExit": { argTypes: [null], result: VOID },
|
|
146
182
|
"stdin.onData": { argTypes: [null, BOOL], result: VOID },
|
|
@@ -188,6 +224,7 @@ export const LIB_FN_SIGS = {
|
|
|
188
224
|
"net.getAutoSelTimeout": { argTypes: [], result: F64 },
|
|
189
225
|
"net.setAutoSelTimeout": { argTypes: [F64], result: VOID },
|
|
190
226
|
"fs.realpathSync": { argTypes: [STRING], result: STRING },
|
|
227
|
+
"fs.realpathNativeSync": { argTypes: [STRING], result: STRING },
|
|
191
228
|
"os.userName": { argTypes: [], result: STRING },
|
|
192
229
|
"os.userShell": { argTypes: [], result: STRING },
|
|
193
230
|
"os.userHomedir": { argTypes: [], result: STRING },
|
|
@@ -204,20 +241,31 @@ export const LIB_FN_SIGS = {
|
|
|
204
241
|
"math.trunc": { argTypes: [F64], result: F64 },
|
|
205
242
|
"math.ceil": { argTypes: [F64], result: F64 },
|
|
206
243
|
"math.sin": { argTypes: [F64], result: F64 },
|
|
244
|
+
"math.sinh": { argTypes: [F64], result: F64 },
|
|
207
245
|
"math.cos": { argTypes: [F64], result: F64 },
|
|
246
|
+
"math.cosh": { argTypes: [F64], result: F64 },
|
|
208
247
|
"math.tan": { argTypes: [F64], result: F64 },
|
|
248
|
+
"math.tanh": { argTypes: [F64], result: F64 },
|
|
209
249
|
"math.asin": { argTypes: [F64], result: F64 },
|
|
250
|
+
"math.asinh": { argTypes: [F64], result: F64 },
|
|
210
251
|
"math.acos": { argTypes: [F64], result: F64 },
|
|
252
|
+
"math.acosh": { argTypes: [F64], result: F64 },
|
|
211
253
|
"math.atan": { argTypes: [F64], result: F64 },
|
|
254
|
+
"math.atanh": { argTypes: [F64], result: F64 },
|
|
212
255
|
"math.cbrt": { argTypes: [F64], result: F64 },
|
|
256
|
+
"math.clz32": { argTypes: [F64], result: F64 },
|
|
213
257
|
"math.sign": { argTypes: [F64], result: F64 },
|
|
214
258
|
"math.exp": { argTypes: [F64], result: F64 },
|
|
259
|
+
"math.expm1": { argTypes: [F64], result: F64 },
|
|
260
|
+
"math.fround": { argTypes: [F64], result: F64 },
|
|
215
261
|
"math.sqrt": { argTypes: [F64], result: F64 },
|
|
216
262
|
"math.log": { argTypes: [F64], result: F64 },
|
|
263
|
+
"math.log1p": { argTypes: [F64], result: F64 },
|
|
217
264
|
"math.log2": { argTypes: [F64], result: F64 },
|
|
218
265
|
"math.log10": { argTypes: [F64], result: F64 },
|
|
219
266
|
"math.atan2": { argTypes: [F64, F64], result: F64 },
|
|
220
267
|
"math.pow": { argTypes: [F64, F64], result: F64 },
|
|
268
|
+
"math.imul": { argTypes: [F64, F64], result: F64 },
|
|
221
269
|
"math.min": { argTypes: [F64, F64], result: F64 },
|
|
222
270
|
"math.max": { argTypes: [F64, F64], result: F64 },
|
|
223
271
|
"math.random": { argTypes: [], result: F64 },
|
|
@@ -242,6 +290,7 @@ export const LIB_FN_SIGS = {
|
|
|
242
290
|
"sym.new": { argTypes: [STRING], result: SYMBOL_T },
|
|
243
291
|
"sym.newAnon": { argTypes: [], result: SYMBOL_T },
|
|
244
292
|
"sym.for": { argTypes: [STRING], result: SYMBOL_T },
|
|
293
|
+
"sym.wellKnown": { argTypes: [STRING], result: SYMBOL_T },
|
|
245
294
|
// Result is the interned `string | undefined` union — the libCall case
|
|
246
295
|
// checks the arms (the spawnRes.error pattern).
|
|
247
296
|
"sym.keyFor": { argTypes: [SYMBOL_T], result: VOID },
|
|
@@ -277,6 +326,7 @@ export const LIB_FN_SIGS = {
|
|
|
277
326
|
"bigint.dataViewGet": { argTypes: [BYTES_U8, F64, BOOL, BOOL], result: BIGINT_T },
|
|
278
327
|
"bigint.dataViewSet": { argTypes: [BYTES_U8, F64, BIGINT_T, BOOL], result: VOID },
|
|
279
328
|
"url.new": { argTypes: [STRING], result: URL_T },
|
|
329
|
+
"url.newBase": { argTypes: [STRING, STRING], result: URL_T },
|
|
280
330
|
"url.protocol": { argTypes: [URL_T], result: STRING },
|
|
281
331
|
"url.origin": { argTypes: [URL_T], result: STRING },
|
|
282
332
|
"url.username": { argTypes: [URL_T], result: STRING },
|
|
@@ -287,8 +337,10 @@ export const LIB_FN_SIGS = {
|
|
|
287
337
|
"url.pathname": { argTypes: [URL_T], result: STRING },
|
|
288
338
|
"url.href": { argTypes: [URL_T], result: STRING },
|
|
289
339
|
"url.fileURLToPathUrl": { argTypes: [URL_T], result: STRING },
|
|
340
|
+
"url.fileURLToPathChecked": { argTypes: [DYN], result: STRING },
|
|
290
341
|
"url.fileURLToPathStr": { argTypes: [STRING], result: STRING },
|
|
291
342
|
"url.pathToFileURL": { argTypes: [STRING], result: URL_T },
|
|
343
|
+
"url.pathToFileURLPlatform": { argTypes: [STRING, BOOL], result: URL_T },
|
|
292
344
|
"url.pathToFileURLWin32": { argTypes: [STRING], result: URL_T },
|
|
293
345
|
"sp.new": { argTypes: [], result: SEARCH_PARAMS_T },
|
|
294
346
|
"sp.parse": { argTypes: [STRING], result: SEARCH_PARAMS_T },
|
|
@@ -898,6 +950,8 @@ export const LIB_FN_SIGS = {
|
|
|
898
950
|
// The Buffer statics and the fs/zlib Buffer forms: fixed always-u8
|
|
899
951
|
// signatures (Buffer IS a Uint8Array — one bytes kind).
|
|
900
952
|
"buffer.fromStr": { argTypes: [STRING, STRING], result: BYTES_U8 },
|
|
953
|
+
"buffer.brand": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
954
|
+
"buffer.fromDyn": { argTypes: [DYN, STRING], result: BYTES_U8 },
|
|
901
955
|
"buffer.concat": { argTypes: [arrayOf(BYTES_U8)], result: BYTES_U8 },
|
|
902
956
|
"buffer.byteLenStr": { argTypes: [STRING, STRING], result: F64 },
|
|
903
957
|
"buffer.isEncoding": { argTypes: [STRING], result: BOOL },
|
|
@@ -926,10 +980,12 @@ export const LIB_FN_SIGS = {
|
|
|
926
980
|
"emitter.setDefaultMaxChk": { argTypes: [DYN, STRING], result: VOID },
|
|
927
981
|
"fs.readFileSyncBytes": { argTypes: [STRING], result: BYTES_U8 },
|
|
928
982
|
"fs.writeFileSyncBytes": { argTypes: [STRING, BYTES_U8], result: VOID },
|
|
983
|
+
"fs.appendFileSyncBytes": { argTypes: [STRING, BYTES_U8], result: VOID },
|
|
929
984
|
"fsp.readFileBytes": { argTypes: [STRING], result: { kind: "promise", inner: BYTES_U8 } },
|
|
930
985
|
"zlib.deflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
931
986
|
"zlib.inflateSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
932
987
|
"zlib.deflateRawSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
988
|
+
"zlib.deflateLevelSync": { argTypes: [BYTES_U8, F64, F64], result: BYTES_U8 },
|
|
933
989
|
"zlib.inflateRawSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
934
990
|
"zlib.gzipSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
935
991
|
"zlib.gunzipSync": { argTypes: [BYTES_U8], result: BYTES_U8 },
|
|
@@ -999,26 +1055,52 @@ export const LIB_FN_SIGS = {
|
|
|
999
1055
|
"process.getgid": { argTypes: [], result: F64 },
|
|
1000
1056
|
"process.execPath": { argTypes: [], result: STRING },
|
|
1001
1057
|
"process.arch": { argTypes: [], result: STRING },
|
|
1058
|
+
"process.versions": { argTypes: [], result: DYN },
|
|
1059
|
+
"process.builtinId": { argTypes: [DYN, arrayOf(STRING)], result: STRING },
|
|
1060
|
+
"process.builtinModule": { argTypes: [STRING, DYN], result: DYN },
|
|
1061
|
+
"process.builtinUnsupported": { argTypes: [STRING, STRING], result: DYN },
|
|
1062
|
+
"process.hrtimeValue": { argTypes: [], result: DYN },
|
|
1002
1063
|
"process.versionsNode": { argTypes: [], result: STRING },
|
|
1003
1064
|
"process.versionsOpenssl": { argTypes: [], result: STRING },
|
|
1004
1065
|
"process.kill": { argTypes: [F64, STRING], result: BOOL },
|
|
1005
1066
|
"process.killNum": { argTypes: [F64, F64], result: BOOL },
|
|
1006
1067
|
"process.stdoutWrite": { argTypes: [STRING], result: BOOL },
|
|
1068
|
+
"process.stdio": { argTypes: [F64], result: DYN },
|
|
1007
1069
|
"process.stderrWrite": { argTypes: [STRING], result: BOOL },
|
|
1008
1070
|
// error.new's result and the receiver slots are builtin-error classes —
|
|
1009
1071
|
// program-dependent object types, checked in the libCall case.
|
|
1010
1072
|
"error.new": { argTypes: [STRING], result: VOID },
|
|
1073
|
+
"error.newOptions": { argTypes: [DYN, DYN], result: VOID },
|
|
1074
|
+
"error.ctorOptions": { argTypes: [null, DYN, DYN], result: VOID },
|
|
1075
|
+
"error.cause": { argTypes: [null], result: DYN },
|
|
1076
|
+
"error.hasCause": { argTypes: [null], result: BOOL },
|
|
1077
|
+
"error.setCause": { argTypes: [null, DYN], result: VOID },
|
|
1078
|
+
"error.deleteCause": { argTypes: [null], result: VOID },
|
|
1011
1079
|
"error.nodeThrow": { argTypes: [F64, STRING, STRING], result: VOID },
|
|
1012
1080
|
"dyn.toStringCoerce": { argTypes: [DYN], result: STRING },
|
|
1081
|
+
"dyn.stringConstructor": { argTypes: [DYN], result: STRING },
|
|
1082
|
+
"dyn.propertyKey": { argTypes: [DYN], result: DYN },
|
|
1083
|
+
"dyn.toNumeric": { argTypes: [DYN], result: DYN },
|
|
1084
|
+
"dyn.increment": { argTypes: [DYN, BOOL], result: DYN },
|
|
1085
|
+
"dyn.numberConstructor": { argTypes: [DYN], result: F64 },
|
|
1013
1086
|
"dyn.toNumberCoerce": { argTypes: [DYN], result: F64 },
|
|
1087
|
+
"dyn.add": { argTypes: [DYN, DYN], result: DYN },
|
|
1088
|
+
"dyn.arithmetic": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1089
|
+
"dyn.bitwise": { argTypes: [DYN, DYN, STRING], result: DYN },
|
|
1090
|
+
"dyn.proxyNew": { argTypes: [DYN, DYN], result: DYN },
|
|
1014
1091
|
// Always throws; the result is the READ's declared type (a typed dummy
|
|
1015
1092
|
// the unwind abandons) — the libCall case skips the result check.
|
|
1016
1093
|
"global.undefRead": { argTypes: [STRING], result: VOID },
|
|
1094
|
+
"console.native": { argTypes: [], result: DYN },
|
|
1095
|
+
"global.native": { argTypes: [arrayOf(STRING)], result: DYN },
|
|
1017
1096
|
// `X.name` through a class value: the arg is a program-dependent
|
|
1018
1097
|
// classval (a null slot; the libCall case checks the kind).
|
|
1019
1098
|
"class.name": { argTypes: [null], result: STRING },
|
|
1020
1099
|
"error.ctor": { argTypes: [null, STRING], result: VOID },
|
|
1021
1100
|
"error.toString": { argTypes: [null], result: STRING },
|
|
1101
|
+
"error.stack": { argTypes: [null], result: STRING },
|
|
1102
|
+
"error.stackLimitGet": { argTypes: [], result: F64 },
|
|
1103
|
+
"error.stackLimitSet": { argTypes: [F64], result: VOID },
|
|
1022
1104
|
// Receiver (any error-hierarchy object) and the program-dependent
|
|
1023
1105
|
// `string | undefined` result are checked in the libCall case.
|
|
1024
1106
|
"error.code": { argTypes: [null], result: VOID },
|
|
@@ -1033,20 +1115,63 @@ export const LIB_FN_SIGS = {
|
|
|
1033
1115
|
"error.domCause": { argTypes: [null], result: DYN },
|
|
1034
1116
|
"error.domClone": { argTypes: [null, DYN], result: VOID },
|
|
1035
1117
|
"dyn.errInstanceof": { argTypes: [DYN, F64], result: BOOL },
|
|
1118
|
+
"weakMap.is": { argTypes: [DYN], result: BOOL },
|
|
1119
|
+
"weakSet.is": { argTypes: [DYN], result: BOOL },
|
|
1120
|
+
"weakMap.new": { argTypes: [DYN], result: DYN },
|
|
1121
|
+
"weakSet.new": { argTypes: [DYN], result: DYN },
|
|
1122
|
+
"dyn.fromEntries": { argTypes: [DYN], result: DYN },
|
|
1123
|
+
"arrayBuffer.new": { argTypes: [DYN], result: DYN },
|
|
1124
|
+
"ffi.argument": { argTypes: [DYN, STRING], result: DYN },
|
|
1125
|
+
"ffi.memoryModule": { argTypes: [DYN], result: DYN },
|
|
1126
|
+
"intl.segmenterNew": { argTypes: [], result: DYN },
|
|
1127
|
+
"arrayBuffer.is": { argTypes: [DYN], result: BOOL },
|
|
1128
|
+
"arrayBuffer.isView": { argTypes: [DYN], result: BOOL },
|
|
1129
|
+
"arrayBuffer.byteLengthGetter": { argTypes: [], result: F64 },
|
|
1130
|
+
"arrayBuffer.byteLengthDescriptor": { argTypes: [DYN], result: DYN },
|
|
1131
|
+
"arrayBuffer.viewU8C": { argTypes: [DYN, DYN, DYN], result: bytesOf("u8c") },
|
|
1132
|
+
"arrayBuffer.viewI8": { argTypes: [DYN, DYN, DYN], result: bytesOf("i8") },
|
|
1133
|
+
"arrayBuffer.viewU16": { argTypes: [DYN, DYN, DYN], result: bytesOf("u16") },
|
|
1134
|
+
"arrayBuffer.viewI16": { argTypes: [DYN, DYN, DYN], result: bytesOf("i16") },
|
|
1135
|
+
"arrayBuffer.viewU8": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
|
1136
|
+
"arrayBuffer.viewU32": { argTypes: [DYN, DYN, DYN], result: bytesOf("u32") },
|
|
1137
|
+
"arrayBuffer.viewI32": { argTypes: [DYN, DYN, DYN], result: bytesOf("i32") },
|
|
1138
|
+
"arrayBuffer.viewF32": { argTypes: [DYN, DYN, DYN], result: bytesOf("f32") },
|
|
1139
|
+
"arrayBuffer.viewF64": { argTypes: [DYN, DYN, DYN], result: bytesOf("f64") },
|
|
1140
|
+
"arrayBuffer.viewDV": { argTypes: [DYN, DYN, DYN], result: BYTES_U8 },
|
|
1036
1141
|
"dyn.objKeys": { argTypes: [DYN], result: DYN },
|
|
1142
|
+
"dyn.forInKeys": { argTypes: [DYN], result: DYN },
|
|
1037
1143
|
"dyn.hasOwn": { argTypes: [DYN, STRING], result: BOOL },
|
|
1144
|
+
"dyn.propertyIsEnumerable": { argTypes: [DYN, STRING], result: BOOL },
|
|
1038
1145
|
"dyn.assign": { argTypes: [DYN, DYN], result: DYN },
|
|
1146
|
+
"dyn.copyDataProperties": { argTypes: [DYN, DYN], result: DYN },
|
|
1039
1147
|
"dyn.packPush": { argTypes: [DYN, DYN], result: VOID },
|
|
1040
1148
|
"dyn.packPushSpread": { argTypes: [DYN, DYN, STRING], result: VOID },
|
|
1041
1149
|
"dyn.packPushSpreadIter": { argTypes: [DYN, DYN], result: VOID },
|
|
1042
1150
|
"dyn.assignAll": { argTypes: [DYN, DYN], result: DYN },
|
|
1043
1151
|
"dyn.objCreateNullProto": { argTypes: [], result: DYN },
|
|
1152
|
+
"dyn.arrayPrototype": { argTypes: [], result: DYN },
|
|
1153
|
+
"dyn.classPrototype": { argTypes: [DYN, DYN], result: DYN },
|
|
1154
|
+
"dyn.classBasePrototype": { argTypes: [DYN], result: DYN },
|
|
1155
|
+
"dyn.classSuper": { argTypes: [DYN, DYN, DYN], result: VOID },
|
|
1156
|
+
"dyn.assignPrototype": { argTypes: [DYN, DYN, DYN], result: DYN },
|
|
1157
|
+
"dyn.objCreate": { argTypes: [DYN], result: DYN },
|
|
1158
|
+
"dyn.objCreateWithProperties": { argTypes: [DYN, DYN], result: DYN },
|
|
1159
|
+
"dyn.getPrototype": { argTypes: [DYN], result: DYN },
|
|
1160
|
+
"dyn.setPrototype": { argTypes: [DYN, DYN], result: DYN },
|
|
1161
|
+
"dyn.getOwnPropertyNames": { argTypes: [DYN], result: DYN },
|
|
1162
|
+
"dyn.getOwnPropertySymbols": { argTypes: [DYN], result: DYN },
|
|
1163
|
+
"dyn.getOwnPropertyDescriptors": { argTypes: [DYN], result: DYN },
|
|
1164
|
+
"dyn.preventExtensions": { argTypes: [DYN], result: DYN },
|
|
1165
|
+
"dyn.isExtensible": { argTypes: [DYN], result: BOOL },
|
|
1166
|
+
"dyn.seal": { argTypes: [DYN], result: DYN },
|
|
1167
|
+
"dyn.isSealed": { argTypes: [DYN], result: BOOL },
|
|
1044
1168
|
"dyn.objValues": { argTypes: [DYN], result: DYN },
|
|
1045
1169
|
"dyn.objEntries": { argTypes: [DYN], result: DYN },
|
|
1046
1170
|
"dyn.structuredClone": { argTypes: [DYN, DYN], result: DYN },
|
|
1047
1171
|
"dyn.cloneMissing": { argTypes: [], result: DYN },
|
|
1048
1172
|
"dyn.cloneTransferFail": { argTypes: [], result: DYN },
|
|
1049
1173
|
"regex.new": { argTypes: [STRING, STRING], result: REGEX },
|
|
1174
|
+
"regex.newChecked": { argTypes: [DYN, DYN], result: REGEX },
|
|
1050
1175
|
// node:events EventEmitter: receivers are emitter-hierarchy objects and
|
|
1051
1176
|
// the chaining forms (on/off/removeAll/setMax) return the receiver's
|
|
1052
1177
|
// own class — program-dependent object types, checked in the libCall
|
|
@@ -1071,6 +1196,7 @@ export const LIB_FN_SIGS = {
|
|
|
1071
1196
|
"emitter.emitError": { argTypes: [null, STRING, null], result: BOOL },
|
|
1072
1197
|
"emitter.count": { argTypes: [null, STRING], result: F64 },
|
|
1073
1198
|
"emitter.countFn": { argTypes: [null, STRING, null], result: F64 },
|
|
1199
|
+
"emitter.countDyn": { argTypes: [null, STRING, DYN], result: F64 },
|
|
1074
1200
|
"emitter.names": { argTypes: [null], result: VOID },
|
|
1075
1201
|
"emitter.listeners": { argTypes: [null, STRING], result: VOID },
|
|
1076
1202
|
"emitter.onData": { argTypes: [null, STRING, null, BOOL, BOOL], result: VOID },
|
|
@@ -1258,6 +1384,8 @@ export const LIB_FN_SIGS = {
|
|
|
1258
1384
|
"dc.tcTraceSync": { argTypes: [F64, DYN, DYN, DYN, DYN], result: DYN },
|
|
1259
1385
|
"dc.tcTraceCallback": { argTypes: [F64, DYN, F64, DYN, DYN, DYN], result: DYN },
|
|
1260
1386
|
"dc.tcTracePromise": { argTypes: [F64, DYN, DYN, DYN, DYN], result: { kind: "promise", inner: DYN } },
|
|
1387
|
+
"process.onUncaughtException": { argTypes: [DYN, BOOL, BOOL], result: VOID },
|
|
1388
|
+
"process.offUncaughtException": { argTypes: [DYN, BOOL], result: VOID },
|
|
1261
1389
|
"process.onUnhandledRejection": { argTypes: [DYN, BOOL], result: VOID },
|
|
1262
1390
|
"process.offUnhandledRejection": { argTypes: [DYN], result: VOID },
|
|
1263
1391
|
"process.onRejectionHandled": { argTypes: [DYN, BOOL], result: VOID },
|
|
@@ -1327,6 +1455,7 @@ export const LIB_FN_SIGS = {
|
|
|
1327
1455
|
// Arg 0 is a packed f64[] OR a bytes value (the spread-typed-array
|
|
1328
1456
|
// form) — checked in the libCall case.
|
|
1329
1457
|
"string.fromCharCode": { argTypes: [null], result: STRING },
|
|
1458
|
+
"string.fromCodePoint": { argTypes: [null], result: STRING },
|
|
1330
1459
|
"string.lastIndexOf": { argTypes: [STRING, STRING], result: F64 },
|
|
1331
1460
|
"string.lastIndexOfFrom": { argTypes: [STRING, STRING, F64], result: F64 },
|
|
1332
1461
|
"string.raw": { argTypes: [arrayOf(STRING), arrayOf(STRING)], result: STRING },
|
|
@@ -1375,6 +1504,30 @@ export function validateModule(mod) {
|
|
|
1375
1504
|
}
|
|
1376
1505
|
const retainedFfiCallbacks = new Map();
|
|
1377
1506
|
for (const entry of mod.ffiImports ?? []) {
|
|
1507
|
+
if (entry.callbackOperation !== undefined) {
|
|
1508
|
+
const fail = (detail) => { errors.push({ message: `FFI callback operation "${entry.name}" ${detail}`, loc: moduleLoc }); };
|
|
1509
|
+
if (!entry.library || entry.library.includes("\0"))
|
|
1510
|
+
fail("requires a library name");
|
|
1511
|
+
if (entry.callbackOperation === "register") {
|
|
1512
|
+
const param = entry.params[0];
|
|
1513
|
+
if (entry.params.length !== 1 || !param || !isFfiCallbackParam(param) ||
|
|
1514
|
+
param.callback.id !== "callback" || param.callback.lifetime !== "retained" || param.callback.invoke !== "script-thread" ||
|
|
1515
|
+
param.callback.params.some(p => typeof p !== "string" || ["cstring", "string", "bytes"].includes(p)) ||
|
|
1516
|
+
entry.returns !== "pointer" || entry.callbackTarget !== undefined)
|
|
1517
|
+
fail("has an invalid registration ABI");
|
|
1518
|
+
}
|
|
1519
|
+
else if (entry.callbackOperation === "release") {
|
|
1520
|
+
const target = entry.callbackTarget ? ffiByName.get(entry.callbackTarget) : undefined;
|
|
1521
|
+
if (entry.params.length !== 0 || entry.returns !== "void" || target?.callbackOperation !== "register" ||
|
|
1522
|
+
target.library !== entry.library)
|
|
1523
|
+
fail("has an invalid release target or ABI");
|
|
1524
|
+
}
|
|
1525
|
+
else
|
|
1526
|
+
fail("has an invalid operation");
|
|
1527
|
+
}
|
|
1528
|
+
else if (entry.callbackTarget !== undefined) {
|
|
1529
|
+
errors.push({ message: `FFI binding "${entry.name}" has a callback target without a release operation`, loc: moduleLoc });
|
|
1530
|
+
}
|
|
1378
1531
|
const ids = new Set();
|
|
1379
1532
|
for (const param of entry.params) {
|
|
1380
1533
|
if (!isFfiCallbackParam(param))
|
|
@@ -1387,6 +1540,9 @@ export function validateModule(mod) {
|
|
|
1387
1540
|
errors.push({ message: `FFI callback "${entry.name}:${param.callback.id}" has invalid invoke mode`, loc: moduleLoc });
|
|
1388
1541
|
}
|
|
1389
1542
|
if (param.callback.invoke === "foreign") {
|
|
1543
|
+
if (param.callback.params.some((p) => p === "i64" || p === "u64" || p === "pointer")) {
|
|
1544
|
+
errors.push({ message: `FFI foreign callback "${entry.name}:${param.callback.id}" has unsupported 64-bit or pointer arguments`, loc: moduleLoc });
|
|
1545
|
+
}
|
|
1390
1546
|
if (param.callback.lifetime !== "retained") {
|
|
1391
1547
|
errors.push({ message: `FFI foreign callback "${entry.name}:${param.callback.id}" is not retained`, loc: moduleLoc });
|
|
1392
1548
|
}
|
|
@@ -1524,6 +1680,30 @@ export function validateModule(mod) {
|
|
|
1524
1680
|
errors.push({ message: `duplicate class "${cls.name}"`, loc: cls.loc });
|
|
1525
1681
|
}
|
|
1526
1682
|
classesByName.set(cls.name, cls);
|
|
1683
|
+
if (cls.localCaptures !== undefined && (cls.runtime || cls.genericOf !== undefined)) {
|
|
1684
|
+
errors.push({ message: `class ${cls.name}: local class cannot use a runtime or generic family layout`, loc: cls.loc });
|
|
1685
|
+
}
|
|
1686
|
+
if (cls.localCaptures !== undefined) {
|
|
1687
|
+
const environment = cls.fields.find((field) => field.name === `%classEnvironment:${cls.name}`);
|
|
1688
|
+
if (environment?.type.kind !== "classval" || environment.type.className !== cls.name) {
|
|
1689
|
+
errors.push({ message: `class ${cls.name}: local class requires its constructor environment field`, loc: cls.loc });
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
if (cls.localBaseCapture !== undefined) {
|
|
1693
|
+
const base = cls.localCaptures?.[cls.localBaseCapture];
|
|
1694
|
+
if (!Number.isInteger(cls.localBaseCapture) || base?.type.kind !== "classval" || base.type.className !== cls.base) {
|
|
1695
|
+
errors.push({ message: `class ${cls.name}: invalid local base capture`, loc: cls.loc });
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
if (cls.jsLength !== undefined && (!Number.isSafeInteger(cls.jsLength) || cls.jsLength < 0)) {
|
|
1699
|
+
errors.push({ message: `class ${cls.name}: invalid constructor length`, loc: cls.loc });
|
|
1700
|
+
}
|
|
1701
|
+
if (cls.prototypeDataHelper !== undefined) {
|
|
1702
|
+
const helper = functionsByName.get(cls.prototypeDataHelper);
|
|
1703
|
+
if (!helper || helper.params.length !== 0 || helper.returnType.kind !== "dyn" || helper.captures !== undefined || helper.classCaptures !== undefined) {
|
|
1704
|
+
errors.push({ message: `class ${cls.name}: prototype data helper must be a noncapturing () => dyn function`, loc: cls.loc });
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1527
1707
|
const seen = new Set();
|
|
1528
1708
|
for (const f of cls.fields) {
|
|
1529
1709
|
if (seen.has(f.name)) {
|
|
@@ -1566,6 +1746,9 @@ export function validateModule(mod) {
|
|
|
1566
1746
|
errors.push({ message: `class ${cls.name}: undeclared base "${cls.base}"`, loc: cls.loc });
|
|
1567
1747
|
continue;
|
|
1568
1748
|
}
|
|
1749
|
+
if (base.localCaptures !== undefined && cls.localBaseCapture === undefined) {
|
|
1750
|
+
errors.push({ message: `class ${cls.name}: local base requires a captured constructor`, loc: cls.loc });
|
|
1751
|
+
}
|
|
1569
1752
|
const seen = new Set([cls.name]);
|
|
1570
1753
|
for (let c = base; c; c = c.base !== undefined ? classesByName.get(c.base) : undefined) {
|
|
1571
1754
|
if (seen.has(c.name)) {
|
|
@@ -1619,11 +1802,9 @@ export function validateModule(mod) {
|
|
|
1619
1802
|
}
|
|
1620
1803
|
seen.add(f.name);
|
|
1621
1804
|
// Unit kinds (undefinedT/nullT) exist only as union arms — a BARE
|
|
1622
|
-
// unit field is as malformed as a void one. dyn
|
|
1623
|
-
//
|
|
1624
|
-
|
|
1625
|
-
if (f.type.kind === "void" || f.type.kind === "jsval" ||
|
|
1626
|
-
isUnitType(f.type)) {
|
|
1805
|
+
// unit field is as malformed as a void one. dyn and jsval slots
|
|
1806
|
+
// are valid; both are refcounted values held by the record shape.
|
|
1807
|
+
if (f.type.kind === "void" || isUnitType(f.type)) {
|
|
1627
1808
|
errors.push({ message: `record ${rec.id}: field "${f.name}" is ${f.type.kind}`, loc: noLoc });
|
|
1628
1809
|
}
|
|
1629
1810
|
if (f.type.kind === "record" && !new Set((mod.records ?? []).map((r) => r.id)).has(f.type.shapeId)) {
|
|
@@ -1642,9 +1823,16 @@ export function validateModule(mod) {
|
|
|
1642
1823
|
// field count) — anything else has no honest index/JSON story.
|
|
1643
1824
|
if (rec.tuple) {
|
|
1644
1825
|
const names = new Set(rec.fields.map((f) => f.name));
|
|
1826
|
+
let positionsComplete = true;
|
|
1827
|
+
for (let i = 0; i < rec.fields.length; i++) {
|
|
1828
|
+
if (!names.has(String(i))) {
|
|
1829
|
+
positionsComplete = false;
|
|
1830
|
+
break;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1645
1833
|
if (rec.fields.length === 0 ||
|
|
1646
1834
|
names.size !== rec.fields.length ||
|
|
1647
|
-
|
|
1835
|
+
!positionsComplete) {
|
|
1648
1836
|
errors.push({ message: `record ${rec.id}: tuple fields are not "0".."${rec.fields.length - 1}"`, loc: noLoc });
|
|
1649
1837
|
}
|
|
1650
1838
|
if (rec.indexValue) {
|
|
@@ -1666,31 +1854,64 @@ export function validateModule(mod) {
|
|
|
1666
1854
|
errors.push({ message: `duplicate union "${u.id}"`, loc: noLoc });
|
|
1667
1855
|
}
|
|
1668
1856
|
unionsById.set(u.id, u);
|
|
1857
|
+
}
|
|
1858
|
+
for (const u of mod.unions ?? []) {
|
|
1669
1859
|
if (u.arms.length < 2) {
|
|
1670
1860
|
errors.push({ message: `union ${u.id}: fewer than 2 arms`, loc: noLoc });
|
|
1671
1861
|
}
|
|
1862
|
+
if (u.discriminant) {
|
|
1863
|
+
const { field, cases } = u.discriminant;
|
|
1864
|
+
const tags = new Set();
|
|
1865
|
+
const values = new Set();
|
|
1866
|
+
for (const candidate of cases) {
|
|
1867
|
+
const arm = u.arms[candidate.tag];
|
|
1868
|
+
const record = arm?.kind === "record" ? recordsById.get(arm.shapeId) : undefined;
|
|
1869
|
+
const member = record?.fields.find((entry) => entry.name === field);
|
|
1870
|
+
if (!Number.isInteger(candidate.tag) || candidate.tag < 0 || !member || tags.has(candidate.tag)) {
|
|
1871
|
+
errors.push({ message: `union ${u.id}: invalid discriminant tag ${candidate.tag}`, loc: noLoc });
|
|
1872
|
+
}
|
|
1873
|
+
tags.add(candidate.tag);
|
|
1874
|
+
if (candidate.values.length === 0) {
|
|
1875
|
+
errors.push({ message: `union ${u.id}: empty discriminant values for tag ${candidate.tag}`, loc: noLoc });
|
|
1876
|
+
}
|
|
1877
|
+
for (const value of candidate.values) {
|
|
1878
|
+
if (value === undefined) {
|
|
1879
|
+
errors.push({ message: `union ${u.id}: undefined discriminant value`, loc: noLoc });
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1882
|
+
const fieldTypes = member?.type.kind === "union"
|
|
1883
|
+
? unionsById.get(member.type.unionId)?.arms ?? [] : member ? [member.type] : [];
|
|
1884
|
+
const valid = fieldTypes.some((type) => typeof value === "string" ? type.kind === "string"
|
|
1885
|
+
: typeof value === "boolean" ? type.kind === "bool"
|
|
1886
|
+
: typeof value === "number" && Number.isFinite(value) && type.kind === "f64");
|
|
1887
|
+
const key = typeof value + ":" + String(value);
|
|
1888
|
+
if (!valid || values.has(key)) {
|
|
1889
|
+
errors.push({ message: `union ${u.id}: invalid or repeated discriminant value ${key}`, loc: noLoc });
|
|
1890
|
+
}
|
|
1891
|
+
values.add(key);
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
for (let tag = 0; tag < u.arms.length; tag++) {
|
|
1895
|
+
if (u.arms[tag].kind === "record" && !tags.has(tag)) {
|
|
1896
|
+
errors.push({ message: `union ${u.id}: missing discriminant for record arm ${tag}`, loc: noLoc });
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1672
1900
|
u.arms.forEach((arm, i) => {
|
|
1673
1901
|
// The unit kinds (undefinedT/nullT) are valid arms — union membership
|
|
1674
|
-
// is the ONLY place they may appear
|
|
1675
|
-
//
|
|
1676
|
-
//
|
|
1677
|
-
// sibling rules live in unionFuncSetArmsOk (shared with the frontend's
|
|
1678
|
-
// union builders): a func arm allows unit and FUNC siblings (the
|
|
1679
|
-
// nullable-callback shape, and the primitive-constructor tables where
|
|
1680
|
-
// closure pointer identity per tag is the narrowing); a set arm is
|
|
1681
|
-
// valid exactly when every other arm is a unit (the defaulted-Set-
|
|
1682
|
-
// param ABI); func/set-beside-data stays out.
|
|
1902
|
+
// is the ONLY place they may appear. Containers are valid beside
|
|
1903
|
+
// unit arms: tag tests distinguish absence while the reference
|
|
1904
|
+
// payload preserves identity. The shared rule refuses data siblings.
|
|
1683
1905
|
if (arm.kind === "void" ||
|
|
1684
1906
|
arm.kind === "union" ||
|
|
1685
|
-
arm.kind === "map" ||
|
|
1686
1907
|
arm.kind === "dyn" ||
|
|
1687
1908
|
arm.kind === "jsval" ||
|
|
1688
1909
|
arm.kind === "date" ||
|
|
1689
1910
|
arm.kind === "generator") {
|
|
1690
1911
|
errors.push({ message: `union ${u.id}: arm ${i} is ${arm.kind}`, loc: noLoc });
|
|
1691
1912
|
}
|
|
1692
|
-
if ((arm.kind === "
|
|
1693
|
-
!
|
|
1913
|
+
if ((arm.kind === "map" || arm.kind === "set" || arm.kind === "promise") &&
|
|
1914
|
+
!unionContainerArmsOk(u.arms)) {
|
|
1694
1915
|
errors.push({ message: `union ${u.id}: ${arm.kind} arm ${i} beside non-unit arms`, loc: noLoc });
|
|
1695
1916
|
}
|
|
1696
1917
|
if (arm.kind === "record" && !recordsById.has(arm.shapeId)) {
|
|
@@ -1782,6 +2003,9 @@ export function validateModule(mod) {
|
|
|
1782
2003
|
}
|
|
1783
2004
|
};
|
|
1784
2005
|
for (const g of mod.globals ?? []) {
|
|
2006
|
+
if (g.tdz && g.type.kind !== "record" && g.type.kind !== "func" && g.type.kind !== "dyn") {
|
|
2007
|
+
errors.push({ message: `TDZ global "${g.name}" must have record, function, or checked-value storage`, loc: noLoc });
|
|
2008
|
+
}
|
|
1785
2009
|
if (isUnitType(g.type)) {
|
|
1786
2010
|
errors.push({ message: `global "${g.name}" has bare unit type ${g.type.kind}`, loc: noLoc });
|
|
1787
2011
|
}
|
|
@@ -1881,6 +2105,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1881
2105
|
// Unit kinds live only inside unions: a bare-unit local, param, or
|
|
1882
2106
|
// return type is frontend breakage (mapType never produces them).
|
|
1883
2107
|
for (const l of fn.locals) {
|
|
2108
|
+
if (l.tdz && !l.boxed)
|
|
2109
|
+
err(`TDZ local "${l.name}" must be boxed`, fn.loc);
|
|
1884
2110
|
if (isUnitType(l.type))
|
|
1885
2111
|
err(`local "${l.name}" has bare unit type ${l.type.kind}`, fn.loc);
|
|
1886
2112
|
}
|
|
@@ -1899,15 +2125,30 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1899
2125
|
if (p.type.kind === "caught")
|
|
1900
2126
|
err(`param "${p.name}" is caught-typed`, fn.loc);
|
|
1901
2127
|
}
|
|
1902
|
-
for (const c of fn.captures ?? []) {
|
|
2128
|
+
for (const c of [...(fn.captures ?? []), ...(fn.classCaptures ?? [])]) {
|
|
1903
2129
|
const local = locals.get(c.localId);
|
|
1904
2130
|
if (!local)
|
|
1905
2131
|
err(`capture "${c.name}" has no local entry "${c.localId}"`, fn.loc);
|
|
1906
2132
|
else if (!local.boxed)
|
|
1907
2133
|
err(`capture local "${c.localId}" is not boxed`, fn.loc);
|
|
2134
|
+
else if (!typeEquals(local.type, c.type))
|
|
2135
|
+
err(`capture local "${c.localId}" has the wrong type`, fn.loc);
|
|
1908
2136
|
if (c.type.kind === "caught")
|
|
1909
2137
|
err(`capture "${c.name}" is caught-typed`, fn.loc);
|
|
1910
2138
|
}
|
|
2139
|
+
if (fn.classCaptures !== undefined) {
|
|
2140
|
+
const self = fn.params[0];
|
|
2141
|
+
const cls = self?.type.kind === "object" ? classes.get(self.type.className) : undefined;
|
|
2142
|
+
if (fn.captures !== undefined || cls?.localCaptures === undefined) {
|
|
2143
|
+
err("class captures require a local-class instance receiver and no closure environment", fn.loc);
|
|
2144
|
+
}
|
|
2145
|
+
for (const capture of fn.classCaptures) {
|
|
2146
|
+
const slot = cls?.localCaptures?.[capture.slot];
|
|
2147
|
+
if (!Number.isInteger(capture.slot) || !slot || !typeEquals(slot.type, capture.type)) {
|
|
2148
|
+
err(`class capture "${capture.name}" has an invalid slot or type`, fn.loc);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
1911
2152
|
const expectType = (expr, want, what) => {
|
|
1912
2153
|
if (!typeEquals(expr.type, want)) {
|
|
1913
2154
|
// Same-kind mismatches (func vs func, record vs record) would be
|
|
@@ -1948,12 +2189,218 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
1948
2189
|
seen.add(type.unionId);
|
|
1949
2190
|
return unions.get(type.unionId)?.arms.some((arm) => liveDynRefEligible(arm, seen)) ?? false;
|
|
1950
2191
|
};
|
|
2192
|
+
function checkNullishOperands(e) {
|
|
2193
|
+
expectType(e.right, e.type, "nullish right operand");
|
|
2194
|
+
// The ISLAND form: `a ?? b` over an engine value — left, right,
|
|
2195
|
+
// and result are all handles (the emitters' jsval nullish arm).
|
|
2196
|
+
if (e.left.type.kind === "jsval") {
|
|
2197
|
+
if (e.type.kind !== "jsval")
|
|
2198
|
+
err("jsval nullish must answer jsval", e.loc);
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
// The CHECKED-DYNAMIC form: the runtime kind decides (the
|
|
2202
|
+
// emitters' scr_dyn_is_nullish arm) — left, right, and result
|
|
2203
|
+
// all live in the checked-dynamic tree.
|
|
2204
|
+
if (e.left.type.kind === "dyn") {
|
|
2205
|
+
if (e.type.kind !== "dyn")
|
|
2206
|
+
err("dyn nullish must answer dyn", e.loc);
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
if (e.left.type.kind !== "union") {
|
|
2210
|
+
err(`nullish left must be a union, got ${e.left.type.kind}`, e.loc);
|
|
2211
|
+
return;
|
|
2212
|
+
}
|
|
2213
|
+
const def = unions.get(e.left.type.unionId);
|
|
2214
|
+
if (!def) {
|
|
2215
|
+
err(`nullish left references unknown union ${e.left.type.unionId}`, e.loc);
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
if (!def.arms.some(isUnitType)) {
|
|
2219
|
+
err("nullish left union has no unit arm (frontend must fence)", e.loc);
|
|
2220
|
+
}
|
|
2221
|
+
// Two shapes: pass-through (type === left's union) or narrowed
|
|
2222
|
+
// (type === the union's SINGLE non-unit arm).
|
|
2223
|
+
if (!typeEquals(e.type, e.left.type)) {
|
|
2224
|
+
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2225
|
+
if (rest.length !== 1 || !typeEquals(e.type, rest[0])) {
|
|
2226
|
+
err("nullish type must be the left union or its single non-unit arm", e.loc);
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
function checkBranchingTree(root) {
|
|
2231
|
+
// Predicates and conditional dispatch can nest in either direction.
|
|
2232
|
+
// Preserve child-before-parent diagnostics with bounded native stack
|
|
2233
|
+
// use, including trees that mix the three branching operators.
|
|
2234
|
+
const pending = [{ expr: root, visited: false }];
|
|
2235
|
+
while (pending.length !== 0) {
|
|
2236
|
+
const task = pending.pop();
|
|
2237
|
+
const e = task.expr;
|
|
2238
|
+
if (!task.visited) {
|
|
2239
|
+
if (e.kind === "logical" || e.kind === "nullish") {
|
|
2240
|
+
pending.push({ expr: e, visited: true });
|
|
2241
|
+
pending.push({ expr: e.right, visited: false });
|
|
2242
|
+
pending.push({ expr: e.left, visited: false });
|
|
2243
|
+
}
|
|
2244
|
+
else if (e.kind === "ternary") {
|
|
2245
|
+
pending.push({ expr: e, visited: true });
|
|
2246
|
+
pending.push({ expr: e.else_, visited: false });
|
|
2247
|
+
pending.push({ expr: e.then, visited: false });
|
|
2248
|
+
pending.push({ expr: e.cond, visited: false });
|
|
2249
|
+
}
|
|
2250
|
+
else {
|
|
2251
|
+
checkExpr(e);
|
|
2252
|
+
}
|
|
2253
|
+
continue;
|
|
2254
|
+
}
|
|
2255
|
+
if (e.kind === "logical") {
|
|
2256
|
+
if (e.type.kind !== "f64" && e.type.kind !== "string" && e.type.kind !== "bool" &&
|
|
2257
|
+
e.type.kind !== "jsval" && e.type.kind !== "union" && e.type.kind !== "dyn") {
|
|
2258
|
+
err(`logical ${e.op} must be f64|string|bool|jsval|union|dyn, got ${e.type.kind}`, e.loc);
|
|
2259
|
+
}
|
|
2260
|
+
if (e.type.kind === "union")
|
|
2261
|
+
checkTruthyUnion(e.type.unionId, e.loc);
|
|
2262
|
+
expectType(e.left, e.type, `logical ${e.op} left`);
|
|
2263
|
+
expectType(e.right, e.type, `logical ${e.op} right`);
|
|
2264
|
+
}
|
|
2265
|
+
else if (e.kind === "nullish") {
|
|
2266
|
+
checkNullishOperands(e);
|
|
2267
|
+
}
|
|
2268
|
+
else if (e.kind === "ternary") {
|
|
2269
|
+
expectType(e.cond, BOOL, "ternary condition");
|
|
2270
|
+
expectType(e.then, e.type, "ternary then-branch");
|
|
2271
|
+
expectType(e.else_, e.type, "ternary else-branch");
|
|
2272
|
+
if (e.type.kind === "void")
|
|
2273
|
+
err("ternary must not be void", e.loc);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
// Keep expression families in separate functions so native bootstrap builds
|
|
2278
|
+
// do not feed LLVM a single control-flow graph containing every IR check.
|
|
1951
2279
|
function checkExpr(e) {
|
|
2280
|
+
switch (e.kind) {
|
|
2281
|
+
case "numLit":
|
|
2282
|
+
case "strLit":
|
|
2283
|
+
case "moduleNsRef":
|
|
2284
|
+
case "boolLit":
|
|
2285
|
+
case "unitLit":
|
|
2286
|
+
case "varRef":
|
|
2287
|
+
case "bin":
|
|
2288
|
+
case "unary":
|
|
2289
|
+
case "incDec":
|
|
2290
|
+
case "fieldIncDec":
|
|
2291
|
+
case "assignExpr":
|
|
2292
|
+
case "seqExpr":
|
|
2293
|
+
case "dynDestrCheck":
|
|
2294
|
+
case "dynIterN":
|
|
2295
|
+
case "toBool":
|
|
2296
|
+
case "logical":
|
|
2297
|
+
case "nullish":
|
|
2298
|
+
case "ternary":
|
|
2299
|
+
case "unionEq":
|
|
2300
|
+
case "unionFuncEq":
|
|
2301
|
+
return checkScalarExpr(e);
|
|
2302
|
+
case "strConcat":
|
|
2303
|
+
case "strEq":
|
|
2304
|
+
case "strCmp":
|
|
2305
|
+
case "optChain":
|
|
2306
|
+
case "chainRecv":
|
|
2307
|
+
case "orDefault":
|
|
2308
|
+
case "toString":
|
|
2309
|
+
case "strIntrinsic":
|
|
2310
|
+
case "regexLit":
|
|
2311
|
+
case "templateStrings":
|
|
2312
|
+
case "regexIntrinsic":
|
|
2313
|
+
return checkStringExpr(e);
|
|
2314
|
+
case "arrayLit":
|
|
2315
|
+
case "arrayNewLen":
|
|
2316
|
+
case "arrayGet":
|
|
2317
|
+
case "arrayHas":
|
|
2318
|
+
case "arrayState":
|
|
2319
|
+
case "bytesNew":
|
|
2320
|
+
case "bytesIntrinsic":
|
|
2321
|
+
case "arrIntrinsic":
|
|
2322
|
+
return checkArrayExpr(e);
|
|
2323
|
+
case "mapNew":
|
|
2324
|
+
case "mapIntrinsic":
|
|
2325
|
+
case "setNew":
|
|
2326
|
+
case "setIntrinsic":
|
|
2327
|
+
return checkCollectionExpr(e);
|
|
2328
|
+
case "call":
|
|
2329
|
+
case "ffiCall":
|
|
2330
|
+
case "closure":
|
|
2331
|
+
case "callValue":
|
|
2332
|
+
return checkCallExpr(e);
|
|
2333
|
+
case "selfRef":
|
|
2334
|
+
case "new":
|
|
2335
|
+
case "fieldGet":
|
|
2336
|
+
case "promiseVoidWiden":
|
|
2337
|
+
case "upcast":
|
|
2338
|
+
case "downcast":
|
|
2339
|
+
case "classRef":
|
|
2340
|
+
case "newValue":
|
|
2341
|
+
case "instanceOfValue":
|
|
2342
|
+
case "instanceOf":
|
|
2343
|
+
case "virtualCall":
|
|
2344
|
+
return checkClassExpr(e);
|
|
2345
|
+
case "recordLit":
|
|
2346
|
+
case "recordClone":
|
|
2347
|
+
case "recordGet":
|
|
2348
|
+
case "recordKeyGet":
|
|
2349
|
+
case "recordOvfHas":
|
|
2350
|
+
case "recordOvfKeys":
|
|
2351
|
+
return checkRecordExpr(e);
|
|
2352
|
+
case "dynFrom":
|
|
2353
|
+
case "dynFromJsval":
|
|
2354
|
+
case "dynCall":
|
|
2355
|
+
case "dynInvoke":
|
|
2356
|
+
case "dynObjLit":
|
|
2357
|
+
case "dynArrLit":
|
|
2358
|
+
case "unionWrap":
|
|
2359
|
+
case "dynTest":
|
|
2360
|
+
case "dynKeyGet":
|
|
2361
|
+
case "dynHasKey":
|
|
2362
|
+
case "dynScalarEq":
|
|
2363
|
+
case "caughtTest":
|
|
2364
|
+
case "caughtCheck":
|
|
2365
|
+
case "caughtToDyn":
|
|
2366
|
+
case "caughtNarrow":
|
|
2367
|
+
return checkDynamicExpr(e);
|
|
2368
|
+
case "unionNarrow":
|
|
2369
|
+
case "unionDisc":
|
|
2370
|
+
case "unionKeyGet":
|
|
2371
|
+
case "unionIsTag":
|
|
2372
|
+
return checkUnionExpr(e);
|
|
2373
|
+
case "intrinsic":
|
|
2374
|
+
return checkIntrinsicExpr(e);
|
|
2375
|
+
case "libCall":
|
|
2376
|
+
return checkLibCall(e);
|
|
2377
|
+
case "jsonStringify":
|
|
2378
|
+
case "dynCheck":
|
|
2379
|
+
return checkConversionExpr(e);
|
|
2380
|
+
case "awaitExpr":
|
|
2381
|
+
case "yieldExpr":
|
|
2382
|
+
case "genResume":
|
|
2383
|
+
case "awaitUnionExpr":
|
|
2384
|
+
case "newPromise":
|
|
2385
|
+
case "promiseWithResolvers":
|
|
2386
|
+
return checkAsyncExpr(e);
|
|
2387
|
+
case "jsMarshal":
|
|
2388
|
+
case "jsOp":
|
|
2389
|
+
case "jsExit":
|
|
2390
|
+
case "jsBridgePromise":
|
|
2391
|
+
return checkIslandExpr(e);
|
|
2392
|
+
default: {
|
|
2393
|
+
const _exhaustive = e;
|
|
2394
|
+
void _exhaustive;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
function checkScalarExpr(e) {
|
|
1952
2399
|
switch (e.kind) {
|
|
1953
2400
|
case "numLit":
|
|
1954
2401
|
// ±Infinity and NaN are real literals (the globals
|
|
1955
|
-
// `Infinity`/`NaN`, Number constants) —
|
|
1956
|
-
// (
|
|
2402
|
+
// `Infinity`/`NaN`, Number constants) — the backend spells them
|
|
2403
|
+
// (bit-encoded f64 in LLVM).
|
|
1957
2404
|
// procStream is the ONE non-f64 numLit: process.stdout/stderr as
|
|
1958
2405
|
// first-class values mint the stream's fd (1/2) as the scalar —
|
|
1959
2406
|
// the prefixStream idiom.
|
|
@@ -2017,6 +2464,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2017
2464
|
(e.left.type.kind === "array" ||
|
|
2018
2465
|
e.left.type.kind === "map" ||
|
|
2019
2466
|
e.left.type.kind === "set" ||
|
|
2467
|
+
e.left.type.kind === "regex" ||
|
|
2468
|
+
e.left.type.kind === "url" ||
|
|
2020
2469
|
e.left.type.kind === "object" ||
|
|
2021
2470
|
e.left.type.kind === "record" ||
|
|
2022
2471
|
// Symbol identity IS pointer identity (the frontend's rule).
|
|
@@ -2120,12 +2569,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2120
2569
|
// Statements in an expression cannot jump out of the expression,
|
|
2121
2570
|
// but a local state branch is valid: optional array stores must
|
|
2122
2571
|
// choose ARRAY_VALUE versus ARRAY_UNDEFINED before the final result
|
|
2123
|
-
// is evaluated.
|
|
2124
|
-
|
|
2572
|
+
// is evaluated. Delegation also needs a local loop. Nested control
|
|
2573
|
+
// flow is checked recursively; jumps still cannot leave the region.
|
|
2574
|
+
const allowed = new Set(["varDecl", "assign", "exprStmt", "fieldSet", "recordSet", "recordKeySet", "arraySet", "arraySetLength", "arraySetUndefined", "arrayDelete", "bytesSet", "block", "if", "while"]);
|
|
2575
|
+
if (e.generatorDelegate) {
|
|
2576
|
+
if (!fn.generator || fn.async)
|
|
2577
|
+
err("delegation sequence outside a synchronous generator", e.loc);
|
|
2578
|
+
allowed.add("return");
|
|
2579
|
+
allowed.add("throw");
|
|
2580
|
+
allowed.add("runtimeFence");
|
|
2581
|
+
}
|
|
2125
2582
|
const flat = (ss) => {
|
|
2126
2583
|
for (const s of ss) {
|
|
2127
2584
|
if (!allowed.has(s.kind)) {
|
|
2128
|
-
err(`seqExpr statement kind "${s.kind}"
|
|
2585
|
+
err(`seqExpr statement kind "${s.kind}" can leave the expression`, s.loc);
|
|
2129
2586
|
continue;
|
|
2130
2587
|
}
|
|
2131
2588
|
if (s.kind === "block") {
|
|
@@ -2139,6 +2596,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2139
2596
|
checkExpr(s.cond);
|
|
2140
2597
|
continue;
|
|
2141
2598
|
}
|
|
2599
|
+
if (s.kind === "while") {
|
|
2600
|
+
expectType(s.cond, BOOL, "seqExpr while condition");
|
|
2601
|
+
checkExpr(s.cond);
|
|
2602
|
+
flat(s.body);
|
|
2603
|
+
continue;
|
|
2604
|
+
}
|
|
2142
2605
|
checkStmt(s);
|
|
2143
2606
|
}
|
|
2144
2607
|
};
|
|
@@ -2181,16 +2644,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2181
2644
|
err("toBool must be bool", e.loc);
|
|
2182
2645
|
break;
|
|
2183
2646
|
case "logical":
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
e.type.kind !== "jsval" && e.type.kind !== "union" && e.type.kind !== "dyn") {
|
|
2188
|
-
err(`logical ${e.op} must be f64|string|bool|jsval|union|dyn, got ${e.type.kind}`, e.loc);
|
|
2189
|
-
}
|
|
2190
|
-
if (e.type.kind === "union")
|
|
2191
|
-
checkTruthyUnion(e.type.unionId, e.loc);
|
|
2192
|
-
expectType(e.left, e.type, `logical ${e.op} left`);
|
|
2193
|
-
expectType(e.right, e.type, `logical ${e.op} right`);
|
|
2647
|
+
case "nullish":
|
|
2648
|
+
case "ternary":
|
|
2649
|
+
checkBranchingTree(e);
|
|
2194
2650
|
break;
|
|
2195
2651
|
case "unionEq": {
|
|
2196
2652
|
checkExpr(e.left);
|
|
@@ -2224,6 +2680,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2224
2680
|
err("unionFuncEq must be bool", e.loc);
|
|
2225
2681
|
break;
|
|
2226
2682
|
}
|
|
2683
|
+
default: {
|
|
2684
|
+
const _exhaustive = e;
|
|
2685
|
+
void _exhaustive;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
function checkStringExpr(e) {
|
|
2690
|
+
switch (e.kind) {
|
|
2227
2691
|
case "strConcat":
|
|
2228
2692
|
checkExpr(e.left);
|
|
2229
2693
|
checkExpr(e.right);
|
|
@@ -2241,16 +2705,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2241
2705
|
if (e.type.kind !== "bool")
|
|
2242
2706
|
err(`${e.kind} must be bool`, e.loc);
|
|
2243
2707
|
break;
|
|
2244
|
-
case "ternary":
|
|
2245
|
-
checkExpr(e.cond);
|
|
2246
|
-
checkExpr(e.then);
|
|
2247
|
-
checkExpr(e.else_);
|
|
2248
|
-
expectType(e.cond, BOOL, "ternary condition");
|
|
2249
|
-
expectType(e.then, e.type, "ternary then-branch");
|
|
2250
|
-
expectType(e.else_, e.type, "ternary else-branch");
|
|
2251
|
-
if (e.type.kind === "void")
|
|
2252
|
-
err("ternary must not be void", e.loc);
|
|
2253
|
-
break;
|
|
2254
2708
|
case "optChain": {
|
|
2255
2709
|
checkExpr(e.receiver);
|
|
2256
2710
|
// An island-handle chain (`x?.y` on 'any'): the nullish test is a
|
|
@@ -2303,13 +2757,13 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2303
2757
|
break;
|
|
2304
2758
|
}
|
|
2305
2759
|
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2306
|
-
if (rest.length
|
|
2307
|
-
err("optChain receiver must have unit arms and
|
|
2760
|
+
if (rest.length === 0 || rest.length === def.arms.length) {
|
|
2761
|
+
err("optChain receiver must have unit arms and at least one non-unit arm", e.loc);
|
|
2308
2762
|
break;
|
|
2309
2763
|
}
|
|
2310
2764
|
if (activeChains.has(e.id))
|
|
2311
2765
|
err(`optChain id "${e.id}" shadows an active chain`, e.loc);
|
|
2312
|
-
activeChains.set(e.id, rest[0]);
|
|
2766
|
+
activeChains.set(e.id, rest.length === 1 ? rest[0] : e.receiver.type);
|
|
2313
2767
|
checkExpr(e.body);
|
|
2314
2768
|
activeChains.delete(e.id);
|
|
2315
2769
|
if (e.type.kind === "void") {
|
|
@@ -2338,47 +2792,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2338
2792
|
expectType(e, bound, "chainRecv");
|
|
2339
2793
|
break;
|
|
2340
2794
|
}
|
|
2341
|
-
case "nullish": {
|
|
2342
|
-
checkExpr(e.left);
|
|
2343
|
-
checkExpr(e.right);
|
|
2344
|
-
expectType(e.right, e.type, "nullish right operand");
|
|
2345
|
-
// The ISLAND form: `a ?? b` over an engine value — left, right,
|
|
2346
|
-
// and result are all handles (the emitters' jsval nullish arm).
|
|
2347
|
-
if (e.left.type.kind === "jsval") {
|
|
2348
|
-
if (e.type.kind !== "jsval")
|
|
2349
|
-
err("jsval nullish must answer jsval", e.loc);
|
|
2350
|
-
break;
|
|
2351
|
-
}
|
|
2352
|
-
// The CHECKED-DYNAMIC form: the runtime kind decides (the
|
|
2353
|
-
// emitters' scr_dyn_is_nullish arm) — left, right, and result
|
|
2354
|
-
// all live in the checked-dynamic tree.
|
|
2355
|
-
if (e.left.type.kind === "dyn") {
|
|
2356
|
-
if (e.type.kind !== "dyn")
|
|
2357
|
-
err("dyn nullish must answer dyn", e.loc);
|
|
2358
|
-
break;
|
|
2359
|
-
}
|
|
2360
|
-
if (e.left.type.kind !== "union") {
|
|
2361
|
-
err(`nullish left must be a union, got ${e.left.type.kind}`, e.loc);
|
|
2362
|
-
break;
|
|
2363
|
-
}
|
|
2364
|
-
const def = unions.get(e.left.type.unionId);
|
|
2365
|
-
if (!def) {
|
|
2366
|
-
err(`nullish left references unknown union ${e.left.type.unionId}`, e.loc);
|
|
2367
|
-
break;
|
|
2368
|
-
}
|
|
2369
|
-
if (!def.arms.some(isUnitType)) {
|
|
2370
|
-
err("nullish left union has no unit arm (frontend must fence)", e.loc);
|
|
2371
|
-
}
|
|
2372
|
-
// Two shapes: pass-through (type === left's union) or narrowed
|
|
2373
|
-
// (type === the union's SINGLE non-unit arm).
|
|
2374
|
-
if (!typeEquals(e.type, e.left.type)) {
|
|
2375
|
-
const rest = def.arms.filter((a) => !isUnitType(a));
|
|
2376
|
-
if (rest.length !== 1 || !typeEquals(e.type, rest[0])) {
|
|
2377
|
-
err("nullish type must be the left union or its single non-unit arm", e.loc);
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
break;
|
|
2381
|
-
}
|
|
2382
2795
|
case "orDefault": {
|
|
2383
2796
|
checkExpr(e.left);
|
|
2384
2797
|
checkExpr(e.right);
|
|
@@ -2512,6 +2925,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2512
2925
|
}
|
|
2513
2926
|
break;
|
|
2514
2927
|
}
|
|
2928
|
+
default: {
|
|
2929
|
+
const _exhaustive = e;
|
|
2930
|
+
void _exhaustive;
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
function checkArrayExpr(e) {
|
|
2935
|
+
switch (e.kind) {
|
|
2515
2936
|
case "arrayLit": {
|
|
2516
2937
|
if (e.type.kind !== "array") {
|
|
2517
2938
|
err(`arrayLit must be array-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -2593,21 +3014,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2593
3014
|
if (e.source) {
|
|
2594
3015
|
checkExpr(e.source);
|
|
2595
3016
|
const sk = e.source.type;
|
|
2596
|
-
if (sk.kind === "
|
|
2597
|
-
// Same-elem copies only (cross-kind construction is fenced).
|
|
2598
|
-
if (!typeEquals(sk, e.type)) {
|
|
2599
|
-
err(`bytesNew copy source elem mismatch`, e.loc);
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
else if (sk.kind === "array") {
|
|
3017
|
+
if (sk.kind === "array") {
|
|
2603
3018
|
if (sk.elem.kind !== "f64") {
|
|
2604
3019
|
err(`bytesNew array source must hold f64, got ${sk.elem.kind}`, e.loc);
|
|
2605
3020
|
}
|
|
2606
3021
|
}
|
|
2607
|
-
else if (sk.kind !== "f64") {
|
|
3022
|
+
else if (sk.kind !== "f64" && sk.kind !== "bytes" && sk.kind !== "dyn") {
|
|
2608
3023
|
err(`bytesNew source of kind ${sk.kind}`, e.loc);
|
|
2609
3024
|
}
|
|
2610
3025
|
}
|
|
3026
|
+
if (e.from && e.source?.type.kind !== "dyn")
|
|
3027
|
+
err("bytesNew from requires a dyn source", e.loc);
|
|
2611
3028
|
break;
|
|
2612
3029
|
}
|
|
2613
3030
|
case "bytesIntrinsic": {
|
|
@@ -2643,6 +3060,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2643
3060
|
err(`bytesIntrinsic ${e.method} args[1] must be a strLit encoding`, e.loc);
|
|
2644
3061
|
}
|
|
2645
3062
|
const EXTRA_SIGS = {
|
|
3063
|
+
buffer: { argTypes: [], minArgs: 0, result: DYN },
|
|
3064
|
+
setFromDyn: { argTypes: [DYN, F64], minArgs: 1, result: VOID },
|
|
3065
|
+
copyWithin: { argTypes: [F64, F64, F64], minArgs: 3, result: bytesOf(recv.elem) },
|
|
2646
3066
|
equals: { argTypes: [BYTES_U8], minArgs: 1, result: BOOL },
|
|
2647
3067
|
compareBuf: { argTypes: [BYTES_U8, F64, F64, F64, F64], minArgs: 1, result: F64 },
|
|
2648
3068
|
// [needle, align, byteOffset?] — an OMITTED byteOffset is Node's
|
|
@@ -2682,7 +3102,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2682
3102
|
: e.method === "toArray"
|
|
2683
3103
|
? { argTypes: [], minArgs: 0, result: arrayOf(F64) }
|
|
2684
3104
|
: e.method === "setFrom"
|
|
2685
|
-
? { argTypes: [bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
|
|
3105
|
+
? { argTypes: [e.args[0]?.type.kind === "bytes" ? e.args[0].type : bytesOf(recv.elem), F64], minArgs: 1, result: VOID }
|
|
2686
3106
|
: e.method === "toString" || e.method === "toStringVar"
|
|
2687
3107
|
? { argTypes: [STRING, F64, F64], minArgs: 1, result: STRING }
|
|
2688
3108
|
: e.method === "readNum"
|
|
@@ -2794,7 +3214,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2794
3214
|
// misjudge JS ===; the frontend fences these.
|
|
2795
3215
|
err(`arrIntrinsic ${e.method} on union elements (frontend must reject)`, e.loc);
|
|
2796
3216
|
}
|
|
2797
|
-
if (e.method === "shift" || e.method === "pop") {
|
|
3217
|
+
if ((e.method === "shift" || e.method === "pop") && !(elem.kind === "dyn" && e.type.kind === "dyn")) {
|
|
2798
3218
|
const rdef = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
2799
3219
|
if (!rdef ||
|
|
2800
3220
|
!rdef.arms.some((arm) => arm.kind === "undefinedT") ||
|
|
@@ -2820,12 +3240,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2820
3240
|
}
|
|
2821
3241
|
break;
|
|
2822
3242
|
}
|
|
3243
|
+
default: {
|
|
3244
|
+
const _exhaustive = e;
|
|
3245
|
+
void _exhaustive;
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
function checkCollectionExpr(e) {
|
|
3250
|
+
switch (e.kind) {
|
|
2823
3251
|
case "mapNew": {
|
|
2824
3252
|
if (e.type.kind !== "map") {
|
|
2825
3253
|
err(`mapNew must be map-typed, got ${e.type.kind}`, e.loc);
|
|
2826
3254
|
break;
|
|
2827
3255
|
}
|
|
2828
|
-
if (!isSupportedMapKey(e.type.key)) {
|
|
3256
|
+
if (!isSupportedMapKey(e.type.key, e.type.key.kind === "union" ? unions.get(e.type.key.unionId)?.arms : undefined)) {
|
|
2829
3257
|
err(`mapNew key kind ${e.type.key.kind} (frontend must fence)`, e.loc);
|
|
2830
3258
|
}
|
|
2831
3259
|
if (!isSupportedMapValue(e.type.value)) {
|
|
@@ -2859,6 +3287,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2859
3287
|
}
|
|
2860
3288
|
checkExpr(e.args[0]);
|
|
2861
3289
|
expectType(e.args[0], key, "mapIntrinsic get key");
|
|
3290
|
+
if (value.kind === "dyn") {
|
|
3291
|
+
expectType(e, DYN, "mapIntrinsic get result");
|
|
3292
|
+
break;
|
|
3293
|
+
}
|
|
2862
3294
|
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
2863
3295
|
const rest = def ? def.arms.filter((a) => a.kind !== "undefinedT") : [];
|
|
2864
3296
|
// When V is itself a union its own undefined arm (if any) folds
|
|
@@ -2908,7 +3340,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2908
3340
|
err(`setNew must be set-typed, got ${e.type.kind}`, e.loc);
|
|
2909
3341
|
break;
|
|
2910
3342
|
}
|
|
2911
|
-
if (!isSupportedSetElem(e.type.elem)) {
|
|
3343
|
+
if (!isSupportedSetElem(e.type.elem, e.type.elem.kind === "union" ? unions.get(e.type.elem.unionId)?.arms : undefined)) {
|
|
2912
3344
|
err(`setNew element kind ${e.type.elem.kind} (frontend must fence)`, e.loc);
|
|
2913
3345
|
}
|
|
2914
3346
|
// The seed is one T[]-typed expression (T = the element type).
|
|
@@ -2952,6 +3384,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
2952
3384
|
}
|
|
2953
3385
|
break;
|
|
2954
3386
|
}
|
|
3387
|
+
default: {
|
|
3388
|
+
const _exhaustive = e;
|
|
3389
|
+
void _exhaustive;
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
function checkCallExpr(e) {
|
|
3394
|
+
switch (e.kind) {
|
|
2955
3395
|
case "call": {
|
|
2956
3396
|
for (const a of e.args)
|
|
2957
3397
|
checkExpr(a);
|
|
@@ -3051,6 +3491,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3051
3491
|
}
|
|
3052
3492
|
case "callValue": {
|
|
3053
3493
|
checkExpr(e.callee);
|
|
3494
|
+
if (e.receiver !== undefined) {
|
|
3495
|
+
checkExpr(e.receiver);
|
|
3496
|
+
expectType(e.receiver, DYN, "callValue receiver");
|
|
3497
|
+
}
|
|
3054
3498
|
for (const a of e.args)
|
|
3055
3499
|
checkExpr(a);
|
|
3056
3500
|
if (e.callee.type.kind !== "func") {
|
|
@@ -3071,6 +3515,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3071
3515
|
}
|
|
3072
3516
|
break;
|
|
3073
3517
|
}
|
|
3518
|
+
default: {
|
|
3519
|
+
const _exhaustive = e;
|
|
3520
|
+
void _exhaustive;
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
function checkClassExpr(e) {
|
|
3525
|
+
switch (e.kind) {
|
|
3074
3526
|
case "selfRef":
|
|
3075
3527
|
if (fn.captures === undefined) {
|
|
3076
3528
|
err("selfRef outside a lifted function", e.loc);
|
|
@@ -3087,6 +3539,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3087
3539
|
break;
|
|
3088
3540
|
}
|
|
3089
3541
|
const ctor = functions.get(`%${e.className}.constructor`);
|
|
3542
|
+
if (cls.localCaptures !== undefined)
|
|
3543
|
+
err(`new ${e.className}: local class requires a class value`, e.loc);
|
|
3090
3544
|
if (!ctor) {
|
|
3091
3545
|
err(`new ${e.className}: missing constructor function`, e.loc);
|
|
3092
3546
|
break;
|
|
@@ -3196,6 +3650,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3196
3650
|
if (!typeEquals(e.type, { kind: "classval", className: e.className })) {
|
|
3197
3651
|
err(`classRef to "${e.className}" must have that classval type`, e.loc);
|
|
3198
3652
|
}
|
|
3653
|
+
if ((e.captures === undefined) !== (cls.localCaptures === undefined) ||
|
|
3654
|
+
(e.captures?.length ?? 0) !== (cls.localCaptures?.length ?? 0)) {
|
|
3655
|
+
err(`classRef to "${e.className}" must supply its class captures`, e.loc);
|
|
3656
|
+
}
|
|
3657
|
+
(e.captures ?? []).forEach((id, index) => {
|
|
3658
|
+
const local = locals.get(id);
|
|
3659
|
+
const wanted = cls.localCaptures?.[index];
|
|
3660
|
+
if (!local?.boxed || (wanted && !typeEquals(local.type, wanted.type))) {
|
|
3661
|
+
err(`classRef capture "${id}" must name a box with the declared type`, e.loc);
|
|
3662
|
+
}
|
|
3663
|
+
});
|
|
3199
3664
|
break;
|
|
3200
3665
|
}
|
|
3201
3666
|
case "newValue": {
|
|
@@ -3239,6 +3704,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3239
3704
|
// Both sides must be hierarchy members: the operand needs a vt
|
|
3240
3705
|
// word to read; a standalone target class has one possible value
|
|
3241
3706
|
// and the frontend folds it statically.
|
|
3707
|
+
if (classes.get(e.classValue.type.className)?.localCaptures !== undefined &&
|
|
3708
|
+
e.value.type.kind === "object" && classes.get(e.value.type.className)?.localCaptures !== undefined)
|
|
3709
|
+
break;
|
|
3242
3710
|
if (!hierarchy.has(e.classValue.type.className)) {
|
|
3243
3711
|
err(`instanceOfValue against standalone class "${e.classValue.type.className}"`, e.loc);
|
|
3244
3712
|
}
|
|
@@ -3316,6 +3784,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3316
3784
|
}
|
|
3317
3785
|
break;
|
|
3318
3786
|
}
|
|
3787
|
+
default: {
|
|
3788
|
+
const _exhaustive = e;
|
|
3789
|
+
void _exhaustive;
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
function checkRecordExpr(e) {
|
|
3794
|
+
switch (e.kind) {
|
|
3319
3795
|
case "recordLit": {
|
|
3320
3796
|
if (e.type.kind !== "record") {
|
|
3321
3797
|
err(`recordLit must be record-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3435,8 +3911,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3435
3911
|
// literal key naming no declared field) skip the declared check
|
|
3436
3912
|
// and require the overflow to exist.
|
|
3437
3913
|
const surfaces = (t) => typeEquals(t, e.type) ||
|
|
3438
|
-
(e.type.kind === "union" &&
|
|
3439
|
-
|
|
3914
|
+
(e.type.kind === "union" && (() => {
|
|
3915
|
+
const result = unions.get(e.type.unionId);
|
|
3916
|
+
const source = t.kind === "union" ? unions.get(t.unionId) : undefined;
|
|
3917
|
+
return !!result && (result.arms.some((a) => typeEquals(a, t)) ||
|
|
3918
|
+
(!!source && unionWideningTags(source.arms, result.arms) !== null));
|
|
3919
|
+
})()) ||
|
|
3440
3920
|
e.type.kind === "dyn";
|
|
3441
3921
|
if (e.overflowOnly && !shape.indexValue) {
|
|
3442
3922
|
err(`recordKeyGet on ${e.shapeId}: overflowOnly read of a shape without an index signature`, e.loc);
|
|
@@ -3452,6 +3932,20 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3452
3932
|
}
|
|
3453
3933
|
break;
|
|
3454
3934
|
}
|
|
3935
|
+
case "recordOvfHas": {
|
|
3936
|
+
checkExpr(e.obj);
|
|
3937
|
+
checkExpr(e.key);
|
|
3938
|
+
const shape = records.get(e.shapeId);
|
|
3939
|
+
if (!shape)
|
|
3940
|
+
err(`recordOvfHas on undeclared shape "${e.shapeId}"`, e.loc);
|
|
3941
|
+
else if (!shape.indexValue || shape.tuple)
|
|
3942
|
+
err(`recordOvfHas on ${e.shapeId}: requires an index-signature record`, e.loc);
|
|
3943
|
+
expectType(e.obj, { kind: "record", shapeId: e.shapeId }, "recordOvfHas receiver");
|
|
3944
|
+
expectType(e.key, STRING, "recordOvfHas key");
|
|
3945
|
+
if (e.type.kind !== "bool")
|
|
3946
|
+
err("recordOvfHas must be bool", e.loc);
|
|
3947
|
+
break;
|
|
3948
|
+
}
|
|
3455
3949
|
case "recordOvfKeys": {
|
|
3456
3950
|
checkExpr(e.obj);
|
|
3457
3951
|
const shape = records.get(e.shapeId);
|
|
@@ -3467,6 +3961,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3467
3961
|
}
|
|
3468
3962
|
break;
|
|
3469
3963
|
}
|
|
3964
|
+
default: {
|
|
3965
|
+
const _exhaustive = e;
|
|
3966
|
+
void _exhaustive;
|
|
3967
|
+
}
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
function checkDynamicExpr(e) {
|
|
3971
|
+
switch (e.kind) {
|
|
3470
3972
|
case "dynFrom": {
|
|
3471
3973
|
if (e.type.kind !== "dyn")
|
|
3472
3974
|
err(`dynFrom must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3508,6 +4010,10 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3508
4010
|
}
|
|
3509
4011
|
case "dynCall": {
|
|
3510
4012
|
checkExpr(e.callee);
|
|
4013
|
+
if (e.receiver !== undefined) {
|
|
4014
|
+
checkExpr(e.receiver);
|
|
4015
|
+
expectType(e.receiver, DYN, "dynCall receiver");
|
|
4016
|
+
}
|
|
3511
4017
|
expectType(e.callee, DYN, "dynCall callee");
|
|
3512
4018
|
if (e.type.kind !== "dyn")
|
|
3513
4019
|
err(`dynCall must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
@@ -3550,8 +4056,8 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3550
4056
|
err(`dynObjLit must be dyn-typed, got ${e.type.kind}`, e.loc);
|
|
3551
4057
|
for (const f of e.fields ?? []) {
|
|
3552
4058
|
checkExpr(f.key);
|
|
3553
|
-
if (f.key.type.kind !== "string")
|
|
3554
|
-
err(`dynObjLit key of kind ${f.key.type.kind} (must be string)`, e.loc);
|
|
4059
|
+
if (f.key.type.kind !== "string" && f.key.type.kind !== "dyn")
|
|
4060
|
+
err(`dynObjLit key of kind ${f.key.type.kind} (must be string or dyn)`, e.loc);
|
|
3555
4061
|
checkExpr(f.value);
|
|
3556
4062
|
if (f.value.type.kind !== "dyn")
|
|
3557
4063
|
err(`dynObjLit field value of kind ${f.value.type.kind} (must be dyn)`, e.loc);
|
|
@@ -3613,14 +4119,17 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3613
4119
|
expectType(e.value, { kind: "dyn" }, "dynTest operand");
|
|
3614
4120
|
if (e.type.kind !== "bool")
|
|
3615
4121
|
err("dynTest must be bool", e.loc);
|
|
4122
|
+
if (e.bytesElem !== undefined && (e.test !== "bytes" || !Object.hasOwn(BYTES_ELEMENT_NAME, e.bytesElem))) {
|
|
4123
|
+
err("dynTest bytesElem requires a valid bytes test", e.loc);
|
|
4124
|
+
}
|
|
3616
4125
|
break;
|
|
3617
4126
|
}
|
|
3618
4127
|
case "dynKeyGet": {
|
|
3619
4128
|
checkExpr(e.value);
|
|
3620
4129
|
checkExpr(e.key);
|
|
3621
4130
|
expectType(e.value, { kind: "dyn" }, "dynKeyGet operand");
|
|
3622
|
-
if (e.key.type.kind !== "string")
|
|
3623
|
-
err(`dynKeyGet key is ${e.key.type.kind}, not string`, e.loc);
|
|
4131
|
+
if (e.key.type.kind !== "string" && e.key.type.kind !== "dyn")
|
|
4132
|
+
err(`dynKeyGet key is ${e.key.type.kind}, not string or dyn`, e.loc);
|
|
3624
4133
|
if (e.type.kind !== "dyn")
|
|
3625
4134
|
err("dynKeyGet must be dyn", e.loc);
|
|
3626
4135
|
break;
|
|
@@ -3695,6 +4204,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3695
4204
|
}
|
|
3696
4205
|
break;
|
|
3697
4206
|
}
|
|
4207
|
+
default: {
|
|
4208
|
+
const _exhaustive = e;
|
|
4209
|
+
void _exhaustive;
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
function checkUnionExpr(e) {
|
|
4214
|
+
switch (e.kind) {
|
|
3698
4215
|
case "unionNarrow": {
|
|
3699
4216
|
checkExpr(e.value);
|
|
3700
4217
|
const def = unions.get(e.unionId);
|
|
@@ -3768,7 +4285,11 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3768
4285
|
// non-unit arms have no keyed read at all. Number keys read ARRAY
|
|
3769
4286
|
// arms; string keys read RECORD arms.
|
|
3770
4287
|
const resultUnion = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
3771
|
-
const surfaces = (t) => typeEquals(t, e.type) || !!resultUnion?.arms.some((a) => typeEquals(a, t))
|
|
4288
|
+
const surfaces = (t) => typeEquals(t, e.type) || !!resultUnion?.arms.some((a) => typeEquals(a, t)) ||
|
|
4289
|
+
(t.kind === "union" && !!resultUnion && (() => {
|
|
4290
|
+
const source = unions.get(t.unionId);
|
|
4291
|
+
return !!source && unionWideningTags(source.arms, resultUnion.arms) !== null;
|
|
4292
|
+
})());
|
|
3772
4293
|
def.arms.forEach((arm, i) => {
|
|
3773
4294
|
if (arm.kind === "undefinedT" || arm.kind === "nullT") {
|
|
3774
4295
|
if (!resultUnion?.arms.some((a) => a.kind === "undefinedT")) {
|
|
@@ -3823,1296 +4344,1346 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
3823
4344
|
err("unionIsTag must be bool", e.loc);
|
|
3824
4345
|
break;
|
|
3825
4346
|
}
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
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
|
-
if (
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
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
|
-
|
|
4347
|
+
default: {
|
|
4348
|
+
const _exhaustive = e;
|
|
4349
|
+
void _exhaustive;
|
|
4350
|
+
}
|
|
4351
|
+
}
|
|
4352
|
+
}
|
|
4353
|
+
function checkIntrinsicExpr(e) {
|
|
4354
|
+
if (e.name === "module.await") {
|
|
4355
|
+
if (e.args.length !== 1)
|
|
4356
|
+
err("module.await takes exactly one argument", e.loc);
|
|
4357
|
+
for (const a of e.args) {
|
|
4358
|
+
checkExpr(a);
|
|
4359
|
+
if (a.type.kind !== "promise" || a.type.inner.kind !== "void") {
|
|
4360
|
+
err(`${typeKey(a.type)} argument to module.await (needs promise<void>)`, a.loc);
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
if (e.type.kind !== "void")
|
|
4364
|
+
err("module.await must be void", e.loc);
|
|
4365
|
+
return;
|
|
4366
|
+
}
|
|
4367
|
+
if (e.name === "promise.all") {
|
|
4368
|
+
// ONE argument: an array of promises whose inner type is the
|
|
4369
|
+
// result's array element (or void, collapsing to promise<void>).
|
|
4370
|
+
// The exact-inner-type rule is the frontend's fence; the coarse
|
|
4371
|
+
// shape keeps hand-written IR honest.
|
|
4372
|
+
if (e.args.length !== 1)
|
|
4373
|
+
err("promise.all takes exactly one argument", e.loc);
|
|
4374
|
+
for (const a of e.args) {
|
|
4375
|
+
checkExpr(a);
|
|
4376
|
+
if (a.type.kind !== "array" || a.type.elem.kind !== "promise") {
|
|
4377
|
+
err(`${a.type.kind} argument to promise.all (needs an array of promises)`, a.loc);
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
if (e.type.kind !== "promise")
|
|
4381
|
+
err("promise.all must be promise-typed", e.loc);
|
|
4382
|
+
else if (e.type.inner.kind !== "array" && e.type.inner.kind !== "void") {
|
|
4383
|
+
err("promise.all result must be a promise of an array (or void)", e.loc);
|
|
4384
|
+
}
|
|
4385
|
+
return;
|
|
4386
|
+
}
|
|
4387
|
+
if (e.name === "promise.reject") {
|
|
4388
|
+
// ONE argument: the %Error-rooted reason object (the rejection
|
|
4389
|
+
// payload shares the thrown-Error representation — the
|
|
4390
|
+
// frontend's fence pins the hierarchy; the coarse object shape
|
|
4391
|
+
// keeps hand-written IR honest) or a checked-dynamic reason
|
|
4392
|
+
// (the thrown-dyn representation — identity flows to catch and
|
|
4393
|
+
// unhandledRejection observers). The result is the
|
|
4394
|
+
// context-named promise.
|
|
4395
|
+
if (e.args.length !== 1)
|
|
4396
|
+
err("promise.reject takes exactly one argument", e.loc);
|
|
4397
|
+
for (const a of e.args) {
|
|
4398
|
+
checkExpr(a);
|
|
4399
|
+
if (a.type.kind !== "object" && a.type.kind !== "dyn") {
|
|
4400
|
+
err(`${a.type.kind} argument to promise.reject (needs an Error object or a dyn reason)`, a.loc);
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
if (e.type.kind !== "promise")
|
|
4404
|
+
err("promise.reject must be promise-typed", e.loc);
|
|
4405
|
+
return;
|
|
4406
|
+
}
|
|
4407
|
+
if (e.name === "promise.resolve") {
|
|
4408
|
+
// Zero args (Promise<void>) or one plain value of the result's
|
|
4409
|
+
// inner type — promise arguments never reach the intrinsic
|
|
4410
|
+
// (the frontend returns them as-is).
|
|
4411
|
+
if (e.args.length > 1)
|
|
4412
|
+
err("promise.resolve takes at most one argument", e.loc);
|
|
4413
|
+
for (const a of e.args) {
|
|
4414
|
+
checkExpr(a);
|
|
4415
|
+
if (a.type.kind === "promise") {
|
|
4416
|
+
err("promise argument to promise.resolve (identity belongs in the frontend)", a.loc);
|
|
4417
|
+
}
|
|
4418
|
+
}
|
|
4419
|
+
if (e.type.kind !== "promise")
|
|
4420
|
+
err("promise.resolve must be promise-typed", e.loc);
|
|
4421
|
+
else if (e.args.length === 0 && e.type.inner.kind !== "void") {
|
|
4422
|
+
err("zero-argument promise.resolve must be promise<void>", e.loc);
|
|
4423
|
+
}
|
|
4424
|
+
else if (e.args.length === 1 && !typeEquals(e.args[0].type, e.type.inner)) {
|
|
4425
|
+
err("promise.resolve argument must be the result's inner type", e.loc);
|
|
4426
|
+
}
|
|
4427
|
+
return;
|
|
4428
|
+
}
|
|
4429
|
+
if (e.name === "promise.race") {
|
|
4430
|
+
// Entries are promises; the result is the combined promise. The
|
|
4431
|
+
// per-entry inner-type compatibility (equal to the result inner,
|
|
4432
|
+
// one of its union arms, or a sub-union of it) is the frontend's
|
|
4433
|
+
// fence; here the coarse shape keeps hand-written IR honest.
|
|
4434
|
+
if (e.args.length === 0)
|
|
4435
|
+
err("promise.race with no entries", e.loc);
|
|
4436
|
+
for (const a of e.args) {
|
|
4437
|
+
checkExpr(a);
|
|
4438
|
+
if (a.type.kind !== "promise") {
|
|
4439
|
+
err(`${a.type.kind} entry in promise.race`, a.loc);
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
if (e.type.kind !== "promise")
|
|
4443
|
+
err("promise.race must be promise-typed", e.loc);
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
for (const a of e.args) {
|
|
4447
|
+
checkExpr(a);
|
|
4448
|
+
// Arrays/functions/records/unions stay out of console.log (and
|
|
4449
|
+
// its stderr twin console.error) by design (the ambient signature
|
|
4450
|
+
// accepts number|string|boolean; a union of those satisfies it,
|
|
4451
|
+
// so the frontend rejects union args explicitly) — inspect
|
|
4452
|
+
// formatting is unimplemented, so the backend must never see one.
|
|
4453
|
+
if (a.type.kind !== "f64" && a.type.kind !== "string" && a.type.kind !== "bool") {
|
|
4454
|
+
err(`${a.type.kind} argument to ${e.name}`, a.loc);
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4457
|
+
if (e.type.kind !== "void")
|
|
4458
|
+
err(`${e.name} must be void`, e.loc);
|
|
4459
|
+
}
|
|
4460
|
+
function checkLibCall(e) {
|
|
4461
|
+
const sig = LIB_FN_SIGS[e.fn];
|
|
4462
|
+
if (!sig) {
|
|
4463
|
+
err(`libCall of unknown library function "${e.fn}"`, e.loc);
|
|
4464
|
+
return;
|
|
4465
|
+
}
|
|
4466
|
+
// emitter.emit is variadic: (recv, name) plus the event's tuple.
|
|
4467
|
+
// The stream constructors (trailing option callbacks), write/end
|
|
4468
|
+
// (the optional chunk/cb tail), and unpipe (the optional
|
|
4469
|
+
// destination) admit a longer list the same way.
|
|
4470
|
+
const variadic = e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" ||
|
|
4471
|
+
e.fn === "readable.new" || e.fn === "writable.new" ||
|
|
4472
|
+
e.fn === "duplex.new" || e.fn === "transform.new" ||
|
|
4473
|
+
e.fn === "passthrough.new" ||
|
|
4474
|
+
e.fn === "readable.init" || e.fn === "writable.init" ||
|
|
4475
|
+
e.fn === "duplex.init" || e.fn === "transform.init" ||
|
|
4476
|
+
e.fn === "passthrough.init" ||
|
|
4477
|
+
e.fn === "readable.initDyn" || e.fn === "writable.initDyn" ||
|
|
4478
|
+
e.fn === "duplex.initDyn" || e.fn === "transform.initDyn" ||
|
|
4479
|
+
e.fn === "passthrough.initDyn" ||
|
|
4480
|
+
e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn" ||
|
|
4481
|
+
e.fn === "sp.pipeline" ||
|
|
4482
|
+
e.fn === "writable.write" ||
|
|
4483
|
+
e.fn === "writable.writeStr" || e.fn === "writable.writeU" ||
|
|
4484
|
+
e.fn === "writable.end" ||
|
|
4485
|
+
e.fn === "readable.unpipe";
|
|
4486
|
+
if (variadic
|
|
4487
|
+
? e.args.length < sig.argTypes.length
|
|
4488
|
+
: e.args.length !== sig.argTypes.length) {
|
|
4489
|
+
err(`libCall ${e.fn}: ${e.args.length} args, expected ${sig.argTypes.length}`, e.loc);
|
|
4490
|
+
}
|
|
4491
|
+
e.args.forEach((a, i) => {
|
|
4492
|
+
checkExpr(a);
|
|
4493
|
+
const want = sig.argTypes[i];
|
|
4494
|
+
if (want)
|
|
4495
|
+
expectType(a, want, `libCall ${e.fn} arg ${i}`);
|
|
4496
|
+
});
|
|
4497
|
+
if (checkLibValueCall(e))
|
|
4498
|
+
return;
|
|
4499
|
+
if (checkLibNetworkCall(e))
|
|
4500
|
+
return;
|
|
4501
|
+
if (checkLibFileCall(e))
|
|
4502
|
+
return;
|
|
4503
|
+
if (checkLibProcessCall(e))
|
|
4504
|
+
return;
|
|
4505
|
+
if (checkLibSpecialCall(e))
|
|
4506
|
+
return;
|
|
4507
|
+
if (checkLibStreamCall(e, sig.argTypes.length, sig.result))
|
|
4508
|
+
return;
|
|
4509
|
+
if (checkLibEmitterCall(e, sig.result))
|
|
4510
|
+
return;
|
|
4511
|
+
if (e.fn === "error.stack" || e.fn === "error.cause" || e.fn === "error.hasCause" || e.fn === "error.setCause" || e.fn === "error.deleteCause") {
|
|
4512
|
+
const recv = e.args[0];
|
|
4513
|
+
let cls = recv?.type.kind === "object" ? classes.get(recv.type.className) : undefined;
|
|
4514
|
+
while (cls?.base)
|
|
4515
|
+
cls = classes.get(cls.base);
|
|
4516
|
+
if (cls?.name !== "%Error")
|
|
4517
|
+
err(`libCall ${e.fn} receiver must be an error object`, e.loc);
|
|
4518
|
+
}
|
|
4519
|
+
if (e.fn === "error.ctor" || e.fn === "error.ctorOptions" || e.fn === "error.toString") {
|
|
4520
|
+
const recv = e.args[0];
|
|
4521
|
+
const wantErrorRoot = e.fn === "error.toString";
|
|
4522
|
+
const ok = recv &&
|
|
4523
|
+
isBuiltinErrorObject(recv.type) &&
|
|
4524
|
+
(!wantErrorRoot || (recv.type.kind === "object" && recv.type.className === "%Error"));
|
|
4525
|
+
if (!ok) {
|
|
4526
|
+
err(`libCall ${e.fn} receiver must be ${wantErrorRoot ? "'%Error'" : "a builtin error class"}`, e.loc);
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
if (!typeEquals(e.type, sig.result)) {
|
|
4530
|
+
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
function checkLibValueCall(e) {
|
|
4534
|
+
if (e.fn === "fileHandle.read" || e.fn === "fileHandle.writeBytes" || e.fn === "fileHandle.writeStr") {
|
|
4535
|
+
const inner = e.type.kind === "promise" ? e.type.inner : undefined;
|
|
4536
|
+
const shape = inner?.kind === "record" ? records.get(inner.shapeId) : undefined;
|
|
4537
|
+
const countName = e.fn === "fileHandle.read" ? "bytesRead" : "bytesWritten";
|
|
4538
|
+
const payload = e.args[1]?.type;
|
|
4539
|
+
const count = shape?.fields.find((f) => f.name === countName);
|
|
4540
|
+
const buffer = shape?.fields.find((f) => f.name === "buffer");
|
|
4541
|
+
const ok = shape !== undefined && !shape.tuple && shape.indexValue === undefined && shape.fields.length === 2 &&
|
|
4542
|
+
count?.type.kind === "f64" && payload !== undefined && buffer !== undefined &&
|
|
4543
|
+
typeEquals(buffer.type, payload);
|
|
4544
|
+
if (!ok) {
|
|
4545
|
+
err(`libCall ${e.fn} must return a promise of { ${countName}: number, buffer }`, e.loc);
|
|
4546
|
+
}
|
|
4547
|
+
return true;
|
|
4548
|
+
}
|
|
4549
|
+
if (e.fn === "fetch.streamFrom") {
|
|
4550
|
+
const t = e.args[0]?.type;
|
|
4551
|
+
const ok = t?.kind === "string" ||
|
|
4552
|
+
(t?.kind === "bytes" && t.elem === "u8") ||
|
|
4553
|
+
(t?.kind === "array" &&
|
|
4554
|
+
canConvertToDyn(t.elem, (id) => records.get(id), (id) => unions.get(id))) ||
|
|
4555
|
+
t?.kind === "dyn";
|
|
4556
|
+
if (!ok) {
|
|
4557
|
+
err(`libCall fetch.streamFrom arg 0: expected a supported iterable, got ${t?.kind}`, e.loc);
|
|
4558
|
+
}
|
|
4559
|
+
return true;
|
|
4560
|
+
}
|
|
4561
|
+
if (e.fn === "fetch.readerRead") {
|
|
4562
|
+
if (e.type.kind !== "promise" || e.type.inner.kind !== "record") {
|
|
4563
|
+
err(`libCall fetch.readerRead must return a promise of a read-result record`, e.loc);
|
|
4564
|
+
}
|
|
4565
|
+
return true;
|
|
4566
|
+
}
|
|
4567
|
+
if (e.fn === "fetch.responseText" || e.fn === "fetch.responseBytes") {
|
|
4568
|
+
const valueType = e.fn === "fetch.responseText" ? STRING : BYTES_U8;
|
|
4569
|
+
const inner = e.type.kind === "promise" ? e.type.inner : null;
|
|
4570
|
+
const union = inner?.kind === "union" ? unions.get(inner.unionId) : undefined;
|
|
4571
|
+
if (inner === null ||
|
|
4572
|
+
(!typeEquals(inner, valueType) &&
|
|
4573
|
+
!union?.arms.some((arm) => typeEquals(arm, valueType)))) {
|
|
4574
|
+
err(`libCall ${e.fn} must return a promise whose value includes ${valueType.kind}`, e.loc);
|
|
4575
|
+
}
|
|
4576
|
+
return true;
|
|
4577
|
+
}
|
|
4578
|
+
if (e.fn === "string.fromCharCode" || e.fn === "string.fromCodePoint") {
|
|
4579
|
+
// One packed f64[] or one bytes value (the spread form).
|
|
4580
|
+
const t = e.args[0]?.type;
|
|
4581
|
+
const ok = t && ((t.kind === "array" && t.elem.kind === "f64") || t.kind === "bytes");
|
|
4582
|
+
if (!ok) {
|
|
4583
|
+
err(`libCall ${e.fn} arg 0: expected number[] or bytes, got ${t?.kind}`, e.loc);
|
|
4584
|
+
}
|
|
4585
|
+
return true;
|
|
4586
|
+
}
|
|
4587
|
+
if (e.fn === "process.envGet") {
|
|
4588
|
+
// Result is the module's interned `string | undefined` union.
|
|
4589
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4590
|
+
const ok = def &&
|
|
4591
|
+
def.arms.length === 2 &&
|
|
4592
|
+
def.arms[0].kind === "string" &&
|
|
4593
|
+
def.arms[1].kind === "undefinedT";
|
|
4594
|
+
if (!ok) {
|
|
4595
|
+
err(`libCall process.envGet must return the 'string | undefined' union`, e.loc);
|
|
4596
|
+
}
|
|
4597
|
+
return true;
|
|
4598
|
+
}
|
|
4599
|
+
if (e.fn === "process.columns" || e.fn === "process.rows") {
|
|
4600
|
+
// Result is the module's interned `number | undefined` union.
|
|
4601
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4602
|
+
const ok = def &&
|
|
4603
|
+
def.arms.length === 2 &&
|
|
4604
|
+
def.arms[0].kind === "f64" &&
|
|
4605
|
+
def.arms[1].kind === "undefinedT";
|
|
4606
|
+
if (!ok) {
|
|
4607
|
+
err(`libCall ${e.fn} must return the 'number | undefined' union`, e.loc);
|
|
4608
|
+
}
|
|
4609
|
+
return true;
|
|
4610
|
+
}
|
|
4611
|
+
return false;
|
|
4612
|
+
}
|
|
4613
|
+
function checkLibNetworkCall(e) {
|
|
4614
|
+
if (e.fn === "http.createServer" || e.fn === "http2.createServerReq") {
|
|
4615
|
+
// The request handler: void, at most (req, res) in order.
|
|
4616
|
+
const cbT = e.args[0]?.type;
|
|
4617
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4618
|
+
if (ok && cbT?.kind === "func") {
|
|
4619
|
+
const [p0, p1] = cbT.params;
|
|
4620
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4621
|
+
ok = false;
|
|
4622
|
+
if (p1 !== undefined && p1.kind !== "httpRes")
|
|
4623
|
+
ok = false;
|
|
4624
|
+
}
|
|
4625
|
+
if (!ok) {
|
|
4626
|
+
err(`libCall ${e.fn} handler shape (frontend must fence)`, e.loc);
|
|
4627
|
+
}
|
|
4628
|
+
return true;
|
|
4629
|
+
}
|
|
4630
|
+
if (e.fn === "http.serverOnRequest") {
|
|
4631
|
+
// The 'request' listener: the same shape as http.createServer's
|
|
4632
|
+
// handler — void, at most (req, res) in order.
|
|
4633
|
+
const cbT = e.args[1]?.type;
|
|
4634
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4635
|
+
if (ok && cbT?.kind === "func") {
|
|
4636
|
+
const [p0, p1] = cbT.params;
|
|
4637
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4638
|
+
ok = false;
|
|
4639
|
+
if (p1 !== undefined && p1.kind !== "httpRes")
|
|
4640
|
+
ok = false;
|
|
4641
|
+
}
|
|
4642
|
+
if (!ok) {
|
|
4643
|
+
err(`libCall http.serverOnRequest handler shape (frontend must fence)`, e.loc);
|
|
4644
|
+
}
|
|
4645
|
+
return true;
|
|
4646
|
+
}
|
|
4647
|
+
if (e.fn === "http2.serverOnSessionError") {
|
|
4648
|
+
const cbT = e.args[1]?.type;
|
|
4649
|
+
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" &&
|
|
4650
|
+
cbT.params.length <= 2 &&
|
|
4651
|
+
(cbT.params[0] === undefined ||
|
|
4652
|
+
(cbT.params[0].kind === "object" && cbT.params[0].className === "%Error")) &&
|
|
4653
|
+
(cbT.params[1] === undefined || cbT.params[1].kind === "http2Session");
|
|
4654
|
+
if (!ok) {
|
|
4655
|
+
err(`libCall http2.serverOnSessionError callback shape (frontend must fence)`, e.loc);
|
|
4656
|
+
}
|
|
4657
|
+
return true;
|
|
4658
|
+
}
|
|
4659
|
+
if (e.fn === "http.reqOnData") {
|
|
4660
|
+
const cbT = e.args[1]?.type;
|
|
4661
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4662
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4663
|
+
const p = cbT.params[0];
|
|
4664
|
+
// dyn = the checked-dynamic listener's adapter (the chunk
|
|
4665
|
+
// boxes Buffer-flavored in the runtime data thunk).
|
|
4666
|
+
ok = (p.kind === "bytes" && p.elem === "u8") || p.kind === "dyn";
|
|
4667
|
+
}
|
|
4668
|
+
if (!ok) {
|
|
4669
|
+
err(`libCall http.reqOnData callback shape (frontend must fence)`, e.loc);
|
|
4670
|
+
}
|
|
4671
|
+
return true;
|
|
4672
|
+
}
|
|
4673
|
+
if (e.fn === "http.reqStatusCode") {
|
|
4674
|
+
// Result is the module's interned `number | undefined` union.
|
|
4675
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4676
|
+
const ok = def &&
|
|
4677
|
+
def.arms.length === 2 &&
|
|
4678
|
+
def.arms[0].kind === "f64" &&
|
|
4679
|
+
def.arms[1].kind === "undefinedT";
|
|
4680
|
+
if (!ok) {
|
|
4681
|
+
err(`libCall http.reqStatusCode must return the 'number | undefined' union`, e.loc);
|
|
4682
|
+
}
|
|
4683
|
+
return true;
|
|
4684
|
+
}
|
|
4685
|
+
if (e.fn === "net.sockRemoteAddress") {
|
|
4686
|
+
// Result is the interned `string | undefined` union (envGet's).
|
|
4687
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4688
|
+
const ok = def &&
|
|
4689
|
+
def.arms.length === 2 &&
|
|
4690
|
+
def.arms[0].kind === "string" &&
|
|
4691
|
+
def.arms[1].kind === "undefinedT";
|
|
4692
|
+
if (!ok) {
|
|
4693
|
+
err(`libCall net.sockRemoteAddress must return the 'string | undefined' union`, e.loc);
|
|
4694
|
+
}
|
|
4695
|
+
return true;
|
|
4696
|
+
}
|
|
4697
|
+
if (e.fn === "net.sockEncrypted") {
|
|
4698
|
+
// Result is the interned `boolean | undefined` union.
|
|
4699
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4700
|
+
const ok = def &&
|
|
4701
|
+
def.arms.length === 2 &&
|
|
4702
|
+
def.arms[0].kind === "bool" &&
|
|
4703
|
+
def.arms[1].kind === "undefinedT";
|
|
4704
|
+
if (!ok) {
|
|
4705
|
+
err(`libCall net.sockEncrypted must return the 'boolean | undefined' union`, e.loc);
|
|
4706
|
+
}
|
|
4707
|
+
return true;
|
|
4708
|
+
}
|
|
4709
|
+
if (e.fn === "tls.sockAuthError") {
|
|
4710
|
+
// Result is the interned `string | null` union (Node's
|
|
4711
|
+
// authorizationError: the verify-failure code string, or null).
|
|
4712
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4713
|
+
const ok = def &&
|
|
4714
|
+
def.arms.length === 2 &&
|
|
4715
|
+
def.arms[0].kind === "string" &&
|
|
4716
|
+
def.arms[1].kind === "nullT";
|
|
4717
|
+
if (!ok) {
|
|
4718
|
+
err(`libCall tls.sockAuthError must return the 'string | null' union`, e.loc);
|
|
4719
|
+
}
|
|
4720
|
+
return true;
|
|
4721
|
+
}
|
|
4722
|
+
if (e.fn === "http.requestCb" || e.fn === "https.requestCb" ||
|
|
4723
|
+
e.fn === "http.requestUrlCb" || e.fn === "http.clientOnResponse" ||
|
|
4724
|
+
e.fn === "http.requestAgentCb" || e.fn === "https.requestAgentCb" ||
|
|
4725
|
+
e.fn === "https.requestUrlCb") {
|
|
4726
|
+
// The response listener: void, no params or exactly (res: httpReq).
|
|
4727
|
+
const cbT = e.args[e.fn === "http.requestCb" ? 7
|
|
4728
|
+
: e.fn === "https.requestCb" ? 9
|
|
4729
|
+
: e.fn === "http.requestUrlCb" || e.fn === "https.requestUrlCb" ? 3
|
|
4730
|
+
: e.fn === "http.requestAgentCb" ? 8
|
|
4731
|
+
: e.fn === "https.requestAgentCb" ? 10
|
|
4732
|
+
: 1]?.type;
|
|
4733
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4734
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4735
|
+
ok = cbT.params[0].kind === "httpReq";
|
|
4736
|
+
}
|
|
4737
|
+
if (!ok) {
|
|
4738
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4739
|
+
}
|
|
4740
|
+
return true;
|
|
4741
|
+
}
|
|
4742
|
+
if (e.fn === "http.reqOnError" || e.fn === "http.clientOnError") {
|
|
4743
|
+
// The error listener: void, no params or exactly (err: %Error).
|
|
4744
|
+
const cbT = e.args[1]?.type;
|
|
4745
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4746
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4747
|
+
const p = cbT.params[0];
|
|
4748
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4749
|
+
}
|
|
4750
|
+
if (!ok) {
|
|
4751
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4752
|
+
}
|
|
4753
|
+
return true;
|
|
4754
|
+
}
|
|
4755
|
+
if (e.fn === "net.sockRead") {
|
|
4756
|
+
// Result is the interned `Buffer | null` union.
|
|
4757
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4758
|
+
const ok = def &&
|
|
4759
|
+
def.arms.length === 2 &&
|
|
4760
|
+
def.arms.some((a) => a.kind === "bytes" && a.elem === "u8") &&
|
|
4761
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
4762
|
+
if (!ok) {
|
|
4763
|
+
err(`libCall net.sockRead must return the 'Buffer | null' union`, e.loc);
|
|
4764
|
+
}
|
|
4765
|
+
return true;
|
|
4766
|
+
}
|
|
4767
|
+
if (e.fn === "http.serverOnUpgrade" || e.fn === "http.clientOnUpgrade" ||
|
|
4768
|
+
e.fn === "http.serverOnConnect") {
|
|
4769
|
+
// (req, socket, head) or any shorter prefix, void return. The
|
|
4770
|
+
// 'connect' registration additionally admits a socket slot
|
|
4771
|
+
// that is a UNION carrying a netSocket arm (the h2 compat
|
|
4772
|
+
// listener — the emitted adapter wraps the socket there).
|
|
4773
|
+
const cbT = e.args[1]?.type;
|
|
4774
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 3;
|
|
4775
|
+
if (ok && cbT?.kind === "func") {
|
|
4776
|
+
const [p0, p1, p2] = cbT.params;
|
|
4777
|
+
if (p0 !== undefined && p0.kind !== "httpReq")
|
|
4778
|
+
ok = false;
|
|
4779
|
+
if (p1 !== undefined && p1.kind !== "netSocket") {
|
|
4780
|
+
if (e.fn === "http.serverOnConnect" && p1?.kind === "union") {
|
|
4781
|
+
const def = unions.get(p1.unionId);
|
|
4782
|
+
if (!def || !def.arms.some((a) => a.kind === "netSocket"))
|
|
4223
4783
|
ok = false;
|
|
4224
4784
|
}
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
}
|
|
4228
|
-
break;
|
|
4229
|
-
}
|
|
4230
|
-
if (e.fn === "net.listenOptsCb" || e.fn === "net.listenOptsReusePortCb") {
|
|
4231
|
-
const cbIndex = e.fn === "net.listenOptsReusePortCb" ? 5 : 4;
|
|
4232
|
-
const t = e.args[cbIndex]?.type;
|
|
4233
|
-
const funcOk = (x) => x?.kind === "func" && x.params.length === 0 && x.ret.kind === "void";
|
|
4234
|
-
let ok = funcOk(t);
|
|
4235
|
-
if (!ok && t?.kind === "union") {
|
|
4236
|
-
const def = unions.get(t.unionId);
|
|
4237
|
-
ok = !!def && def.arms.length === 2 && def.arms.some((a) => funcOk(a)) &&
|
|
4238
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4239
|
-
}
|
|
4240
|
-
if (!ok) {
|
|
4241
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4242
|
-
}
|
|
4243
|
-
break;
|
|
4244
|
-
}
|
|
4245
|
-
if (e.fn === "net.connectLookup") {
|
|
4246
|
-
// The caller's resolver: (hostname: string, options: unknown,
|
|
4247
|
-
// callback: (err: <union>, addresses: <record[]>) => void) =>
|
|
4248
|
-
// void — the emitter synthesizes the answer thunk from these
|
|
4249
|
-
// types, so the structure must hold.
|
|
4250
|
-
const t = e.args[2]?.type;
|
|
4251
|
-
let ok = t?.kind === "func" && t.ret.kind === "void" && t.params.length === 3 &&
|
|
4252
|
-
t.params[0].kind === "string" && t.params[1].kind === "dyn";
|
|
4253
|
-
if (ok && t?.kind === "func") {
|
|
4254
|
-
const cbT = t.params[2];
|
|
4255
|
-
ok = cbT.kind === "func" && cbT.ret.kind === "void" && cbT.params.length === 2 &&
|
|
4256
|
-
cbT.params[0].kind === "union" &&
|
|
4257
|
-
cbT.params[1].kind === "array" && cbT.params[1].elem.kind === "record";
|
|
4258
|
-
}
|
|
4259
|
-
if (!ok) {
|
|
4260
|
-
err(`libCall net.connectLookup resolver shape (frontend must fence)`, e.loc);
|
|
4261
|
-
}
|
|
4262
|
-
break;
|
|
4263
|
-
}
|
|
4264
|
-
if (e.fn === "http.requestConn" || e.fn === "http.requestConnCb") {
|
|
4265
|
-
const dialT = e.args[0]?.type;
|
|
4266
|
-
if (!(dialT?.kind === "func" && dialT.params.length === 0 && dialT.ret.kind === "netSocket")) {
|
|
4267
|
-
err(`libCall ${e.fn} dialer shape (frontend must fence)`, e.loc);
|
|
4268
|
-
break;
|
|
4269
|
-
}
|
|
4270
|
-
if (e.fn === "http.requestConnCb") {
|
|
4271
|
-
const cbT = e.args[6]?.type;
|
|
4272
|
-
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1 &&
|
|
4273
|
-
(cbT.params[0] === undefined || cbT.params[0].kind === "httpReq");
|
|
4274
|
-
if (!ok)
|
|
4275
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4276
|
-
}
|
|
4277
|
-
break;
|
|
4278
|
-
}
|
|
4279
|
-
if (e.fn === "http.reqStatusMessage" || e.fn === "http.resStatusMsgGet") {
|
|
4280
|
-
// Result is the interned `string | undefined` union (reqHeader's).
|
|
4281
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4282
|
-
const ok = def &&
|
|
4283
|
-
def.arms.length === 2 &&
|
|
4284
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4285
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4286
|
-
if (!ok) {
|
|
4287
|
-
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4785
|
+
else {
|
|
4786
|
+
ok = false;
|
|
4288
4787
|
}
|
|
4289
|
-
break;
|
|
4290
4788
|
}
|
|
4291
|
-
if (
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4789
|
+
if (p2 !== undefined && !(p2.kind === "bytes" && p2.elem === "u8"))
|
|
4790
|
+
ok = false;
|
|
4791
|
+
}
|
|
4792
|
+
if (!ok) {
|
|
4793
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4794
|
+
}
|
|
4795
|
+
return true;
|
|
4796
|
+
}
|
|
4797
|
+
if (e.fn === "net.listenOptsCb" || e.fn === "net.listenOptsReusePortCb") {
|
|
4798
|
+
const cbIndex = e.fn === "net.listenOptsReusePortCb" ? 5 : 4;
|
|
4799
|
+
const t = e.args[cbIndex]?.type;
|
|
4800
|
+
const funcOk = (x) => x?.kind === "func" && x.params.length === 0 && x.ret.kind === "void";
|
|
4801
|
+
let ok = funcOk(t);
|
|
4802
|
+
if (!ok && t?.kind === "union") {
|
|
4803
|
+
const def = unions.get(t.unionId);
|
|
4804
|
+
ok = !!def && def.arms.length === 2 && def.arms.some((a) => funcOk(a)) &&
|
|
4805
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4806
|
+
}
|
|
4807
|
+
if (!ok) {
|
|
4808
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4809
|
+
}
|
|
4810
|
+
return true;
|
|
4811
|
+
}
|
|
4812
|
+
if (e.fn === "net.connectLookup") {
|
|
4813
|
+
// The caller's resolver: (hostname: string, options: unknown,
|
|
4814
|
+
// callback: (err: <union>, addresses: <record[]>) => void) =>
|
|
4815
|
+
// void — the emitter synthesizes the answer thunk from these
|
|
4816
|
+
// types, so the structure must hold.
|
|
4817
|
+
const t = e.args[2]?.type;
|
|
4818
|
+
let ok = t?.kind === "func" && t.ret.kind === "void" && t.params.length === 3 &&
|
|
4819
|
+
t.params[0].kind === "string" && t.params[1].kind === "dyn";
|
|
4820
|
+
if (ok && t?.kind === "func") {
|
|
4821
|
+
const cbT = t.params[2];
|
|
4822
|
+
ok = cbT.kind === "func" && cbT.ret.kind === "void" && cbT.params.length === 2 &&
|
|
4823
|
+
cbT.params[0].kind === "union" &&
|
|
4824
|
+
cbT.params[1].kind === "array" && cbT.params[1].elem.kind === "record";
|
|
4825
|
+
}
|
|
4826
|
+
if (!ok) {
|
|
4827
|
+
err(`libCall net.connectLookup resolver shape (frontend must fence)`, e.loc);
|
|
4828
|
+
}
|
|
4829
|
+
return true;
|
|
4830
|
+
}
|
|
4831
|
+
if (e.fn === "http.requestConn" || e.fn === "http.requestConnCb") {
|
|
4832
|
+
const dialT = e.args[0]?.type;
|
|
4833
|
+
if (!(dialT?.kind === "func" && dialT.params.length === 0 && dialT.ret.kind === "netSocket")) {
|
|
4834
|
+
err(`libCall ${e.fn} dialer shape (frontend must fence)`, e.loc);
|
|
4835
|
+
return true;
|
|
4836
|
+
}
|
|
4837
|
+
if (e.fn === "http.requestConnCb") {
|
|
4838
|
+
const cbT = e.args[6]?.type;
|
|
4839
|
+
const ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1 &&
|
|
4840
|
+
(cbT.params[0] === undefined || cbT.params[0].kind === "httpReq");
|
|
4841
|
+
if (!ok)
|
|
4842
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4843
|
+
}
|
|
4844
|
+
return true;
|
|
4845
|
+
}
|
|
4846
|
+
if (e.fn === "http.reqStatusMessage" || e.fn === "http.resStatusMsgGet") {
|
|
4847
|
+
// Result is the interned `string | undefined` union (reqHeader's).
|
|
4848
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4849
|
+
const ok = def &&
|
|
4850
|
+
def.arms.length === 2 &&
|
|
4851
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
4852
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4853
|
+
if (!ok) {
|
|
4854
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4855
|
+
}
|
|
4856
|
+
return true;
|
|
4857
|
+
}
|
|
4858
|
+
if (e.fn === "http.resSocket") {
|
|
4859
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4860
|
+
const ok = def && def.arms.length === 2 &&
|
|
4861
|
+
def.arms.some((a) => a.kind === "netSocket") &&
|
|
4862
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
4863
|
+
if (!ok)
|
|
4864
|
+
err(`libCall http.resSocket must return the 'Socket | null' union`, e.loc);
|
|
4865
|
+
return true;
|
|
4866
|
+
}
|
|
4867
|
+
if (e.fn === "http.reqH2Stream") {
|
|
4868
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4869
|
+
const ok = def && def.arms.length === 2 &&
|
|
4870
|
+
def.arms.some((a) => a.kind === "http2Stream") &&
|
|
4871
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
4872
|
+
if (!ok)
|
|
4873
|
+
err(`libCall http.reqH2Stream must return the 'Http2Stream | undefined' union`, e.loc);
|
|
4874
|
+
return true;
|
|
4875
|
+
}
|
|
4876
|
+
if (e.fn === "http.reqHeader" || e.fn === "http.reqTrailer" || e.fn === "http.resGetHeader" || e.fn === "http.clientGetHeader") {
|
|
4877
|
+
// Result is the interned `string | undefined` union (envGet's).
|
|
4878
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4879
|
+
const ok = def &&
|
|
4880
|
+
def.arms.length === 2 &&
|
|
4881
|
+
def.arms[0].kind === "string" &&
|
|
4882
|
+
def.arms[1].kind === "undefinedT";
|
|
4883
|
+
if (!ok) {
|
|
4884
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
4885
|
+
}
|
|
4886
|
+
return true;
|
|
4887
|
+
}
|
|
4888
|
+
if (e.fn === "http.reqHeaderValues" || e.fn === "http.reqTrailerValues") {
|
|
4889
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4890
|
+
const ok = def && def.arms.length === 2 &&
|
|
4891
|
+
def.arms[0].kind === "array" && def.arms[0].elem.kind === "string" &&
|
|
4892
|
+
def.arms[1].kind === "undefinedT";
|
|
4893
|
+
if (!ok)
|
|
4894
|
+
err(`libCall ${e.fn} must return the 'string[] | undefined' union`, e.loc);
|
|
4895
|
+
return true;
|
|
4896
|
+
}
|
|
4897
|
+
if (e.fn === "net.createServerCb" || e.fn === "net.serverOnConnection" ||
|
|
4898
|
+
e.fn === "net.serverOnSecureConnection" ||
|
|
4899
|
+
e.fn === "http.serverSetTimeoutCb" || e.fn === "http.serverOnTimeout" ||
|
|
4900
|
+
e.fn === "http.clientOnSocket" ||
|
|
4901
|
+
e.fn === "net.sockOnData" || e.fn === "net.serverOnError" ||
|
|
4902
|
+
e.fn === "net.sockOnError") {
|
|
4903
|
+
// The program-dependent listener shapes: a void closure with no
|
|
4904
|
+
// params, or exactly the one supported parameter per event
|
|
4905
|
+
// (socket handle / data chunk bytes / error %Error). The
|
|
4906
|
+
// callback slot is arg 0 for createServerCb, arg 1 otherwise.
|
|
4907
|
+
const cbT = e.args[e.fn === "net.createServerCb" ? 0 : e.fn === "http.serverSetTimeoutCb" ? 2 : 1]?.type;
|
|
4908
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4909
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4910
|
+
const p = cbT.params[0];
|
|
4911
|
+
if (e.fn === "net.sockOnData")
|
|
4912
|
+
ok = (p.kind === "bytes" && p.elem === "u8") || p.kind === "dyn";
|
|
4913
|
+
else if (e.fn === "net.serverOnError" || e.fn === "net.sockOnError") {
|
|
4914
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4915
|
+
}
|
|
4916
|
+
else
|
|
4917
|
+
ok = p.kind === "netSocket";
|
|
4918
|
+
}
|
|
4919
|
+
if (!ok) {
|
|
4920
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4921
|
+
}
|
|
4922
|
+
return true;
|
|
4923
|
+
}
|
|
4924
|
+
if (e.fn === "http2.createSecureServerSni") {
|
|
4925
|
+
// The SNI callback: (servername: string, cb: (err, ctx?) => void)
|
|
4926
|
+
// => void — as a bare func, or the `| undefined` union from the
|
|
4927
|
+
// conditional-spread spelling (exactly two arms: the func and
|
|
4928
|
+
// undefined). The cb's own params are program-interned unions
|
|
4929
|
+
// (Error|null, SecureContext|undefined) whose arms the emitted
|
|
4930
|
+
// answer thunk decodes; here the structural func shape is what
|
|
4931
|
+
// the validator can pin.
|
|
4932
|
+
const sniOk = (t) => t?.kind === "func" && t.ret.kind === "void" && t.params.length === 2 &&
|
|
4933
|
+
t.params[0].kind === "string" && t.params[1].kind === "func";
|
|
4934
|
+
const argT = e.args[2]?.type;
|
|
4935
|
+
let ok = sniOk(argT);
|
|
4936
|
+
if (!ok && argT?.kind === "union") {
|
|
4937
|
+
const def = unions.get(argT.unionId);
|
|
4938
|
+
ok = def !== undefined && def.arms.length === 2 &&
|
|
4939
|
+
def.arms.some((a) => a.kind === "undefinedT") &&
|
|
4940
|
+
def.arms.some((a) => sniOk(a));
|
|
4941
|
+
}
|
|
4942
|
+
if (!ok) {
|
|
4943
|
+
err(`libCall ${e.fn} SNI callback shape (frontend must fence)`, e.loc);
|
|
4944
|
+
}
|
|
4945
|
+
return true;
|
|
4946
|
+
}
|
|
4947
|
+
if (e.fn === "dgram.onMessage" || e.fn === "dgram.onError") {
|
|
4948
|
+
// The dgram listener shapes: a void closure with no params, or
|
|
4949
|
+
// the per-event parameter shapes — message takes (msg: bytes<u8>
|
|
4950
|
+
// [, rinfo: record]), error the one %Error param.
|
|
4951
|
+
const cbT = e.args[1]?.type;
|
|
4952
|
+
const maxParams = e.fn === "dgram.onMessage" ? 2 : 1;
|
|
4953
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4954
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4955
|
+
if (e.fn === "dgram.onMessage") {
|
|
4956
|
+
const p0 = cbT.params[0];
|
|
4957
|
+
ok = p0.kind === "bytes" && p0.elem === "u8";
|
|
4958
|
+
const p1 = cbT.params[1];
|
|
4959
|
+
if (ok && p1 !== undefined)
|
|
4960
|
+
ok = p1.kind === "record";
|
|
4299
4961
|
}
|
|
4300
|
-
|
|
4301
|
-
const
|
|
4302
|
-
|
|
4303
|
-
def.arms.some((a) => a.kind === "http2Stream") &&
|
|
4304
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4305
|
-
if (!ok)
|
|
4306
|
-
err(`libCall http.reqH2Stream must return the 'Http2Stream | undefined' union`, e.loc);
|
|
4307
|
-
break;
|
|
4962
|
+
else {
|
|
4963
|
+
const p = cbT.params[0];
|
|
4964
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4308
4965
|
}
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4966
|
+
}
|
|
4967
|
+
if (!ok) {
|
|
4968
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4969
|
+
}
|
|
4970
|
+
return true;
|
|
4971
|
+
}
|
|
4972
|
+
if (e.fn === "dns.lookup") {
|
|
4973
|
+
// The callback: void, at most (err: Error | null, address:
|
|
4974
|
+
// string, family: number).
|
|
4975
|
+
const cbT = e.args[2]?.type;
|
|
4976
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 3;
|
|
4977
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4978
|
+
const p0 = cbT.params[0];
|
|
4979
|
+
const def = p0.kind === "union" ? unions.get(p0.unionId) : undefined;
|
|
4980
|
+
ok =
|
|
4981
|
+
def !== undefined &&
|
|
4313
4982
|
def.arms.length === 2 &&
|
|
4314
|
-
def.arms
|
|
4315
|
-
def.arms
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4983
|
+
def.arms.some((a) => a.kind === "nullT") &&
|
|
4984
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error");
|
|
4985
|
+
const p1 = cbT.params[1];
|
|
4986
|
+
if (ok && p1 !== undefined)
|
|
4987
|
+
ok = p1.kind === "string";
|
|
4988
|
+
const p2 = cbT.params[2];
|
|
4989
|
+
if (ok && p2 !== undefined)
|
|
4990
|
+
ok = p2.kind === "f64";
|
|
4991
|
+
}
|
|
4992
|
+
if (!ok) {
|
|
4993
|
+
err(`libCall dns.lookup callback shape (frontend must fence)`, e.loc);
|
|
4994
|
+
}
|
|
4995
|
+
return true;
|
|
4996
|
+
}
|
|
4997
|
+
return false;
|
|
4998
|
+
}
|
|
4999
|
+
function checkLibFileCall(e) {
|
|
5000
|
+
if (e.fn === "zlib.deflateCb" || e.fn === "zlib.inflateCb" ||
|
|
5001
|
+
e.fn === "zlib.deflateRawCb" || e.fn === "zlib.inflateRawCb" ||
|
|
5002
|
+
e.fn === "zlib.gzipCb" || e.fn === "zlib.gunzipCb" || e.fn === "zlib.unzipCb") {
|
|
5003
|
+
const cbT = e.args[1]?.type;
|
|
5004
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
5005
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5006
|
+
const error = cbT.params[0];
|
|
5007
|
+
if (error.kind !== "dyn") {
|
|
5008
|
+
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
5009
|
+
ok = def !== undefined &&
|
|
5010
|
+
def.arms.some((arm) => arm.kind === "nullT") &&
|
|
5011
|
+
def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error") &&
|
|
5012
|
+
def.arms.every((arm) => arm.kind === "nullT" || arm.kind === "undefinedT" ||
|
|
5013
|
+
(arm.kind === "object" && arm.className === "%Error"));
|
|
5014
|
+
}
|
|
5015
|
+
}
|
|
5016
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 2) {
|
|
5017
|
+
const value = cbT.params[1];
|
|
5018
|
+
ok = value.kind === "dyn" || (value.kind === "bytes" && value.elem === "u8");
|
|
5019
|
+
}
|
|
5020
|
+
if (!ok)
|
|
5021
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5022
|
+
return true;
|
|
5023
|
+
}
|
|
5024
|
+
if (e.fn === "fs.renameCb" ||
|
|
5025
|
+
e.fn === "process.stdoutWriteBytesCb" ||
|
|
5026
|
+
e.fn === "process.stderrWriteBytesCb") {
|
|
5027
|
+
// The callback is void and accepts either no parameters, one
|
|
5028
|
+
// checked-dynamic error slot (JS), or Error | null (optionally
|
|
5029
|
+
// including undefined for an explicitly optional parameter).
|
|
5030
|
+
const cbT = e.args[2]?.type;
|
|
5031
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
5032
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5033
|
+
const p = cbT.params[0];
|
|
5034
|
+
if (p.kind === "dyn") {
|
|
5035
|
+
ok = true;
|
|
4320
5036
|
}
|
|
4321
|
-
|
|
4322
|
-
const def =
|
|
4323
|
-
|
|
4324
|
-
def
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
5037
|
+
else {
|
|
5038
|
+
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
5039
|
+
ok =
|
|
5040
|
+
def !== undefined &&
|
|
5041
|
+
def.arms.some((a) => a.kind === "nullT") &&
|
|
5042
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
5043
|
+
def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
|
|
5044
|
+
(a.kind === "object" && a.className === "%Error"));
|
|
4329
5045
|
}
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
5046
|
+
}
|
|
5047
|
+
if (!ok) {
|
|
5048
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5049
|
+
}
|
|
5050
|
+
return true;
|
|
5051
|
+
}
|
|
5052
|
+
if (e.fn === "net.serverAddress") {
|
|
5053
|
+
// Result is the {address, family, port} record (dgram.address's
|
|
5054
|
+
// check, another receiver).
|
|
5055
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5056
|
+
const ok = shape !== undefined &&
|
|
5057
|
+
shape.fields.length === 3 &&
|
|
5058
|
+
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
5059
|
+
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
5060
|
+
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
5061
|
+
if (!ok) {
|
|
5062
|
+
err(`libCall net.serverAddress must return the {address, family, port} record`, e.loc);
|
|
5063
|
+
}
|
|
5064
|
+
return true;
|
|
5065
|
+
}
|
|
5066
|
+
if (e.fn === "dgram.address") {
|
|
5067
|
+
// Result is the {address, family, port} record.
|
|
5068
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5069
|
+
const ok = shape !== undefined &&
|
|
5070
|
+
shape.fields.length === 3 &&
|
|
5071
|
+
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
5072
|
+
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
5073
|
+
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
5074
|
+
if (!ok) {
|
|
5075
|
+
err(`libCall dgram.address must return the {address, family, port} record`, e.loc);
|
|
5076
|
+
}
|
|
5077
|
+
return true;
|
|
5078
|
+
}
|
|
5079
|
+
if (e.fn === "fs.readdirTypesSync" || e.fn === "fsp.readdirTypes") {
|
|
5080
|
+
// Result: the interned Dirent record array — {%dtype: f64,
|
|
5081
|
+
// name: string, parentPath: string} rows (canonical field
|
|
5082
|
+
// order; the structure lowerFsReaddirTypesCall pinned).
|
|
5083
|
+
const result = e.fn === "fsp.readdirTypes"
|
|
5084
|
+
? e.type.kind === "promise" ? e.type.inner : undefined
|
|
5085
|
+
: e.type;
|
|
5086
|
+
const shape = result?.kind === "array" && result.elem.kind === "record"
|
|
5087
|
+
? records.get(result.elem.shapeId)
|
|
5088
|
+
: undefined;
|
|
5089
|
+
const ok = shape !== undefined &&
|
|
5090
|
+
!shape.tuple &&
|
|
5091
|
+
shape.indexValue === undefined &&
|
|
5092
|
+
shape.fields.length === 3 &&
|
|
5093
|
+
shape.fields[0].name === "%dtype" && shape.fields[0].type.kind === "f64" &&
|
|
5094
|
+
shape.fields[1].name === "name" && shape.fields[1].type.kind === "string" &&
|
|
5095
|
+
shape.fields[2].name === "parentPath" && shape.fields[2].type.kind === "string";
|
|
5096
|
+
if (!ok) {
|
|
5097
|
+
err(`libCall ${e.fn} must return ${e.fn === "fsp.readdirTypes" ? "a promise of " : ""}the Dirent record array`, e.loc);
|
|
5098
|
+
}
|
|
5099
|
+
return true;
|
|
5100
|
+
}
|
|
5101
|
+
if (e.fn === "os.networkInterfaces") {
|
|
5102
|
+
// Result: a pure index-signature record whose value is
|
|
5103
|
+
// `Info[] | undefined`, Info a two-record union (one arm's
|
|
5104
|
+
// scopeid f64, the other's `number | undefined`) — the structure
|
|
5105
|
+
// lowerOsNetworkInterfacesCall pinned.
|
|
5106
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5107
|
+
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
5108
|
+
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
5109
|
+
const arrArm = ivDef?.arms.find((a) => a.kind === "array");
|
|
5110
|
+
ok = ok && ivDef !== undefined && ivDef.arms.length === 2 && arrArm !== undefined && ivDef.arms.some((a) => a.kind === "undefinedT");
|
|
5111
|
+
const infoDef = ok && arrArm.kind === "array" && arrArm.elem.kind === "union" ? unions.get(arrArm.elem.unionId) : undefined;
|
|
5112
|
+
ok = ok && infoDef !== undefined && infoDef.arms.length === 2 && infoDef.arms.every((a) => a.kind === "record");
|
|
5113
|
+
if (!ok) {
|
|
5114
|
+
err(`libCall os.networkInterfaces must return the NetworkInterfaceInfo dictionary record`, e.loc);
|
|
5115
|
+
}
|
|
5116
|
+
return true;
|
|
5117
|
+
}
|
|
5118
|
+
if (e.fn === "qs.parse") {
|
|
5119
|
+
// Result: a pure index-signature record whose value union
|
|
5120
|
+
// carries a string arm and a string[] arm (undefined tolerated
|
|
5121
|
+
// — @types/node's Dict — and f64 too: the header-family
|
|
5122
|
+
// canonicalization interns every such dictionary with the
|
|
5123
|
+
// number arm, type-level only) — the structure
|
|
5124
|
+
// lowerQuerystringParseCall pinned.
|
|
5125
|
+
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
5126
|
+
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
5127
|
+
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
5128
|
+
ok = ok && ivDef !== undefined &&
|
|
5129
|
+
ivDef.arms.some((a) => a.kind === "string") &&
|
|
5130
|
+
ivDef.arms.some((a) => a.kind === "array" && a.elem.kind === "string") &&
|
|
5131
|
+
ivDef.arms.every((a) => a.kind === "string" || a.kind === "array" || a.kind === "undefinedT" || a.kind === "f64");
|
|
5132
|
+
if (!ok) {
|
|
5133
|
+
err(`libCall qs.parse must return the ParsedUrlQuery dictionary record`, e.loc);
|
|
5134
|
+
}
|
|
5135
|
+
return true;
|
|
5136
|
+
}
|
|
5137
|
+
return false;
|
|
5138
|
+
}
|
|
5139
|
+
function checkLibProcessCall(e) {
|
|
5140
|
+
if (e.fn === "cp.execFile") {
|
|
5141
|
+
const cb = e.args[2]?.type;
|
|
5142
|
+
if (cb?.kind !== "func" || cb.rest === true || cb.params.length > 3 || cb.ret.kind !== "void") {
|
|
5143
|
+
err(`libCall cp.execFile callback must be a non-rest void function with at most three parameters`, e.loc);
|
|
5144
|
+
}
|
|
5145
|
+
else {
|
|
5146
|
+
const error = cb.params[0];
|
|
5147
|
+
if (error !== undefined) {
|
|
5148
|
+
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
5149
|
+
if (!def || def.arms.length !== 2 ||
|
|
5150
|
+
!def.arms.some((arm) => arm.kind === "nullT") ||
|
|
5151
|
+
!def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error")) {
|
|
5152
|
+
err(`libCall cp.execFile callback error parameter must be Error | null`, e.loc);
|
|
4354
5153
|
}
|
|
4355
|
-
break;
|
|
4356
5154
|
}
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
// conditional-spread spelling (exactly two arms: the func and
|
|
4361
|
-
// undefined). The cb's own params are program-interned unions
|
|
4362
|
-
// (Error|null, SecureContext|undefined) whose arms the emitted
|
|
4363
|
-
// answer thunk decodes; here the structural func shape is what
|
|
4364
|
-
// the validator can pin.
|
|
4365
|
-
const sniOk = (t) => t?.kind === "func" && t.ret.kind === "void" && t.params.length === 2 &&
|
|
4366
|
-
t.params[0].kind === "string" && t.params[1].kind === "func";
|
|
4367
|
-
const argT = e.args[2]?.type;
|
|
4368
|
-
let ok = sniOk(argT);
|
|
4369
|
-
if (!ok && argT?.kind === "union") {
|
|
4370
|
-
const def = unions.get(argT.unionId);
|
|
4371
|
-
ok = def !== undefined && def.arms.length === 2 &&
|
|
4372
|
-
def.arms.some((a) => a.kind === "undefinedT") &&
|
|
4373
|
-
def.arms.some((a) => sniOk(a));
|
|
4374
|
-
}
|
|
4375
|
-
if (!ok) {
|
|
4376
|
-
err(`libCall ${e.fn} SNI callback shape (frontend must fence)`, e.loc);
|
|
4377
|
-
}
|
|
4378
|
-
break;
|
|
5155
|
+
const stdout = cb.params[1];
|
|
5156
|
+
if (stdout !== undefined && stdout.kind !== "string") {
|
|
5157
|
+
err(`libCall cp.execFile callback stdout parameter must be string`, e.loc);
|
|
4379
5158
|
}
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
// [, rinfo: record]), error the one %Error param.
|
|
4384
|
-
const cbT = e.args[1]?.type;
|
|
4385
|
-
const maxParams = e.fn === "dgram.onMessage" ? 2 : 1;
|
|
4386
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4387
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4388
|
-
if (e.fn === "dgram.onMessage") {
|
|
4389
|
-
const p0 = cbT.params[0];
|
|
4390
|
-
ok = p0.kind === "bytes" && p0.elem === "u8";
|
|
4391
|
-
const p1 = cbT.params[1];
|
|
4392
|
-
if (ok && p1 !== undefined)
|
|
4393
|
-
ok = p1.kind === "record";
|
|
4394
|
-
}
|
|
4395
|
-
else {
|
|
4396
|
-
const p = cbT.params[0];
|
|
4397
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4398
|
-
}
|
|
4399
|
-
}
|
|
4400
|
-
if (!ok) {
|
|
4401
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4402
|
-
}
|
|
4403
|
-
break;
|
|
5159
|
+
const stderr = cb.params[2];
|
|
5160
|
+
if (stderr !== undefined && stderr.kind !== "string") {
|
|
5161
|
+
err(`libCall cp.execFile callback stderr parameter must be string`, e.loc);
|
|
4404
5162
|
}
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5165
|
+
if (e.fn === "child.onExit" || e.fn === "child.onClose" || e.fn === "child.onError") {
|
|
5166
|
+
// The listener: a closure with no params, or exactly the
|
|
5167
|
+
// supported parameter shapes per event — exit takes (code:
|
|
5168
|
+
// number | null) with an optional (signal: string | null)
|
|
5169
|
+
// second parameter, error exactly (err: %Error).
|
|
5170
|
+
const cb = e.args[1];
|
|
5171
|
+
const cbT = cb?.type;
|
|
5172
|
+
const maxParams = e.fn === "child.onError" ? 1 : 2;
|
|
5173
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
5174
|
+
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
5175
|
+
const p = cbT.params[0];
|
|
5176
|
+
if (e.fn === "child.onExit" || e.fn === "child.onClose") {
|
|
5177
|
+
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
5178
|
+
ok =
|
|
5179
|
+
def !== undefined &&
|
|
5180
|
+
def.arms.length === 2 &&
|
|
5181
|
+
def.arms[0].kind === "f64" &&
|
|
5182
|
+
def.arms[1].kind === "nullT";
|
|
5183
|
+
if (ok && cbT.params.length === 2) {
|
|
5184
|
+
const s = cbT.params[1];
|
|
5185
|
+
const sdef = s.kind === "union" ? unions.get(s.unionId) : undefined;
|
|
4413
5186
|
ok =
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
const p1 = cbT.params[1];
|
|
4419
|
-
if (ok && p1 !== undefined)
|
|
4420
|
-
ok = p1.kind === "string";
|
|
4421
|
-
const p2 = cbT.params[2];
|
|
4422
|
-
if (ok && p2 !== undefined)
|
|
4423
|
-
ok = p2.kind === "f64";
|
|
4424
|
-
}
|
|
4425
|
-
if (!ok) {
|
|
4426
|
-
err(`libCall dns.lookup callback shape (frontend must fence)`, e.loc);
|
|
4427
|
-
}
|
|
4428
|
-
break;
|
|
4429
|
-
}
|
|
4430
|
-
if (e.fn === "zlib.deflateCb" || e.fn === "zlib.inflateCb" ||
|
|
4431
|
-
e.fn === "zlib.deflateRawCb" || e.fn === "zlib.inflateRawCb" ||
|
|
4432
|
-
e.fn === "zlib.gzipCb" || e.fn === "zlib.gunzipCb" || e.fn === "zlib.unzipCb") {
|
|
4433
|
-
const cbT = e.args[1]?.type;
|
|
4434
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 2;
|
|
4435
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4436
|
-
const error = cbT.params[0];
|
|
4437
|
-
if (error.kind !== "dyn") {
|
|
4438
|
-
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
4439
|
-
ok = def !== undefined &&
|
|
4440
|
-
def.arms.some((arm) => arm.kind === "nullT") &&
|
|
4441
|
-
def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error") &&
|
|
4442
|
-
def.arms.every((arm) => arm.kind === "nullT" || arm.kind === "undefinedT" ||
|
|
4443
|
-
(arm.kind === "object" && arm.className === "%Error"));
|
|
4444
|
-
}
|
|
4445
|
-
}
|
|
4446
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 2) {
|
|
4447
|
-
const value = cbT.params[1];
|
|
4448
|
-
ok = value.kind === "dyn" || (value.kind === "bytes" && value.elem === "u8");
|
|
4449
|
-
}
|
|
4450
|
-
if (!ok)
|
|
4451
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4452
|
-
break;
|
|
4453
|
-
}
|
|
4454
|
-
if (e.fn === "fs.renameCb" ||
|
|
4455
|
-
e.fn === "process.stdoutWriteBytesCb" ||
|
|
4456
|
-
e.fn === "process.stderrWriteBytesCb") {
|
|
4457
|
-
// The callback is void and accepts either no parameters, one
|
|
4458
|
-
// checked-dynamic error slot (JS), or Error | null (optionally
|
|
4459
|
-
// including undefined for an explicitly optional parameter).
|
|
4460
|
-
const cbT = e.args[2]?.type;
|
|
4461
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4462
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4463
|
-
const p = cbT.params[0];
|
|
4464
|
-
if (p.kind === "dyn") {
|
|
4465
|
-
ok = true;
|
|
4466
|
-
}
|
|
4467
|
-
else {
|
|
4468
|
-
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
4469
|
-
ok =
|
|
4470
|
-
def !== undefined &&
|
|
4471
|
-
def.arms.some((a) => a.kind === "nullT") &&
|
|
4472
|
-
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
4473
|
-
def.arms.every((a) => a.kind === "nullT" || a.kind === "undefinedT" ||
|
|
4474
|
-
(a.kind === "object" && a.className === "%Error"));
|
|
4475
|
-
}
|
|
4476
|
-
}
|
|
4477
|
-
if (!ok) {
|
|
4478
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4479
|
-
}
|
|
4480
|
-
break;
|
|
4481
|
-
}
|
|
4482
|
-
if (e.fn === "net.serverAddress") {
|
|
4483
|
-
// Result is the {address, family, port} record (dgram.address's
|
|
4484
|
-
// check, another receiver).
|
|
4485
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4486
|
-
const ok = shape !== undefined &&
|
|
4487
|
-
shape.fields.length === 3 &&
|
|
4488
|
-
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
4489
|
-
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
4490
|
-
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
4491
|
-
if (!ok) {
|
|
4492
|
-
err(`libCall net.serverAddress must return the {address, family, port} record`, e.loc);
|
|
4493
|
-
}
|
|
4494
|
-
break;
|
|
4495
|
-
}
|
|
4496
|
-
if (e.fn === "dgram.address") {
|
|
4497
|
-
// Result is the {address, family, port} record.
|
|
4498
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4499
|
-
const ok = shape !== undefined &&
|
|
4500
|
-
shape.fields.length === 3 &&
|
|
4501
|
-
shape.fields[0].name === "address" && shape.fields[0].type.kind === "string" &&
|
|
4502
|
-
shape.fields[1].name === "family" && shape.fields[1].type.kind === "string" &&
|
|
4503
|
-
shape.fields[2].name === "port" && shape.fields[2].type.kind === "f64";
|
|
4504
|
-
if (!ok) {
|
|
4505
|
-
err(`libCall dgram.address must return the {address, family, port} record`, e.loc);
|
|
4506
|
-
}
|
|
4507
|
-
break;
|
|
4508
|
-
}
|
|
4509
|
-
if (e.fn === "fs.readdirTypesSync" || e.fn === "fsp.readdirTypes") {
|
|
4510
|
-
// Result: the interned Dirent record array — {%dtype: f64,
|
|
4511
|
-
// name: string, parentPath: string} rows (canonical field
|
|
4512
|
-
// order; the structure lowerFsReaddirTypesCall pinned).
|
|
4513
|
-
const result = e.fn === "fsp.readdirTypes"
|
|
4514
|
-
? e.type.kind === "promise" ? e.type.inner : undefined
|
|
4515
|
-
: e.type;
|
|
4516
|
-
const shape = result?.kind === "array" && result.elem.kind === "record"
|
|
4517
|
-
? records.get(result.elem.shapeId)
|
|
4518
|
-
: undefined;
|
|
4519
|
-
const ok = shape !== undefined &&
|
|
4520
|
-
!shape.tuple &&
|
|
4521
|
-
shape.indexValue === undefined &&
|
|
4522
|
-
shape.fields.length === 3 &&
|
|
4523
|
-
shape.fields[0].name === "%dtype" && shape.fields[0].type.kind === "f64" &&
|
|
4524
|
-
shape.fields[1].name === "name" && shape.fields[1].type.kind === "string" &&
|
|
4525
|
-
shape.fields[2].name === "parentPath" && shape.fields[2].type.kind === "string";
|
|
4526
|
-
if (!ok) {
|
|
4527
|
-
err(`libCall ${e.fn} must return ${e.fn === "fsp.readdirTypes" ? "a promise of " : ""}the Dirent record array`, e.loc);
|
|
4528
|
-
}
|
|
4529
|
-
break;
|
|
4530
|
-
}
|
|
4531
|
-
if (e.fn === "os.networkInterfaces") {
|
|
4532
|
-
// Result: a pure index-signature record whose value is
|
|
4533
|
-
// `Info[] | undefined`, Info a two-record union (one arm's
|
|
4534
|
-
// scopeid f64, the other's `number | undefined`) — the structure
|
|
4535
|
-
// lowerOsNetworkInterfacesCall pinned.
|
|
4536
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4537
|
-
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
4538
|
-
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
4539
|
-
const arrArm = ivDef?.arms.find((a) => a.kind === "array");
|
|
4540
|
-
ok = ok && ivDef !== undefined && ivDef.arms.length === 2 && arrArm !== undefined && ivDef.arms.some((a) => a.kind === "undefinedT");
|
|
4541
|
-
const infoDef = ok && arrArm.kind === "array" && arrArm.elem.kind === "union" ? unions.get(arrArm.elem.unionId) : undefined;
|
|
4542
|
-
ok = ok && infoDef !== undefined && infoDef.arms.length === 2 && infoDef.arms.every((a) => a.kind === "record");
|
|
4543
|
-
if (!ok) {
|
|
4544
|
-
err(`libCall os.networkInterfaces must return the NetworkInterfaceInfo dictionary record`, e.loc);
|
|
4545
|
-
}
|
|
4546
|
-
break;
|
|
4547
|
-
}
|
|
4548
|
-
if (e.fn === "qs.parse") {
|
|
4549
|
-
// Result: a pure index-signature record whose value union
|
|
4550
|
-
// carries a string arm and a string[] arm (undefined tolerated
|
|
4551
|
-
// — @types/node's Dict — and f64 too: the header-family
|
|
4552
|
-
// canonicalization interns every such dictionary with the
|
|
4553
|
-
// number arm, type-level only) — the structure
|
|
4554
|
-
// lowerQuerystringParseCall pinned.
|
|
4555
|
-
const shape = e.type.kind === "record" ? records.get(e.type.shapeId) : undefined;
|
|
4556
|
-
let ok = shape !== undefined && !shape.tuple && shape.fields.length === 0 && shape.indexValue !== undefined;
|
|
4557
|
-
const ivDef = ok && shape.indexValue.kind === "union" ? unions.get(shape.indexValue.unionId) : undefined;
|
|
4558
|
-
ok = ok && ivDef !== undefined &&
|
|
4559
|
-
ivDef.arms.some((a) => a.kind === "string") &&
|
|
4560
|
-
ivDef.arms.some((a) => a.kind === "array" && a.elem.kind === "string") &&
|
|
4561
|
-
ivDef.arms.every((a) => a.kind === "string" || a.kind === "array" || a.kind === "undefinedT" || a.kind === "f64");
|
|
4562
|
-
if (!ok) {
|
|
4563
|
-
err(`libCall qs.parse must return the ParsedUrlQuery dictionary record`, e.loc);
|
|
4564
|
-
}
|
|
4565
|
-
break;
|
|
4566
|
-
}
|
|
4567
|
-
if (e.fn === "cp.execFile") {
|
|
4568
|
-
const cb = e.args[2]?.type;
|
|
4569
|
-
if (cb?.kind !== "func" || cb.rest === true || cb.params.length > 3 || cb.ret.kind !== "void") {
|
|
4570
|
-
err(`libCall cp.execFile callback must be a non-rest void function with at most three parameters`, e.loc);
|
|
4571
|
-
}
|
|
4572
|
-
else {
|
|
4573
|
-
const error = cb.params[0];
|
|
4574
|
-
if (error !== undefined) {
|
|
4575
|
-
const def = error.kind === "union" ? unions.get(error.unionId) : undefined;
|
|
4576
|
-
if (!def || def.arms.length !== 2 ||
|
|
4577
|
-
!def.arms.some((arm) => arm.kind === "nullT") ||
|
|
4578
|
-
!def.arms.some((arm) => arm.kind === "object" && arm.className === "%Error")) {
|
|
4579
|
-
err(`libCall cp.execFile callback error parameter must be Error | null`, e.loc);
|
|
4580
|
-
}
|
|
4581
|
-
}
|
|
4582
|
-
const stdout = cb.params[1];
|
|
4583
|
-
if (stdout !== undefined && stdout.kind !== "string") {
|
|
4584
|
-
err(`libCall cp.execFile callback stdout parameter must be string`, e.loc);
|
|
4585
|
-
}
|
|
4586
|
-
const stderr = cb.params[2];
|
|
4587
|
-
if (stderr !== undefined && stderr.kind !== "string") {
|
|
4588
|
-
err(`libCall cp.execFile callback stderr parameter must be string`, e.loc);
|
|
4589
|
-
}
|
|
5187
|
+
sdef !== undefined &&
|
|
5188
|
+
sdef.arms.length === 2 &&
|
|
5189
|
+
sdef.arms.some((a) => a.kind === "string") &&
|
|
5190
|
+
sdef.arms.some((a) => a.kind === "nullT");
|
|
4590
5191
|
}
|
|
4591
5192
|
}
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
// supported parameter shapes per event — exit takes (code:
|
|
4595
|
-
// number | null) with an optional (signal: string | null)
|
|
4596
|
-
// second parameter, error exactly (err: %Error).
|
|
4597
|
-
const cb = e.args[1];
|
|
4598
|
-
const cbT = cb?.type;
|
|
4599
|
-
const maxParams = e.fn === "child.onError" ? 1 : 2;
|
|
4600
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4601
|
-
if (ok && cbT?.kind === "func" && cbT.params.length >= 1) {
|
|
4602
|
-
const p = cbT.params[0];
|
|
4603
|
-
if (e.fn === "child.onExit" || e.fn === "child.onClose") {
|
|
4604
|
-
const def = p.kind === "union" ? unions.get(p.unionId) : undefined;
|
|
4605
|
-
ok =
|
|
4606
|
-
def !== undefined &&
|
|
4607
|
-
def.arms.length === 2 &&
|
|
4608
|
-
def.arms[0].kind === "f64" &&
|
|
4609
|
-
def.arms[1].kind === "nullT";
|
|
4610
|
-
if (ok && cbT.params.length === 2) {
|
|
4611
|
-
const s = cbT.params[1];
|
|
4612
|
-
const sdef = s.kind === "union" ? unions.get(s.unionId) : undefined;
|
|
4613
|
-
ok =
|
|
4614
|
-
sdef !== undefined &&
|
|
4615
|
-
sdef.arms.length === 2 &&
|
|
4616
|
-
sdef.arms.some((a) => a.kind === "string") &&
|
|
4617
|
-
sdef.arms.some((a) => a.kind === "nullT");
|
|
4618
|
-
}
|
|
4619
|
-
}
|
|
4620
|
-
else {
|
|
4621
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4622
|
-
}
|
|
4623
|
-
}
|
|
4624
|
-
if (!ok) {
|
|
4625
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4626
|
-
}
|
|
4627
|
-
break;
|
|
4628
|
-
}
|
|
4629
|
-
if (e.fn === "writer.onDrain" || e.fn === "writer.onFinish" || e.fn === "writer.onError") {
|
|
4630
|
-
const cbT = e.args[1]?.type;
|
|
4631
|
-
const maxParams = e.fn === "writer.onError" ? 1 : 0;
|
|
4632
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
4633
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4634
|
-
const p = cbT.params[0];
|
|
4635
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4636
|
-
}
|
|
4637
|
-
if (!ok)
|
|
4638
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4639
|
-
break;
|
|
4640
|
-
}
|
|
4641
|
-
if (e.fn === "process.onExit" || e.fn === "process.offExit" ||
|
|
4642
|
-
e.fn === "stdin.onData" || e.fn === "stdin.onError") {
|
|
4643
|
-
// The listener: a void closure with no params, or exactly the
|
|
4644
|
-
// one supported parameter shape per event (code number / data
|
|
4645
|
-
// chunk bytes / error %Error).
|
|
4646
|
-
const cbT = e.args[0]?.type;
|
|
4647
|
-
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
4648
|
-
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
4649
|
-
const p = cbT.params[0];
|
|
4650
|
-
if (e.fn === "stdin.onData")
|
|
4651
|
-
ok = p.kind === "bytes" && p.elem === "u8";
|
|
4652
|
-
else if (e.fn === "stdin.onError")
|
|
4653
|
-
ok = p.kind === "object" && p.className === "%Error";
|
|
4654
|
-
else
|
|
4655
|
-
ok = p.kind === "f64";
|
|
4656
|
-
}
|
|
4657
|
-
if (!ok) {
|
|
4658
|
-
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
4659
|
-
}
|
|
4660
|
-
break;
|
|
4661
|
-
}
|
|
4662
|
-
if (e.fn === "spawnRes.status") {
|
|
4663
|
-
// Result is the module's interned `number | null` union.
|
|
4664
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4665
|
-
const ok = def &&
|
|
4666
|
-
def.arms.length === 2 &&
|
|
4667
|
-
def.arms[0].kind === "f64" &&
|
|
4668
|
-
def.arms[1].kind === "nullT";
|
|
4669
|
-
if (!ok) {
|
|
4670
|
-
err(`libCall spawnRes.status must return the 'number | null' union`, e.loc);
|
|
4671
|
-
}
|
|
4672
|
-
break;
|
|
5193
|
+
else {
|
|
5194
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
4673
5195
|
}
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
5196
|
+
}
|
|
5197
|
+
if (!ok) {
|
|
5198
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5199
|
+
}
|
|
5200
|
+
return true;
|
|
5201
|
+
}
|
|
5202
|
+
if (e.fn === "writer.onDrain" || e.fn === "writer.onFinish" || e.fn === "writer.onError") {
|
|
5203
|
+
const cbT = e.args[1]?.type;
|
|
5204
|
+
const maxParams = e.fn === "writer.onError" ? 1 : 0;
|
|
5205
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= maxParams;
|
|
5206
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5207
|
+
const p = cbT.params[0];
|
|
5208
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
5209
|
+
}
|
|
5210
|
+
if (!ok)
|
|
5211
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5212
|
+
return true;
|
|
5213
|
+
}
|
|
5214
|
+
if (e.fn === "process.onExit" || e.fn === "process.offExit" ||
|
|
5215
|
+
e.fn === "stdin.onData" || e.fn === "stdin.onError") {
|
|
5216
|
+
// The listener: a void closure with no params, or exactly the
|
|
5217
|
+
// one supported parameter shape per event (code number / data
|
|
5218
|
+
// chunk bytes / error %Error).
|
|
5219
|
+
const cbT = e.args[0]?.type;
|
|
5220
|
+
let ok = cbT?.kind === "func" && cbT.ret.kind === "void" && cbT.params.length <= 1;
|
|
5221
|
+
if (ok && cbT?.kind === "func" && cbT.params.length === 1) {
|
|
5222
|
+
const p = cbT.params[0];
|
|
5223
|
+
if (e.fn === "stdin.onData")
|
|
5224
|
+
ok = p.kind === "bytes" && p.elem === "u8";
|
|
5225
|
+
else if (e.fn === "stdin.onError")
|
|
5226
|
+
ok = p.kind === "object" && p.className === "%Error";
|
|
5227
|
+
else
|
|
5228
|
+
ok = p.kind === "f64";
|
|
5229
|
+
}
|
|
5230
|
+
if (!ok) {
|
|
5231
|
+
err(`libCall ${e.fn} callback shape (frontend must fence)`, e.loc);
|
|
5232
|
+
}
|
|
5233
|
+
return true;
|
|
5234
|
+
}
|
|
5235
|
+
if (e.fn === "spawnRes.status") {
|
|
5236
|
+
// Result is the module's interned `number | null` union.
|
|
5237
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5238
|
+
const ok = def &&
|
|
5239
|
+
def.arms.length === 2 &&
|
|
5240
|
+
def.arms[0].kind === "f64" &&
|
|
5241
|
+
def.arms[1].kind === "nullT";
|
|
5242
|
+
if (!ok) {
|
|
5243
|
+
err(`libCall spawnRes.status must return the 'number | null' union`, e.loc);
|
|
5244
|
+
}
|
|
5245
|
+
return true;
|
|
5246
|
+
}
|
|
5247
|
+
if (e.fn === "spawnRes.signal") {
|
|
5248
|
+
// Result is the module's interned `string | null` union.
|
|
5249
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5250
|
+
const ok = def &&
|
|
5251
|
+
def.arms.length === 2 &&
|
|
5252
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5253
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5254
|
+
if (!ok) {
|
|
5255
|
+
err(`libCall spawnRes.signal must return the 'string | null' union`, e.loc);
|
|
5256
|
+
}
|
|
5257
|
+
return true;
|
|
5258
|
+
}
|
|
5259
|
+
if (e.fn === "sp.get") {
|
|
5260
|
+
// Result is the interned `string | null` union (the runtime
|
|
5261
|
+
// answers +1-or-NULL; the backend builds the arms).
|
|
5262
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5263
|
+
const ok = def &&
|
|
5264
|
+
def.arms.length === 2 &&
|
|
5265
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5266
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5267
|
+
if (!ok) {
|
|
5268
|
+
err(`libCall sp.get must return the 'string | null' union`, e.loc);
|
|
5269
|
+
}
|
|
5270
|
+
return true;
|
|
5271
|
+
}
|
|
5272
|
+
if (e.fn === "sp.fromPairs") {
|
|
5273
|
+
const t = e.args[0]?.type;
|
|
5274
|
+
const ok = t && t.kind === "array" && t.elem.kind === "array" && t.elem.elem.kind === "string";
|
|
5275
|
+
if (!ok) {
|
|
5276
|
+
err(`libCall sp.fromPairs arg 0: expected string[][], got ${t?.kind}`, e.loc);
|
|
5277
|
+
}
|
|
5278
|
+
return true;
|
|
5279
|
+
}
|
|
5280
|
+
if (e.fn === "sym.desc" || e.fn === "sym.keyFor") {
|
|
5281
|
+
// Result is the interned `string | undefined` union (the
|
|
5282
|
+
// runtime answers +1-or-NULL; the backend builds the arms).
|
|
5283
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5284
|
+
const ok = def &&
|
|
5285
|
+
def.arms.length === 2 &&
|
|
5286
|
+
def.arms.some((a) => a.kind === "string") &&
|
|
5287
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5288
|
+
if (!ok) {
|
|
5289
|
+
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
5290
|
+
}
|
|
5291
|
+
return true;
|
|
5292
|
+
}
|
|
5293
|
+
if (e.fn === "spawnRes.error") {
|
|
5294
|
+
// Result is the interned `%Error | undefined` union.
|
|
5295
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5296
|
+
const ok = def &&
|
|
5297
|
+
def.arms.length === 2 &&
|
|
5298
|
+
def.arms.some((a) => a.kind === "object" && a.className === "%Error") &&
|
|
5299
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5300
|
+
if (!ok) {
|
|
5301
|
+
err(`libCall spawnRes.error must return the 'Error | undefined' union`, e.loc);
|
|
5302
|
+
}
|
|
5303
|
+
return true;
|
|
5304
|
+
}
|
|
5305
|
+
if (e.fn === "child.pid" || e.fn === "child.exitCode") {
|
|
5306
|
+
// pid: the interned `number | undefined`; exitCode: `number | null`.
|
|
5307
|
+
const wantUnit = e.fn === "child.pid" ? "undefinedT" : "nullT";
|
|
5308
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5309
|
+
const ok = def &&
|
|
5310
|
+
def.arms.length === 2 &&
|
|
5311
|
+
def.arms[0].kind === "f64" &&
|
|
5312
|
+
def.arms[1].kind === wantUnit;
|
|
5313
|
+
if (!ok) {
|
|
5314
|
+
err(`libCall ${e.fn} must return the 'number | ${wantUnit === "nullT" ? "null" : "undefined"}' union`, e.loc);
|
|
5315
|
+
}
|
|
5316
|
+
return true;
|
|
5317
|
+
}
|
|
5318
|
+
if (e.fn === "net.serverCloseBind") {
|
|
5319
|
+
// The bound close: (cbUnion) => netServer, cbUnion carrying a
|
|
5320
|
+
// void-returning func arm (≤1 param) and the undefined arm.
|
|
5321
|
+
const t = e.type;
|
|
5322
|
+
const cbU = t.kind === "func" && t.params.length === 1 ? t.params[0] : null;
|
|
5323
|
+
const def = cbU?.kind === "union" ? unions.get(cbU.unionId) : undefined;
|
|
5324
|
+
const ok = t.kind === "func" && (t.ret.kind === "netServer" || t.ret.kind === "void") &&
|
|
5325
|
+
def &&
|
|
5326
|
+
def.arms.some((a) => a.kind === "func" && a.params.length <= 1 && a.ret.kind === "void") &&
|
|
5327
|
+
def.arms.some((a) => a.kind === "undefinedT");
|
|
5328
|
+
if (!ok) {
|
|
5329
|
+
err(`libCall net.serverCloseBind must produce the bound-close func type`, e.loc);
|
|
5330
|
+
}
|
|
5331
|
+
return true;
|
|
5332
|
+
}
|
|
5333
|
+
if (e.fn === "child.stdin" || e.fn === "child.stdout" || e.fn === "child.stderr") {
|
|
5334
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5335
|
+
const handleKind = e.fn === "child.stdin" ? "childWriter" : "childStream";
|
|
5336
|
+
const ok = def &&
|
|
5337
|
+
def.arms.length === 2 &&
|
|
5338
|
+
def.arms.some((a) => a.kind === handleKind) &&
|
|
5339
|
+
def.arms.some((a) => a.kind === "nullT");
|
|
5340
|
+
if (!ok) {
|
|
5341
|
+
err(`libCall ${e.fn} must return the '${e.fn === "child.stdin" ? "Writable" : "Readable"} | null' union`, e.loc);
|
|
5342
|
+
}
|
|
5343
|
+
return true;
|
|
5344
|
+
}
|
|
5345
|
+
return false;
|
|
5346
|
+
}
|
|
5347
|
+
function checkLibSpecialCall(e) {
|
|
5348
|
+
if (e.fn === "island.castFail") {
|
|
5349
|
+
// The deferred boundary failure's typed dummy: a promise (the
|
|
5350
|
+
// only cast shape the frontend defers).
|
|
5351
|
+
if (e.type.kind !== "promise") {
|
|
5352
|
+
err(`libCall island.castFail must return a promise type, got ${e.type.kind}`, e.loc);
|
|
5353
|
+
}
|
|
5354
|
+
return true;
|
|
5355
|
+
}
|
|
5356
|
+
if (e.fn === "global.undefRead") {
|
|
5357
|
+
// Always throws — the result type is whatever the declared type
|
|
5358
|
+
// of the undefined global mapped to (never materialized).
|
|
5359
|
+
return true;
|
|
5360
|
+
}
|
|
5361
|
+
if (e.fn === "error.nodeThrow" || e.fn === "error.argTypeThrow" || e.fn === "error.propTypeThrow" ||
|
|
5362
|
+
e.fn === "fs.mkdtempChk" || e.fn === "fs.readFileChk" ||
|
|
5363
|
+
e.fn === "fs.opendirChk" || e.fn === "fs.watchFileChk" || e.fn === "fs.lchmodChk" ||
|
|
5364
|
+
e.fn === "fs.readChk" || e.fn === "fs.streamOptsChk" || e.fn === "net.connectOptsChk" ||
|
|
5365
|
+
e.fn === "tls.caCertsChk") {
|
|
5366
|
+
// Always throws — the result type is the replaced expression's
|
|
5367
|
+
// own (never materialized; the global.undefRead pattern). The
|
|
5368
|
+
// fs Chk ladders qualify: every validation failure throws
|
|
5369
|
+
// Node's typed error, and a full pass throws the trailing
|
|
5370
|
+
// compiler-rendered fence.
|
|
5371
|
+
return true;
|
|
5372
|
+
}
|
|
5373
|
+
if (e.fn === "error.new" || e.fn === "error.newOptions") {
|
|
5374
|
+
// Which builtin the runtime constructs is named by the result type.
|
|
5375
|
+
if (!isBuiltinErrorObject(e.type)) {
|
|
5376
|
+
err(`libCall ${e.fn} must return a builtin error class, got ${e.type.kind}`, e.loc);
|
|
5377
|
+
}
|
|
5378
|
+
return true;
|
|
5379
|
+
}
|
|
5380
|
+
if (e.fn === "error.newDom") {
|
|
5381
|
+
if (e.type.kind !== "object" || e.type.className !== "%DOMException") {
|
|
5382
|
+
err(`libCall error.newDom must return %DOMException, got ${e.type.kind}`, e.loc);
|
|
5383
|
+
}
|
|
5384
|
+
return true;
|
|
5385
|
+
}
|
|
5386
|
+
if (e.fn === "error.domCode" || e.fn === "error.domHasCause" || e.fn === "error.domCause" || e.fn === "error.domClone") {
|
|
5387
|
+
// Receiver: exactly %DOMException (subclassing is fenced — the
|
|
5388
|
+
// hidden runtime slots admit no other layout).
|
|
5389
|
+
const recv = e.args[0];
|
|
5390
|
+
if (!recv || recv.type.kind !== "object" || recv.type.className !== "%DOMException") {
|
|
5391
|
+
err(`libCall ${e.fn} receiver must be %DOMException`, e.loc);
|
|
5392
|
+
}
|
|
5393
|
+
return true;
|
|
5394
|
+
}
|
|
5395
|
+
if (e.fn === "class.name") {
|
|
5396
|
+
// The arg is any class value (program-dependent classval).
|
|
5397
|
+
if (e.args[0]?.type.kind !== "classval") {
|
|
5398
|
+
err(`libCall class.name takes a class value`, e.loc);
|
|
5399
|
+
}
|
|
5400
|
+
if (e.type.kind !== "string") {
|
|
5401
|
+
err(`libCall class.name must return string`, e.loc);
|
|
5402
|
+
}
|
|
5403
|
+
return true;
|
|
5404
|
+
}
|
|
5405
|
+
if (e.fn === "assert.refEqBytes" || e.fn === "assert.bytesDeepEq") {
|
|
5406
|
+
// Both value slots: ONE static bytes type (the frontend's
|
|
5407
|
+
// same-static-type gate — a u8/u32 mix would memcmp garbage).
|
|
5408
|
+
const a = e.args[0]?.type;
|
|
5409
|
+
const b = e.args[1]?.type;
|
|
5410
|
+
if (a?.kind !== "bytes" || b === undefined || !typeEquals(a, b)) {
|
|
5411
|
+
err(`libCall ${e.fn} takes two same-typed bytes values`, e.loc);
|
|
5412
|
+
}
|
|
5413
|
+
return true;
|
|
5414
|
+
}
|
|
5415
|
+
if (e.fn === "assert.refEqFn") {
|
|
5416
|
+
// ANY two function signatures: the compare is pointer identity.
|
|
5417
|
+
if (e.args[0]?.type.kind !== "func" || e.args[1]?.type.kind !== "func") {
|
|
5418
|
+
err(`libCall assert.refEqFn takes two function values`, e.loc);
|
|
5419
|
+
}
|
|
5420
|
+
return true;
|
|
5421
|
+
}
|
|
5422
|
+
if (e.fn === "error.code") {
|
|
5423
|
+
// Receiver: any error-hierarchy object (a user subclass embeds
|
|
5424
|
+
// the code slot in its prefix); result: the interned
|
|
5425
|
+
// `string | undefined` union (the process.envGet pattern).
|
|
5426
|
+
const recv = e.args[0];
|
|
5427
|
+
if (!recv || recv.type.kind !== "object") {
|
|
5428
|
+
err(`libCall error.code receiver must be an error object`, e.loc);
|
|
5429
|
+
return true;
|
|
5430
|
+
}
|
|
5431
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5432
|
+
const ok = def &&
|
|
5433
|
+
def.arms.length === 2 &&
|
|
5434
|
+
def.arms[0].kind === "string" &&
|
|
5435
|
+
def.arms[1].kind === "undefinedT";
|
|
5436
|
+
if (!ok) {
|
|
5437
|
+
err(`libCall error.code must return the 'string | undefined' union`, e.loc);
|
|
5438
|
+
}
|
|
5439
|
+
return true;
|
|
5440
|
+
}
|
|
5441
|
+
return false;
|
|
5442
|
+
}
|
|
5443
|
+
function checkLibStreamCall(e, fixedArgs, result) {
|
|
5444
|
+
if (e.fn.startsWith("readable.") || e.fn.startsWith("writable.") ||
|
|
5445
|
+
e.fn.startsWith("duplex.") || e.fn.startsWith("transform.") ||
|
|
5446
|
+
e.fn.startsWith("passthrough.") || e.fn === "stream.destroy" ||
|
|
5447
|
+
e.fn === "stream.destroyErr" || e.fn === "stream.iteratorClose" || e.fn === "stream.prop" ||
|
|
5448
|
+
e.fn === "stream.errored" || e.fn === "stream.finished" ||
|
|
5449
|
+
e.fn === "stream.finishedDyn" || e.fn === "stream.pipeline" ||
|
|
5450
|
+
e.fn === "stream.pipelineDyn") {
|
|
5451
|
+
// Receiver/result: stream-hierarchy objects (a class whose base
|
|
5452
|
+
// chain reaches a runtime stream class). Constructors have no
|
|
5453
|
+
// receiver — their RESULT names the class; chaining forms
|
|
5454
|
+
// return the receiver's static type; pipe returns its
|
|
5455
|
+
// destination's.
|
|
5456
|
+
const isStreamObject = (t) => {
|
|
5457
|
+
if (t?.kind !== "object")
|
|
5458
|
+
return false;
|
|
5459
|
+
let name = t.className;
|
|
5460
|
+
while (name !== undefined) {
|
|
5461
|
+
if (RUNTIME_STREAM_CLASSES.has(name))
|
|
5462
|
+
return true;
|
|
5463
|
+
name = classes.get(name)?.base;
|
|
5464
|
+
}
|
|
5465
|
+
return false;
|
|
5466
|
+
};
|
|
5467
|
+
if (e.fn.endsWith(".new")) {
|
|
5468
|
+
if (!isStreamObject(e.type)) {
|
|
5469
|
+
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
5470
|
+
}
|
|
5471
|
+
for (let i = fixedArgs; i < e.args.length; i++) {
|
|
5472
|
+
if (e.args[i].type.kind !== "func") {
|
|
5473
|
+
err(`libCall ${e.fn} option callback ${i} must be a func`, e.loc);
|
|
4683
5474
|
}
|
|
4684
|
-
break;
|
|
4685
5475
|
}
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4693
|
-
def.arms.some((a) => a.kind === "nullT");
|
|
4694
|
-
if (!ok) {
|
|
4695
|
-
err(`libCall sp.get must return the 'string | null' union`, e.loc);
|
|
4696
|
-
}
|
|
4697
|
-
break;
|
|
5476
|
+
return true;
|
|
5477
|
+
}
|
|
5478
|
+
if (e.fn.endsWith(".newDyn")) {
|
|
5479
|
+
// The dyn-options constructor: (optsDyn) → the stream class.
|
|
5480
|
+
if (!isStreamObject(e.type)) {
|
|
5481
|
+
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4698
5482
|
}
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
}
|
|
4705
|
-
break;
|
|
5483
|
+
return true;
|
|
5484
|
+
}
|
|
5485
|
+
if (e.fn.endsWith(".initDyn")) {
|
|
5486
|
+
// (recv, optsDyn, flags, ...fallback wrapper closures).
|
|
5487
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5488
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4706
5489
|
}
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4711
|
-
const ok = def &&
|
|
4712
|
-
def.arms.length === 2 &&
|
|
4713
|
-
def.arms.some((a) => a.kind === "string") &&
|
|
4714
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4715
|
-
if (!ok) {
|
|
4716
|
-
err(`libCall ${e.fn} must return the 'string | undefined' union`, e.loc);
|
|
5490
|
+
for (let i = fixedArgs; i < e.args.length; i++) {
|
|
5491
|
+
if (e.args[i].type.kind !== "func") {
|
|
5492
|
+
err(`libCall ${e.fn} fallback callback ${i} must be a func`, e.loc);
|
|
4717
5493
|
}
|
|
4718
|
-
break;
|
|
4719
5494
|
}
|
|
4720
|
-
if (e.
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
err(`libCall spawnRes.error must return the 'Error | undefined' union`, e.loc);
|
|
4729
|
-
}
|
|
4730
|
-
break;
|
|
5495
|
+
if (e.type.kind !== "void")
|
|
5496
|
+
err(`libCall ${e.fn} must be void`, e.loc);
|
|
5497
|
+
return true;
|
|
5498
|
+
}
|
|
5499
|
+
if (e.fn === "stream.finished" || e.fn === "stream.finishedDyn") {
|
|
5500
|
+
// (recv, cb) → the cleanup closure.
|
|
5501
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5502
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4731
5503
|
}
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4736
|
-
const ok = def &&
|
|
4737
|
-
def.arms.length === 2 &&
|
|
4738
|
-
def.arms[0].kind === "f64" &&
|
|
4739
|
-
def.arms[1].kind === wantUnit;
|
|
4740
|
-
if (!ok) {
|
|
4741
|
-
err(`libCall ${e.fn} must return the 'number | ${wantUnit === "nullT" ? "null" : "undefined"}' union`, e.loc);
|
|
4742
|
-
}
|
|
4743
|
-
break;
|
|
5504
|
+
const cbK = e.args[1]?.type.kind;
|
|
5505
|
+
if (e.fn === "stream.finished" ? cbK !== "func" : cbK !== "dyn") {
|
|
5506
|
+
err(`libCall ${e.fn} callback must be ${e.fn === "stream.finished" ? "a func" : "dyn"}`, e.loc);
|
|
4744
5507
|
}
|
|
4745
|
-
if (e.
|
|
4746
|
-
|
|
4747
|
-
// void-returning func arm (≤1 param) and the undefined arm.
|
|
4748
|
-
const t = e.type;
|
|
4749
|
-
const cbU = t.kind === "func" && t.params.length === 1 ? t.params[0] : null;
|
|
4750
|
-
const def = cbU?.kind === "union" ? unions.get(cbU.unionId) : undefined;
|
|
4751
|
-
const ok = t.kind === "func" && (t.ret.kind === "netServer" || t.ret.kind === "void") &&
|
|
4752
|
-
def &&
|
|
4753
|
-
def.arms.some((a) => a.kind === "func" && a.params.length <= 1 && a.ret.kind === "void") &&
|
|
4754
|
-
def.arms.some((a) => a.kind === "undefinedT");
|
|
4755
|
-
if (!ok) {
|
|
4756
|
-
err(`libCall net.serverCloseBind must produce the bound-close func type`, e.loc);
|
|
4757
|
-
}
|
|
4758
|
-
break;
|
|
5508
|
+
if (e.type.kind !== "func") {
|
|
5509
|
+
err(`libCall ${e.fn} must return the cleanup closure, got ${e.type.kind}`, e.loc);
|
|
4759
5510
|
}
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
}
|
|
4770
|
-
break;
|
|
5511
|
+
return true;
|
|
5512
|
+
}
|
|
5513
|
+
if (e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn") {
|
|
5514
|
+
// (count, s1..sn, cb) → the destination's type.
|
|
5515
|
+
const count = e.args[0];
|
|
5516
|
+
const n = count?.kind === "numLit" ? count.value : -1;
|
|
5517
|
+
if (n < 2 || e.args.length !== n + 2) {
|
|
5518
|
+
err(`libCall ${e.fn} count/arity mismatch`, e.loc);
|
|
5519
|
+
return true;
|
|
4771
5520
|
}
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
if (e.type.kind !== "promise") {
|
|
4776
|
-
err(`libCall island.castFail must return a promise type, got ${e.type.kind}`, e.loc);
|
|
5521
|
+
for (let i = 1; i <= n; i++) {
|
|
5522
|
+
if (!isStreamObject(e.args[i]?.type)) {
|
|
5523
|
+
err(`libCall ${e.fn} stage ${i} must be a stream-hierarchy object`, e.loc);
|
|
4777
5524
|
}
|
|
4778
|
-
break;
|
|
4779
5525
|
}
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
break;
|
|
5526
|
+
const cbK = e.args[n + 1]?.type.kind;
|
|
5527
|
+
if (e.fn === "stream.pipeline" ? cbK !== "func" : cbK !== "dyn") {
|
|
5528
|
+
err(`libCall ${e.fn} callback must be ${e.fn === "stream.pipeline" ? "a func" : "dyn"}`, e.loc);
|
|
4784
5529
|
}
|
|
4785
|
-
if (e.
|
|
4786
|
-
e.fn
|
|
4787
|
-
e.fn === "fs.opendirChk" || e.fn === "fs.watchFileChk" || e.fn === "fs.lchmodChk" ||
|
|
4788
|
-
e.fn === "fs.readChk" || e.fn === "fs.streamOptsChk" || e.fn === "net.connectOptsChk" ||
|
|
4789
|
-
e.fn === "tls.caCertsChk") {
|
|
4790
|
-
// Always throws — the result type is the replaced expression's
|
|
4791
|
-
// own (never materialized; the global.undefRead pattern). The
|
|
4792
|
-
// fs Chk ladders qualify: every validation failure throws
|
|
4793
|
-
// Node's typed error, and a full pass throws the trailing
|
|
4794
|
-
// compiler-rendered fence.
|
|
4795
|
-
break;
|
|
5530
|
+
if (!typeEquals(e.type, e.args[n].type)) {
|
|
5531
|
+
err(`libCall ${e.fn} must return its destination's type`, e.loc);
|
|
4796
5532
|
}
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
5533
|
+
return true;
|
|
5534
|
+
}
|
|
5535
|
+
if (e.fn === "readable.fromArr") {
|
|
5536
|
+
// No receiver: the seed array leads; the result is the class.
|
|
5537
|
+
if (e.args[0]?.type.kind !== "array" || !isStreamObject(e.type)) {
|
|
5538
|
+
err(`libCall readable.fromArr must take an array and return a stream class`, e.loc);
|
|
4803
5539
|
}
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
5540
|
+
return true;
|
|
5541
|
+
}
|
|
5542
|
+
if (!isStreamObject(e.args[0]?.type)) {
|
|
5543
|
+
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
5544
|
+
return true;
|
|
5545
|
+
}
|
|
5546
|
+
if (e.fn === "readable.nextChunk" || e.fn === "readable.nextChunkDyn") {
|
|
5547
|
+
if (e.type.kind !== "promise") {
|
|
5548
|
+
err(`libCall ${e.fn} must return a promise, got ${e.type.kind}`, e.loc);
|
|
4809
5549
|
}
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
5550
|
+
return true;
|
|
5551
|
+
}
|
|
5552
|
+
if (e.fn === "readable.pause" || e.fn === "readable.resume" ||
|
|
5553
|
+
e.fn === "readable.unpipe" || e.fn === "writable.end" ||
|
|
5554
|
+
e.fn === "readable.setEncoding" || e.fn === "readable.pushEncoding" ||
|
|
5555
|
+
e.fn === "stream.destroy" || e.fn === "stream.destroyErr" ||
|
|
5556
|
+
e.fn === "stream.iteratorClose") {
|
|
5557
|
+
if (!typeEquals(e.type, e.args[0].type)) {
|
|
5558
|
+
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
4818
5559
|
}
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
if (e.type.kind !== "string") {
|
|
4825
|
-
err(`libCall class.name must return string`, e.loc);
|
|
4826
|
-
}
|
|
4827
|
-
break;
|
|
5560
|
+
return true;
|
|
5561
|
+
}
|
|
5562
|
+
if (e.fn === "readable.pipe") {
|
|
5563
|
+
if (!isStreamObject(e.args[1]?.type) || !typeEquals(e.type, e.args[1].type)) {
|
|
5564
|
+
err(`libCall readable.pipe must return its destination's type`, e.loc);
|
|
4828
5565
|
}
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
5566
|
+
return true;
|
|
5567
|
+
}
|
|
5568
|
+
if (e.fn === "readable.read" || e.fn === "readable.flowing" || e.fn === "stream.errored") {
|
|
5569
|
+
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
5570
|
+
const wantArm = (t) => e.fn === "readable.read" ? t.kind === "bytes" :
|
|
5571
|
+
e.fn === "readable.flowing" ? t.kind === "bool" :
|
|
5572
|
+
t.kind === "object";
|
|
5573
|
+
const ok = def && def.arms.length === 2 &&
|
|
5574
|
+
def.arms.some(wantArm) && def.arms.some((a) => a.kind === "nullT");
|
|
5575
|
+
if (!ok)
|
|
5576
|
+
err(`libCall ${e.fn} must return its nullable union`, e.loc);
|
|
5577
|
+
return true;
|
|
5578
|
+
}
|
|
5579
|
+
if (e.fn === "stream.prop") {
|
|
5580
|
+
if (e.type.kind !== "bool" && e.type.kind !== "f64") {
|
|
5581
|
+
err(`libCall stream.prop must be bool or f64, got ${e.type.kind}`, e.loc);
|
|
4838
5582
|
}
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
5583
|
+
return true;
|
|
5584
|
+
}
|
|
5585
|
+
if (!typeEquals(e.type, result)) {
|
|
5586
|
+
err(`libCall ${e.fn} must be ${result.kind}, got ${e.type.kind}`, e.loc);
|
|
5587
|
+
}
|
|
5588
|
+
return true;
|
|
5589
|
+
}
|
|
5590
|
+
return false;
|
|
5591
|
+
}
|
|
5592
|
+
function checkLibEmitterCall(e, result) {
|
|
5593
|
+
if (e.fn.startsWith("emitter.") && e.fn !== "emitter.setDefaultMax" &&
|
|
5594
|
+
e.fn !== "emitter.setDefaultMaxChk" &&
|
|
5595
|
+
e.fn !== "emitter.getDefaultMax" && e.fn !== "emitter.checkListener") {
|
|
5596
|
+
// Receiver: an emitter-hierarchy object (the %EventEmitter class
|
|
5597
|
+
// itself, or a class whose base chain reaches it). emitter.new
|
|
5598
|
+
// has no receiver — its RESULT is the bare emitter class.
|
|
5599
|
+
const isEmitterObject = (t) => {
|
|
5600
|
+
if (t?.kind !== "object")
|
|
5601
|
+
return false;
|
|
5602
|
+
let name = t.className;
|
|
5603
|
+
while (name !== undefined) {
|
|
5604
|
+
if (name === RUNTIME_EMITTER_CLASS)
|
|
5605
|
+
return true;
|
|
5606
|
+
name = classes.get(name)?.base;
|
|
5607
|
+
}
|
|
5608
|
+
return false;
|
|
5609
|
+
};
|
|
5610
|
+
if (e.fn === "emitter.new") {
|
|
5611
|
+
if (e.type.kind !== "object" || e.type.className !== RUNTIME_EMITTER_CLASS) {
|
|
5612
|
+
err(`libCall emitter.new must return '%EventEmitter', got ${e.type.kind}`, e.loc);
|
|
4845
5613
|
}
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
if (!ok) {
|
|
4861
|
-
err(`libCall error.code must return the 'string | undefined' union`, e.loc);
|
|
4862
|
-
}
|
|
4863
|
-
break;
|
|
5614
|
+
return true;
|
|
5615
|
+
}
|
|
5616
|
+
if (!isEmitterObject(e.args[0]?.type)) {
|
|
5617
|
+
err(`libCall ${e.fn} receiver must be an emitter-hierarchy object`, e.loc);
|
|
5618
|
+
return true;
|
|
5619
|
+
}
|
|
5620
|
+
// The chaining forms return the receiver's own static class.
|
|
5621
|
+
if (e.fn === "emitter.on" || e.fn === "emitter.off" ||
|
|
5622
|
+
e.fn === "emitter.onDyn" || e.fn === "emitter.onFlex" || e.fn === "emitter.offDyn" ||
|
|
5623
|
+
e.fn === "emitter.onData" || e.fn === "emitter.onDataDyn" ||
|
|
5624
|
+
e.fn === "emitter.removeAll" || e.fn === "emitter.setMax" ||
|
|
5625
|
+
e.fn === "emitter.setMaxChk") {
|
|
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);
|
|
4864
5628
|
}
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
e.fn
|
|
4869
|
-
e.fn === "stream.errored" || e.fn === "stream.finished" ||
|
|
4870
|
-
e.fn === "stream.finishedDyn" || e.fn === "stream.pipeline" ||
|
|
4871
|
-
e.fn === "stream.pipelineDyn") {
|
|
4872
|
-
// Receiver/result: stream-hierarchy objects (a class whose base
|
|
4873
|
-
// chain reaches a runtime stream class). Constructors have no
|
|
4874
|
-
// receiver — their RESULT names the class; chaining forms
|
|
4875
|
-
// return the receiver's static type; pipe returns its
|
|
4876
|
-
// destination's.
|
|
4877
|
-
const isStreamObject = (t) => {
|
|
4878
|
-
if (t?.kind !== "object")
|
|
4879
|
-
return false;
|
|
4880
|
-
let name = t.className;
|
|
4881
|
-
while (name !== undefined) {
|
|
4882
|
-
if (RUNTIME_STREAM_CLASSES.has(name))
|
|
4883
|
-
return true;
|
|
4884
|
-
name = classes.get(name)?.base;
|
|
4885
|
-
}
|
|
4886
|
-
return false;
|
|
4887
|
-
};
|
|
4888
|
-
if (e.fn.endsWith(".new")) {
|
|
4889
|
-
if (!isStreamObject(e.type)) {
|
|
4890
|
-
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4891
|
-
}
|
|
4892
|
-
for (let i = sig.argTypes.length; i < e.args.length; i++) {
|
|
4893
|
-
if (e.args[i].type.kind !== "func") {
|
|
4894
|
-
err(`libCall ${e.fn} option callback ${i} must be a func`, e.loc);
|
|
4895
|
-
}
|
|
4896
|
-
}
|
|
4897
|
-
break;
|
|
4898
|
-
}
|
|
4899
|
-
if (e.fn.endsWith(".newDyn")) {
|
|
4900
|
-
// The dyn-options constructor: (optsDyn) → the stream class.
|
|
4901
|
-
if (!isStreamObject(e.type)) {
|
|
4902
|
-
err(`libCall ${e.fn} must return a stream class, got ${e.type.kind}`, e.loc);
|
|
4903
|
-
}
|
|
4904
|
-
break;
|
|
4905
|
-
}
|
|
4906
|
-
if (e.fn.endsWith(".initDyn")) {
|
|
4907
|
-
// (recv, optsDyn, flags, ...fallback wrapper closures).
|
|
4908
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4909
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4910
|
-
}
|
|
4911
|
-
for (let i = sig.argTypes.length; i < e.args.length; i++) {
|
|
4912
|
-
if (e.args[i].type.kind !== "func") {
|
|
4913
|
-
err(`libCall ${e.fn} fallback callback ${i} must be a func`, e.loc);
|
|
4914
|
-
}
|
|
4915
|
-
}
|
|
4916
|
-
if (e.type.kind !== "void")
|
|
4917
|
-
err(`libCall ${e.fn} must be void`, e.loc);
|
|
4918
|
-
break;
|
|
4919
|
-
}
|
|
4920
|
-
if (e.fn === "stream.finished" || e.fn === "stream.finishedDyn") {
|
|
4921
|
-
// (recv, cb) → the cleanup closure.
|
|
4922
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4923
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4924
|
-
}
|
|
4925
|
-
const cbK = e.args[1]?.type.kind;
|
|
4926
|
-
if (e.fn === "stream.finished" ? cbK !== "func" : cbK !== "dyn") {
|
|
4927
|
-
err(`libCall ${e.fn} callback must be ${e.fn === "stream.finished" ? "a func" : "dyn"}`, e.loc);
|
|
4928
|
-
}
|
|
4929
|
-
if (e.type.kind !== "func") {
|
|
4930
|
-
err(`libCall ${e.fn} must return the cleanup closure, got ${e.type.kind}`, e.loc);
|
|
4931
|
-
}
|
|
4932
|
-
break;
|
|
4933
|
-
}
|
|
4934
|
-
if (e.fn === "stream.pipeline" || e.fn === "stream.pipelineDyn") {
|
|
4935
|
-
// (count, s1..sn, cb) → the destination's type.
|
|
4936
|
-
const count = e.args[0];
|
|
4937
|
-
const n = count?.kind === "numLit" ? count.value : -1;
|
|
4938
|
-
if (n < 2 || e.args.length !== n + 2) {
|
|
4939
|
-
err(`libCall ${e.fn} count/arity mismatch`, e.loc);
|
|
4940
|
-
break;
|
|
4941
|
-
}
|
|
4942
|
-
for (let i = 1; i <= n; i++) {
|
|
4943
|
-
if (!isStreamObject(e.args[i]?.type)) {
|
|
4944
|
-
err(`libCall ${e.fn} stage ${i} must be a stream-hierarchy object`, e.loc);
|
|
4945
|
-
}
|
|
4946
|
-
}
|
|
4947
|
-
const cbK = e.args[n + 1]?.type.kind;
|
|
4948
|
-
if (e.fn === "stream.pipeline" ? cbK !== "func" : cbK !== "dyn") {
|
|
4949
|
-
err(`libCall ${e.fn} callback must be ${e.fn === "stream.pipeline" ? "a func" : "dyn"}`, e.loc);
|
|
4950
|
-
}
|
|
4951
|
-
if (!typeEquals(e.type, e.args[n].type)) {
|
|
4952
|
-
err(`libCall ${e.fn} must return its destination's type`, e.loc);
|
|
4953
|
-
}
|
|
4954
|
-
break;
|
|
4955
|
-
}
|
|
4956
|
-
if (e.fn === "readable.fromArr") {
|
|
4957
|
-
// No receiver: the seed array leads; the result is the class.
|
|
4958
|
-
if (e.args[0]?.type.kind !== "array" || !isStreamObject(e.type)) {
|
|
4959
|
-
err(`libCall readable.fromArr must take an array and return a stream class`, e.loc);
|
|
4960
|
-
}
|
|
4961
|
-
break;
|
|
4962
|
-
}
|
|
4963
|
-
if (!isStreamObject(e.args[0]?.type)) {
|
|
4964
|
-
err(`libCall ${e.fn} receiver must be a stream-hierarchy object`, e.loc);
|
|
4965
|
-
break;
|
|
4966
|
-
}
|
|
4967
|
-
if (e.fn === "readable.nextChunk" || e.fn === "readable.nextChunkDyn") {
|
|
4968
|
-
if (e.type.kind !== "promise") {
|
|
4969
|
-
err(`libCall ${e.fn} must return a promise, got ${e.type.kind}`, e.loc);
|
|
4970
|
-
}
|
|
4971
|
-
break;
|
|
4972
|
-
}
|
|
4973
|
-
if (e.fn === "readable.pause" || e.fn === "readable.resume" ||
|
|
4974
|
-
e.fn === "readable.unpipe" || e.fn === "writable.end" ||
|
|
4975
|
-
e.fn === "readable.setEncoding" || e.fn === "readable.pushEncoding" ||
|
|
4976
|
-
e.fn === "stream.destroy" || e.fn === "stream.destroyErr" ||
|
|
4977
|
-
e.fn === "stream.iteratorClose") {
|
|
4978
|
-
if (!typeEquals(e.type, e.args[0].type)) {
|
|
4979
|
-
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
4980
|
-
}
|
|
4981
|
-
break;
|
|
4982
|
-
}
|
|
4983
|
-
if (e.fn === "readable.pipe") {
|
|
4984
|
-
if (!isStreamObject(e.args[1]?.type) || !typeEquals(e.type, e.args[1].type)) {
|
|
4985
|
-
err(`libCall readable.pipe must return its destination's type`, e.loc);
|
|
4986
|
-
}
|
|
4987
|
-
break;
|
|
4988
|
-
}
|
|
4989
|
-
if (e.fn === "readable.read" || e.fn === "readable.flowing" || e.fn === "stream.errored") {
|
|
4990
|
-
const def = e.type.kind === "union" ? unions.get(e.type.unionId) : undefined;
|
|
4991
|
-
const wantArm = (t) => e.fn === "readable.read" ? t.kind === "bytes" :
|
|
4992
|
-
e.fn === "readable.flowing" ? t.kind === "bool" :
|
|
4993
|
-
t.kind === "object";
|
|
4994
|
-
const ok = def && def.arms.length === 2 &&
|
|
4995
|
-
def.arms.some(wantArm) && def.arms.some((a) => a.kind === "nullT");
|
|
4996
|
-
if (!ok)
|
|
4997
|
-
err(`libCall ${e.fn} must return its nullable union`, e.loc);
|
|
4998
|
-
break;
|
|
4999
|
-
}
|
|
5000
|
-
if (e.fn === "stream.prop") {
|
|
5001
|
-
if (e.type.kind !== "bool" && e.type.kind !== "f64") {
|
|
5002
|
-
err(`libCall stream.prop must be bool or f64, got ${e.type.kind}`, e.loc);
|
|
5003
|
-
}
|
|
5004
|
-
break;
|
|
5005
|
-
}
|
|
5006
|
-
if (!typeEquals(e.type, sig.result)) {
|
|
5007
|
-
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
5008
|
-
}
|
|
5009
|
-
break;
|
|
5629
|
+
// The listener slots carry closures (the dyn family's checked-
|
|
5630
|
+
// dynamic listener is table-checked; its adapter is a func).
|
|
5631
|
+
if ((e.fn === "emitter.on" || e.fn === "emitter.off" || e.fn === "emitter.onData") && e.args[2]?.type.kind !== "func") {
|
|
5632
|
+
err(`libCall ${e.fn} listener must be a func`, e.loc);
|
|
5010
5633
|
}
|
|
5011
|
-
if (e.fn.
|
|
5012
|
-
e.fn
|
|
5013
|
-
e.fn !== "emitter.getDefaultMax" && e.fn !== "emitter.checkListener") {
|
|
5014
|
-
// Receiver: an emitter-hierarchy object (the %EventEmitter class
|
|
5015
|
-
// itself, or a class whose base chain reaches it). emitter.new
|
|
5016
|
-
// has no receiver — its RESULT is the bare emitter class.
|
|
5017
|
-
const isEmitterObject = (t) => {
|
|
5018
|
-
if (t?.kind !== "object")
|
|
5019
|
-
return false;
|
|
5020
|
-
let name = t.className;
|
|
5021
|
-
while (name !== undefined) {
|
|
5022
|
-
if (name === RUNTIME_EMITTER_CLASS)
|
|
5023
|
-
return true;
|
|
5024
|
-
name = classes.get(name)?.base;
|
|
5025
|
-
}
|
|
5026
|
-
return false;
|
|
5027
|
-
};
|
|
5028
|
-
if (e.fn === "emitter.new") {
|
|
5029
|
-
if (e.type.kind !== "object" || e.type.className !== RUNTIME_EMITTER_CLASS) {
|
|
5030
|
-
err(`libCall emitter.new must return '%EventEmitter', got ${e.type.kind}`, e.loc);
|
|
5031
|
-
}
|
|
5032
|
-
break;
|
|
5033
|
-
}
|
|
5034
|
-
if (!isEmitterObject(e.args[0]?.type)) {
|
|
5035
|
-
err(`libCall ${e.fn} receiver must be an emitter-hierarchy object`, e.loc);
|
|
5036
|
-
break;
|
|
5037
|
-
}
|
|
5038
|
-
// The chaining forms return the receiver's own static class.
|
|
5039
|
-
if (e.fn === "emitter.on" || e.fn === "emitter.off" ||
|
|
5040
|
-
e.fn === "emitter.onDyn" || e.fn === "emitter.onFlex" || e.fn === "emitter.offDyn" ||
|
|
5041
|
-
e.fn === "emitter.onData" || e.fn === "emitter.onDataDyn" ||
|
|
5042
|
-
e.fn === "emitter.removeAll" || e.fn === "emitter.setMax" ||
|
|
5043
|
-
e.fn === "emitter.setMaxChk") {
|
|
5044
|
-
if (!typeEquals(e.type, e.args[0].type)) {
|
|
5045
|
-
err(`libCall ${e.fn} must return its receiver's type (the chaining 'this')`, e.loc);
|
|
5046
|
-
}
|
|
5047
|
-
// The listener slots carry closures (the dyn family's checked-
|
|
5048
|
-
// dynamic listener is table-checked; its adapter is a func).
|
|
5049
|
-
if ((e.fn === "emitter.on" || e.fn === "emitter.off" || e.fn === "emitter.onData") && e.args[2]?.type.kind !== "func") {
|
|
5050
|
-
err(`libCall ${e.fn} listener must be a func`, e.loc);
|
|
5051
|
-
}
|
|
5052
|
-
if ((e.fn === "emitter.onDyn" || e.fn === "emitter.onDataDyn") && e.args[3]?.type.kind !== "func") {
|
|
5053
|
-
err(`libCall ${e.fn} adapter must be a func`, e.loc);
|
|
5054
|
-
}
|
|
5055
|
-
break;
|
|
5056
|
-
}
|
|
5057
|
-
if (e.fn === "emitter.emitData") {
|
|
5058
|
-
const chunkT = e.args[2]?.type;
|
|
5059
|
-
const ok = chunkT !== undefined &&
|
|
5060
|
-
((chunkT.kind === "bytes" && chunkT.elem === "u8") || chunkT.kind === "string");
|
|
5061
|
-
if (!ok)
|
|
5062
|
-
err(`libCall emitter.emitData chunk must be bytes<u8> or string`, e.loc);
|
|
5063
|
-
if (e.type.kind !== "bool")
|
|
5064
|
-
err(`libCall emitter.emitData must be bool`, e.loc);
|
|
5065
|
-
break;
|
|
5066
|
-
}
|
|
5067
|
-
if (e.fn === "emitter.countFn" && e.args[2]?.type.kind !== "func") {
|
|
5068
|
-
err(`libCall emitter.countFn listener must be a func`, e.loc);
|
|
5069
|
-
break;
|
|
5070
|
-
}
|
|
5071
|
-
if (e.fn === "emitter.emitError" && e.args[2]?.type.kind !== "object") {
|
|
5072
|
-
err(`libCall emitter.emitError payload must be an error-hierarchy object`, e.loc);
|
|
5073
|
-
break;
|
|
5074
|
-
}
|
|
5075
|
-
if (e.fn === "emitter.names") {
|
|
5076
|
-
const ok = e.type.kind === "array" && e.type.elem.kind === "string";
|
|
5077
|
-
if (!ok)
|
|
5078
|
-
err(`libCall emitter.names must return string[]`, e.loc);
|
|
5079
|
-
break;
|
|
5080
|
-
}
|
|
5081
|
-
if (e.fn === "emitter.listeners") {
|
|
5082
|
-
const ok = e.type.kind === "array" && e.type.elem.kind === "func";
|
|
5083
|
-
if (!ok)
|
|
5084
|
-
err(`libCall emitter.listeners must return a func array`, e.loc);
|
|
5085
|
-
break;
|
|
5086
|
-
}
|
|
5087
|
-
if (e.fn === "emitter.emitFlex") {
|
|
5088
|
-
if (e.args.slice(2).some((arg) => arg.type.kind !== "dyn")) {
|
|
5089
|
-
err("libCall emitter.emitFlex payloads must be checked-dynamic", e.loc);
|
|
5090
|
-
}
|
|
5091
|
-
}
|
|
5092
|
-
if (e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" || e.fn === "emitter.count" ||
|
|
5093
|
-
e.fn === "emitter.getMax" || e.fn === "emitter.ctor" ||
|
|
5094
|
-
e.fn === "emitter.countFn" || e.fn === "emitter.emitError") {
|
|
5095
|
-
if (!typeEquals(e.type, sig.result)) {
|
|
5096
|
-
err(`libCall ${e.fn} must be ${sig.result.kind}, got ${e.type.kind}`, e.loc);
|
|
5097
|
-
}
|
|
5098
|
-
break;
|
|
5099
|
-
}
|
|
5634
|
+
if ((e.fn === "emitter.onDyn" || e.fn === "emitter.onDataDyn") && e.args[3]?.type.kind !== "func") {
|
|
5635
|
+
err(`libCall ${e.fn} adapter must be a func`, e.loc);
|
|
5100
5636
|
}
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5637
|
+
return true;
|
|
5638
|
+
}
|
|
5639
|
+
if (e.fn === "emitter.emitData") {
|
|
5640
|
+
const chunkT = e.args[2]?.type;
|
|
5641
|
+
const ok = chunkT !== undefined &&
|
|
5642
|
+
((chunkT.kind === "bytes" && chunkT.elem === "u8") || chunkT.kind === "string");
|
|
5643
|
+
if (!ok)
|
|
5644
|
+
err(`libCall emitter.emitData chunk must be bytes<u8> or string`, e.loc);
|
|
5645
|
+
if (e.type.kind !== "bool")
|
|
5646
|
+
err(`libCall emitter.emitData must be bool`, e.loc);
|
|
5647
|
+
return true;
|
|
5648
|
+
}
|
|
5649
|
+
if (e.fn === "emitter.countFn" && e.args[2]?.type.kind !== "func") {
|
|
5650
|
+
err(`libCall emitter.countFn listener must be a func`, e.loc);
|
|
5651
|
+
return true;
|
|
5652
|
+
}
|
|
5653
|
+
if (e.fn === "emitter.emitError" && e.args[2]?.type.kind !== "object") {
|
|
5654
|
+
err(`libCall emitter.emitError payload must be an error-hierarchy object`, e.loc);
|
|
5655
|
+
return true;
|
|
5656
|
+
}
|
|
5657
|
+
if (e.fn === "emitter.names") {
|
|
5658
|
+
const ok = e.type.kind === "array" && e.type.elem.kind === "string";
|
|
5659
|
+
if (!ok)
|
|
5660
|
+
err(`libCall emitter.names must return string[]`, e.loc);
|
|
5661
|
+
return true;
|
|
5662
|
+
}
|
|
5663
|
+
if (e.fn === "emitter.listeners") {
|
|
5664
|
+
const ok = e.type.kind === "array" && e.type.elem.kind === "func";
|
|
5665
|
+
if (!ok)
|
|
5666
|
+
err(`libCall emitter.listeners must return a func array`, e.loc);
|
|
5667
|
+
return true;
|
|
5668
|
+
}
|
|
5669
|
+
if (e.fn === "emitter.emitFlex") {
|
|
5670
|
+
if (e.args.slice(2).some((arg) => arg.type.kind !== "dyn")) {
|
|
5671
|
+
err("libCall emitter.emitFlex payloads must be checked-dynamic", e.loc);
|
|
5110
5672
|
}
|
|
5111
|
-
|
|
5112
|
-
|
|
5673
|
+
}
|
|
5674
|
+
if (e.fn === "emitter.emit" || e.fn === "emitter.emitFlex" || e.fn === "emitter.count" ||
|
|
5675
|
+
e.fn === "emitter.getMax" || e.fn === "emitter.ctor" ||
|
|
5676
|
+
e.fn === "emitter.countFn" || e.fn === "emitter.countDyn" || e.fn === "emitter.emitError") {
|
|
5677
|
+
if (!typeEquals(e.type, result)) {
|
|
5678
|
+
err(`libCall ${e.fn} must be ${result.kind}, got ${e.type.kind}`, e.loc);
|
|
5113
5679
|
}
|
|
5114
|
-
|
|
5680
|
+
return true;
|
|
5115
5681
|
}
|
|
5682
|
+
}
|
|
5683
|
+
return false;
|
|
5684
|
+
}
|
|
5685
|
+
function checkConversionExpr(e) {
|
|
5686
|
+
switch (e.kind) {
|
|
5116
5687
|
case "jsonStringify": {
|
|
5117
5688
|
checkExpr(e.value);
|
|
5118
5689
|
if (e.type.kind !== "string") {
|
|
@@ -5157,11 +5728,19 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5157
5728
|
// Runtime HANDLE targets unwrap the checked-dynamic tree's handle kind by tag (a
|
|
5158
5729
|
// retained reference, no copy — DYN_HANDLE_KINDS).
|
|
5159
5730
|
const handleOk = DYN_HANDLE_KINDS.has(e.type.kind);
|
|
5160
|
-
if (!
|
|
5731
|
+
if (!canDynCheckTo(e.type, (id) => records.get(id), (id) => unions.get(id)) && !undefArmedOk && !bytesOk && !errorOk && !classOk && !funcOk && !handleOk) {
|
|
5161
5732
|
err(`dynCheck against non-JSON-representable type ${e.type.kind}`, e.loc);
|
|
5162
5733
|
}
|
|
5163
5734
|
break;
|
|
5164
5735
|
}
|
|
5736
|
+
default: {
|
|
5737
|
+
const _exhaustive = e;
|
|
5738
|
+
void _exhaustive;
|
|
5739
|
+
}
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
function checkAsyncExpr(e) {
|
|
5743
|
+
switch (e.kind) {
|
|
5165
5744
|
case "awaitExpr": {
|
|
5166
5745
|
checkExpr(e.value);
|
|
5167
5746
|
if (e.value.type.kind !== "promise") {
|
|
@@ -5189,7 +5768,12 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5189
5768
|
}
|
|
5190
5769
|
// The undefined next-channel has no C value form: such yields are
|
|
5191
5770
|
// void-typed (statement position only — the frontend fences reads).
|
|
5192
|
-
if (
|
|
5771
|
+
if (e.captureCompletion) {
|
|
5772
|
+
if (fn.async || e.type.kind !== "dyn" || !typeEquals(e.captureCompletion.returnType, fn.returnType)) {
|
|
5773
|
+
err("invalid captured generator completion", e.loc);
|
|
5774
|
+
}
|
|
5775
|
+
}
|
|
5776
|
+
else if (fn.generator.nextT.kind === "undefinedT") {
|
|
5193
5777
|
if (e.type.kind !== "void")
|
|
5194
5778
|
err("yield result must be void on an undefined next-channel", e.loc);
|
|
5195
5779
|
}
|
|
@@ -5230,7 +5814,6 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5230
5814
|
err("genResume throw with no payload", e.loc);
|
|
5231
5815
|
}
|
|
5232
5816
|
else if (e.arg.type.kind === "void" ||
|
|
5233
|
-
e.arg.type.kind === "dyn" ||
|
|
5234
5817
|
e.arg.type.kind === "caught" ||
|
|
5235
5818
|
e.arg.type.kind === "date") {
|
|
5236
5819
|
err(`genResume throw of a ${e.arg.type.kind} value`, e.loc);
|
|
@@ -5368,6 +5951,14 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5368
5951
|
}
|
|
5369
5952
|
break;
|
|
5370
5953
|
}
|
|
5954
|
+
default: {
|
|
5955
|
+
const _exhaustive = e;
|
|
5956
|
+
void _exhaustive;
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
}
|
|
5960
|
+
function checkIslandExpr(e) {
|
|
5961
|
+
switch (e.kind) {
|
|
5371
5962
|
case "jsMarshal": {
|
|
5372
5963
|
checkExpr(e.value);
|
|
5373
5964
|
if (e.type.kind !== "jsval")
|
|
@@ -5521,6 +6112,9 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5521
6112
|
}
|
|
5522
6113
|
case "assign": {
|
|
5523
6114
|
const binding = locals.get(s.localId) ?? globals.get(s.localId);
|
|
6115
|
+
if (s.initializes && !binding?.tdz) {
|
|
6116
|
+
err(`initializing assign requires a TDZ binding "${s.localId}"`, s.loc);
|
|
6117
|
+
}
|
|
5524
6118
|
if (!binding)
|
|
5525
6119
|
err(`assign to undeclared local/global "${s.localId}"`, s.loc);
|
|
5526
6120
|
// Global initialization happens via assign inside %init functions,
|
|
@@ -5529,7 +6123,7 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5529
6123
|
// emits the init-time one. Locals keep the strict check — except a
|
|
5530
6124
|
// TDZ const, whose source declaration IS an assign into the
|
|
5531
6125
|
// scope-entry box (tsc rejects user reassignment there too).
|
|
5532
|
-
else if (!binding.mutable && locals.has(s.localId) && !(
|
|
6126
|
+
else if (!binding.mutable && locals.has(s.localId) && !locals.get(s.localId)?.tdz) {
|
|
5533
6127
|
err(`assign to immutable local "${binding.name}"`, s.loc);
|
|
5534
6128
|
}
|
|
5535
6129
|
if (binding?.type.kind === "caught") {
|
|
@@ -5840,138 +6434,4 @@ function validateFunction(fn, functions, ffiByName, classes, records, unions, gl
|
|
|
5840
6434
|
err(`non-void function may complete without returning`, fn.loc);
|
|
5841
6435
|
}
|
|
5842
6436
|
}
|
|
5843
|
-
/** Conservative "all paths return" — mirrors what tsc already guarantees. */
|
|
5844
|
-
function alwaysReturns(stmts, unions) {
|
|
5845
|
-
for (const s of stmts) {
|
|
5846
|
-
switch (s.kind) {
|
|
5847
|
-
case "return":
|
|
5848
|
-
return true;
|
|
5849
|
-
case "throw":
|
|
5850
|
-
case "rethrow":
|
|
5851
|
-
case "runtimeFence":
|
|
5852
|
-
// Terminates the path like return: control unwinds (to a handler or
|
|
5853
|
-
// out of the function), never falling off the end. tsc agrees —
|
|
5854
|
-
// `function f(): T { throw x; }` typechecks without a return.
|
|
5855
|
-
return true;
|
|
5856
|
-
case "exprStmt":
|
|
5857
|
-
// process.exit never returns (fflush + _Exit): the path terminates
|
|
5858
|
-
// like a throw. Mirrors tsc's own never-based reachability, which
|
|
5859
|
-
// accepted the function without a trailing return — the
|
|
5860
|
-
// parseAsync().catch entry handler ends exactly this way.
|
|
5861
|
-
if (s.expr.kind === "libCall" && s.expr.fn === "process.exit")
|
|
5862
|
-
return true;
|
|
5863
|
-
break;
|
|
5864
|
-
case "tryCatch":
|
|
5865
|
-
// Normal completion requires the try body to complete normally (and
|
|
5866
|
-
// the catch, when the try raised) — if both always terminate, so
|
|
5867
|
-
// does the whole statement. Without a catch, an exception keeps
|
|
5868
|
-
// propagating (never a normal completion), so the try body alone
|
|
5869
|
-
// decides. A finally that always terminates (throw) also decides.
|
|
5870
|
-
if (alwaysReturns(s.tryBody, unions) &&
|
|
5871
|
-
(s.catchBody === null || alwaysReturns(s.catchBody, unions))) {
|
|
5872
|
-
return true;
|
|
5873
|
-
}
|
|
5874
|
-
if (s.finallyBody && alwaysReturns(s.finallyBody, unions))
|
|
5875
|
-
return true;
|
|
5876
|
-
break;
|
|
5877
|
-
case "if":
|
|
5878
|
-
if (s.else_ && alwaysReturns(s.then, unions) && alwaysReturns(s.else_, unions))
|
|
5879
|
-
return true;
|
|
5880
|
-
break;
|
|
5881
|
-
case "while":
|
|
5882
|
-
// `while (true)` with no break never completes normally (tsc treats
|
|
5883
|
-
// it the same way), so anything after it is unreachable.
|
|
5884
|
-
if (s.cond.kind === "boolLit" && s.cond.value && !containsBreak(s.body))
|
|
5885
|
-
return true;
|
|
5886
|
-
break;
|
|
5887
|
-
case "for":
|
|
5888
|
-
// `for (;;)` — no condition, or a literal-true one — with no break
|
|
5889
|
-
// never completes normally either (the walk-up-until-root idiom:
|
|
5890
|
-
// every exit is a return).
|
|
5891
|
-
if ((s.cond === null || (s.cond.kind === "boolLit" && s.cond.value)) &&
|
|
5892
|
-
!containsBreak(s.body)) {
|
|
5893
|
-
return true;
|
|
5894
|
-
}
|
|
5895
|
-
break;
|
|
5896
|
-
case "block":
|
|
5897
|
-
if (alwaysReturns(s.body, unions))
|
|
5898
|
-
return true;
|
|
5899
|
-
break;
|
|
5900
|
-
case "doWhile":
|
|
5901
|
-
// The body runs at least once: if it returns on all paths, so does
|
|
5902
|
-
// the loop. `do {} while (true)` with no break never completes.
|
|
5903
|
-
if (alwaysReturns(s.body, unions))
|
|
5904
|
-
return true;
|
|
5905
|
-
if (s.cond.kind === "boolLit" && s.cond.value && !containsBreak(s.body))
|
|
5906
|
-
return true;
|
|
5907
|
-
break;
|
|
5908
|
-
case "switch": {
|
|
5909
|
-
// A switch always returns when no case body ever breaks out, every
|
|
5910
|
-
// possible entry point (any case) reaches a return, and dispatch
|
|
5911
|
-
// cannot miss every case: either a default exists, or the switch is
|
|
5912
|
-
// an EXHAUSTIVE discriminant switch — the discriminant is a
|
|
5913
|
-
// `unionDisc` over a union with N arms, every test is a distinct
|
|
5914
|
-
// literal, and there are at least N of them. (At least: several
|
|
5915
|
-
// discriminant VALUES can share one deduped IR arm, e.g.
|
|
5916
|
-
// `{op: 0; a} | {op: 2; a}` is one record shape.) The real
|
|
5917
|
-
// exhaustiveness guarantee is tsc's — it accepted the function
|
|
5918
|
-
// without a trailing return (trust-the-checker, like narrowing
|
|
5919
|
-
// itself); this condition only keeps hand-written IR conservative.
|
|
5920
|
-
// With no switch-level breaks, execution from case i runs bodies
|
|
5921
|
-
// i..end as a straight line — check that flattened suffix.
|
|
5922
|
-
const hasDefault = s.cases.some((c) => c.test === null);
|
|
5923
|
-
const literalTests = s.cases.map((c) => c.test).filter((t) => t !== null && (t.kind === "numLit" || t.kind === "strLit" || t.kind === "boolLit"));
|
|
5924
|
-
const distinct = new Set(literalTests.map((t) => `${t.kind}:${String(t.value)}`));
|
|
5925
|
-
const exhaustive = !hasDefault &&
|
|
5926
|
-
s.disc.kind === "unionDisc" &&
|
|
5927
|
-
literalTests.length === s.cases.length &&
|
|
5928
|
-
distinct.size === s.cases.length &&
|
|
5929
|
-
s.cases.length >= (unions.get(s.disc.unionId)?.arms.length ?? Infinity);
|
|
5930
|
-
if (!hasDefault && !exhaustive)
|
|
5931
|
-
break;
|
|
5932
|
-
if (s.cases.some((c) => containsBreak(c.body)))
|
|
5933
|
-
break;
|
|
5934
|
-
const bodies = s.cases.map((c) => c.body);
|
|
5935
|
-
const everyEntryReturns = bodies.every((_, i) => alwaysReturns(bodies.slice(i).flat(), unions));
|
|
5936
|
-
if (everyEntryReturns)
|
|
5937
|
-
return true;
|
|
5938
|
-
break;
|
|
5939
|
-
}
|
|
5940
|
-
default:
|
|
5941
|
-
break;
|
|
5942
|
-
}
|
|
5943
|
-
}
|
|
5944
|
-
return false;
|
|
5945
|
-
}
|
|
5946
|
-
/** Break at this level (not inside a nested loop or switch, whose bodies
|
|
5947
|
-
* own their breaks). */
|
|
5948
|
-
function containsBreak(stmts) {
|
|
5949
|
-
for (const s of stmts) {
|
|
5950
|
-
switch (s.kind) {
|
|
5951
|
-
case "break":
|
|
5952
|
-
return true;
|
|
5953
|
-
case "if":
|
|
5954
|
-
if (containsBreak(s.then) || (s.else_ && containsBreak(s.else_)))
|
|
5955
|
-
return true;
|
|
5956
|
-
break;
|
|
5957
|
-
case "block":
|
|
5958
|
-
if (containsBreak(s.body))
|
|
5959
|
-
return true;
|
|
5960
|
-
break;
|
|
5961
|
-
case "tryCatch":
|
|
5962
|
-
// Plain try/catch does not capture breaks — a break inside binds to
|
|
5963
|
-
// the enclosing loop/switch (finally-crossing jumps are rejected
|
|
5964
|
-
// upstream, so reachable IR only has these in plain try/catch).
|
|
5965
|
-
if (containsBreak(s.tryBody) ||
|
|
5966
|
-
(s.catchBody !== null && containsBreak(s.catchBody)) ||
|
|
5967
|
-
(s.finallyBody !== null && containsBreak(s.finallyBody))) {
|
|
5968
|
-
return true;
|
|
5969
|
-
}
|
|
5970
|
-
break;
|
|
5971
|
-
default:
|
|
5972
|
-
break; // while/for/doWhile/switch bodies own their breaks
|
|
5973
|
-
}
|
|
5974
|
-
}
|
|
5975
|
-
return false;
|
|
5976
|
-
}
|
|
5977
6437
|
//# sourceMappingURL=validate.js.map
|