@scriptc/compiler 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +98 -39
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +15 -0
- package/dist/backend/build-cache.d.ts +1 -3
- package/dist/backend/build-cache.js +3 -22
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cache-root.d.ts +3 -0
- package/dist/backend/cache-root.js +23 -0
- package/dist/backend/cache-root.js.map +1 -0
- package/dist/backend/cycle-analysis.d.ts +15 -0
- package/dist/backend/cycle-analysis.js +108 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/executable-features.d.ts +4 -0
- package/dist/backend/executable-features.js +42 -0
- package/dist/backend/executable-features.js.map +1 -0
- package/dist/backend/external-c.d.ts +5 -27
- package/dist/backend/external-c.js +5 -40
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +2 -3
- package/dist/backend/ffi-callbacks.js +2 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.d.ts +4 -9
- package/dist/backend/library-identity-markers.js +11 -49
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +5 -0
- package/dist/backend/library-pack.js +123 -0
- package/dist/backend/library-pack.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +20 -0
- package/dist/backend/link-plan-core.js +18 -0
- package/dist/backend/link-plan-core.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +16 -17
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/link-trace.d.ts +2 -0
- package/dist/backend/link-trace.js +24 -0
- package/dist/backend/link-trace.js.map +1 -0
- package/dist/backend/linker.js +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.d.ts +9 -0
- package/dist/backend/literals.js +35 -0
- package/dist/backend/literals.js.map +1 -0
- package/dist/backend/literals.test.d.ts +1 -0
- package/dist/backend/literals.test.js +53 -0
- package/dist/backend/literals.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +2 -0
- package/dist/backend/llvm/blocks.js +9 -4
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.d.ts +1 -0
- package/dist/backend/llvm/blocks.test.js +91 -0
- package/dist/backend/llvm/blocks.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +14 -8
- package/dist/backend/llvm/classes.js +88 -30
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -7
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/debug-info.test.d.ts +1 -0
- package/dist/backend/llvm/debug-info.test.js +110 -0
- package/dist/backend/llvm/debug-info.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +21 -2
- package/dist/backend/llvm/dyn.js +647 -251
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +596 -1
- package/dist/backend/llvm/emitter.js +769 -425
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -2
- package/dist/backend/llvm/expr-bytes.js +60 -31
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +10 -6
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +78 -81
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +62 -31
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +54 -7
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +220 -131
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +30 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +2 -0
- package/dist/backend/llvm/lib-http2.js +215 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -0
- package/dist/backend/llvm/lib-lookup.d.ts +2 -0
- package/dist/backend/llvm/lib-lookup.js +39 -0
- package/dist/backend/llvm/lib-lookup.js.map +1 -0
- package/dist/backend/llvm/lib-network.js +25 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +44 -19
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +162 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +42 -131
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +12 -30
- package/dist/backend/native-toolchain.js +83 -233
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +77 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +73 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +103 -34
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +72 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +37 -7
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +5 -10
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +5 -6
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +16 -17
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +14 -0
- package/dist/executable/prepare.js +66 -0
- package/dist/executable/prepare.js.map +1 -0
- package/dist/ffi/ffi-manifest.d.ts +11 -4
- package/dist/ffi/ffi-manifest.js +170 -58
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.d.ts +1 -0
- package/dist/ffi/ffi-manifest.test.js +111 -0
- package/dist/ffi/ffi-manifest.test.js.map +1 -0
- package/dist/format-integer.d.ts +3 -0
- package/dist/format-integer.js +14 -0
- package/dist/format-integer.js.map +1 -0
- package/dist/frontend/analysis.d.ts +5 -0
- package/dist/frontend/analysis.js +88 -0
- package/dist/frontend/analysis.js.map +1 -0
- package/dist/frontend/arguments-usage.d.ts +1 -3
- package/dist/frontend/arguments-usage.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-lexer.d.ts +4 -25
- package/dist/frontend/cjs-lexer.js +6 -806
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/cjs-resolve.d.ts +5 -0
- package/dist/frontend/cjs-resolve.js +429 -0
- package/dist/frontend/cjs-resolve.js.map +1 -0
- package/dist/frontend/cjs-syntax.d.ts +26 -0
- package/dist/frontend/cjs-syntax.js +806 -0
- package/dist/frontend/cjs-syntax.js.map +1 -0
- package/dist/frontend/comptime-node.d.ts +4 -0
- package/dist/frontend/comptime-node.js +16 -0
- package/dist/frontend/comptime-node.js.map +1 -0
- package/dist/frontend/comptime-node.test.d.ts +1 -0
- package/dist/frontend/comptime-node.test.js +37 -0
- package/dist/frontend/comptime-node.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +3 -4
- package/dist/frontend/dts-paths.js +15 -8
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +2 -2
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/helper-tokens.d.ts +1 -0
- package/dist/frontend/helper-tokens.js +147 -0
- package/dist/frontend/helper-tokens.js.map +1 -0
- package/dist/frontend/helper-tokens.test.d.ts +1 -0
- package/dist/frontend/helper-tokens.test.js +35 -0
- package/dist/frontend/helper-tokens.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
- package/dist/frontend/inferred-js-diagnostics.js +69 -0
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +5 -2
- package/dist/frontend/input-tracker.js +24 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +23 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +32 -24
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.d.ts +4 -0
- package/dist/frontend/literal-values.js +21 -0
- package/dist/frontend/literal-values.js.map +1 -0
- package/dist/frontend/literal-values.test.d.ts +1 -0
- package/dist/frontend/literal-values.test.js +91 -0
- package/dist/frontend/literal-values.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
- package/dist/frontend/lowering/abstract-equality.js +3 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -1
- package/dist/frontend/lowering/array-values.js +43 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
- package/dist/frontend/lowering/class-callbacks.js +74 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-construction.d.ts +12 -0
- package/dist/frontend/lowering/class-construction.js +156 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +10 -0
- package/dist/frontend/lowering/class-descriptors.js +114 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +51 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1158 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +93 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +67 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +13 -0
- package/dist/frontend/lowering/class-method-values.js +235 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +19 -0
- package/dist/frontend/lowering/class-prototypes.js +242 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +66 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +208 -163
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +58 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +14 -0
- package/dist/frontend/lowering/error-methods.js +177 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +51 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +132 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +509 -183
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +88 -24
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +101 -0
- package/dist/frontend/lowering/function-context.js +109 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +143 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +4 -1
- package/dist/frontend/lowering/lib-boundary.js +112 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtin-values.js +249 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +33 -46
- package/dist/frontend/lowering/lower-builtins.js +676 -365
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +28 -22
- package/dist/frontend/lowering/lower-calls.js +1660 -412
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +95 -57
- package/dist/frontend/lowering/lower-classes.js +1491 -404
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +36 -32
- package/dist/frontend/lowering/lower-containers.js +925 -181
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +37 -13
- package/dist/frontend/lowering/lower-exprs.js +2163 -863
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +88 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -8
- package/dist/frontend/lowering/lower-island.js +66 -33
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +445 -39
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +39 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +17 -17
- package/dist/frontend/lowering/lower-stmts.js +855 -514
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +20 -11
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +140 -190
- package/dist/frontend/lowering/lowerer.js +1193 -712
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +172 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +10 -3
- package/dist/frontend/lowering/surfaces.js +86 -37
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +12 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +82 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +121 -38
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +9 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +39 -20
- package/dist/frontend/program.js +393 -189
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +105 -2
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/provenance-core.d.ts +9 -0
- package/dist/frontend/provenance-core.js +435 -0
- package/dist/frontend/provenance-core.js.map +1 -0
- package/dist/frontend/provenance.d.ts +0 -4
- package/dist/frontend/provenance.js +4 -459
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +3 -1
- package/dist/frontend/resolve.js +6 -3
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +4 -3
- package/dist/frontend/runtime-resolve.js +22 -18
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +53 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.d.ts +5 -0
- package/dist/frontend/services-node.js +19 -0
- package/dist/frontend/services-node.js.map +1 -0
- package/dist/frontend/services-node.test.d.ts +1 -0
- package/dist/frontend/services-node.test.js +70 -0
- package/dist/frontend/services-node.test.js.map +1 -0
- package/dist/frontend/services.d.ts +44 -0
- package/dist/frontend/services.js +90 -0
- package/dist/frontend/services.js.map +1 -0
- package/dist/frontend/services.test.d.ts +1 -0
- package/dist/frontend/services.test.js +174 -0
- package/dist/frontend/services.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +3 -3
- package/dist/frontend/ts7/adapter.js +14 -31
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/api.d.ts +16 -0
- package/dist/frontend/ts7/api.js +24 -0
- package/dist/frontend/ts7/api.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
- package/dist/frontend/ts7/ast-bytes.js +137 -0
- package/dist/frontend/ts7/ast-bytes.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-bytes.test.js +73 -0
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
- package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-guards.test.js +43 -0
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +194 -0
- package/dist/frontend/ts7/ast-node.js +448 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -0
- package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-node.test.js +266 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -0
- package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
- package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
- package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-text.d.ts +6 -0
- package/dist/frontend/ts7/ast-text.js +124 -0
- package/dist/frontend/ts7/ast-text.js.map +1 -0
- package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-text.test.js +38 -0
- package/dist/frontend/ts7/ast-text.test.js.map +1 -0
- package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
- package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
- package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.d.ts +42 -0
- package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
- package/dist/frontend/ts7/ast-types.generated.js +5 -0
- package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.js +3 -0
- package/dist/frontend/ts7/ast-types.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +58 -0
- package/dist/frontend/ts7/ast-wire.js +267 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire.test.js +151 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
- package/dist/frontend/ts7/ast.d.ts +14 -14
- package/dist/frontend/ts7/ast.js +25 -18
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +47 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +34 -18
- package/dist/frontend/type-mapper.js +552 -131
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +146 -2
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +16 -0
- package/dist/frontend/union-discriminants.js +98 -0
- package/dist/frontend/union-discriminants.js.map +1 -0
- package/dist/frontend/union-discriminants.test.d.ts +1 -0
- package/dist/frontend/union-discriminants.test.js +182 -0
- package/dist/frontend/union-discriminants.test.js.map +1 -0
- package/dist/index.d.ts +7 -198
- package/dist/index.js +369 -1572
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +23 -4
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.js +67 -49
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/control-flow.d.ts +6 -0
- package/dist/ir/control-flow.js +142 -0
- package/dist/ir/control-flow.js.map +1 -0
- package/dist/ir/control-flow.test.d.ts +1 -0
- package/dist/ir/control-flow.test.js +113 -0
- package/dist/ir/control-flow.test.js.map +1 -0
- package/dist/ir/integer-loops.js +7 -18
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.js +53 -27
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +334 -176
- package/dist/ir/ir.js +710 -903
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +162 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +33 -14
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +57 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +2018 -1498
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +536 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +137 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +94 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +85 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +107 -98
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -536
- package/dist/backend/c/c-emitter.js +0 -1932
- package/dist/backend/c/c-emitter.js.map +0 -1
- package/dist/backend/c/exprs.d.ts +0 -15
- package/dist/backend/c/exprs.js +0 -8847
- package/dist/backend/c/exprs.js.map +0 -1
- package/dist/backend/c/island.d.ts +0 -45
- package/dist/backend/c/island.js +0 -281
- package/dist/backend/c/island.js.map +0 -1
- package/dist/backend/c/may-throw.js.map +0 -1
- package/dist/backend/c/shapes.d.ts +0 -142
- package/dist/backend/c/shapes.js +0 -603
- package/dist/backend/c/shapes.js.map +0 -1
- package/dist/backend/c/stmts.d.ts +0 -76
- package/dist/backend/c/stmts.js +0 -1108
- package/dist/backend/c/stmts.js.map +0 -1
- package/dist/backend/c/types.d.ts +0 -71
- package/dist/backend/c/types.js +0 -459
- package/dist/backend/c/types.js.map +0 -1
- package/dist/backend/c/types.test.js +0 -32
- package/dist/backend/c/types.test.js.map +0 -1
- package/dist/backend/c/walkers.d.ts +0 -134
- package/dist/backend/c/walkers.js +0 -1772
- package/dist/backend/c/walkers.js.map +0 -1
- /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
import { pathModuleValue } from "./lower-builtin-values.js";
|
|
2
|
+
import { everyExprChild, everyStmtChild } from "../../ir/traverse.js";
|
|
3
|
+
import { RuntimeOptionalLocals } from "./runtime-optional-locals.js";
|
|
4
|
+
import { sanitizeUnregisteredClassTypes } from "./sanitize-class-types.js";
|
|
5
|
+
import { UnregisteredClassTypes } from "./unregistered-class-types.js";
|
|
6
|
+
import { buildUnionNarrow } from "./union-narrow.js";
|
|
7
|
+
import { planUnionRetag, buildUnionRetag, planRecordUnionWrap, buildRecordUnionWrap } from "./union-retag.js";
|
|
8
|
+
import { bindingInContext, captureContextBinding, declareContextLocal, declareContextThis } from "./function-context.js";
|
|
9
|
+
export { newFnCtx } from "./function-context.js";
|
|
1
10
|
import { InternalCompilerError } from "../../errors.js";
|
|
11
|
+
import { defaultAfterUndefined, lowerStaticallyUndefinedArgument } from "./optional-arguments.js";
|
|
12
|
+
import { ClassDynamicDispatch } from "./class-dynamic-dispatch.js";
|
|
13
|
+
import { finalizeClassMethodValues } from "./class-method-values.js";
|
|
2
14
|
/* AST + checker → IR.
|
|
3
15
|
*
|
|
4
16
|
* Invariants:
|
|
@@ -17,24 +29,29 @@ import { resolve } from "node:path";
|
|
|
17
29
|
import { bindingSource } from "../binding-source.js";
|
|
18
30
|
import { tsgoPath } from "../dts-paths.js";
|
|
19
31
|
import * as ts from "../ts7/adapter.js";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
32
|
+
import { literalValues } from "../literal-values.js";
|
|
33
|
+
import { discriminantOwners, literalUnionArm } from "../union-discriminants.js";
|
|
34
|
+
import { anyOpRequiresDynamicDiag, blockedBindingUseDiag, checkerPanicDiag, componentTypeDiag, isCheckerPanic, genericSignatureTypeDiag, indexSignatureTypeDiag, intersectionTypeDiag, noLoweringDiag, overloadedSignatureTypeDiag, recordShapeMismatchDiag, requiresDynamicApiDiag, requiresDynamicPackageDiag, requiresDynamicTypeDiag, unionMismatchDiag, UNSUPPORTED, unsupportedDiag, unsupportedTypeDiag, } from "../../diagnostics/diagnostic.js";
|
|
35
|
+
import { arrayOf, BOOL, canAdaptDynFuncTo, canDynCheckTo, canConvertToDyn, canCrossIslandBoundary, canExitIslandToType, canMarshalTypedFuncIntoIsland, DYN, DYN_HANDLE_KINDS, F64, isDynTypedRefType, isJsonSafeType, isJsonStringifySafeType, isSupportedMapKey, isSupportedMapValue, isUndefinedArmedUnion, isUnitType, JSVAL, NULL_T, RUNTIME_ERROR_CLASSES, STRING, typeEquals, UNDEFINED_T, VOID } from "../../ir/ir.js";
|
|
36
|
+
import {} from "../npm.js";
|
|
22
37
|
import { provenanceActive } from "../provenance-registry.js";
|
|
23
38
|
import { ambientDtsPath, canonicalBuiltinModule, cjsExportAssignmentOf, cjsExportDiscardReason, fallbackDtsPath, isCjsExportTableLiteral, isCjsJsFile, isJsSourceFile, isNodeEsmFile, isNodeTypesPath, locOf, orderedImportsOf, overridesDtsPath, npmStaticDepSf7, requireSpecOf, resolveImport, workspacePackageOfPath, } from "../program.js";
|
|
24
|
-
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
|
|
39
|
+
import { containsRecord, containsUnion, describeComponentBlocker, describeRecordMemberBlocker, formatIrType, ISLAND_AMBIENT_TYPES, isUnitOnlyTsType, jsOpenObjectType, mapType, ShapeRegistry, typeKey, UnionRegistry, withUndefinedArm as withUndefinedArmCanonical, } from "../type-mapper.js";
|
|
25
40
|
import { boundaryIntoIslandMsg, boundaryOutOfIslandMsg, builtinConstLit, builtinModuleConstOf, builtinModulesArrayLit, builtinFenceHintOf, builtinModuleFnOf, stdlibMemberFence, isStdlibMember, isStdlibSymbol, isStdlibGlobal, stdlibGlobalMember, nodeTypesOnlySymbol } from "./surfaces.js";
|
|
26
41
|
import { splitFiles, collectProgram, collectNpmImports, collectJsonImports, moduleArtifacts, collectGlobals, declSymbolOf, defaultExportSymbolOf, lowerFileInit, lowerDefaultExport, buildMain, appendDynamicImportModules, appendForkModules } from "./lower-modules.js";
|
|
27
42
|
import { prepareCjsModuleGraph } from "./lower-node-module.js";
|
|
28
|
-
import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor,
|
|
43
|
+
import { registerBuiltinErrorClasses, registerBuiltinEmitterClass, registerBuiltinStreamClasses, builtinErrorInfoOf, builtinEmitterInfoOf, builtinStreamInfoOf, analyzeClassDecoration, classIteratorDrainCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, classIteratorRestDrainCall, classMemberNameOf, classValueRef, collectClassShape, exactClassOfReceiver, collectClassShapeInner, ctorAbiEquals, findMethodOn, findStaticOn, findGenericMethodOn, findGenericStaticOn, genericClassInstanceType, isSubclassOf, inHierarchy, overrideBelow, staticShadowBelow, upcastTo, lowerClassMembers, lowerClassCtor, lowerClassExpression, lowerClassExpressionInfo, lowerClassMethodMember, lowerClassValueProperty, lowerStaticMethod, throwingSetterFn, fieldInitStmts, lowerStaticFieldInits, lowerStaticFieldRead, lowerDerivedCtorBody, superCallStmt, lowerSuperMethodCall, superThisRef, lowerSuperAccessorRead, lowerSuperAccessorWrite, inheritsBuiltinErrorCtor, inheritsBuiltinEmitterCtor, errorConstructorArgs, lowerNew, accessorCall } from "./lower-classes.js";
|
|
29
44
|
import { mixinCallClassInfoOf, mixinIntersectionInstanceType } from "./lower-mixins.js";
|
|
45
|
+
import { implicitAnyParamSymbolsOf } from "./lower-calls.js";
|
|
46
|
+
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
30
47
|
import { bindingNeverReassigned, bodyReadsArguments, funcTypeFromParamShapes, implicitMonoFile, isThisParameter, paramShape, paramShapes, checkDefaultParamBodyType, completeArgs, wrappedUndefined, undefinedArgFor, requireExactArityValue, bodyReturnType, declaredReturnType, collectSignature, collectSignatureInner, collectGenericSignature, genericFnOf, lowerGenericCall, lowerGenericFnValue, inferTypeParamBindings, lowerGenericInstance, lowerCall, lowerFfiCall, lowerTimersMemberCall, lowerPromiseMethodCall, lowerFilterNarrowCall, isTopLevelFnSymbol, lowerNestedFunctionDecl, lambdaSignature, lowerLambda, lowerFunction, validateFfiImports } from "./lower-calls.js";
|
|
31
48
|
import { lowerArrayMethodCall, lowerMapMethodCall, lowerMapForEachCall, buildMapForEachFn, lowerRecordOvfCaptureHelper, lowerEnvToPairsHelper, lowerSetMethodCall, lowerSetForEachCall, buildSetForEachFn } from "./lower-containers.js";
|
|
32
49
|
import { lowerBufferStaticCall, lowerBytesMethodCall, lowerBytesNew } from "./containers/bytes.js";
|
|
33
50
|
import { lowerRegexMethodCall, lowerStringMethodCall } from "./containers/string-and-regexp.js";
|
|
34
51
|
import { lowerStreamModuleCall } from "./lower-stream.js";
|
|
35
52
|
import { lowerEmitOverrideSpec } from "./lower-event-emitter.js";
|
|
36
|
-
import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleOf, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerNodeModuleCall, lowerTimersPromisesSetInterval, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecFileCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, registerPromisifiedBuiltinDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerCryptoModuleCall, lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall
|
|
37
|
-
import { fenceFetchObjectAssignment, fenceFetchObjectBinding, fenceStaticAbortControllerMemberRead, fenceStaticHeadersIteration, fenceStaticHeadersMember, fenceStaticReadableStreamMember, fenceStaticResponseMember, fenceUnsupportedFetchConstructorMember, isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerAbortControllerNew, lowerDynamicHeadersIteratorCall, lowerDynamicHeadersSpread, lowerDynamicImportCall, lowerFetchCall, lowerFetchElementMethodCall, lowerResponseNew, lowerStaticFetchCompanionCall, lowerStaticAbortControllerCall, lowerStaticAbortSignalListenerCall, lowerStaticReadableStreamCancelCall, lowerStaticReadableStreamControllerCall, lowerStaticReadableStreamNew, lowerStaticReadableStreamReaderCall, lowerStaticResponseCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
53
|
+
import { builtinImportOf, createRequireBindingDecl, createRequireNamespaceDecl, createRequireProgramModuleOf, createRequireSpecOf, stripTypeCasts, lowerBuiltinModuleCall, lowerNodeModuleCall, lowerTimersPromisesSetInterval, lowerFsToUnixTimestampCall, lowerFsLadderCall, lowerChildArgsArg, lowerSpawnSyncCall, lowerSpawnCall, lowerExecFileCall, lowerExecSyncCall, recordToEnvPairs, lowerJsonMethodCall, fencedBuiltinImportOf, lowerCryptoComposedCall, lowerUrlMethodCall, lowerSearchParamsMethodCall, lowerStatsMethodCall, lowerChildMethodCall, lowerAtomicsCall, lowerBuiltinExtraProperty, registerPromisifiedBuiltinDecl, lowerExecFileAsyncCall, execFileAsyncHelper, lowerStringDecoderMethodCall, strdecHelper, lowerReadlineMethodCall, lowerDcChannelMethodCall, lowerDcChannelProperty, lowerAlsMethodCall, lowerDcTracingChannelMethodCall, lowerDcTracingChannelProperty, lowerJsonProperty, lowerErrorCodeProperty, lowerProcessProperty, isProcessEnv, envValueType, lowerProcessEnvGet, lowerProcessMethodCall, lowerProcessOptionalMethodCall, lowerTimeoutMethodCall, envSnapshotHelper, isConsoleLog, consoleCallMember, lowerNumberStaticCall, lowerNumberStaticProperty, lowerDateCall, lowerTextCodecCall, lowerCryptoModuleCall, lowerFsConstantsProperty, lowerBuiltinConstantsProperty, builtinConstantBindingOf, builtinConstantsDestructureDecl, lowerProcessStreamProperty, lowerStringStaticCall, lowerStringLastIndexOfCall, lowerPromiseStaticCall } from "./lower-builtins.js";
|
|
54
|
+
import { fenceFetchObjectAssignment, fenceFetchObjectBinding, fenceStaticAbortControllerMemberRead, fenceStaticHeadersIteration, fenceStaticHeadersMember, fenceStaticReadableStreamMember, fenceStaticResponseMember, fenceUnsupportedFetchConstructorMember, isIslandExpr, islandFuncValueFence, islandRegexpOf, jsvalIn, requireDynamicApi, islandGlobalFnOf, lowerAbortControllerNew, lowerDynamicHeadersIteratorCall, lowerDynamicHeadersSpread, lowerDynamicImportCall, lowerFetchCall, lowerFetchElementMethodCall, lowerResponseNew, lowerFetchWebNew, lowerStaticFetchCompanionCall, lowerStaticAbortControllerCall, lowerStaticAbortSignalListenerCall, lowerStaticReadableStreamCancelCall, lowerStaticReadableStreamControllerCall, lowerStaticReadableStreamNew, lowerStaticReadableStreamReaderCall, lowerStaticResponseCall, lowerIslandMethodCall, lowerMathProperty, npmPackageOf, npmMemberFence, npmPackageOfSymbol } from "./lower-island.js";
|
|
38
55
|
import { lowerHttpHeadersElement, lowerNetModuleCall, lowerServerMethodCall, lowerServerProperty, lowerTlsRootCertificates } from "./lower-server.js";
|
|
39
56
|
import { lowerDgramDnsModuleCall, lowerDgramMethodCall } from "./lower-dgram.js";
|
|
40
57
|
import { lowerNodeTestModuleCall, lowerTestDirectCall, lowerTestMethodCall, lowerTestCtxProperty } from "./lower-test.js";
|
|
@@ -49,6 +66,7 @@ import { lowerRecordFieldCall, lowerObjectMethodCall } from "./lower-calls.js";
|
|
|
49
66
|
import { fenceCrossBlockNsRef, nsPathPrefix } from "./lower-namespaces.js";
|
|
50
67
|
import { numLit, varRef } from "../../ir/build.js";
|
|
51
68
|
import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
|
|
69
|
+
import { lowerTernary } from "./lower-exprs.js";
|
|
52
70
|
/** Entry function name. '%' cannot appear in a TS identifier, so a user
|
|
53
71
|
* function can never collide with it (mangling is injective per prefix). */
|
|
54
72
|
export const ENTRY_NAME = "%main";
|
|
@@ -62,24 +80,6 @@ export class PoisonError extends Error {
|
|
|
62
80
|
export function own(table, key) {
|
|
63
81
|
return Object.hasOwn(table, key) ? table[key] : undefined;
|
|
64
82
|
}
|
|
65
|
-
/** Sentinel binding key for `this` (which has no ts.Symbol): a stable
|
|
66
|
-
* object identity used in the same scope/capture maps as real symbols, so
|
|
67
|
-
* arrows capturing `this` ride the ordinary capture machinery. */
|
|
68
|
-
const THIS_BINDING = { escapedName: "%this" };
|
|
69
|
-
export function newFnCtx(lifted, selfSymbol, selfType, returnType) {
|
|
70
|
-
return {
|
|
71
|
-
locals: [],
|
|
72
|
-
scopes: [new Map()],
|
|
73
|
-
localCounters: new Map(),
|
|
74
|
-
captures: lifted ? [] : null,
|
|
75
|
-
captureSources: [],
|
|
76
|
-
captureBySymbol: new Map(),
|
|
77
|
-
selfSymbol,
|
|
78
|
-
selfType,
|
|
79
|
-
returnType,
|
|
80
|
-
ctl: [],
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
83
|
/** IrStmt discriminants — the island walk below must not descend into
|
|
84
84
|
* NESTED statements (each is counted individually by its own lowerStmts
|
|
85
85
|
* visit; descending would attribute a nested island statement to every
|
|
@@ -90,10 +90,6 @@ const IR_STMT_KINDS = new Set([
|
|
|
90
90
|
"arraySet", "arraySetLength", "arraySetUndefined", "arrayDelete", "forOf", "return", "fieldSet", "recordSet", "break",
|
|
91
91
|
"continue", "block", "tryCatch", "throw", "rethrow", "runtimeFence",
|
|
92
92
|
]);
|
|
93
|
-
/** True when a lowered statement's OWN expressions contain island
|
|
94
|
-
* constructs — a generic JSON walk (like moduleUsesRegex): `kind`
|
|
95
|
-
* discriminants live only on IR objects, so user string values can never
|
|
96
|
-
* false-positive. Nested statements are skipped (counted separately). */
|
|
97
93
|
/** Every identifier a binding name binds: the identifier itself, or all
|
|
98
94
|
* identifiers of a (possibly nested) destructuring pattern in source
|
|
99
95
|
* order. */
|
|
@@ -110,31 +106,22 @@ export function boundIdentifiersOf(name) {
|
|
|
110
106
|
}
|
|
111
107
|
return out;
|
|
112
108
|
}
|
|
109
|
+
/** Inspect executable children directly, without boxing the statement tree
|
|
110
|
+
* into checked-dynamic storage just to calculate coverage. */
|
|
113
111
|
export function stmtUsesIsland(stmts) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return;
|
|
122
|
-
|
|
123
|
-
const kind = v.kind;
|
|
124
|
-
if (!root && typeof kind === "string" && IR_STMT_KINDS.has(kind))
|
|
125
|
-
return;
|
|
126
|
-
const fn = v.fn;
|
|
127
|
-
if (kind === "jsOp" || kind === "jsExit" || kind === "jsBridgePromise" ||
|
|
128
|
-
fn === "island.eval" || fn === "island.import" || fn === "island.importDyn" ||
|
|
129
|
-
fn === "island.castFail") {
|
|
130
|
-
found = true;
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
for (const value of Object.values(v))
|
|
134
|
-
visit(value, false);
|
|
112
|
+
// Keep the accounting boundary at the source statement: nested statement
|
|
113
|
+
// lists are counted by their own lowerStmts invocation.
|
|
114
|
+
const nested = (stmt) => IR_STMT_KINDS.has(stmt.kind) || everyStmtChild(stmt, expr, nested);
|
|
115
|
+
const expr = (node) => {
|
|
116
|
+
if (node.kind === "jsOp" || node.kind === "jsExit" || node.kind === "jsBridgePromise" ||
|
|
117
|
+
(node.kind === "libCall" && (node.fn === "island.eval" || node.fn === "island.import" ||
|
|
118
|
+
node.fn === "island.importDyn" || node.fn === "island.castFail")))
|
|
119
|
+
return false;
|
|
120
|
+
return everyExprChild(node, expr, nested);
|
|
135
121
|
};
|
|
136
|
-
|
|
137
|
-
|
|
122
|
+
if (Array.isArray(stmts))
|
|
123
|
+
return !stmts.every((stmt) => everyStmtChild(stmt, expr, nested));
|
|
124
|
+
return !everyStmtChild(stmts, expr, nested);
|
|
138
125
|
}
|
|
139
126
|
function directExternalTypeSpecifiersByFile(externalTypes) {
|
|
140
127
|
const out = new Map();
|
|
@@ -173,12 +160,14 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
173
160
|
if (!phaseTiming)
|
|
174
161
|
return;
|
|
175
162
|
const now = performance.now();
|
|
176
|
-
|
|
163
|
+
const event = {
|
|
177
164
|
phase,
|
|
178
165
|
phase_ms: Math.round((now - phaseLast) * 10) / 10,
|
|
179
166
|
total_ms: Math.round((now - phaseStarted) * 10) / 10,
|
|
180
|
-
|
|
181
|
-
|
|
167
|
+
};
|
|
168
|
+
for (const key of Object.keys(detail))
|
|
169
|
+
event[key] = detail[key];
|
|
170
|
+
process.stderr.write(`scriptc lowering ${JSON.stringify(event)}\n`);
|
|
182
171
|
phaseLast = now;
|
|
183
172
|
};
|
|
184
173
|
const dynamic = options.dynamic ?? false;
|
|
@@ -216,6 +205,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
216
205
|
const externalTypeSpecifiersByFile = options.externalTypeSpecifiersByFile ??
|
|
217
206
|
directExternalTypeSpecifiersByFile(externalTypes);
|
|
218
207
|
const validation = new Lowerer(program, entry, moduleOrder, dynamic, {
|
|
208
|
+
frontendServices: options.frontendServices,
|
|
219
209
|
targetPlatform,
|
|
220
210
|
startupCrash,
|
|
221
211
|
ffiImports,
|
|
@@ -234,6 +224,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
234
224
|
const reachableEmit = ffiImports.length === 0
|
|
235
225
|
? validation
|
|
236
226
|
: new Lowerer(program, entry, moduleOrder, dynamic, {
|
|
227
|
+
frontendServices: options.frontendServices,
|
|
237
228
|
targetPlatform,
|
|
238
229
|
startupCrash,
|
|
239
230
|
ffiImports,
|
|
@@ -261,6 +252,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
261
252
|
// without such a settled fence retain checker-backed IR exactly once.
|
|
262
253
|
if (reachableEmit.requiresHistoricalOrderRelower) {
|
|
263
254
|
const emit = new Lowerer(program, entry, moduleOrder, dynamic, {
|
|
255
|
+
frontendServices: options.frontendServices,
|
|
264
256
|
reachable,
|
|
265
257
|
targetPlatform,
|
|
266
258
|
startupCrash,
|
|
@@ -282,6 +274,7 @@ export function lowerToIr(program, entry, moduleOrder, options = {}) {
|
|
|
282
274
|
if (options.coverage !== true)
|
|
283
275
|
return result;
|
|
284
276
|
const remainder = new Lowerer(program, entry, moduleOrder, dynamic, {
|
|
277
|
+
frontendServices: options.frontendServices,
|
|
285
278
|
reachable,
|
|
286
279
|
remainder: true,
|
|
287
280
|
alreadyFlushed: resultLowerer.flushedSymbols,
|
|
@@ -353,7 +346,7 @@ export function staticImportNamespaceType(lowerer, expr) {
|
|
|
353
346
|
if (moduleId === null) {
|
|
354
347
|
const symbol = lowerer.checker.getSymbolAtLocation(arg);
|
|
355
348
|
const source = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isSourceFile(decl) && !decl.isDeclarationFile);
|
|
356
|
-
if (source && !source.fileName.endsWith(".cts") && !isCjsJsFile(source) &&
|
|
349
|
+
if (source && !source.fileName.endsWith(".cts") && !isCjsJsFile(source, lowerer.program) &&
|
|
357
350
|
lowerer.moduleOrder.includes(source)) {
|
|
358
351
|
moduleId = `file:${tsgoPath(resolve(source.fileName))}`;
|
|
359
352
|
}
|
|
@@ -522,11 +515,38 @@ export function dynFallbackType(lowerer, node, t) {
|
|
|
522
515
|
if (!isJsSourceFile(node.getSourceFile())) {
|
|
523
516
|
if (t.flags & ts.TypeFlags.Any)
|
|
524
517
|
return DYN;
|
|
518
|
+
const symbol = t.getSymbol();
|
|
519
|
+
const args = symbol && lowerer.isStdlibSymbol(symbol) ? lowerer.checker.getTypeArguments(t) : [];
|
|
520
|
+
if (symbol?.name === "Promise" && args[0] && args[0].flags & ts.TypeFlags.Any)
|
|
521
|
+
return jsFallbackPromiseType(lowerer, t);
|
|
522
|
+
if (symbol && ["Generator", "AsyncGenerator", "IterableIterator"].includes(symbol.name) && args.some((arg) => arg.flags & ts.TypeFlags.Any))
|
|
523
|
+
return jsFallbackGeneratorType(lowerer, t);
|
|
524
|
+
if (lowerer.checker.isArrayType(t) && ((lowerer.checker.getTypeArguments(t)[0]?.flags ?? 0) & ts.TypeFlags.Any) !== 0)
|
|
525
|
+
return DYN;
|
|
525
526
|
// TS single-call-signature function types: per-piece fallback, but
|
|
526
527
|
// ONLY `any` pieces fall to dyn — any other unmappable piece keeps
|
|
527
528
|
// the whole type's own fence.
|
|
528
529
|
return anyPiecedFuncType(lowerer, node, t);
|
|
529
530
|
}
|
|
531
|
+
const promise = jsFallbackPromiseType(lowerer, t);
|
|
532
|
+
if (promise)
|
|
533
|
+
return promise;
|
|
534
|
+
const generator = jsFallbackGeneratorType(lowerer, t);
|
|
535
|
+
if (generator)
|
|
536
|
+
return generator;
|
|
537
|
+
const symbol = t.getSymbol();
|
|
538
|
+
if ((symbol?.name === "Map" || symbol?.name === "ReadonlyMap") && lowerer.isStdlibSymbol(symbol)) {
|
|
539
|
+
const args = lowerer.checker.getTypeArguments(t);
|
|
540
|
+
if (args.length === 2) {
|
|
541
|
+
const key = lowerer.mapTypeOf(args[0]);
|
|
542
|
+
const value = lowerer.mapTypeOf(args[1]);
|
|
543
|
+
return {
|
|
544
|
+
kind: "map",
|
|
545
|
+
key: key && isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) ? key : DYN,
|
|
546
|
+
value: value && isSupportedMapValue(value) ? value : DYN,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
530
550
|
// JS inference commonly spells a callback field initialized to null as
|
|
531
551
|
// `((value: any) => any) | null`. Preserve the callable arm and its
|
|
532
552
|
// checked-dynamic pieces instead of collapsing the whole slot to dyn.
|
|
@@ -588,6 +608,32 @@ export function dynFallbackType(lowerer, node, t) {
|
|
|
588
608
|
return fallbackFunction;
|
|
589
609
|
return DYN;
|
|
590
610
|
}
|
|
611
|
+
/** An inferred JS promise keeps its asynchronous ABI even when its payload
|
|
612
|
+
* has no fixed shape. The settled value crosses the checked native boundary. */
|
|
613
|
+
function jsFallbackPromiseType(lowerer, t) {
|
|
614
|
+
const symbol = t.getSymbol();
|
|
615
|
+
if (symbol?.name !== "Promise" || !lowerer.isStdlibSymbol(symbol))
|
|
616
|
+
return null;
|
|
617
|
+
const inner = lowerer.checker.getTypeArguments(t)[0];
|
|
618
|
+
return inner ? { kind: "promise", inner: lowerer.mapTypeOf(inner) ?? DYN } : null;
|
|
619
|
+
}
|
|
620
|
+
/** An inferred generator with channels outside the typed result union
|
|
621
|
+
* keeps its fiber ABI and carries yielded/resumed values as checked values. */
|
|
622
|
+
function jsFallbackGeneratorType(lowerer, t) {
|
|
623
|
+
const symbol = t.getSymbol();
|
|
624
|
+
if (!symbol || !["Generator", "AsyncGenerator", "IterableIterator"].includes(symbol.name) ||
|
|
625
|
+
!lowerer.isStdlibSymbol(symbol))
|
|
626
|
+
return null;
|
|
627
|
+
const [yielded, returned, resumed] = lowerer.checker.getTypeArguments(t);
|
|
628
|
+
const unit = ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Never;
|
|
629
|
+
return {
|
|
630
|
+
kind: "generator",
|
|
631
|
+
...(symbol.name === "AsyncGenerator" ? { async: true } : {}),
|
|
632
|
+
yieldT: yielded && yielded.flags & ts.TypeFlags.Never ? VOID : DYN,
|
|
633
|
+
retT: !returned || returned.flags & unit ? VOID : DYN,
|
|
634
|
+
nextT: !resumed || resumed.flags & unit ? UNDEFINED_T : DYN,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
591
637
|
function jsFallbackFunctionType(lowerer, node, t) {
|
|
592
638
|
const sig = pureSingleCallSignatureOf(lowerer, t);
|
|
593
639
|
if (!sig)
|
|
@@ -602,6 +648,7 @@ function jsFallbackFunctionType(lowerer, node, t) {
|
|
|
602
648
|
// `enabled = true`) rather than that call-site type, so recover the
|
|
603
649
|
// syntactic optionality from the parameter declaration.
|
|
604
650
|
const decl = lowerer.checker.valueDeclarationOf(p);
|
|
651
|
+
mapped = jsOpenObjectType(decl, mapped, lowerer.shapes, lowerer.unions);
|
|
605
652
|
const optional = decl !== undefined &&
|
|
606
653
|
ts.isParameter(decl) &&
|
|
607
654
|
(decl.questionToken !== undefined || decl.initializer !== undefined);
|
|
@@ -614,12 +661,16 @@ function jsFallbackFunctionType(lowerer, node, t) {
|
|
|
614
661
|
return mapped;
|
|
615
662
|
});
|
|
616
663
|
const retT = lowerer.checker.getReturnTypeOfSignature(sig);
|
|
617
|
-
const
|
|
664
|
+
const sigDecl = lowerer.checker.signatureDeclaration(sig);
|
|
665
|
+
const jsUnitReturn = sigDecl !== undefined && isJsSourceFile(sigDecl.getSourceFile()) &&
|
|
666
|
+
(retT.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0;
|
|
667
|
+
const ret = jsUnitReturn ? DYN : retT.flags & ts.TypeFlags.Void ? VOID
|
|
668
|
+
: lowerer.mapTypeOf(retT) ?? jsFallbackPromiseType(lowerer, retT) ?? jsFallbackGeneratorType(lowerer, retT) ?? DYN;
|
|
618
669
|
return { kind: "func", params, ret };
|
|
619
670
|
}
|
|
620
|
-
/**
|
|
621
|
-
*
|
|
622
|
-
*
|
|
671
|
+
/** Recover a JavaScript variadic callable's native ABI from its declaration.
|
|
672
|
+
* Rest parameters and an implicit `arguments` array must keep their packing
|
|
673
|
+
* convention when the function flows through a value or an export. */
|
|
623
674
|
function jsArgumentsFunctionType(lowerer, t) {
|
|
624
675
|
if (!(t.flags & ts.TypeFlags.Object))
|
|
625
676
|
return null;
|
|
@@ -627,16 +678,19 @@ function jsArgumentsFunctionType(lowerer, t) {
|
|
|
627
678
|
if (sigs.length !== 1 || sigs[0].getTypeParameters().length !== 0 || lowerer.checker.getConstructSignatures(t).length !== 0 || lowerer.checker.getPropertiesOfType(t).length !== 0)
|
|
628
679
|
return null;
|
|
629
680
|
const decl = lowerer.checker.signatureDeclaration(sigs[0]);
|
|
630
|
-
if (decl === undefined || !(ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ||
|
|
631
|
-
!isJsSourceFile(decl.getSourceFile())
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
681
|
+
if (decl === undefined || !(ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl) || ts.isArrowFunction(decl)) ||
|
|
682
|
+
!isJsSourceFile(decl.getSourceFile()))
|
|
683
|
+
return null;
|
|
684
|
+
const hasRest = decl.parameters.some((p) => p.dotDotDotToken !== undefined);
|
|
685
|
+
if (!hasRest && (ts.isArrowFunction(decl) || !bodyReadsArguments(decl) ||
|
|
686
|
+
decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)))
|
|
635
687
|
return null;
|
|
636
688
|
const shapes = paramShapes(lowerer, decl.parameters);
|
|
637
689
|
const retType = lowerer.checker.getReturnTypeOfSignature(sigs[0]);
|
|
638
|
-
const ret = retType.flags & ts.TypeFlags.
|
|
639
|
-
|
|
690
|
+
const ret = retType.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)
|
|
691
|
+
? DYN
|
|
692
|
+
: retType.flags & ts.TypeFlags.Void ? VOID : lowerer.mapTypeOf(retType) ?? DYN;
|
|
693
|
+
return funcTypeFromParamShapes(hasRest ? shapes : [...shapes, { type: DYN, mode: "arguments" }], ret);
|
|
640
694
|
}
|
|
641
695
|
/** The one call signature of a PURE function type — single signature, no
|
|
642
696
|
* properties, no construct signatures, no type parameters, no rest params
|
|
@@ -720,6 +774,9 @@ export function jsFuncNameOf(node) {
|
|
|
720
774
|
if (p && ts.isVariableDeclaration(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
721
775
|
return p.name.text;
|
|
722
776
|
}
|
|
777
|
+
if (p && ts.isBindingElement(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
778
|
+
return p.name.text;
|
|
779
|
+
}
|
|
723
780
|
if (p && ts.isPropertyAssignment(p) && p.initializer === n && ts.isIdentifier(p.name)) {
|
|
724
781
|
return p.name.text;
|
|
725
782
|
}
|
|
@@ -731,6 +788,7 @@ export class Lowerer {
|
|
|
731
788
|
entry;
|
|
732
789
|
moduleOrder;
|
|
733
790
|
dynamic;
|
|
791
|
+
frontendServices;
|
|
734
792
|
checker;
|
|
735
793
|
diags = [];
|
|
736
794
|
fnSigsBySymbol = new Map();
|
|
@@ -935,6 +993,7 @@ export class Lowerer {
|
|
|
935
993
|
/** Non-null while an instance body lowers: type-parameter symbol →
|
|
936
994
|
* concrete IR type, consulted inside mapType's recursion. */
|
|
937
995
|
typeParamBindings = null;
|
|
996
|
+
localClassInstantiations = [];
|
|
938
997
|
/** The ts-level twin of typeParamBindings, non-null while a CALL-keyed
|
|
939
998
|
* instance body lowers: type-parameter symbol → the bound CHECKER type,
|
|
940
999
|
* consulted where the mapped IrType has already widened away information
|
|
@@ -959,10 +1018,23 @@ export class Lowerer {
|
|
|
959
1018
|
* aliases, so this carries the var/let form the checker cannot.
|
|
960
1019
|
* Scoped strictly by narrowingAliases (lowerIf / lowerCondition). */
|
|
961
1020
|
aliasNarrowTypes = new Map();
|
|
1021
|
+
/** These caches belong to this lowering pass. The program already owns
|
|
1022
|
+
* their symbol/node keys; no module-level cache should retain a pass. */
|
|
1023
|
+
classSymbolKeys = new Map();
|
|
1024
|
+
registeredClassSymbols = new Map();
|
|
1025
|
+
httpClientFnBindings = new Map();
|
|
1026
|
+
streamPropMutatedSyms = null;
|
|
1027
|
+
requestInitPropMutatedSyms = null;
|
|
1028
|
+
emitterEventTable = null;
|
|
1029
|
+
emitterComputedPatterns = [];
|
|
962
1030
|
/** Locals widened beyond the checker's type because an inferred indexed
|
|
963
1031
|
* read can be absent at runtime. Bare reads preserve that union until a
|
|
964
1032
|
* surrounding JavaScript guard/default consumes it. */
|
|
965
|
-
runtimeOptionalLocals = new
|
|
1033
|
+
runtimeOptionalLocals = new RuntimeOptionalLocals();
|
|
1034
|
+
/** An effectful switch test can change the original binding after the
|
|
1035
|
+
* discriminant was captured. A case match narrows the captured value,
|
|
1036
|
+
* not that mutable binding; preserve its tagged representation on reads. */
|
|
1037
|
+
unstableSwitchBindings = new Set();
|
|
966
1038
|
/** All storage slots widened for runtime absence, including slots whose
|
|
967
1039
|
* current control-flow branch has temporarily narrowed the value. */
|
|
968
1040
|
runtimeOptionalStorageLocals = new Set();
|
|
@@ -981,18 +1053,21 @@ export class Lowerer {
|
|
|
981
1053
|
runtimeOptionalBindingTypes = new Map();
|
|
982
1054
|
/** Concise callback/lambda returns promoted by the HOF callback prepass;
|
|
983
1055
|
* arrows have no declaration symbol to key in fnSigsBySymbol. */
|
|
984
|
-
runtimeOptionalFunctionReturns = new
|
|
1056
|
+
runtimeOptionalFunctionReturns = new Map();
|
|
1057
|
+
/** Intrinsic callback slots can supply a destination for fresh return
|
|
1058
|
+
* literals, such as a reduce accumulator with recursive union fields. */
|
|
1059
|
+
contextualFunctionReturns = new Map();
|
|
985
1060
|
/** Arithmetic over an unchecked string read can answer either NaN or a
|
|
986
1061
|
* string. Bindings and returns use this marker to retain that result union
|
|
987
1062
|
* through checker-bare string annotations. */
|
|
988
|
-
runtimeOptionalArithmeticTypes = new
|
|
1063
|
+
runtimeOptionalArithmeticTypes = new Map();
|
|
989
1064
|
/** Record fields promoted to an undefined-armed union by an indexed-read
|
|
990
1065
|
* value. The key is the concrete emitted shape and field name. */
|
|
991
1066
|
runtimeOptionalFields = new Set();
|
|
992
1067
|
/** Callback pattern parameters carry an optional source without making
|
|
993
1068
|
* every name destructured from a present source optional. */
|
|
994
|
-
runtimeOptionalPatternTypes = new
|
|
995
|
-
runtimeOptionalReduceTypes = new
|
|
1069
|
+
runtimeOptionalPatternTypes = new Map();
|
|
1070
|
+
runtimeOptionalReduceTypes = new Map();
|
|
996
1071
|
/** Capture entries and their origin share one mutable box. Normalize each
|
|
997
1072
|
* entry to the origin so writes and flow proofs stay synchronized. */
|
|
998
1073
|
runtimeOptionalRoots = new Map();
|
|
@@ -1268,6 +1343,15 @@ export class Lowerer {
|
|
|
1268
1343
|
/** Union re-tag helpers (%union.retag.N), interned per (from, to)
|
|
1269
1344
|
* unionId pair — see unionRetagHelper. */
|
|
1270
1345
|
retagHelpers = new Map();
|
|
1346
|
+
/** Copy-only routes depend on the two union contracts and discriminator
|
|
1347
|
+
* layouts, without recursive width assumptions or evolving class members. */
|
|
1348
|
+
copyRetagHelpers = new Map();
|
|
1349
|
+
unionLiteralOwners = new Map();
|
|
1350
|
+
strippedUndefinedArms = new Map();
|
|
1351
|
+
stdlibSymbols = new Map();
|
|
1352
|
+
/** Method adapter names are owned by class-method-values. Looking them
|
|
1353
|
+
* up must not scan and retain every unrelated lifted function. */
|
|
1354
|
+
classMethodValueHelpers = new Set();
|
|
1271
1355
|
/** Callee names of every interned coercion helper whose CALL mints a
|
|
1272
1356
|
* FRESH closure per evaluation (%fn.width.*, %fn.adapt.*,
|
|
1273
1357
|
* %fnval.spawnres.*). Registered at the mint site — NOT recovered by
|
|
@@ -1352,6 +1436,15 @@ export class Lowerer {
|
|
|
1352
1436
|
/** Keyed by program-wide qualified class name (what IR object types carry). */
|
|
1353
1437
|
classes = new Map();
|
|
1354
1438
|
classBySymbol = new Map();
|
|
1439
|
+
/** Named method slots observed before class collection need a callable
|
|
1440
|
+
* ABI and shared prototype descriptors instead of call-site specialization. */
|
|
1441
|
+
prototypeMethodAccesses = new Map();
|
|
1442
|
+
/** Inferred JS methods participating in an override chain keep a vtable
|
|
1443
|
+
* ABI instead of call-site specialization. Filled before class collection. */
|
|
1444
|
+
virtualJsMethods = new Set();
|
|
1445
|
+
/** Largest fixed argument list below a JS method, discovered before any
|
|
1446
|
+
* base vtable signature is collected. Unused checked slots carry undefined. */
|
|
1447
|
+
virtualJsMethodArity = new Map();
|
|
1355
1448
|
/** The class whose members are lowering — `super` binds lexically to it
|
|
1356
1449
|
* (arrows inside methods lower within this window, so they see it too). */
|
|
1357
1450
|
currentClass = null;
|
|
@@ -1404,6 +1497,7 @@ export class Lowerer {
|
|
|
1404
1497
|
* engine handle (a dynamic import's namespace object) — paramShape's
|
|
1405
1498
|
* early-out. */
|
|
1406
1499
|
jsvalParamOverrides = new Set();
|
|
1500
|
+
checkedCallbackParams = new Set();
|
|
1407
1501
|
/** Inline Promise.then parameters whose contextual type is a builtin
|
|
1408
1502
|
* module namespace anonymous object. The settled native token is the
|
|
1409
1503
|
* ABI truth even when the checker type has no stable module symbol. */
|
|
@@ -1493,27 +1587,19 @@ export class Lowerer {
|
|
|
1493
1587
|
// top level, top = the innermost nested function currently lowering).
|
|
1494
1588
|
fnStack = [];
|
|
1495
1589
|
liftedFns = [];
|
|
1590
|
+
/** One Error-method helper belongs to this lowering session. Its cached
|
|
1591
|
+
* dispatch revision needs no weak-key identity or process-global state. */
|
|
1592
|
+
errorMethodDispatchRevision = null;
|
|
1593
|
+
errorPropertyDispatchRevision = null;
|
|
1496
1594
|
lambdaCounter = 0;
|
|
1595
|
+
preparedClassFactories = new Map();
|
|
1596
|
+
preparingClassFactories = new Set();
|
|
1497
1597
|
/** Statement lists currently mid-lowering, innermost last: the forward-
|
|
1498
1598
|
* capture machinery needs to know which later statements of an OPEN list
|
|
1499
1599
|
* a symbol's declaration sits in, which scope frame list-level declarations
|
|
1500
1600
|
* register into, and where to insert predeclarations before closures or
|
|
1501
1601
|
* earlier source statements need them. */
|
|
1502
1602
|
activeStmtLists = [];
|
|
1503
|
-
/** Forward-captured consts pre-declared as TDZ boxes, keyed by symbol:
|
|
1504
|
-
* lowerVarDecl consumes the entry when the source declaration arrives and
|
|
1505
|
-
* emits the initializing `assign` instead of a fresh declaration. */
|
|
1506
|
-
tdzPredeclared = new Map();
|
|
1507
|
-
/** Nested function DECLARATIONS lowered eagerly by the forward-hoisting
|
|
1508
|
-
* machinery (predeclareForwardFnDecl — a reference above the declaration
|
|
1509
|
-
* in the same function, JS's function hoisting): the statement loop skips
|
|
1510
|
-
* the source statement when it arrives. */
|
|
1511
|
-
hoistedFnDecls = new Set();
|
|
1512
|
-
/** `var` bindings hoisted to their function root (hoistVarBinding), keyed
|
|
1513
|
-
* by the checker's merged symbol — every same-name `var` in one function
|
|
1514
|
-
* is one symbol, so one slot. Module-scope vars live in globalsBySymbol
|
|
1515
|
-
* instead. */
|
|
1516
|
-
hoistedVars = new Map();
|
|
1517
1603
|
/** Per-file `var` module globals whose type carries an undefined arm:
|
|
1518
1604
|
* lowerFileInit assigns them the interned undefined right after the
|
|
1519
1605
|
* run-once guard — JS hoists module vars to `undefined` at entry, so a
|
|
@@ -1602,13 +1688,19 @@ export class Lowerer {
|
|
|
1602
1688
|
let s = this.statsByFile.get(file);
|
|
1603
1689
|
if (!s)
|
|
1604
1690
|
this.statsByFile.set(file, (s = { total: 0, failed: 0, island: 0 }));
|
|
1605
|
-
|
|
1691
|
+
if (kind === "total")
|
|
1692
|
+
s.total += 1;
|
|
1693
|
+
else if (kind === "failed")
|
|
1694
|
+
s.failed += 1;
|
|
1695
|
+
else
|
|
1696
|
+
s.island += 1;
|
|
1606
1697
|
}
|
|
1607
1698
|
constructor(program, entry, moduleOrder, dynamic, mode = {}) {
|
|
1608
1699
|
this.program = program;
|
|
1609
1700
|
this.entry = entry;
|
|
1610
1701
|
this.moduleOrder = moduleOrder;
|
|
1611
1702
|
this.dynamic = dynamic;
|
|
1703
|
+
this.frontendServices = mode.frontendServices;
|
|
1612
1704
|
this.reachable = mode.reachable ?? null;
|
|
1613
1705
|
this.remainder = mode.remainder ?? false;
|
|
1614
1706
|
this.alreadyFlushed = mode.alreadyFlushed ?? new Set();
|
|
@@ -1633,10 +1725,46 @@ export class Lowerer {
|
|
|
1633
1725
|
classNamer: this.classNamer,
|
|
1634
1726
|
resolveTypeParam: this.typeParamResolver,
|
|
1635
1727
|
resolveTypeParamTs: this.typeParamTsResolver,
|
|
1636
|
-
genericClassInstance: (decl, ref) => this.genericClassInstanceType(decl, ref),
|
|
1728
|
+
genericClassInstance: (decl, ref, mapArgument) => this.genericClassInstanceType(decl, ref, mapArgument),
|
|
1637
1729
|
mixinClassInstance: (decl) => this.mixinTypeContext && this.mixinTypeContext.classNode === decl
|
|
1638
1730
|
? { kind: "object", className: this.mixinTypeContext.className }
|
|
1639
1731
|
: null,
|
|
1732
|
+
localClassInstance: (decl) => {
|
|
1733
|
+
// Computed heritage can close over parameters of its factory.
|
|
1734
|
+
// A speculative checker query outside that factory must not lower
|
|
1735
|
+
// the extends expression in the caller's lexical scope.
|
|
1736
|
+
if (!this.classes.has(this.classNamer(decl)) && !this.collectingExprClasses.has(decl) &&
|
|
1737
|
+
decl.heritageClauses?.some((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.some((base) => {
|
|
1738
|
+
const expression = base.expression;
|
|
1739
|
+
if (ts.isCallExpression(expression))
|
|
1740
|
+
return true;
|
|
1741
|
+
if (ts.isIdentifier(expression) && this.isStdlibGlobal(expression, expression.text))
|
|
1742
|
+
return false;
|
|
1743
|
+
const symbol = this.checker.getSymbolAtLocation(ts.isPropertyAccessExpression(expression) ? expression.name : expression);
|
|
1744
|
+
const resolved = symbol && symbol.flags & ts.SymbolFlags.Alias ? this.checker.getAliasedSymbol(symbol) : symbol;
|
|
1745
|
+
if (ts.isPropertyAccessExpression(expression) && this.isStdlibGlobal(expression.expression, "globalThis") &&
|
|
1746
|
+
this.builtinErrorInfoOf(resolved))
|
|
1747
|
+
return false;
|
|
1748
|
+
if (resolved && this.classBySymbol.has(resolved))
|
|
1749
|
+
return false;
|
|
1750
|
+
const mapped = this.mapTypeOf(this.typeOf(expression));
|
|
1751
|
+
return mapped?.kind !== "classval" || !this.classes.has(mapped.className);
|
|
1752
|
+
})))
|
|
1753
|
+
return null;
|
|
1754
|
+
for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
1755
|
+
if (!ts.isFunctionDeclaration(parent) && !ts.isFunctionExpression(parent) &&
|
|
1756
|
+
!ts.isArrowFunction(parent) && !ts.isMethodDeclaration(parent))
|
|
1757
|
+
continue;
|
|
1758
|
+
if (this.localClassInstantiations.some((entry) => entry.owner === parent))
|
|
1759
|
+
break;
|
|
1760
|
+
if (parent.typeParameters?.length || (implicitMonoFile(parent.getSourceFile()) && implicitAnyParamSymbolsOf(this, parent)))
|
|
1761
|
+
return null;
|
|
1762
|
+
}
|
|
1763
|
+
const className = this.classNamer(decl);
|
|
1764
|
+
if (!this.collectingExprClasses.has(decl))
|
|
1765
|
+
this.lowerClassExpressionInfo(decl);
|
|
1766
|
+
return { kind: "object", className };
|
|
1767
|
+
},
|
|
1640
1768
|
mixinIntersectionInstance: (widened) => mixinIntersectionInstanceType(this, widened),
|
|
1641
1769
|
isStdlibFile: this.isStdlibFile,
|
|
1642
1770
|
isNpmFile: this.isNpmFile,
|
|
@@ -1678,7 +1806,7 @@ export class Lowerer {
|
|
|
1678
1806
|
sym = this.checker.getAliasedSymbol(sym);
|
|
1679
1807
|
for (const decl of this.checker.declarationsOf(sym)) {
|
|
1680
1808
|
if (ts.isSourceFile(decl) && !decl.isDeclarationFile &&
|
|
1681
|
-
!decl.fileName.endsWith(".cts") && !isCjsJsFile(decl) &&
|
|
1809
|
+
!decl.fileName.endsWith(".cts") && !isCjsJsFile(decl, this.program) &&
|
|
1682
1810
|
this.moduleOrder.includes(decl)) {
|
|
1683
1811
|
return `file:${tsgoPath(resolve(decl.fileName))}`;
|
|
1684
1812
|
}
|
|
@@ -1717,9 +1845,25 @@ export class Lowerer {
|
|
|
1717
1845
|
* builds (no counter can drift between invocations),
|
|
1718
1846
|
* program-unique through the file qualifier, and collision-free with
|
|
1719
1847
|
* user identifiers ('%'). */
|
|
1720
|
-
classNamer = (decl) =>
|
|
1721
|
-
|
|
1722
|
-
|
|
1848
|
+
classNamer = (decl) => {
|
|
1849
|
+
const name = ts.isClassExpression(decl) || (() => {
|
|
1850
|
+
for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
1851
|
+
if (ts.isFunctionLike(parent))
|
|
1852
|
+
return true;
|
|
1853
|
+
}
|
|
1854
|
+
return false;
|
|
1855
|
+
})()
|
|
1856
|
+
? this.qualify(decl.getSourceFile(), `%cx${decl.getStart()}.${decl.name?.text ?? ""}`)
|
|
1857
|
+
: this.qualify(decl.getSourceFile(), nsPathPrefix(decl) + (decl.name ? decl.name.text : "%anon"));
|
|
1858
|
+
for (let index = this.localClassInstantiations.length - 1; index >= 0; index--) {
|
|
1859
|
+
const entry = this.localClassInstantiations[index];
|
|
1860
|
+
for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
1861
|
+
if (parent === entry.owner)
|
|
1862
|
+
return `${name}%${entry.name}`;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return name;
|
|
1866
|
+
};
|
|
1723
1867
|
/** Follows import aliases to the original declaration's symbol. Every
|
|
1724
1868
|
* value reference resolves through here, so it doubles as the flush
|
|
1725
1869
|
* point for deferred collection diagnostics: resolving a reference to a
|
|
@@ -1931,7 +2075,7 @@ export class Lowerer {
|
|
|
1931
2075
|
: undefined;
|
|
1932
2076
|
if (namespaceDecl === undefined)
|
|
1933
2077
|
return null;
|
|
1934
|
-
const importDecl = namespaceDecl.parent
|
|
2078
|
+
const importDecl = namespaceDecl.parent?.parent;
|
|
1935
2079
|
if (!ts.isImportDeclaration(importDecl) || !ts.isStringLiteral(importDecl.moduleSpecifier))
|
|
1936
2080
|
return null;
|
|
1937
2081
|
if (this.externalTypes.has(importDecl.moduleSpecifier.text))
|
|
@@ -1953,7 +2097,7 @@ export class Lowerer {
|
|
|
1953
2097
|
let specNode;
|
|
1954
2098
|
let importedName = null;
|
|
1955
2099
|
if (ts.isImportSpecifier(decl)) {
|
|
1956
|
-
const importDecl = decl.parent
|
|
2100
|
+
const importDecl = decl.parent?.parent?.parent;
|
|
1957
2101
|
if (ts.isImportDeclaration(importDecl))
|
|
1958
2102
|
specNode = importDecl.moduleSpecifier;
|
|
1959
2103
|
importedName = (decl.propertyName ?? decl.name).text;
|
|
@@ -1964,13 +2108,13 @@ export class Lowerer {
|
|
|
1964
2108
|
importedName = "default";
|
|
1965
2109
|
}
|
|
1966
2110
|
else if (ts.isNamespaceImport(decl)) {
|
|
1967
|
-
const importDecl = decl.parent
|
|
2111
|
+
const importDecl = decl.parent?.parent;
|
|
1968
2112
|
if (ts.isImportDeclaration(importDecl))
|
|
1969
2113
|
specNode = importDecl.moduleSpecifier;
|
|
1970
2114
|
importedName = null;
|
|
1971
2115
|
}
|
|
1972
2116
|
else if (ts.isExportSpecifier(decl)) {
|
|
1973
|
-
const exportDecl = decl.parent
|
|
2117
|
+
const exportDecl = decl.parent?.parent;
|
|
1974
2118
|
if (ts.isExportDeclaration(exportDecl))
|
|
1975
2119
|
specNode = exportDecl.moduleSpecifier;
|
|
1976
2120
|
importedName = (decl.propertyName ?? decl.name).text;
|
|
@@ -2031,13 +2175,13 @@ export class Lowerer {
|
|
|
2031
2175
|
name = "default";
|
|
2032
2176
|
}
|
|
2033
2177
|
else if (d && ts.isImportSpecifier(d)) {
|
|
2034
|
-
const idecl = d.parent
|
|
2178
|
+
const idecl = d.parent?.parent?.parent;
|
|
2035
2179
|
if (ts.isImportDeclaration(idecl))
|
|
2036
2180
|
spec = idecl.moduleSpecifier;
|
|
2037
2181
|
name = (d.propertyName ?? d.name).text;
|
|
2038
2182
|
}
|
|
2039
2183
|
else if (d && ts.isExportSpecifier(d)) {
|
|
2040
|
-
const edecl = d.parent
|
|
2184
|
+
const edecl = d.parent?.parent;
|
|
2041
2185
|
if (ts.isExportDeclaration(edecl))
|
|
2042
2186
|
spec = edecl.moduleSpecifier;
|
|
2043
2187
|
name = (d.propertyName ?? d.name).text;
|
|
@@ -2150,7 +2294,7 @@ export class Lowerer {
|
|
|
2150
2294
|
// relative imports; an opted-in --npm-static package is the fallback.
|
|
2151
2295
|
const dep = resolveImport(this.program, importDecl.getSourceFile(), spec) ??
|
|
2152
2296
|
npmStaticDepSf7(this.program, importDecl.getSourceFile(), spec);
|
|
2153
|
-
if (!dep || !isJsSourceFile(dep) || isNodeEsmFile(dep))
|
|
2297
|
+
if (!dep || !isJsSourceFile(dep) || isNodeEsmFile(dep, this.program))
|
|
2154
2298
|
return null;
|
|
2155
2299
|
return dep;
|
|
2156
2300
|
}
|
|
@@ -2170,8 +2314,8 @@ export class Lowerer {
|
|
|
2170
2314
|
return null;
|
|
2171
2315
|
const directSpec = requireSpecOf(decl.initializer);
|
|
2172
2316
|
if (directSpec !== null) {
|
|
2173
|
-
return resolveImport(this.program, decl.getSourceFile(), directSpec) ??
|
|
2174
|
-
npmStaticDepSf7(this.program, decl.getSourceFile(), directSpec);
|
|
2317
|
+
return resolveImport(this.program, decl.getSourceFile(), directSpec, "require") ??
|
|
2318
|
+
npmStaticDepSf7(this.program, decl.getSourceFile(), directSpec, "require");
|
|
2175
2319
|
}
|
|
2176
2320
|
return createRequireProgramModuleOf(this, decl.initializer)?.dep ?? null;
|
|
2177
2321
|
}
|
|
@@ -2382,7 +2526,7 @@ export class Lowerer {
|
|
|
2382
2526
|
while (changed) {
|
|
2383
2527
|
changed = false;
|
|
2384
2528
|
for (const fp of parts) {
|
|
2385
|
-
if (this.asyncInitFiles.has(fp.sf) || !isNodeEsmFile(fp.sf))
|
|
2529
|
+
if (this.asyncInitFiles.has(fp.sf) || !isNodeEsmFile(fp.sf, this.program))
|
|
2386
2530
|
continue;
|
|
2387
2531
|
if (orderedImportsOf(this.program, fp.sf).some(({ dep }) => dep !== null && this.asyncInitFiles.has(dep))) {
|
|
2388
2532
|
this.asyncInitFiles.add(fp.sf);
|
|
@@ -2406,9 +2550,14 @@ export class Lowerer {
|
|
|
2406
2550
|
}
|
|
2407
2551
|
const orderIndex = new Map(parts.map((fp, i) => [fp.sf, i]));
|
|
2408
2552
|
const partSet = new Set(parts.map((fp) => fp.sf));
|
|
2409
|
-
const staticDeps = (sf) =>
|
|
2410
|
-
|
|
2411
|
-
|
|
2553
|
+
const staticDeps = (sf) => {
|
|
2554
|
+
const dependencies = [];
|
|
2555
|
+
for (const { dep } of orderedImportsOf(this.program, sf)) {
|
|
2556
|
+
if (dep !== null && dep !== sf && partSet.has(dep))
|
|
2557
|
+
dependencies.push(dep);
|
|
2558
|
+
}
|
|
2559
|
+
return dependencies;
|
|
2560
|
+
};
|
|
2412
2561
|
// Tarjan SCCs over the same static graph. The last postorder member is
|
|
2413
2562
|
// a deterministic COMPONENT representative for internal-edge tests
|
|
2414
2563
|
// and global naming. The runtime evaluation root can differ: a cycle
|
|
@@ -2485,8 +2634,8 @@ export class Lowerer {
|
|
|
2485
2634
|
// Without the guarded %init call at this position
|
|
2486
2635
|
// those globals stay uninitialized: the dep's module body would never
|
|
2487
2636
|
// run.
|
|
2488
|
-
const dep = resolveImport(this.program, node.getSourceFile(), spec) ??
|
|
2489
|
-
npmStaticDepSf7(this.program, node.getSourceFile(), spec);
|
|
2637
|
+
const dep = resolveImport(this.program, node.getSourceFile(), spec, "require") ??
|
|
2638
|
+
npmStaticDepSf7(this.program, node.getSourceFile(), spec, "require");
|
|
2490
2639
|
if (!dep || dep.fileName.endsWith(".json"))
|
|
2491
2640
|
return null;
|
|
2492
2641
|
if (this.asyncInitFiles.has(dep)) {
|
|
@@ -2566,6 +2715,9 @@ export class Lowerer {
|
|
|
2566
2715
|
};
|
|
2567
2716
|
const functionDeclBySymbol = new Map();
|
|
2568
2717
|
const signatureBySymbol = new Map();
|
|
2718
|
+
const methodFamilies = new Map();
|
|
2719
|
+
const familyBySymbol = new Map();
|
|
2720
|
+
const optionalMethodFamilies = new Set();
|
|
2569
2721
|
for (const [symbol, sig] of this.fnSigsBySymbol)
|
|
2570
2722
|
signatureBySymbol.set(symbol, { params: sig.params, returnType: sig.returnType, top: sig });
|
|
2571
2723
|
for (const decl of fnDecls) {
|
|
@@ -2589,8 +2741,18 @@ export class Lowerer {
|
|
|
2589
2741
|
continue;
|
|
2590
2742
|
const symbol = symbolOf(member.name);
|
|
2591
2743
|
const sig = info.methods.get(mName);
|
|
2592
|
-
if (symbol && sig)
|
|
2744
|
+
if (symbol && sig) {
|
|
2593
2745
|
signatureBySymbol.set(symbol, { params: sig.params, returnType: sig.ret, method: sig });
|
|
2746
|
+
let root = info;
|
|
2747
|
+
for (let base = info.base; base; base = base.base)
|
|
2748
|
+
if (base.methods.has(mName))
|
|
2749
|
+
root = base;
|
|
2750
|
+
const key = `${root.def.name}:${mName}`;
|
|
2751
|
+
const family = methodFamilies.get(key) ?? [];
|
|
2752
|
+
family.push(symbol);
|
|
2753
|
+
methodFamilies.set(key, family);
|
|
2754
|
+
familyBySymbol.set(symbol, family);
|
|
2755
|
+
}
|
|
2594
2756
|
}
|
|
2595
2757
|
}
|
|
2596
2758
|
const peel = (node) => {
|
|
@@ -2600,6 +2762,32 @@ export class Lowerer {
|
|
|
2600
2762
|
}
|
|
2601
2763
|
return e;
|
|
2602
2764
|
};
|
|
2765
|
+
const callableSymbols = new Map();
|
|
2766
|
+
const callableSymbolOf = (node) => {
|
|
2767
|
+
const cached = callableSymbols.get(node);
|
|
2768
|
+
if (cached !== undefined)
|
|
2769
|
+
return cached;
|
|
2770
|
+
let symbol = symbolOf(ts.isPropertyAccessExpression(node) ? node.name : node);
|
|
2771
|
+
if (symbol === null || signatureBySymbol.has(symbol)) {
|
|
2772
|
+
callableSymbols.set(node, symbol);
|
|
2773
|
+
return symbol;
|
|
2774
|
+
}
|
|
2775
|
+
const seen = new Set();
|
|
2776
|
+
while (symbol && !signatureBySymbol.has(symbol) && !seen.has(symbol)) {
|
|
2777
|
+
seen.add(symbol);
|
|
2778
|
+
const declaration = this.checker.valueDeclarationOf(symbol);
|
|
2779
|
+
if (declaration && ts.isMethodDeclaration(declaration)) {
|
|
2780
|
+
symbol = symbolOf(declaration.name);
|
|
2781
|
+
}
|
|
2782
|
+
else if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isIdentifier(peel(declaration.initializer))) {
|
|
2783
|
+
symbol = symbolOf(peel(declaration.initializer));
|
|
2784
|
+
}
|
|
2785
|
+
else
|
|
2786
|
+
break;
|
|
2787
|
+
}
|
|
2788
|
+
callableSymbols.set(node, symbol);
|
|
2789
|
+
return symbol;
|
|
2790
|
+
};
|
|
2603
2791
|
const explicitlyNonNull = (node) => {
|
|
2604
2792
|
let e = node;
|
|
2605
2793
|
while (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isTypeAssertion(e) || ts.isNonNullExpression(e)) {
|
|
@@ -2661,13 +2849,17 @@ export class Lowerer {
|
|
|
2661
2849
|
this.mapTypeOf(this.typeOf(e))?.kind === "union" &&
|
|
2662
2850
|
this.armTag(this.mapTypeOf(this.typeOf(e)).unionId, UNDEFINED_T) >= 0)
|
|
2663
2851
|
return true;
|
|
2664
|
-
if (ts.isIdentifier(e))
|
|
2665
|
-
|
|
2852
|
+
if (ts.isIdentifier(e)) {
|
|
2853
|
+
const symbol = symbolOf(e);
|
|
2854
|
+
return symbol !== null && optionalSymbols.has(symbol);
|
|
2855
|
+
}
|
|
2666
2856
|
if (ts.isCallExpression(e) && ts.isIdentifier(e.expression)) {
|
|
2667
|
-
|
|
2857
|
+
const symbol = callableSymbolOf(e.expression);
|
|
2858
|
+
return symbol !== null && optionalReturns.has(symbol);
|
|
2668
2859
|
}
|
|
2669
2860
|
if (ts.isCallExpression(e) && ts.isPropertyAccessExpression(e.expression)) {
|
|
2670
|
-
|
|
2861
|
+
const symbol = callableSymbolOf(e.expression);
|
|
2862
|
+
return symbol !== null && optionalReturns.has(symbol);
|
|
2671
2863
|
}
|
|
2672
2864
|
if (ts.isConditionalExpression(e)) {
|
|
2673
2865
|
return mayBeOptional(e.whenTrue) || mayBeOptional(e.whenFalse);
|
|
@@ -2680,7 +2872,8 @@ export class Lowerer {
|
|
|
2680
2872
|
return mayBeOptional(e.left) || mayBeOptional(e.right);
|
|
2681
2873
|
}
|
|
2682
2874
|
if (ts.isPropertyAccessExpression(e) && ts.isIdentifier(e.expression)) {
|
|
2683
|
-
const
|
|
2875
|
+
const symbol = symbolOf(e.expression);
|
|
2876
|
+
const fields = symbol === null ? undefined : optionalFields.get(symbol);
|
|
2684
2877
|
return fields?.has(fieldName(e)) ?? false;
|
|
2685
2878
|
}
|
|
2686
2879
|
return false;
|
|
@@ -2690,9 +2883,11 @@ export class Lowerer {
|
|
|
2690
2883
|
if (!ts.isBinaryExpression(e) || e.operatorToken.kind !== ts.SyntaxKind.PlusToken)
|
|
2691
2884
|
return null;
|
|
2692
2885
|
const stringArrayRead = (part) => {
|
|
2693
|
-
const t = this.mapTypeOf(this.typeOf(part));
|
|
2694
2886
|
const p = peel(part);
|
|
2695
|
-
if (
|
|
2887
|
+
if (!ts.isElementAccessExpression(p))
|
|
2888
|
+
return false;
|
|
2889
|
+
const t = this.mapTypeOf(this.typeOf(part));
|
|
2890
|
+
if (t?.kind !== "string")
|
|
2696
2891
|
return false;
|
|
2697
2892
|
const recv = this.mapTypeOf(this.typeOf(p.expression));
|
|
2698
2893
|
return recv?.kind === "array" && recv.elem.kind === "string";
|
|
@@ -2767,19 +2962,36 @@ export class Lowerer {
|
|
|
2767
2962
|
return [0];
|
|
2768
2963
|
return null;
|
|
2769
2964
|
};
|
|
2770
|
-
|
|
2965
|
+
// Syntax does not change during the fixed point. Reuse its return sites
|
|
2966
|
+
// while recomputing their optionality from each pass's current bindings.
|
|
2967
|
+
const returnSites = new Map();
|
|
2968
|
+
const returnsOf = (fn) => {
|
|
2969
|
+
const cached = returnSites.get(fn);
|
|
2970
|
+
if (cached !== undefined)
|
|
2971
|
+
return cached;
|
|
2972
|
+
const expressions = [];
|
|
2973
|
+
returnSites.set(fn, expressions);
|
|
2771
2974
|
if (!fn.body)
|
|
2772
|
-
return
|
|
2773
|
-
if (!ts.isBlock(fn.body))
|
|
2774
|
-
|
|
2775
|
-
|
|
2975
|
+
return expressions;
|
|
2976
|
+
if (!ts.isBlock(fn.body)) {
|
|
2977
|
+
expressions.push(fn.body);
|
|
2978
|
+
}
|
|
2776
2979
|
ts.walkPreorder(fn.body, (node) => {
|
|
2777
2980
|
if (node !== fn.body && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)))
|
|
2778
2981
|
return "skip";
|
|
2779
|
-
if (ts.isReturnStatement(node) && node.expression
|
|
2780
|
-
|
|
2982
|
+
if (ts.isReturnStatement(node) && node.expression)
|
|
2983
|
+
expressions.push(node.expression);
|
|
2781
2984
|
return undefined;
|
|
2782
2985
|
});
|
|
2986
|
+
return expressions;
|
|
2987
|
+
};
|
|
2988
|
+
const bodyReturnsOptional = (fn) => {
|
|
2989
|
+
if (fn.body && !ts.isBlock(fn.body))
|
|
2990
|
+
return mayBeOptional(fn.body);
|
|
2991
|
+
let found = false;
|
|
2992
|
+
for (const expression of returnsOf(fn))
|
|
2993
|
+
if (mayBeOptional(expression))
|
|
2994
|
+
found = true;
|
|
2783
2995
|
return found;
|
|
2784
2996
|
};
|
|
2785
2997
|
const promoteHofCallback = (callback, parameterIndices, seen = new Set()) => {
|
|
@@ -2791,6 +3003,8 @@ export class Lowerer {
|
|
|
2791
3003
|
};
|
|
2792
3004
|
const promoteNode = (fn) => {
|
|
2793
3005
|
for (const parameterIndex of parameterIndices) {
|
|
3006
|
+
if (parameterIndex === undefined)
|
|
3007
|
+
continue;
|
|
2794
3008
|
const parameter = fn.parameters[parameterIndex];
|
|
2795
3009
|
if (!parameter)
|
|
2796
3010
|
continue;
|
|
@@ -2863,6 +3077,8 @@ export class Lowerer {
|
|
|
2863
3077
|
const sig = signatureBySymbol.get(symbol);
|
|
2864
3078
|
if (sig) {
|
|
2865
3079
|
for (const parameterIndex of parameterIndices) {
|
|
3080
|
+
if (parameterIndex === undefined)
|
|
3081
|
+
continue;
|
|
2866
3082
|
if (!sig.params[parameterIndex])
|
|
2867
3083
|
continue;
|
|
2868
3084
|
const before = sig.params[parameterIndex].type;
|
|
@@ -2878,6 +3094,8 @@ export class Lowerer {
|
|
|
2878
3094
|
if (valueType?.kind === "func") {
|
|
2879
3095
|
const params = valueType.params.slice();
|
|
2880
3096
|
for (const parameterIndex of parameterIndices) {
|
|
3097
|
+
if (parameterIndex === undefined)
|
|
3098
|
+
continue;
|
|
2881
3099
|
if (params[parameterIndex])
|
|
2882
3100
|
params[parameterIndex] = this.runtimeOptionalType(params[parameterIndex]);
|
|
2883
3101
|
}
|
|
@@ -2928,9 +3146,22 @@ export class Lowerer {
|
|
|
2928
3146
|
const decl = this.checker.valueDeclarationOf(symbol);
|
|
2929
3147
|
return !!decl && ts.isVariableDeclaration(decl) && !!decl.initializer && callbackReturnsOptional(decl.initializer, seen);
|
|
2930
3148
|
};
|
|
3149
|
+
const scanSites = new Map();
|
|
3150
|
+
const sitesOf = (sf) => {
|
|
3151
|
+
const cached = scanSites.get(sf);
|
|
3152
|
+
if (cached !== undefined)
|
|
3153
|
+
return cached;
|
|
3154
|
+
const nodes = [];
|
|
3155
|
+
ts.walkPreorder(sf, (node) => {
|
|
3156
|
+
if (ts.isVariableDeclaration(node) || ts.isBinaryExpression(node) || ts.isCallExpression(node))
|
|
3157
|
+
nodes.push(node);
|
|
3158
|
+
});
|
|
3159
|
+
scanSites.set(sf, nodes);
|
|
3160
|
+
return nodes;
|
|
3161
|
+
};
|
|
2931
3162
|
const scanFile = (sf) => {
|
|
2932
3163
|
let changed = false;
|
|
2933
|
-
|
|
3164
|
+
const scan = (node) => {
|
|
2934
3165
|
if (ts.isVariableDeclaration(node)) {
|
|
2935
3166
|
if (node.initializer) {
|
|
2936
3167
|
if (ts.isIdentifier(node.name) && isDynamicObjectEntryRead(node.initializer)) {
|
|
@@ -3021,102 +3252,137 @@ export class Lowerer {
|
|
|
3021
3252
|
}
|
|
3022
3253
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
|
|
3023
3254
|
const callbackIndices = hofCallbackIndices(node.expression.name.text, node.arguments.length >= 2);
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
receiver
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3255
|
+
const callback = node.arguments[0];
|
|
3256
|
+
if (callbackIndices !== null && callback !== undefined && !ts.isSpreadElement(callback)) {
|
|
3257
|
+
const receiverNode = node.expression.expression;
|
|
3258
|
+
const receiverTs = this.typeOf(receiverNode);
|
|
3259
|
+
let receiver = this.mapTypeOf(receiverTs);
|
|
3260
|
+
// An array method after an optional-chain guard only runs on the
|
|
3261
|
+
// present receiver. The checker includes the chain's short-circuit
|
|
3262
|
+
// undefined in intermediate call types, so use the same narrowed
|
|
3263
|
+
// receiver the method lowerer sees when promoting HOF callbacks.
|
|
3264
|
+
if (receiver?.kind === "union" &&
|
|
3265
|
+
(node.expression.questionDotToken !== undefined || isOptionalChainTail(this, node))) {
|
|
3266
|
+
receiver = this.mapTypeOf(this.checker.getNonNullableType(receiverTs));
|
|
3267
|
+
}
|
|
3268
|
+
const tuple = receiver?.kind === "record" && this.shapes.get(receiver.shapeId)?.tuple === true;
|
|
3269
|
+
// A JS/evolving-any array may have acquired a precise FLOW type
|
|
3270
|
+
// at this call while its actual binding remains a checked-dynamic
|
|
3271
|
+
// array. Its callback consumes DYN values through runtime method
|
|
3272
|
+
// dispatch, so widening that callback to the native array value
|
|
3273
|
+
// ABI makes it impossible to box back into DYN. Judge a simple
|
|
3274
|
+
// binding by its declaration type, the same storage fact local
|
|
3275
|
+
// declaration lowering uses.
|
|
3276
|
+
let nativeArrayReceiver = receiver?.kind === "array" || tuple;
|
|
3277
|
+
if (nativeArrayReceiver && ts.isIdentifier(receiverNode)) {
|
|
3278
|
+
const receiverSymbol = symbolOf(receiverNode);
|
|
3279
|
+
const declaration = receiverSymbol ? this.checker.valueDeclarationOf(receiverSymbol) : undefined;
|
|
3280
|
+
if (declaration && ts.isVariableDeclaration(declaration)) {
|
|
3281
|
+
const declared = this.mapTypeOf(this.typeOf(declaration.name));
|
|
3282
|
+
if (declared?.kind !== "array" && !(declared?.kind === "record" && this.shapes.get(declared.shapeId)?.tuple === true)) {
|
|
3283
|
+
nativeArrayReceiver = false;
|
|
3284
|
+
}
|
|
3052
3285
|
}
|
|
3053
3286
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
if (promoteHofCallback(callback, callbackIndices))
|
|
3057
|
-
changed = true;
|
|
3058
|
-
const method = node.expression.name.text;
|
|
3059
|
-
if ((method === "reduce" || method === "reduceRight") &&
|
|
3060
|
-
(node.arguments.length < 2 || callbackReturnsOptional(callback))) {
|
|
3061
|
-
if (promoteHofCallback(callback, [0, 1]))
|
|
3062
|
-
changed = true;
|
|
3063
|
-
const result = this.runtimeOptionalType(this.irTypeOf(node));
|
|
3064
|
-
const previous = this.runtimeOptionalReduceTypes.get(node);
|
|
3065
|
-
if (!previous || !typeEquals(previous, result)) {
|
|
3066
|
-
this.runtimeOptionalReduceTypes.set(node, result);
|
|
3287
|
+
if (nativeArrayReceiver) {
|
|
3288
|
+
if (promoteHofCallback(callback, callbackIndices))
|
|
3067
3289
|
changed = true;
|
|
3290
|
+
const method = node.expression.name.text;
|
|
3291
|
+
if ((method === "reduce" || method === "reduceRight") &&
|
|
3292
|
+
(node.arguments.length < 2 || callbackReturnsOptional(callback))) {
|
|
3293
|
+
if (promoteHofCallback(callback, [0, 1]))
|
|
3294
|
+
changed = true;
|
|
3295
|
+
const result = this.runtimeOptionalType(this.irTypeOf(node));
|
|
3296
|
+
const previous = this.runtimeOptionalReduceTypes.get(node);
|
|
3297
|
+
if (!previous || !typeEquals(previous, result)) {
|
|
3298
|
+
this.runtimeOptionalReduceTypes.set(node, result);
|
|
3299
|
+
changed = true;
|
|
3300
|
+
}
|
|
3068
3301
|
}
|
|
3069
3302
|
}
|
|
3070
3303
|
}
|
|
3071
3304
|
}
|
|
3072
3305
|
if (ts.isCallExpression(node) &&
|
|
3073
3306
|
(ts.isIdentifier(node.expression) || ts.isPropertyAccessExpression(node.expression))) {
|
|
3074
|
-
const
|
|
3075
|
-
const symbol = symbolOf(calleeNode);
|
|
3307
|
+
const symbol = callableSymbolOf(node.expression);
|
|
3076
3308
|
if (!symbol)
|
|
3077
3309
|
return;
|
|
3078
3310
|
const sig = signatureBySymbol.get(symbol);
|
|
3079
|
-
if (!sig)
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3311
|
+
if (!sig)
|
|
3312
|
+
return;
|
|
3313
|
+
// JSDoc describes the usual value, not a runtime arity check.
|
|
3314
|
+
// A short JavaScript call still passes undefined. Widen only the
|
|
3315
|
+
// observed slots before bodies lower so both caller and callee
|
|
3316
|
+
// agree on that value's representation.
|
|
3317
|
+
const callee = functionDeclBySymbol.get(symbol);
|
|
3318
|
+
if (callee && isJsSourceFile(callee.getSourceFile()) && !node.arguments.some(ts.isSpreadElement)) {
|
|
3319
|
+
for (let i = 0; i < sig.params.length; i++) {
|
|
3320
|
+
const arg = node.arguments[i];
|
|
3321
|
+
if (arg && (this.typeOf(arg).flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) === 0)
|
|
3322
|
+
continue;
|
|
3323
|
+
const family = familyBySymbol.get(symbol);
|
|
3324
|
+
if (family)
|
|
3325
|
+
optionalMethodFamilies.add(family);
|
|
3326
|
+
for (const target of familyBySymbol.get(symbol) ?? [symbol]) {
|
|
3327
|
+
const shape = signatureBySymbol.get(target)?.params[i];
|
|
3328
|
+
if (!shape || shape.mode !== "required")
|
|
3329
|
+
continue;
|
|
3330
|
+
const widened = addUndefined(shape.type);
|
|
3331
|
+
if (typeEquals(shape.type, widened))
|
|
3332
|
+
continue;
|
|
3333
|
+
shape.type = widened;
|
|
3334
|
+
const parameter = functionDeclBySymbol.get(target)?.parameters[i];
|
|
3335
|
+
if (parameter) {
|
|
3336
|
+
for (const bound of boundIdentifiersOf(parameter.name)) {
|
|
3337
|
+
const boundSymbol = symbolOf(bound);
|
|
3338
|
+
if (boundSymbol) {
|
|
3339
|
+
optionalSymbols.add(boundSymbol);
|
|
3340
|
+
if (ts.isIdentifier(parameter.name))
|
|
3341
|
+
this.runtimeOptionalBindingTypes.set(boundSymbol, shape.type);
|
|
3102
3342
|
}
|
|
3103
3343
|
}
|
|
3104
|
-
}
|
|
3344
|
+
}
|
|
3345
|
+
changed = true;
|
|
3105
3346
|
}
|
|
3106
3347
|
}
|
|
3107
|
-
return;
|
|
3108
3348
|
}
|
|
3109
|
-
|
|
3110
|
-
|
|
3349
|
+
const restAt = sig.params.findIndex((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest" || shape.mode === "arguments");
|
|
3350
|
+
node.arguments.forEach((arg, argumentIndex) => {
|
|
3351
|
+
const i = restAt >= 0 && argumentIndex >= restAt ? restAt : argumentIndex;
|
|
3352
|
+
const shape = sig.params[i];
|
|
3353
|
+
const callbackSlot = shape?.type;
|
|
3111
3354
|
if (callbackSlot?.kind === "func" && !ts.isSpreadElement(arg)) {
|
|
3112
3355
|
const optionalCallbackParams = callbackSlot.params.flatMap((type, index) => type.kind === "union" && this.armTag(type.unionId, UNDEFINED_T) >= 0 ? [index] : []);
|
|
3113
3356
|
if (optionalCallbackParams.length > 0 && promoteHofCallback(arg, optionalCallbackParams)) {
|
|
3114
3357
|
changed = true;
|
|
3115
3358
|
}
|
|
3116
3359
|
}
|
|
3117
|
-
if (ts.isSpreadElement(arg) || !mayBeOptional(arg) || !
|
|
3360
|
+
if (ts.isSpreadElement(arg) || !mayBeOptional(arg) || !shape)
|
|
3361
|
+
return;
|
|
3362
|
+
if (i === restAt) {
|
|
3363
|
+
// A rest binding always receives an array. An unchecked
|
|
3364
|
+
// argument can make its elements undefined, not the pack.
|
|
3365
|
+
// Keep every virtual implementation on the same array ABI.
|
|
3366
|
+
for (const target of familyBySymbol.get(symbol) ?? [symbol]) {
|
|
3367
|
+
const rest = signatureBySymbol.get(target)?.params[i];
|
|
3368
|
+
if (rest?.mode !== "rest" || rest.type.kind !== "array")
|
|
3369
|
+
continue;
|
|
3370
|
+
const widened = arrayOf(addUndefined(rest.type.elem));
|
|
3371
|
+
if (typeEquals(rest.type, widened))
|
|
3372
|
+
continue;
|
|
3373
|
+
rest.type = widened;
|
|
3374
|
+
const parameter = functionDeclBySymbol.get(target)?.parameters[i];
|
|
3375
|
+
if (parameter && ts.isIdentifier(parameter.name)) {
|
|
3376
|
+
const bound = symbolOf(parameter.name);
|
|
3377
|
+
if (bound)
|
|
3378
|
+
this.runtimeOptionalBindingTypes.set(bound, widened);
|
|
3379
|
+
}
|
|
3380
|
+
changed = true;
|
|
3381
|
+
}
|
|
3118
3382
|
return;
|
|
3383
|
+
}
|
|
3119
3384
|
const set = optionalParams.get(symbol) ?? new Set();
|
|
3385
|
+
shape.type = addUndefined(shape.type);
|
|
3120
3386
|
const before = set.size;
|
|
3121
3387
|
set.add(i);
|
|
3122
3388
|
optionalParams.set(symbol, set);
|
|
@@ -3136,40 +3402,24 @@ export class Lowerer {
|
|
|
3136
3402
|
}
|
|
3137
3403
|
});
|
|
3138
3404
|
}
|
|
3139
|
-
}
|
|
3405
|
+
};
|
|
3406
|
+
for (const node of sitesOf(sf))
|
|
3407
|
+
scan(node);
|
|
3140
3408
|
return changed;
|
|
3141
3409
|
};
|
|
3142
3410
|
const scanReturns = (symbol, decl) => {
|
|
3143
|
-
if (!decl.body)
|
|
3144
|
-
return false;
|
|
3145
3411
|
let changed = false;
|
|
3146
|
-
|
|
3147
|
-
optionalReturns.
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
const arithmetic = optionalStringArithmeticType(
|
|
3412
|
+
for (const expression of returnsOf(decl)) {
|
|
3413
|
+
if (mayBeOptional(expression) && !optionalReturns.has(symbol)) {
|
|
3414
|
+
optionalReturns.add(symbol);
|
|
3415
|
+
changed = true;
|
|
3416
|
+
}
|
|
3417
|
+
const arithmetic = optionalStringArithmeticType(expression);
|
|
3152
3418
|
if (arithmetic && !arithmeticReturns.has(symbol)) {
|
|
3153
3419
|
arithmeticReturns.set(symbol, arithmetic);
|
|
3154
3420
|
changed = true;
|
|
3155
3421
|
}
|
|
3156
3422
|
}
|
|
3157
|
-
ts.walkPreorder(decl.body, (node) => {
|
|
3158
|
-
if (node !== decl.body && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isMethodDeclaration(node)))
|
|
3159
|
-
return "skip";
|
|
3160
|
-
if (ts.isReturnStatement(node) && node.expression && mayBeOptional(node.expression) && !optionalReturns.has(symbol)) {
|
|
3161
|
-
optionalReturns.add(symbol);
|
|
3162
|
-
changed = true;
|
|
3163
|
-
}
|
|
3164
|
-
if (ts.isReturnStatement(node) && node.expression) {
|
|
3165
|
-
const arithmetic = optionalStringArithmeticType(node.expression);
|
|
3166
|
-
if (arithmetic && !arithmeticReturns.has(symbol)) {
|
|
3167
|
-
arithmeticReturns.set(symbol, arithmetic);
|
|
3168
|
-
changed = true;
|
|
3169
|
-
}
|
|
3170
|
-
}
|
|
3171
|
-
return undefined;
|
|
3172
|
-
});
|
|
3173
3423
|
return changed;
|
|
3174
3424
|
};
|
|
3175
3425
|
let changed = true;
|
|
@@ -3181,6 +3431,18 @@ export class Lowerer {
|
|
|
3181
3431
|
for (const [symbol, decl] of functionDeclBySymbol)
|
|
3182
3432
|
if (scanReturns(symbol, decl))
|
|
3183
3433
|
changed = true;
|
|
3434
|
+
// Every implementation of a virtual slot must retain the same ABI,
|
|
3435
|
+
// including when just one body forwards an omitted parameter.
|
|
3436
|
+
for (const family of optionalMethodFamilies) {
|
|
3437
|
+
if (!family.some((symbol) => optionalReturns.has(symbol)))
|
|
3438
|
+
continue;
|
|
3439
|
+
for (const symbol of family) {
|
|
3440
|
+
if (!optionalReturns.has(symbol)) {
|
|
3441
|
+
optionalReturns.add(symbol);
|
|
3442
|
+
changed = true;
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3184
3446
|
}
|
|
3185
3447
|
for (const [symbol, sig] of signatureBySymbol) {
|
|
3186
3448
|
const params = optionalParams.get(symbol);
|
|
@@ -3306,7 +3568,7 @@ export class Lowerer {
|
|
|
3306
3568
|
continue;
|
|
3307
3569
|
const sig = declSymbol ? this.fnSigsBySymbol.get(declSymbol) : undefined;
|
|
3308
3570
|
// A body nothing reaches never lowers: its constructs can't fail
|
|
3309
|
-
// the build and it leaves no trace in the emitted
|
|
3571
|
+
// the build and it leaves no trace in the emitted LLVM.
|
|
3310
3572
|
if (sig && !this.wantBody(sig.name))
|
|
3311
3573
|
continue;
|
|
3312
3574
|
const fn = this.lowerFunction(decl);
|
|
@@ -3352,7 +3614,10 @@ export class Lowerer {
|
|
|
3352
3614
|
let gc = 0;
|
|
3353
3615
|
let gi = 0;
|
|
3354
3616
|
let es = 0;
|
|
3355
|
-
|
|
3617
|
+
const classDispatch = new ClassDynamicDispatch();
|
|
3618
|
+
let dispatchChanged = !this.remainder;
|
|
3619
|
+
while (dispatchChanged ||
|
|
3620
|
+
ec < this.exprClasses.length ||
|
|
3356
3621
|
gc < this.genericClassInstances.length ||
|
|
3357
3622
|
gi < this.instantiationQueue.length ||
|
|
3358
3623
|
es < this.emitSpecQueue.length) {
|
|
@@ -3390,6 +3655,9 @@ export class Lowerer {
|
|
|
3390
3655
|
throw e;
|
|
3391
3656
|
}
|
|
3392
3657
|
}
|
|
3658
|
+
dispatchChanged = !this.remainder && classDispatch.process(this, [
|
|
3659
|
+
...functions, ...this.liftedFns, ...this.implicitFns,
|
|
3660
|
+
]);
|
|
3393
3661
|
}
|
|
3394
3662
|
}
|
|
3395
3663
|
// Lambdas lifted while lowering any of the above (plus synthetic
|
|
@@ -3423,6 +3691,7 @@ export class Lowerer {
|
|
|
3423
3691
|
/** Final retention, pruning, and module assembly shared by ordinary emit
|
|
3424
3692
|
* and the retained reachability worklist. */
|
|
3425
3693
|
finishModule(functions) {
|
|
3694
|
+
finalizeClassMethodValues(this, functions);
|
|
3426
3695
|
// Globals typed by a class that never REGISTERED (a JS class whose
|
|
3427
3696
|
// collection fenced — Symbol-keyed fields, an unsupported base): the
|
|
3428
3697
|
// declaration statement and every use compiled to runtime fences, but
|
|
@@ -3433,8 +3702,9 @@ export class Lowerer {
|
|
|
3433
3702
|
// fences), so drop it — guarded by a reference scan, with the
|
|
3434
3703
|
// validator's registration check as the backstop for anything that
|
|
3435
3704
|
// does slip through with a live reference.
|
|
3436
|
-
const
|
|
3437
|
-
const
|
|
3705
|
+
const unregistered = new UnregisteredClassTypes((id) => this.shapes.get(id), (id) => this.unions.get(id), (name) => this.classes.has(name));
|
|
3706
|
+
const brokenGlobals = this.globalsList.filter((g) => unregistered.has(g.type));
|
|
3707
|
+
const brokenLocalFns = functions.filter((fn) => fn.locals.some((l) => unregistered.has(l.type)));
|
|
3438
3708
|
if (brokenGlobals.length > 0 || brokenLocalFns.length > 0) {
|
|
3439
3709
|
const referencedIn = (root) => {
|
|
3440
3710
|
const referenced = new Set();
|
|
@@ -3455,7 +3725,7 @@ export class Lowerer {
|
|
|
3455
3725
|
referenced.add(catchId);
|
|
3456
3726
|
// Closure captures name their source locals as PLAIN STRINGS
|
|
3457
3727
|
// (captures: string[]) — a captured broken-class local is live.
|
|
3458
|
-
if (rec["kind"] === "closure" && Array.isArray(rec["captures"])) {
|
|
3728
|
+
if ((rec["kind"] === "closure" || rec["kind"] === "classRef") && Array.isArray(rec["captures"])) {
|
|
3459
3729
|
for (const c of rec["captures"])
|
|
3460
3730
|
if (typeof c === "string")
|
|
3461
3731
|
referenced.add(c);
|
|
@@ -3483,8 +3753,8 @@ export class Lowerer {
|
|
|
3483
3753
|
for (const fn of brokenLocalFns) {
|
|
3484
3754
|
// Params and captures list their locals by id too — never prune
|
|
3485
3755
|
// those out from under them.
|
|
3486
|
-
const referenced = referencedIn([fn.body, fn.params, fn.captures ?? []]);
|
|
3487
|
-
fn.locals = fn.locals.filter((l) => referenced.has(l.id) || !
|
|
3756
|
+
const referenced = referencedIn([fn.body, fn.params, fn.captures ?? [], fn.classCaptures ?? []]);
|
|
3757
|
+
fn.locals = fn.locals.filter((l) => referenced.has(l.id) || !unregistered.has(l.type));
|
|
3488
3758
|
}
|
|
3489
3759
|
}
|
|
3490
3760
|
// Computed before the module gate: retention resolves every class name
|
|
@@ -3502,13 +3772,10 @@ export class Lowerer {
|
|
|
3502
3772
|
// slots), uniformly across params/locals/globals/fields/body types so
|
|
3503
3773
|
// every producer and consumer agrees. Programs with no unregistered
|
|
3504
3774
|
// reference are untouched — byte-stability holds.
|
|
3505
|
-
if (this.diags.length === 0) {
|
|
3506
|
-
this.sanitizeUnregisteredClassTypes([functions, this.globalsList, artifacts.classes, artifacts.records, artifacts.unions]);
|
|
3507
|
-
}
|
|
3508
3775
|
const module = this.diags.length > 0
|
|
3509
3776
|
? null
|
|
3510
3777
|
: {
|
|
3511
|
-
irVersion:
|
|
3778
|
+
irVersion: 13,
|
|
3512
3779
|
sourceFile: this.entry.fileName,
|
|
3513
3780
|
functions,
|
|
3514
3781
|
classes: artifacts.classes,
|
|
@@ -3519,6 +3786,8 @@ export class Lowerer {
|
|
|
3519
3786
|
entry: ENTRY_NAME,
|
|
3520
3787
|
...(this.ffiImports.length > 0 ? { ffiImports: [...this.ffiImports] } : {}),
|
|
3521
3788
|
};
|
|
3789
|
+
if (module)
|
|
3790
|
+
sanitizeUnregisteredClassTypes(module, (name) => this.classes.has(name));
|
|
3522
3791
|
return {
|
|
3523
3792
|
module,
|
|
3524
3793
|
diagnostics: this.diags,
|
|
@@ -3530,45 +3799,6 @@ export class Lowerer {
|
|
|
3530
3799
|
...(this.npmLazyTraps ? { npmLazyTraps: this.npmLazyTraps } : {}),
|
|
3531
3800
|
};
|
|
3532
3801
|
}
|
|
3533
|
-
/** The unregistered-class type sweep (run()'s last step before the
|
|
3534
|
-
* module assembles): every `{kind:"object"}` TYPE naming a class with
|
|
3535
|
-
* no registered ClassInfo is rewritten IN PLACE to the f64 dummy.
|
|
3536
|
-
* classval types are exempt (they emit the class-independent
|
|
3537
|
-
* `ScrClassObj *` — inert-but-valid storage, the validator's own
|
|
3538
|
-
* stance), and only type objects rewrite — node-level classNames
|
|
3539
|
-
* (`new`, upcasts) cannot reach here (their lowerings fence without a
|
|
3540
|
-
* registered class), so the validator still backstops those. */
|
|
3541
|
-
sanitizeUnregisteredClassTypes(roots) {
|
|
3542
|
-
const isUnregisteredObjectType = (v) => typeof v === "object" && v !== null &&
|
|
3543
|
-
v.kind === "object" &&
|
|
3544
|
-
typeof v.className === "string" &&
|
|
3545
|
-
!this.classes.has(v.className);
|
|
3546
|
-
const sweep = (node) => {
|
|
3547
|
-
if (node === null || typeof node !== "object")
|
|
3548
|
-
return;
|
|
3549
|
-
if (Array.isArray(node)) {
|
|
3550
|
-
node.forEach((item, i) => {
|
|
3551
|
-
if (isUnregisteredObjectType(item))
|
|
3552
|
-
node[i] = F64;
|
|
3553
|
-
else
|
|
3554
|
-
sweep(item);
|
|
3555
|
-
});
|
|
3556
|
-
return;
|
|
3557
|
-
}
|
|
3558
|
-
const rec = node;
|
|
3559
|
-
for (const key of Object.keys(rec)) {
|
|
3560
|
-
if (key === "loc")
|
|
3561
|
-
continue;
|
|
3562
|
-
const v = rec[key];
|
|
3563
|
-
if (isUnregisteredObjectType(v))
|
|
3564
|
-
rec[key] = F64;
|
|
3565
|
-
else
|
|
3566
|
-
sweep(v);
|
|
3567
|
-
}
|
|
3568
|
-
};
|
|
3569
|
-
for (const root of roots)
|
|
3570
|
-
sweep(root);
|
|
3571
|
-
}
|
|
3572
3802
|
/** True when `t` (recursively) names a class instance type with no
|
|
3573
3803
|
* registered ClassInfo — the shape of a JS class whose collection fenced.
|
|
3574
3804
|
* Used by run()'s global pruning; shapes/unions recurse with a seen-set
|
|
@@ -3650,6 +3880,8 @@ export class Lowerer {
|
|
|
3650
3880
|
// before collectProgram visits them one by one; reached body lowering
|
|
3651
3881
|
// will reuse the same answers later.
|
|
3652
3882
|
this.prefetchClassCollection(parts.flatMap((fp) => fp.classDecls));
|
|
3883
|
+
const collectionEdges = new Set();
|
|
3884
|
+
this.onEdge = (name) => { collectionEdges.add(name); };
|
|
3653
3885
|
this.collectProgram(parts);
|
|
3654
3886
|
this.analyzeRuntimeOptionalArrayReads(parts);
|
|
3655
3887
|
// Decorated classes analyze post-collection here too: the %init seeds
|
|
@@ -3666,11 +3898,16 @@ export class Lowerer {
|
|
|
3666
3898
|
const bodyRoots = (...roots) => roots.filter((root) => root !== undefined && root !== null);
|
|
3667
3899
|
const functionRoots = (decl) => bodyRoots(...decl.parameters.map((param) => param.initializer), decl.body);
|
|
3668
3900
|
const classCtorRoots = (info) => bodyRoots(...(info.ctor?.parameters ?? []).map((param) => param.initializer), info.ctor?.body, ...info.fieldOrder.map((field) => field.initializer));
|
|
3669
|
-
const classMemberRoots = (info) =>
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3901
|
+
const classMemberRoots = (info) => {
|
|
3902
|
+
const roots = classCtorRoots(info);
|
|
3903
|
+
for (const { member } of this.classMethodMembers(info))
|
|
3904
|
+
roots.push(...functionRoots(member));
|
|
3905
|
+
if (info.staticMethods) {
|
|
3906
|
+
for (const { member } of info.staticMethods.values())
|
|
3907
|
+
roots.push(...functionRoots(member));
|
|
3908
|
+
}
|
|
3909
|
+
return roots;
|
|
3910
|
+
};
|
|
3674
3911
|
let unitOrder = 0;
|
|
3675
3912
|
for (const fp of parts) {
|
|
3676
3913
|
for (const decl of fp.fnDecls) {
|
|
@@ -3707,13 +3944,13 @@ export class Lowerer {
|
|
|
3707
3944
|
units.set(`%${cName}.constructor`, {
|
|
3708
3945
|
order: unitOrder++,
|
|
3709
3946
|
roots: classCtorRoots(info),
|
|
3710
|
-
lower: () => this.lowerClassCtor(info),
|
|
3947
|
+
lower: () => info.localClass && !info.localClass.ready ? null : this.lowerClassCtor(info),
|
|
3711
3948
|
});
|
|
3712
3949
|
for (const { mName, member } of this.classMethodMembers(info)) {
|
|
3713
3950
|
units.set(`%${cName}.${mName}`, {
|
|
3714
3951
|
order: unitOrder++,
|
|
3715
3952
|
roots: functionRoots(member),
|
|
3716
|
-
lower: () => this.lowerClassMethodMember(info, member),
|
|
3953
|
+
lower: () => info.localClass && !info.localClass.ready ? null : this.lowerClassMethodMember(info, member),
|
|
3717
3954
|
});
|
|
3718
3955
|
}
|
|
3719
3956
|
for (const prop of info.throwingSetters) {
|
|
@@ -3724,12 +3961,14 @@ export class Lowerer {
|
|
|
3724
3961
|
});
|
|
3725
3962
|
}
|
|
3726
3963
|
}
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3964
|
+
if (info.staticMethods) {
|
|
3965
|
+
for (const [name, entry] of info.staticMethods) {
|
|
3966
|
+
units.set(`%${cName}.static:${name}`, {
|
|
3967
|
+
order: unitOrder++,
|
|
3968
|
+
roots: functionRoots(entry.member),
|
|
3969
|
+
lower: () => lowerStaticMethod(this, info, name),
|
|
3970
|
+
});
|
|
3971
|
+
}
|
|
3733
3972
|
}
|
|
3734
3973
|
}
|
|
3735
3974
|
// The old emit pass visited each file's functions and then its classes,
|
|
@@ -3764,8 +4003,10 @@ export class Lowerer {
|
|
|
3764
4003
|
rank(`%${cName}.constructor`);
|
|
3765
4004
|
for (const { mName } of this.classMethodMembers(info))
|
|
3766
4005
|
rank(`%${cName}.${mName}`);
|
|
3767
|
-
|
|
3768
|
-
|
|
4006
|
+
if (info.staticMethods) {
|
|
4007
|
+
for (const name of info.staticMethods.keys())
|
|
4008
|
+
rank(`%${cName}.static:${name}`);
|
|
4009
|
+
}
|
|
3769
4010
|
for (const prop of info.throwingSetters)
|
|
3770
4011
|
rank(`%${cName}.set:${prop}`);
|
|
3771
4012
|
}
|
|
@@ -3805,19 +4046,24 @@ export class Lowerer {
|
|
|
3805
4046
|
const cName = info.def.name;
|
|
3806
4047
|
const register = (name, roots, lower) => {
|
|
3807
4048
|
units.set(name, { order: unitOrder++, roots, lower });
|
|
4049
|
+
if (reachable.has(name))
|
|
4050
|
+
queue.push(name);
|
|
3808
4051
|
metadataPriority.set(name, [3, expressionMetadataOrder++]);
|
|
3809
4052
|
};
|
|
3810
|
-
register(`%${cName}.constructor`, classCtorRoots(info), () => this.lowerClassCtor(info));
|
|
4053
|
+
register(`%${cName}.constructor`, classCtorRoots(info), () => info.localClass && !info.localClass.ready ? null : this.lowerClassCtor(info));
|
|
3811
4054
|
for (const { mName, member } of this.classMethodMembers(info)) {
|
|
3812
|
-
register(`%${cName}.${mName}`, functionRoots(member), () => this.lowerClassMethodMember(info, member));
|
|
3813
|
-
}
|
|
3814
|
-
for (const [name, entry] of info.staticMethods ?? []) {
|
|
3815
|
-
register(`%${cName}.static:${name}`, functionRoots(entry.member), () => lowerStaticMethod(this, info, name));
|
|
4055
|
+
register(`%${cName}.${mName}`, functionRoots(member), () => info.localClass && !info.localClass.ready ? null : this.lowerClassMethodMember(info, member));
|
|
3816
4056
|
}
|
|
4057
|
+
if (info.staticMethods)
|
|
4058
|
+
for (const [name, entry] of info.staticMethods) {
|
|
4059
|
+
register(`%${cName}.static:${name}`, functionRoots(entry.member), () => lowerStaticMethod(this, info, name));
|
|
4060
|
+
}
|
|
3817
4061
|
for (const prop of info.throwingSetters) {
|
|
3818
4062
|
register(`%${cName}.set:${prop}`, [], () => this.throwingSetterFn(info, prop));
|
|
3819
4063
|
}
|
|
3820
4064
|
};
|
|
4065
|
+
for (const name of collectionEdges)
|
|
4066
|
+
this.onEdge(name);
|
|
3821
4067
|
// Generic instances queued by the bodies above lower here (an instance
|
|
3822
4068
|
// body fires edges of its own and can queue further instances of
|
|
3823
4069
|
// either kind — function instances and class instantiations drain to
|
|
@@ -3939,9 +4185,13 @@ export class Lowerer {
|
|
|
3939
4185
|
// turn queue more instances. Continue to the joint fixpoint; the initial
|
|
3940
4186
|
// queue above is the only portion whose discovery order differed from
|
|
3941
4187
|
// historical emit order.
|
|
4188
|
+
const classDispatch = new ClassDynamicDispatch(extraRoots !== undefined);
|
|
3942
4189
|
for (;;) {
|
|
3943
4190
|
drainInstances();
|
|
3944
|
-
|
|
4191
|
+
const dispatchChanged = classDispatch.process(this, [
|
|
4192
|
+
...loweredUnits.values(), ...initFunctions, ...instanceFunctions, ...this.liftedFns, ...this.implicitFns,
|
|
4193
|
+
]);
|
|
4194
|
+
if (queue.length === 0 && !dispatchChanged)
|
|
3945
4195
|
break;
|
|
3946
4196
|
drainUnits();
|
|
3947
4197
|
this.restoreGenericInstanceOrder(instLowered);
|
|
@@ -4027,7 +4277,8 @@ export class Lowerer {
|
|
|
4027
4277
|
if (target.kind === "statement")
|
|
4028
4278
|
return fence;
|
|
4029
4279
|
const params = target.params ?? [];
|
|
4030
|
-
const
|
|
4280
|
+
const targetName = target.name;
|
|
4281
|
+
const name = typeof targetName === "function" ? targetName() : targetName;
|
|
4031
4282
|
const fn = {
|
|
4032
4283
|
name,
|
|
4033
4284
|
params,
|
|
@@ -4198,7 +4449,7 @@ export class Lowerer {
|
|
|
4198
4449
|
// package-declared generic signature stays the package's story.
|
|
4199
4450
|
{
|
|
4200
4451
|
const parts = widened.isUnionType() ? ts.constituentTypes(widened) : [widened];
|
|
4201
|
-
if (parts.some((p) => this.checker.getCallSignatures(p).some((s) =>
|
|
4452
|
+
if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
|
|
4202
4453
|
this.pushDiag(genericSignatureTypeDiag(this.checker.typeToString(type), locOf(node)));
|
|
4203
4454
|
throw new PoisonError();
|
|
4204
4455
|
}
|
|
@@ -4279,8 +4530,8 @@ export class Lowerer {
|
|
|
4279
4530
|
RelativeTimeFormat: intlHint,
|
|
4280
4531
|
Segmenter: intlHint,
|
|
4281
4532
|
DisplayNames: intlHint,
|
|
4282
|
-
TextEncoder: "TextEncoder
|
|
4283
|
-
TextDecoder: "TextDecoder
|
|
4533
|
+
TextEncoder: "TextEncoder instances support encode(string) and encode(); other codec operations require a dedicated lowering",
|
|
4534
|
+
TextDecoder: "TextDecoder instances support recognized labels, fatal/ignoreBOM option literals, and streaming UTF-8/UTF-16/single-byte decode; runtime option objects remain unsupported",
|
|
4284
4535
|
};
|
|
4285
4536
|
this.pushDiag(noLoweringDiag(this.checker.typeToString(type), locOf(node), typeHints[stdlibOwnSym?.name ?? ""]));
|
|
4286
4537
|
throw new PoisonError();
|
|
@@ -4336,6 +4587,12 @@ export class Lowerer {
|
|
|
4336
4587
|
return fenceStaticReadableStreamMember(this, access, use);
|
|
4337
4588
|
}
|
|
4338
4589
|
typeOf(node) {
|
|
4590
|
+
// A checked JS method receives its actual call-site receiver. Its
|
|
4591
|
+
// declaration's inferred class type must not turn property reads back
|
|
4592
|
+
// into native field loads when the method is borrowed by another object.
|
|
4593
|
+
if (node.kind === ts.SyntaxKind.ThisKeyword && isJsSourceFile(node.getSourceFile()) &&
|
|
4594
|
+
this.fnStack.length > 0 && this.resolveThis()?.type.kind === "dyn")
|
|
4595
|
+
return this.checker.getUnknownType();
|
|
4339
4596
|
// Inside an optional-chain body the guarded receiver is typed by its
|
|
4340
4597
|
// NON-NULLISH type (the chain's tag test proved it), so every
|
|
4341
4598
|
// receiver-kind check downstream sees the narrowed arm.
|
|
@@ -4377,6 +4634,11 @@ export class Lowerer {
|
|
|
4377
4634
|
return bound;
|
|
4378
4635
|
if (typeEquals(narrowedIr, boundIr))
|
|
4379
4636
|
return t;
|
|
4637
|
+
// A checked value can contain any runtime kind. A checker-proven
|
|
4638
|
+
// branch narrow therefore cannot contradict this specialization;
|
|
4639
|
+
// reads still validate the payload through maybeNarrow.
|
|
4640
|
+
if (boundIr.kind === "dyn")
|
|
4641
|
+
return t;
|
|
4380
4642
|
// A union binding narrowed to one of its arms (typeof/equality
|
|
4381
4643
|
// guards over string|number bindings) — the narrow is truth.
|
|
4382
4644
|
if (boundIr.kind === "union") {
|
|
@@ -4397,10 +4659,11 @@ export class Lowerer {
|
|
|
4397
4659
|
return t;
|
|
4398
4660
|
}
|
|
4399
4661
|
/** mapType with this Lowerer's registries and (while a generic instance
|
|
4400
|
-
* body lowers) type-parameter bindings threaded through.
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4662
|
+
* body lowers) type-parameter bindings threaded through. A supplied mapper
|
|
4663
|
+
* retains interface-view substitutions while sharing ABI normalization. */
|
|
4664
|
+
mapTypeOf(t, mapper) {
|
|
4665
|
+
const mapped = mapper ? mapper(t) : mapType(t, this.typeCtx);
|
|
4666
|
+
return mapped === null || mapped.kind === "func" ? jsArgumentsFunctionType(this, t) ?? mapped : mapped;
|
|
4404
4667
|
}
|
|
4405
4668
|
/** The one position where a contextual UNION must not be adopted over the
|
|
4406
4669
|
* expression's own: the LEFT operand of `&&`, `||`, or `??`. Adopting a
|
|
@@ -4555,6 +4818,11 @@ export class Lowerer {
|
|
|
4555
4818
|
};
|
|
4556
4819
|
irTypeOf(node) {
|
|
4557
4820
|
const t = this.typeOf(node);
|
|
4821
|
+
// JS inference can leave mutable fields, accessor parameters and
|
|
4822
|
+
// locals at null/undefined despite later writes. Keep mutable native
|
|
4823
|
+
// storage instead of a slot restricted to the initializer's unit value.
|
|
4824
|
+
if (isJsSourceFile(node.getSourceFile()) && (t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)
|
|
4825
|
+
return DYN;
|
|
4558
4826
|
// A never-tainted JS type (neverTaintedJsType) maps — never rides as
|
|
4559
4827
|
// f64 — but must not: pre-empt the mapping so the JS fallback below
|
|
4560
4828
|
// answers instead.
|
|
@@ -4577,7 +4845,7 @@ export class Lowerer {
|
|
|
4577
4845
|
return dyn;
|
|
4578
4846
|
this.badType(node, t);
|
|
4579
4847
|
}
|
|
4580
|
-
return mapped;
|
|
4848
|
+
return jsOpenObjectType(node, mapped, this.shapes, this.unions);
|
|
4581
4849
|
}
|
|
4582
4850
|
/** Exact-shape enforcement (SC2002). Records are monomorphic structs, so
|
|
4583
4851
|
* everywhere a value flows into a typed slot (call arg, initializer,
|
|
@@ -4679,8 +4947,20 @@ export class Lowerer {
|
|
|
4679
4947
|
* this is THE tag for that (union, arm) pair program-wide — every wrap,
|
|
4680
4948
|
* narrow, and tag test agrees by construction. */
|
|
4681
4949
|
armTag(unionId, arm) {
|
|
4950
|
+
return this.unions.armTag(unionId, arm);
|
|
4951
|
+
}
|
|
4952
|
+
/** Literal ownership depends only on the union contract and record layouts.
|
|
4953
|
+
* Recheck it when recursive placeholders close, not for every literal. */
|
|
4954
|
+
literalUnionArm(unionId, values) {
|
|
4682
4955
|
const def = this.unions.get(unionId);
|
|
4683
|
-
|
|
4956
|
+
if (!def || values.length === 0)
|
|
4957
|
+
return null;
|
|
4958
|
+
let cached = this.unionLiteralOwners.get(unionId);
|
|
4959
|
+
if (!cached || cached.shapes !== this.shapes.revision || cached.unions !== this.unions.revision) {
|
|
4960
|
+
cached = { owners: discriminantOwners(def, (id) => this.shapes.get(id)), shapes: this.shapes.revision, unions: this.unions.revision };
|
|
4961
|
+
this.unionLiteralOwners.set(unionId, cached);
|
|
4962
|
+
}
|
|
4963
|
+
return literalUnionArm(def, values, (id) => this.shapes.get(id), cached.owners);
|
|
4684
4964
|
}
|
|
4685
4965
|
/** Implicit union construction. Wherever a value flows into a typed slot
|
|
4686
4966
|
* (initializer, assignment, call argument, return, field write, record
|
|
@@ -4795,24 +5075,29 @@ export class Lowerer {
|
|
|
4795
5075
|
return { kind: "promiseVoidWiden", value: expr, type: expected, loc: expr.loc };
|
|
4796
5076
|
}
|
|
4797
5077
|
if (expected.kind === "dyn" && expr.type.kind !== "dyn") {
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
//
|
|
4805
|
-
//
|
|
4806
|
-
//
|
|
4807
|
-
// errors into untyped helpers constantly.
|
|
5078
|
+
// Native void calls still have a JavaScript value: undefined. Keep
|
|
5079
|
+
// the call's effects before exposing that value to checked JS code.
|
|
5080
|
+
if (expr.type.kind === "void") {
|
|
5081
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr, loc: expr.loc }],
|
|
5082
|
+
result: dynUndefinedExpr(expr.loc), type: DYN, loc: expr.loc };
|
|
5083
|
+
}
|
|
5084
|
+
// Preserve the concrete class so checked property/method dispatch
|
|
5085
|
+
// discovers user Error subclasses. Runtime boxing selects the live
|
|
5086
|
+
// view by vtable even when an error first crosses through its base.
|
|
4808
5087
|
if (expr.type.kind === "object" && this.errorHierarchyClassOf(expr.type.className)) {
|
|
4809
5088
|
return {
|
|
4810
5089
|
kind: "dynFrom",
|
|
4811
|
-
value:
|
|
5090
|
+
value: expr,
|
|
4812
5091
|
type: DYN,
|
|
4813
5092
|
loc: expr.loc,
|
|
4814
5093
|
};
|
|
4815
5094
|
}
|
|
5095
|
+
if (expr.kind === "unitLit" || this.dynConvertible(expr.type)) {
|
|
5096
|
+
const shape = expr.type.kind === "record" ? this.shapes.get(expr.type.shapeId) : undefined;
|
|
5097
|
+
const liveRef = expr.type.kind === "array" || !!shape && (shape.fields.length > 0 || shape.indexValue !== undefined);
|
|
5098
|
+
return { kind: "dynFrom", value: expr, type: DYN, loc: expr.loc,
|
|
5099
|
+
...(liveRef ? { liveRef: true } : {}) };
|
|
5100
|
+
}
|
|
4816
5101
|
return expr;
|
|
4817
5102
|
}
|
|
4818
5103
|
// A dyn ('unknown') ACTUAL flowing into a typed slot the checker
|
|
@@ -4848,7 +5133,7 @@ export class Lowerer {
|
|
|
4848
5133
|
const funcOk = expected.kind === "func" &&
|
|
4849
5134
|
canAdaptDynFuncTo(expected, (id) => this.shapes.get(id), (id) => this.unions.get(id));
|
|
4850
5135
|
const handleOk = DYN_HANDLE_KINDS.has(expected.kind);
|
|
4851
|
-
if (this.
|
|
5136
|
+
if (canDynCheckTo(expected, (id) => this.shapes.get(id), (id) => this.unions.get(id)) || undefArmedOk || bytesOk || errorOk || classOk || funcOk || handleOk) {
|
|
4852
5137
|
return { kind: "dynCheck", value: expr, type: expected, loc: expr.loc };
|
|
4853
5138
|
}
|
|
4854
5139
|
return expr;
|
|
@@ -5005,6 +5290,11 @@ export class Lowerer {
|
|
|
5005
5290
|
return expr;
|
|
5006
5291
|
}
|
|
5007
5292
|
const tag = this.armTag(expected.unionId, expr.type);
|
|
5293
|
+
if (tag >= 0 && expr.type.kind === "record" && expr.kind !== "recordLit") {
|
|
5294
|
+
const helper = this.recordUnionWrapHelper(expr.type, expected.unionId, expr.loc);
|
|
5295
|
+
if (helper)
|
|
5296
|
+
return { kind: "call", callee: helper, args: [expr], type: expected, loc: expr.loc };
|
|
5297
|
+
}
|
|
5008
5298
|
if (tag < 0) {
|
|
5009
5299
|
// A derived class flowing into a union with a base-class arm widens
|
|
5010
5300
|
// first (nearest ancestor arm wins), then wraps like any arm value.
|
|
@@ -5174,9 +5464,11 @@ export class Lowerer {
|
|
|
5174
5464
|
* before any helper exists. The cases, in order:
|
|
5175
5465
|
* copy — exact same type (typeEquals), the field/element moves as is
|
|
5176
5466
|
* retag — union into union, every arm mapped (unionRetagMappable —
|
|
5177
|
-
* identity arms
|
|
5178
|
-
*
|
|
5467
|
+
* identity arms and compatible payload conversions; a shared
|
|
5468
|
+
* discriminant may select different record destinations)
|
|
5179
5469
|
* wrap — a non-unit arm value into a union that contains it
|
|
5470
|
+
* discriminantWrap — identical recursive layouts distinguished by
|
|
5471
|
+
* their literal field value rather than their storage id
|
|
5180
5472
|
* liftWrap — a record/array value into a union with NO identical arm
|
|
5181
5473
|
* but exactly ONE arm it width-lifts into (the findRoute
|
|
5182
5474
|
* rule applied at every level; several candidates are
|
|
@@ -5211,25 +5503,55 @@ export class Lowerer {
|
|
|
5211
5503
|
if (isUnitType(src))
|
|
5212
5504
|
return null;
|
|
5213
5505
|
const tag = this.armTag(dst.unionId, src);
|
|
5214
|
-
if (tag >= 0)
|
|
5215
|
-
return { how: "wrap", tag };
|
|
5216
5506
|
const def = this.unions.get(dst.unionId);
|
|
5217
5507
|
if (!def)
|
|
5218
5508
|
return null;
|
|
5509
|
+
if (tag >= 0) {
|
|
5510
|
+
const shape = src.kind === "record" ? this.shapes.get(src.shapeId) : undefined;
|
|
5511
|
+
if (shape && planRecordUnionWrap(shape, def, (id) => this.shapes.get(id)))
|
|
5512
|
+
return { how: "discriminantWrap" };
|
|
5513
|
+
return { how: "wrap", tag };
|
|
5514
|
+
}
|
|
5219
5515
|
const candidates = [];
|
|
5220
5516
|
def.arms.forEach((arm, i) => {
|
|
5221
5517
|
if (isUnitType(arm))
|
|
5222
5518
|
return;
|
|
5223
5519
|
const sameFamily = (src.kind === "record" && arm.kind === "record") ||
|
|
5224
5520
|
(src.kind === "array" && arm.kind === "array") ||
|
|
5521
|
+
(src.kind === "func" && arm.kind === "func") ||
|
|
5522
|
+
(src.kind === "object" && arm.kind === "object") ||
|
|
5523
|
+
// Tuples already lift into ordinary array slots. Consider that
|
|
5524
|
+
// same conversion when the array is an arm of a union too.
|
|
5525
|
+
(src.kind === "record" && this.shapes.get(src.shapeId)?.tuple === true && arm.kind === "array") ||
|
|
5225
5526
|
(src.kind === "object" && arm.kind === "record") ||
|
|
5226
5527
|
(src.kind === "record" && arm.kind === "object");
|
|
5227
5528
|
if (sameFamily && this.widthLiftPlan(src, arm) !== null)
|
|
5228
5529
|
candidates.push({ tag: i, arm });
|
|
5229
5530
|
});
|
|
5230
|
-
|
|
5531
|
+
let selected = candidates;
|
|
5532
|
+
if (selected.length > 1 && src.kind === "record") {
|
|
5533
|
+
const source = this.shapes.get(src.shapeId);
|
|
5534
|
+
// An inferred JS union may widen its tag while retaining variants
|
|
5535
|
+
// with and without a value. Prefer the unique layout whose omitted
|
|
5536
|
+
// fields are explicitly undefined, rather than filling an optional
|
|
5537
|
+
// unknown slot and making both variants look equally compatible.
|
|
5538
|
+
const absentOnly = selected.filter(({ arm }) => {
|
|
5539
|
+
if (!source || arm.kind !== "record")
|
|
5540
|
+
return false;
|
|
5541
|
+
const target = this.shapes.get(arm.shapeId);
|
|
5542
|
+
return target !== undefined && target.fields.every((field) => {
|
|
5543
|
+
if (source.fields.some((present) => present.name === field.name))
|
|
5544
|
+
return true;
|
|
5545
|
+
return isUnitType(field.type) || field.type.kind === "union" &&
|
|
5546
|
+
this.unions.get(field.type.unionId)?.arms.every(isUnitType) === true;
|
|
5547
|
+
});
|
|
5548
|
+
});
|
|
5549
|
+
if (absentOnly.length === 1)
|
|
5550
|
+
selected = absentOnly;
|
|
5551
|
+
}
|
|
5552
|
+
if (selected.length !== 1)
|
|
5231
5553
|
return null;
|
|
5232
|
-
return { how: "liftWrap", tag:
|
|
5554
|
+
return { how: "liftWrap", tag: selected[0].tag, arm: selected[0].arm };
|
|
5233
5555
|
}
|
|
5234
5556
|
// A UNION source into a slot that is ONE of its arms (a width copy
|
|
5235
5557
|
// whose target field narrowed — the option-table choices shape:
|
|
@@ -5260,6 +5582,25 @@ export class Lowerer {
|
|
|
5260
5582
|
if (dst.kind === "record" && src.kind === "record") {
|
|
5261
5583
|
return this.recordWidthPlan(src.shapeId, dst.shapeId) !== null ? { how: "width" } : null;
|
|
5262
5584
|
}
|
|
5585
|
+
if (dst.kind === "record" && src.kind === "union") {
|
|
5586
|
+
// A union of records can share a structural destination without
|
|
5587
|
+
// choosing one payload layout in advance. Plan every arm: omitted
|
|
5588
|
+
// destination fields need the ordinary optional-field completion,
|
|
5589
|
+
// and a required field missing from any arm still rejects the pair.
|
|
5590
|
+
const from = this.unions.get(src.unionId);
|
|
5591
|
+
if (!from || from.arms.length === 0 || !from.arms.every((arm) => arm.kind === "record"))
|
|
5592
|
+
return null;
|
|
5593
|
+
const key = `unionWidth:${src.unionId}:${dst.shapeId}`;
|
|
5594
|
+
if (this.widthPlanning.has(key))
|
|
5595
|
+
return { how: "unionWidth" };
|
|
5596
|
+
this.widthPlanning.add(key);
|
|
5597
|
+
try {
|
|
5598
|
+
return from.arms.every((arm) => this.widthLiftPlan(arm, dst) !== null) ? { how: "unionWidth" } : null;
|
|
5599
|
+
}
|
|
5600
|
+
finally {
|
|
5601
|
+
this.widthPlanning.delete(key);
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5263
5604
|
if (dst.kind === "record" && src.kind === "object") {
|
|
5264
5605
|
return this.objToRecordPlan(src.className, dst.shapeId) !== null ? { how: "objWidth" } : null;
|
|
5265
5606
|
}
|
|
@@ -5313,6 +5654,14 @@ export class Lowerer {
|
|
|
5313
5654
|
throw new InternalCompilerError("lowerer bug: wrap lift against a non-union");
|
|
5314
5655
|
return { kind: "unionWrap", unionId: dst.unionId, tag: lift.tag, value, type: dst, loc };
|
|
5315
5656
|
}
|
|
5657
|
+
case "discriminantWrap": {
|
|
5658
|
+
if (dst.kind !== "union" || value.type.kind !== "record")
|
|
5659
|
+
throw new InternalCompilerError("lowerer bug: record discriminator lift shape");
|
|
5660
|
+
const helper = this.recordUnionWrapHelper(value.type, dst.unionId, loc);
|
|
5661
|
+
if (!helper)
|
|
5662
|
+
throw new InternalCompilerError("lowerer bug: planned record discriminator lift failed to intern");
|
|
5663
|
+
return { kind: "call", callee: helper, args: [value], type: dst, loc };
|
|
5664
|
+
}
|
|
5316
5665
|
case "retag": {
|
|
5317
5666
|
if (dst.kind !== "union" || value.type.kind !== "union")
|
|
5318
5667
|
throw new InternalCompilerError("lowerer bug: retag lift shape");
|
|
@@ -5338,6 +5687,12 @@ export class Lowerer {
|
|
|
5338
5687
|
throw new InternalCompilerError("lowerer bug: planned width lift failed to intern");
|
|
5339
5688
|
return { kind: "call", callee: helper, args: [value], type: dst, loc };
|
|
5340
5689
|
}
|
|
5690
|
+
case "unionWidth": {
|
|
5691
|
+
if (dst.kind !== "record" || value.type.kind !== "union")
|
|
5692
|
+
throw new InternalCompilerError("lowerer bug: union width lift shape");
|
|
5693
|
+
const helper = this.unionRecordWidthHelper(value.type.unionId, dst, loc);
|
|
5694
|
+
return { kind: "call", callee: helper, args: [value], type: dst, loc };
|
|
5695
|
+
}
|
|
5341
5696
|
case "arr": {
|
|
5342
5697
|
if (dst.kind !== "array" || value.type.kind !== "array")
|
|
5343
5698
|
throw new InternalCompilerError("lowerer bug: arr lift shape");
|
|
@@ -5409,6 +5764,50 @@ export class Lowerer {
|
|
|
5409
5764
|
}
|
|
5410
5765
|
}
|
|
5411
5766
|
}
|
|
5767
|
+
/** Dispatch a structural copy from its runtime union tag. Each record
|
|
5768
|
+
* payload has its own field offsets and optional-field completions;
|
|
5769
|
+
* interpreting all arms as the destination layout would corrupt memory.
|
|
5770
|
+
* Intern before descending so recursive record unions can reuse it. */
|
|
5771
|
+
unionRecordWidthHelper(fromId, target, loc) {
|
|
5772
|
+
const key = `unionWidth:${fromId}:${target.shapeId}`;
|
|
5773
|
+
const existing = this.widthHelpers.get(key);
|
|
5774
|
+
if (existing)
|
|
5775
|
+
return existing;
|
|
5776
|
+
const name = `%union.record.${this.widthHelpers.size}`;
|
|
5777
|
+
this.widthHelpers.set(key, name);
|
|
5778
|
+
const type = { kind: "union", unionId: fromId };
|
|
5779
|
+
const value = varRef("value.0", type, loc);
|
|
5780
|
+
const from = this.unions.get(fromId);
|
|
5781
|
+
if (!from)
|
|
5782
|
+
throw new InternalCompilerError("lowerer bug: missing record union");
|
|
5783
|
+
const body = [];
|
|
5784
|
+
from.arms.forEach((arm, tag) => {
|
|
5785
|
+
const lift = this.widthLiftPlan(arm, target);
|
|
5786
|
+
if (!lift || arm.kind !== "record")
|
|
5787
|
+
throw new InternalCompilerError("lowerer bug: invalid union record plan");
|
|
5788
|
+
const narrowed = { kind: "unionNarrow", unionId: fromId, tag, value, type: arm, loc };
|
|
5789
|
+
body.push({
|
|
5790
|
+
kind: "if",
|
|
5791
|
+
cond: { kind: "unionIsTag", unionId: fromId, tag, negated: false, value, type: BOOL, loc },
|
|
5792
|
+
then: [{ kind: "return", value: this.applyWidthLift(lift, narrowed, target, loc), loc }],
|
|
5793
|
+
else_: null, loc,
|
|
5794
|
+
});
|
|
5795
|
+
});
|
|
5796
|
+
body.push({
|
|
5797
|
+
kind: "throw",
|
|
5798
|
+
value: {
|
|
5799
|
+
kind: "libCall", fn: "error.new",
|
|
5800
|
+
args: [{ kind: "strLit", value: "invalid record union tag", type: STRING, loc }],
|
|
5801
|
+
type: { kind: "object", className: "%TypeError" }, loc,
|
|
5802
|
+
},
|
|
5803
|
+
loc,
|
|
5804
|
+
});
|
|
5805
|
+
this.liftedFns.push({
|
|
5806
|
+
name, params: [{ localId: "value.0", name: "value", type }], returnType: target,
|
|
5807
|
+
locals: [{ id: "value.0", name: "value", type, mutable: false }], body, loc,
|
|
5808
|
+
});
|
|
5809
|
+
return name;
|
|
5810
|
+
}
|
|
5412
5811
|
/** Interned `%rec.width.<n>(r)` — builds the target shape from a source
|
|
5413
5812
|
* record by copying fields: every target field must exist on the source
|
|
5414
5813
|
* with the EXACT same type, or with a type that LIFTS under
|
|
@@ -6157,6 +6556,7 @@ export class Lowerer {
|
|
|
6157
6556
|
{
|
|
6158
6557
|
kind: "callValue",
|
|
6159
6558
|
callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
|
|
6559
|
+
receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
|
|
6160
6560
|
args: [],
|
|
6161
6561
|
type: fromT.ret,
|
|
6162
6562
|
loc,
|
|
@@ -6289,9 +6689,33 @@ export class Lowerer {
|
|
|
6289
6689
|
// value — the call runs (a `never` thrower never comes back, so the
|
|
6290
6690
|
// trap is unreachable there), then the stranded TypeError.
|
|
6291
6691
|
let strandParams = false;
|
|
6692
|
+
const narrowedParams = new Map();
|
|
6693
|
+
const partialDynParams = new Map();
|
|
6292
6694
|
for (let i = 0; i < fromT.params.length; i++) {
|
|
6293
|
-
|
|
6294
|
-
|
|
6695
|
+
const actual = toT.params[i];
|
|
6696
|
+
const expected = fromT.params[i];
|
|
6697
|
+
if (this.coercibleValue(actual, expected))
|
|
6698
|
+
continue;
|
|
6699
|
+
if (actual.kind === "union" && expected.kind === "dyn") {
|
|
6700
|
+
const arms = this.unions.get(actual.unionId)?.arms.filter((arm) => this.dynConvertible(arm)) ?? [];
|
|
6701
|
+
if (arms.length > 0) {
|
|
6702
|
+
partialDynParams.set(i, arms.length === 1 ? arms[0] : { kind: "union", unionId: this.unions.intern(arms) });
|
|
6703
|
+
continue;
|
|
6704
|
+
}
|
|
6705
|
+
}
|
|
6706
|
+
// A stored native builtin can have a narrower supported overload
|
|
6707
|
+
// than its public declaration. Preserve every supported union arm
|
|
6708
|
+
// and reject only an invocation carrying an unsupported arm. This
|
|
6709
|
+
// is the union counterpart of the checked single-arm extraction.
|
|
6710
|
+
if (actual.kind === "union" && expected.kind === "union") {
|
|
6711
|
+
const source = this.unions.get(actual.unionId);
|
|
6712
|
+
const target = this.unions.get(expected.unionId);
|
|
6713
|
+
if (source && target && target.arms.every((arm) => this.armTag(actual.unionId, arm) >= 0)) {
|
|
6714
|
+
narrowedParams.set(i, new Set(source.arms.flatMap((arm, tag) => this.armTag(expected.unionId, arm) < 0 ? [tag] : [])));
|
|
6715
|
+
continue;
|
|
6716
|
+
}
|
|
6717
|
+
}
|
|
6718
|
+
strandParams = true;
|
|
6295
6719
|
}
|
|
6296
6720
|
let voidRet = null;
|
|
6297
6721
|
let strandRet = false;
|
|
@@ -6339,7 +6763,25 @@ export class Lowerer {
|
|
|
6339
6763
|
else {
|
|
6340
6764
|
const args = fromT.params.map((pt, i) => {
|
|
6341
6765
|
const aRef = { kind: "varRef", localId: `a.${i}`, type: toT.params[i], loc };
|
|
6342
|
-
const
|
|
6766
|
+
const partial = partialDynParams.get(i);
|
|
6767
|
+
if (partial && aRef.type.kind === "union") {
|
|
6768
|
+
const source = this.unions.get(aRef.type.unionId);
|
|
6769
|
+
const supported = partial.kind === "union" ? this.unions.get(partial.unionId).arms : [partial];
|
|
6770
|
+
const rejected = new Set(source.arms.flatMap((arm, tag) => supported.some((accepted) => typeEquals(accepted, arm)) ? [] : [tag]));
|
|
6771
|
+
const narrow = partial.kind === "union"
|
|
6772
|
+
? this.unionRetagHelper(aRef.type.unionId, partial.unionId, loc, rejected)
|
|
6773
|
+
: this.narrowedArmHelper(aRef.type.unionId, partial, loc);
|
|
6774
|
+
if (!narrow)
|
|
6775
|
+
throw new InternalCompilerError("lowerer bug: partial callable parameter stopped narrowing");
|
|
6776
|
+
return this.coerceToExpected({ kind: "call", callee: narrow, args: [aRef], type: partial, loc }, pt);
|
|
6777
|
+
}
|
|
6778
|
+
const narrowed = narrowedParams.get(i);
|
|
6779
|
+
const helper = narrowed && aRef.type.kind === "union" && pt.kind === "union"
|
|
6780
|
+
? this.unionRetagHelper(aRef.type.unionId, pt.unionId, loc, narrowed)
|
|
6781
|
+
: null;
|
|
6782
|
+
const converted = helper
|
|
6783
|
+
? { kind: "call", callee: helper, args: [aRef], type: pt, loc }
|
|
6784
|
+
: this.coerceToExpected(aRef, pt);
|
|
6343
6785
|
if (!typeEquals(converted.type, pt))
|
|
6344
6786
|
throw new InternalCompilerError("lowerer bug: probed fn-adapter param stopped coercing");
|
|
6345
6787
|
return converted;
|
|
@@ -6347,6 +6789,7 @@ export class Lowerer {
|
|
|
6347
6789
|
const call = {
|
|
6348
6790
|
kind: "callValue",
|
|
6349
6791
|
callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
|
|
6792
|
+
receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
|
|
6350
6793
|
args,
|
|
6351
6794
|
type: fromT.ret,
|
|
6352
6795
|
loc,
|
|
@@ -6508,6 +6951,7 @@ export class Lowerer {
|
|
|
6508
6951
|
init: {
|
|
6509
6952
|
kind: "callValue",
|
|
6510
6953
|
callee: { kind: "varRef", localId: "f.0", type: fromT, loc },
|
|
6954
|
+
receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
|
|
6511
6955
|
args: params.map((p) => ({ kind: "varRef", localId: p.localId, type: p.type, loc })),
|
|
6512
6956
|
type: fromT.ret,
|
|
6513
6957
|
loc,
|
|
@@ -6543,44 +6987,20 @@ export class Lowerer {
|
|
|
6543
6987
|
});
|
|
6544
6988
|
return name;
|
|
6545
6989
|
}
|
|
6546
|
-
/**
|
|
6547
|
-
*
|
|
6548
|
-
*
|
|
6549
|
-
* (unionNarrow + unionWrap — the payload pointer moves, no copy, so
|
|
6550
|
-
* ref-arm identity is preserved across the re-tag). Arms map by
|
|
6551
|
-
* canonical type (typeEquals): every non-unit source arm must exist in
|
|
6552
|
-
* the destination, or the pair isn't mappable (null — the caller keeps
|
|
6553
|
-
* the SC2003 fence). A stranded UNIT arm (undefined/null with no
|
|
6554
|
-
* destination arm) is different: it means tsc's picture at the site was
|
|
6555
|
-
* NARROWER than the IR type — control-flow narrowing to a sub-union, or
|
|
6556
|
-
* a non-null assertion, both of which erase at lowering — so the arm is
|
|
6557
|
-
* exactly the possibility the checker proved (or the source asserted)
|
|
6558
|
-
* away. It compiles to a runtime trap case throwing a catchable
|
|
6559
|
-
* TypeError-shaped string, the lying-cast stance (SEMANTICS.md): sound
|
|
6560
|
-
* narrowing never reaches it, a lying `!` throws instead of smuggling
|
|
6561
|
-
* an unrepresentable unit into the destination. */
|
|
6562
|
-
/** True when unionRetagHelper can bridge the pair — every non-unit
|
|
6563
|
-
* source arm exists (typeEquals) in the destination, or width-lifts
|
|
6564
|
-
* into exactly one destination arm (widthLiftPlan — record and array
|
|
6565
|
-
* arms compose the re-tag with the per-arm reshape). Pure: callers that
|
|
6566
|
-
* must validate a WHOLE plan before interning anything (recordWidthHelper)
|
|
6567
|
-
* probe with this so a failed later field never orphans a helper. */
|
|
6990
|
+
/** Validate the complete union conversion before interning helpers.
|
|
6991
|
+
* Recursive width plans close through the same in-progress pair guard;
|
|
6992
|
+
* no optimistic result is memoized after that planning stack unwinds. */
|
|
6568
6993
|
unionRetagMappable(fromId, toId) {
|
|
6569
6994
|
const from = this.unions.get(fromId);
|
|
6570
|
-
|
|
6995
|
+
const to = this.unions.get(toId);
|
|
6996
|
+
if (!from || !to)
|
|
6571
6997
|
return false;
|
|
6572
|
-
// The union-pair face of the widthPlanning cycle guard: recursive
|
|
6573
|
-
// aliases can close their cycle through a union without repeating a
|
|
6574
|
-
// record pair (`type Json = Json[] | undefined`) — an in-progress
|
|
6575
|
-
// pair re-entered answers "assume mappable", same greatest-fixed-point
|
|
6576
|
-
// reading as recordWidthPlan's.
|
|
6577
6998
|
const key = `u:${fromId}:${toId}`;
|
|
6578
6999
|
if (this.widthPlanning.has(key))
|
|
6579
7000
|
return true;
|
|
6580
7001
|
this.widthPlanning.add(key);
|
|
6581
7002
|
try {
|
|
6582
|
-
|
|
6583
|
-
return from.arms.every((arm) => isUnitType(arm) || this.widthLiftPlan(arm, toT) !== null);
|
|
7003
|
+
return planUnionRetag(from, to, (id) => this.shapes.get(id), (src, dst) => this.widthLiftPlan(src, dst)) !== null;
|
|
6584
7004
|
}
|
|
6585
7005
|
finally {
|
|
6586
7006
|
this.widthPlanning.delete(key);
|
|
@@ -6751,111 +7171,54 @@ export class Lowerer {
|
|
|
6751
7171
|
}
|
|
6752
7172
|
return { kind: "call", callee: name, args: isUnitType(src) ? [] : [expr], type: expected, loc };
|
|
6753
7173
|
}
|
|
7174
|
+
recordUnionWrapHelper(source, toId, loc) {
|
|
7175
|
+
const shape = this.shapes.get(source.shapeId);
|
|
7176
|
+
const to = this.unions.get(toId);
|
|
7177
|
+
if (!shape || !to)
|
|
7178
|
+
return null;
|
|
7179
|
+
const plan = planRecordUnionWrap(shape, to, (id) => this.shapes.get(id));
|
|
7180
|
+
if (!plan)
|
|
7181
|
+
return null;
|
|
7182
|
+
const key = `recordWrap:${source.shapeId}:${toId}`;
|
|
7183
|
+
const existing = this.retagHelpers.get(key);
|
|
7184
|
+
if (existing)
|
|
7185
|
+
return existing;
|
|
7186
|
+
const name = `%record.wrap.${this.retagHelpers.size}`;
|
|
7187
|
+
this.retagHelpers.set(key, name);
|
|
7188
|
+
this.liftedFns.push(buildRecordUnionWrap(name, source, to, plan, loc, (lift, value, dst) => this.applyWidthLift(lift, value, dst, loc)));
|
|
7189
|
+
return name;
|
|
7190
|
+
}
|
|
6754
7191
|
unionRetagHelper(fromId, toId, loc, trappable) {
|
|
6755
7192
|
const from = this.unions.get(fromId);
|
|
6756
7193
|
const to = this.unions.get(toId);
|
|
6757
7194
|
if (!from || !to)
|
|
6758
7195
|
return null;
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
//
|
|
6767
|
-
//
|
|
6768
|
-
//
|
|
6769
|
-
const
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
if (this.armTag(toId, arm) >= 0 || isUnitType(arm) || (trappable?.has(i) ?? false))
|
|
6773
|
-
return;
|
|
6774
|
-
const lp = this.widthLiftPlan(arm, toT);
|
|
6775
|
-
if (lp && lp.how === "liftWrap")
|
|
6776
|
-
lifts.set(i, lp);
|
|
6777
|
-
});
|
|
6778
|
-
// `trappable` extends the unit-arm rule to arms the CHECKER proved
|
|
6779
|
-
// away at the coercion site (narrowedRetagHelper): those may trap too.
|
|
6780
|
-
const ok = from.arms.every((arm, i) => this.armTag(toId, arm) >= 0 || isUnitType(arm) || (trappable?.has(i) ?? false) || lifts.has(i));
|
|
6781
|
-
if (!ok)
|
|
6782
|
-
return null;
|
|
6783
|
-
const mapping = from.arms.map((arm, i) => {
|
|
6784
|
-
const identity = this.armTag(toId, arm);
|
|
6785
|
-
return identity >= 0 ? identity : (lifts.get(i)?.tag ?? -1);
|
|
6786
|
-
});
|
|
6787
|
-
const stranded = mapping.flatMap((t, i) => (t < 0 ? [i] : []));
|
|
6788
|
-
// Lifts are a pure function of the (from, to) pair, so the historic
|
|
6789
|
-
// key stays sound for them; stranded arms depend on the SITE.
|
|
7196
|
+
const request = `${fromId}:${toId}:${trappable === undefined ? "" : [...trappable].sort((a, b) => a - b).join(".")}`;
|
|
7197
|
+
const cached = this.copyRetagHelpers.get(request);
|
|
7198
|
+
if (cached && cached.shapes === this.shapes.revision && cached.unions === this.unions.revision)
|
|
7199
|
+
return cached.name;
|
|
7200
|
+
const plan = planUnionRetag(from, to, (id) => this.shapes.get(id), (src, dst) => this.widthLiftPlan(src, dst), trappable);
|
|
7201
|
+
if (plan === null)
|
|
7202
|
+
return null;
|
|
7203
|
+
// The registry pair determines every route; only checker-proven
|
|
7204
|
+
// stranded arms vary by site. Publish the name before building widths
|
|
7205
|
+
// so recursive records and arrays can call this same helper.
|
|
7206
|
+
const stranded = [];
|
|
7207
|
+
plan.forEach((arm, tag) => { if (arm.kind === "trap")
|
|
7208
|
+
stranded.push(tag); });
|
|
6790
7209
|
const key = `${fromId}:${toId}:${stranded.join(".")}`;
|
|
6791
7210
|
const existing = this.retagHelpers.get(key);
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
if (tag < 0) {
|
|
6804
|
-
const what = isUnitType(arm)
|
|
6805
|
-
? (arm.kind === "undefinedT" ? "undefined" : "null")
|
|
6806
|
-
: `a '${this.fmt(arm)}' value`;
|
|
6807
|
-
then = [
|
|
6808
|
-
{
|
|
6809
|
-
kind: "throw",
|
|
6810
|
-
value: {
|
|
6811
|
-
kind: "libCall",
|
|
6812
|
-
fn: "error.new",
|
|
6813
|
-
args: [
|
|
6814
|
-
{
|
|
6815
|
-
kind: "strLit",
|
|
6816
|
-
value: `${what} is not representable in the target union (a value narrowed or asserted past it still held it)`,
|
|
6817
|
-
type: STRING,
|
|
6818
|
-
loc,
|
|
6819
|
-
},
|
|
6820
|
-
],
|
|
6821
|
-
type: { kind: "object", className: "%TypeError" },
|
|
6822
|
-
loc,
|
|
6823
|
-
},
|
|
6824
|
-
loc,
|
|
6825
|
-
},
|
|
6826
|
-
];
|
|
6827
|
-
}
|
|
6828
|
-
else {
|
|
6829
|
-
const value = isUnitType(arm)
|
|
6830
|
-
? { kind: "unitLit", unit: arm.kind === "undefinedT" ? "undefined" : "null", type: arm, loc }
|
|
6831
|
-
: { kind: "unionNarrow", unionId: fromId, tag: i, value: u, type: arm, loc };
|
|
6832
|
-
const lift = lifts.get(i);
|
|
6833
|
-
// Width-lifted arm: the narrowed payload reshapes into the
|
|
6834
|
-
// destination arm and wraps (applyWidthLift — planned above, so
|
|
6835
|
-
// the interns cannot fail here); identity arms re-wrap the same
|
|
6836
|
-
// payload pointer.
|
|
6837
|
-
const wrapped = lift
|
|
6838
|
-
? this.applyWidthLift(lift, value, toT, loc)
|
|
6839
|
-
: { kind: "unionWrap", unionId: toId, tag, value, type: toT, loc };
|
|
6840
|
-
then = [{ kind: "return", value: wrapped, loc }];
|
|
6841
|
-
}
|
|
6842
|
-
body.push({ kind: "if", cond, then, else_: null, loc });
|
|
6843
|
-
});
|
|
6844
|
-
// Unreachable when tags are exhaustive (they are, by construction);
|
|
6845
|
-
// satisfies the all-paths-return rule and keeps a corrupted tag loud.
|
|
6846
|
-
body.push({
|
|
6847
|
-
kind: "throw",
|
|
6848
|
-
value: { kind: "strLit", value: "scriptc: internal error: invalid union tag", type: STRING, loc },
|
|
6849
|
-
loc,
|
|
6850
|
-
});
|
|
6851
|
-
this.liftedFns.push({
|
|
6852
|
-
name,
|
|
6853
|
-
params: [{ localId: "u.0", name: "u", type: fromT }],
|
|
6854
|
-
returnType: toT,
|
|
6855
|
-
locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
|
|
6856
|
-
body,
|
|
6857
|
-
loc,
|
|
6858
|
-
});
|
|
7211
|
+
const name = existing ?? `%union.retag.${this.retagHelpers.size}`;
|
|
7212
|
+
if (!existing) {
|
|
7213
|
+
this.retagHelpers.set(key, name);
|
|
7214
|
+
this.liftedFns.push(buildUnionRetag(name, from, to, plan, loc, (lift, value, dst) => this.applyWidthLift(lift, value, dst, loc), (type) => this.fmt(type)));
|
|
7215
|
+
}
|
|
7216
|
+
// Width routes still revalidate on every request. Only a complete plan
|
|
7217
|
+
// of exact payload copies and site-proven traps can bypass planning.
|
|
7218
|
+
if (plan.every((arm) => arm.kind === "trap" || (arm.kind === "direct"
|
|
7219
|
+
? arm.route.lift.how === "copy" : arm.routes.every((route) => route.lift.how === "copy")))) {
|
|
7220
|
+
this.copyRetagHelpers.set(request, { name, shapes: this.shapes.revision, unions: this.unions.revision });
|
|
7221
|
+
}
|
|
6859
7222
|
return name;
|
|
6860
7223
|
}
|
|
6861
7224
|
/** Interned `%union.narrow.<n>(u)` — the CHECKED single-arm extraction
|
|
@@ -6881,55 +7244,10 @@ export class Lowerer {
|
|
|
6881
7244
|
const name = `%union.narrow.${this.narrowHelpers.size}`;
|
|
6882
7245
|
this.narrowHelpers.set(key, name);
|
|
6883
7246
|
this.checkedNarrowHelpers.add(name);
|
|
6884
|
-
const
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
if (i === tag)
|
|
6889
|
-
return; // the fall-through extraction below
|
|
6890
|
-
const what = isUnitType(arm)
|
|
6891
|
-
? (arm.kind === "undefinedT" ? "undefined" : "null")
|
|
6892
|
-
: `a '${this.fmt(arm)}' value`;
|
|
6893
|
-
body.push({
|
|
6894
|
-
kind: "if",
|
|
6895
|
-
cond: { kind: "unionIsTag", unionId: fromId, tag: i, negated: false, value: u, type: BOOL, loc },
|
|
6896
|
-
then: [
|
|
6897
|
-
{
|
|
6898
|
-
kind: "throw",
|
|
6899
|
-
value: {
|
|
6900
|
-
kind: "libCall",
|
|
6901
|
-
fn: "error.new",
|
|
6902
|
-
args: [
|
|
6903
|
-
{
|
|
6904
|
-
kind: "strLit",
|
|
6905
|
-
value: `${what} is not representable in the target union (a value narrowed or asserted past it still held it)`,
|
|
6906
|
-
type: STRING,
|
|
6907
|
-
loc,
|
|
6908
|
-
},
|
|
6909
|
-
],
|
|
6910
|
-
type: { kind: "object", className: "%TypeError" },
|
|
6911
|
-
loc,
|
|
6912
|
-
},
|
|
6913
|
-
loc,
|
|
6914
|
-
},
|
|
6915
|
-
],
|
|
6916
|
-
else_: null,
|
|
6917
|
-
loc,
|
|
6918
|
-
});
|
|
6919
|
-
});
|
|
6920
|
-
body.push({
|
|
6921
|
-
kind: "return",
|
|
6922
|
-
value: { kind: "unionNarrow", unionId: fromId, tag, value: u, type: target, loc },
|
|
6923
|
-
loc,
|
|
6924
|
-
});
|
|
6925
|
-
this.liftedFns.push({
|
|
6926
|
-
name,
|
|
6927
|
-
params: [{ localId: "u.0", name: "u", type: fromT }],
|
|
6928
|
-
returnType: target,
|
|
6929
|
-
locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
|
|
6930
|
-
body,
|
|
6931
|
-
loc,
|
|
6932
|
-
});
|
|
7247
|
+
const fn = buildUnionNarrow(name, from, target, loc, (type) => this.fmt(type));
|
|
7248
|
+
if (!fn)
|
|
7249
|
+
throw new InternalCompilerError("lowerer bug: invalid checked union extraction");
|
|
7250
|
+
this.liftedFns.push(fn);
|
|
6933
7251
|
return name;
|
|
6934
7252
|
}
|
|
6935
7253
|
/** The DEFERRED-INIT field read (`stream!: T` assigned past the
|
|
@@ -6957,32 +7275,13 @@ export class Lowerer {
|
|
|
6957
7275
|
return existing;
|
|
6958
7276
|
const name = `%deferred.read.${this.narrowHelpers.size}`;
|
|
6959
7277
|
this.narrowHelpers.set(key, name);
|
|
6960
|
-
const fromT = { kind: "union", unionId: fromId };
|
|
6961
|
-
const u = { kind: "varRef", localId: "u.0", type: fromT, loc };
|
|
6962
7278
|
const dflt = target.kind === "bool"
|
|
6963
7279
|
? { kind: "boolLit", value: false, type: BOOL, loc }
|
|
6964
7280
|
: { kind: "numLit", value: NaN, type: F64, loc };
|
|
6965
|
-
this.
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
locals: [{ id: "u.0", name: "u", type: fromT, mutable: true }],
|
|
6970
|
-
body: [
|
|
6971
|
-
{
|
|
6972
|
-
kind: "if",
|
|
6973
|
-
cond: { kind: "unionIsTag", unionId: fromId, tag: utag, negated: false, value: u, type: BOOL, loc },
|
|
6974
|
-
then: [{ kind: "return", value: dflt, loc }],
|
|
6975
|
-
else_: null,
|
|
6976
|
-
loc,
|
|
6977
|
-
},
|
|
6978
|
-
{
|
|
6979
|
-
kind: "return",
|
|
6980
|
-
value: { kind: "unionNarrow", unionId: fromId, tag, value: u, type: target, loc },
|
|
6981
|
-
loc,
|
|
6982
|
-
},
|
|
6983
|
-
],
|
|
6984
|
-
loc,
|
|
6985
|
-
});
|
|
7281
|
+
const fn = buildUnionNarrow(name, from, target, loc, (type) => this.fmt(type), dflt);
|
|
7282
|
+
if (!fn)
|
|
7283
|
+
throw new InternalCompilerError("lowerer bug: invalid deferred union extraction");
|
|
7284
|
+
this.liftedFns.push(fn);
|
|
6986
7285
|
return name;
|
|
6987
7286
|
}
|
|
6988
7287
|
/** True when a static value can become ONE island value: jsval itself,
|
|
@@ -7366,7 +7665,68 @@ export class Lowerer {
|
|
|
7366
7665
|
* lowering goes through here (via lowerExprExpecting) or calls this
|
|
7367
7666
|
* directly when the expression was already lowered. */
|
|
7368
7667
|
coerceInto(node, expr, expected) {
|
|
7369
|
-
|
|
7668
|
+
// A union destination can accept the binding's tagged storage directly.
|
|
7669
|
+
// The checker's single-arm flow type can be stale after a callback writes
|
|
7670
|
+
// the binding. Extracting that arm and wrapping it again would discard the
|
|
7671
|
+
// actual tag and could read a different record layout. Retag the stored
|
|
7672
|
+
// value instead; ordinary coercion checks any excluded destination arms.
|
|
7673
|
+
// Explicit assertions keep their own conversion and validation.
|
|
7674
|
+
if (expected.kind === "union" && expr.kind === "unionNarrow") {
|
|
7675
|
+
let source = node;
|
|
7676
|
+
while (ts.isParenthesizedExpression(source) || ts.isSatisfiesExpression(source))
|
|
7677
|
+
source = source.expression;
|
|
7678
|
+
if (ts.isIdentifier(source) || ts.isShorthandPropertyAssignment(source))
|
|
7679
|
+
expr = expr.value;
|
|
7680
|
+
}
|
|
7681
|
+
// A fresh literal can retain a wider runtime-optional field after its
|
|
7682
|
+
// initial contextual layout was chosen. Its known discriminator still
|
|
7683
|
+
// selects the destination arm; validate that payload before wrapping.
|
|
7684
|
+
// Work with the already lowered value so property effects run once.
|
|
7685
|
+
if (expr.type.kind === "record" && expected.kind === "union") {
|
|
7686
|
+
let literal = node;
|
|
7687
|
+
while (ts.isParenthesizedExpression(literal) || ts.isSatisfiesExpression(literal))
|
|
7688
|
+
literal = literal.expression;
|
|
7689
|
+
const def = this.unions.get(expected.unionId);
|
|
7690
|
+
if (def?.discriminant && ts.isObjectLiteralExpression(literal)) {
|
|
7691
|
+
const property = this.checker.getPropertyOfType(this.typeOf(literal), def.discriminant.field);
|
|
7692
|
+
if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
|
|
7693
|
+
const values = literalValues(this.checker.getTypeOfSymbol(property));
|
|
7694
|
+
const arm = values && this.literalUnionArm(def.id, values);
|
|
7695
|
+
if (arm)
|
|
7696
|
+
expr = this.coerceInto(node, expr, arm);
|
|
7697
|
+
}
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
7700
|
+
if (expected.kind === "dyn") {
|
|
7701
|
+
const contextual = this.checker.getContextualType(node);
|
|
7702
|
+
const parts = contextual?.isUnionType() ? ts.constituentTypes(contextual) : contextual ? [contextual] : [];
|
|
7703
|
+
const errorOptions = parts.some((part) => {
|
|
7704
|
+
const sym = part.getAliasSymbol() ?? part.getSymbol();
|
|
7705
|
+
return sym?.name === "ErrorOptions" && this.isStdlibSymbol(sym);
|
|
7706
|
+
});
|
|
7707
|
+
if (errorOptions) {
|
|
7708
|
+
const actual = this.typeOf(node);
|
|
7709
|
+
for (const part of actual.isUnionType() ? ts.constituentTypes(actual) : [actual]) {
|
|
7710
|
+
const cause = this.checker.getPropertyOfType(part, "cause");
|
|
7711
|
+
if (cause && cause.flags & (ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor)) {
|
|
7712
|
+
this.unsupported("SC1090", node, "Error options with a cause accessor (use a data property)");
|
|
7713
|
+
}
|
|
7714
|
+
}
|
|
7715
|
+
}
|
|
7716
|
+
}
|
|
7717
|
+
let e = this.dynamic && expr.type.kind === "dyn" && expected.kind === "array" && expected.elem.kind === "jsval"
|
|
7718
|
+
? { kind: "jsExit", value: this.jsvalIn(expr, node), type: expected, loc: expr.loc }
|
|
7719
|
+
: this.coerceToExpected(expr, expected);
|
|
7720
|
+
// Existing JavaScript arrays retain mutations and identity across checked
|
|
7721
|
+
// slots. Fresh literals have no prior identity and use checked storage
|
|
7722
|
+
// directly, so later writes can change their inferred element type.
|
|
7723
|
+
let literal = node;
|
|
7724
|
+
while (ts.isParenthesizedExpression(literal))
|
|
7725
|
+
literal = literal.expression;
|
|
7726
|
+
if (isJsSourceFile(node.getSourceFile()) && !ts.isArrayLiteralExpression(literal) &&
|
|
7727
|
+
e.kind === "dynFrom" && e.value.type.kind === "array") {
|
|
7728
|
+
e = { ...e, liveRef: true };
|
|
7729
|
+
}
|
|
7370
7730
|
// An 'any' value PROVABLY null/undefined (the unit literal itself, or
|
|
7371
7731
|
// a read of a binding nothing ever assigns a non-unit value) flowing
|
|
7372
7732
|
// implicitly into a primitive slot: the validated exit refuses units
|
|
@@ -7401,6 +7761,20 @@ export class Lowerer {
|
|
|
7401
7761
|
if (helper) {
|
|
7402
7762
|
e = { kind: "call", callee: helper, args: [e], type: expected, loc: e.loc };
|
|
7403
7763
|
}
|
|
7764
|
+
// Shipped JavaScript can select overloads using runtime brand data
|
|
7765
|
+
// that its JSDoc union does not narrow. Preserve the numeric/string/
|
|
7766
|
+
// boolean destination check, just as for an unknown-typed argument;
|
|
7767
|
+
// never reinterpret an object payload as a scalar union arm.
|
|
7768
|
+
if (e.type.kind === "union" && !typeEquals(e.type, expected) && isJsSourceFile(node.getSourceFile()) &&
|
|
7769
|
+
this.dynConvertible(e.type)) {
|
|
7770
|
+
const sourceArms = this.unions.get(e.type.unionId)?.arms ?? [];
|
|
7771
|
+
const targetArms = this.unions.get(expected.unionId)?.arms ?? [];
|
|
7772
|
+
if (sourceArms.some(isDynTypedRefType) && targetArms.length > 0 &&
|
|
7773
|
+
targetArms.every((arm) => isUnitType(arm) || arm.kind === "f64" || arm.kind === "string" || arm.kind === "bool") &&
|
|
7774
|
+
targetArms.some((arm) => !isUnitType(arm) && sourceArms.some((source) => typeEquals(source, arm)))) {
|
|
7775
|
+
e = this.coerceToExpected(this.coerceToExpected(e, DYN), expected);
|
|
7776
|
+
}
|
|
7777
|
+
}
|
|
7404
7778
|
}
|
|
7405
7779
|
// A JS FUNC value outside the island marshal set flowing into a
|
|
7406
7780
|
// jsval slot (`withPlugins(getSupportInfoWithoutPlugins, 0)` — a
|
|
@@ -7414,7 +7788,9 @@ export class Lowerer {
|
|
|
7414
7788
|
this.requireExactShape(node, e.type, expected);
|
|
7415
7789
|
}
|
|
7416
7790
|
catch (err) {
|
|
7417
|
-
|
|
7791
|
+
if (!(err instanceof PoisonError))
|
|
7792
|
+
throw err;
|
|
7793
|
+
const fence = islandFuncValueFence(this, diagsBefore, node);
|
|
7418
7794
|
if (fence)
|
|
7419
7795
|
return fence;
|
|
7420
7796
|
throw err;
|
|
@@ -7492,53 +7868,146 @@ export class Lowerer {
|
|
|
7492
7868
|
return null;
|
|
7493
7869
|
return [...units].sort().join(" or ");
|
|
7494
7870
|
}
|
|
7495
|
-
/**
|
|
7496
|
-
*
|
|
7497
|
-
*
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7871
|
+
/** A key conversion may rebox or upcast a reference, but must never copy
|
|
7872
|
+
* its referent. Apply the ordinary checked narrowing to absent arms from
|
|
7873
|
+
* runtime-optional reads; only present reference arms participate here. */
|
|
7874
|
+
lowerCollectionKey(node, expected) {
|
|
7875
|
+
if (expected.kind === "dyn") {
|
|
7876
|
+
const value = this.lowerExprExpecting(node, expected);
|
|
7877
|
+
// An adapting promise changes identity, while the Error boundary
|
|
7878
|
+
// snapshots mutable fields. Neither is a live collection reference.
|
|
7879
|
+
const copiesReference = (type) => (type.kind === "promise" && type.inner.kind !== "dyn") ||
|
|
7880
|
+
(type.kind === "object" && (RUNTIME_ERROR_CLASSES.has(type.className) || this.isSubclassOf(type.className, "%Error"))) ||
|
|
7881
|
+
(type.kind === "union" && (this.unions.get(type.unionId)?.arms.some(copiesReference) ?? false));
|
|
7882
|
+
if (value.kind === "dynFrom" && copiesReference(value.value.type)) {
|
|
7883
|
+
this.noLowering("collection slot conversion requiring an Error snapshot or promise adapter", node, "use a collection with the original reference type; checked collection slots require identity-preserving conversions");
|
|
7884
|
+
}
|
|
7885
|
+
// Collections expose the stored reference again. Preserve records,
|
|
7886
|
+
// arrays and byte views rather than taking the ordinary dyn snapshot.
|
|
7887
|
+
const hasLiveReference = (type) => type.kind === "record" || type.kind === "array" || type.kind === "bytes" ||
|
|
7888
|
+
(type.kind === "union" && (this.unions.get(type.unionId)?.arms.some(hasLiveReference) ?? false));
|
|
7889
|
+
if (value.kind === "dynFrom" && hasLiveReference(value.value.type)) {
|
|
7890
|
+
return { ...value, liveRef: true };
|
|
7891
|
+
}
|
|
7892
|
+
return value;
|
|
7893
|
+
}
|
|
7894
|
+
let literal = node;
|
|
7895
|
+
while (ts.isParenthesizedExpression(literal))
|
|
7896
|
+
literal = literal.expression;
|
|
7897
|
+
// Fresh literals have no previous outer identity to preserve. Build them
|
|
7898
|
+
// for their storage layout, just as ordinary contextual literals do.
|
|
7899
|
+
if (ts.isObjectLiteralExpression(literal) || ts.isArrayLiteralExpression(literal) || expected.kind === "f64" || expected.kind === "string") {
|
|
7900
|
+
return this.lowerExprExpecting(node, expected);
|
|
7901
|
+
}
|
|
7902
|
+
// Assertions can perform their own conversion before slot coercion.
|
|
7903
|
+
// Inspect the assertion chain so a width copy cannot hide behind its
|
|
7904
|
+
// already-converted result type. Union-arm checks only unwrap a box.
|
|
7905
|
+
let asserted = literal;
|
|
7906
|
+
while (ts.isAsExpression(asserted) || ts.isTypeAssertion(asserted) || ts.isNonNullExpression(asserted) || ts.isParenthesizedExpression(asserted)) {
|
|
7907
|
+
if (ts.isAsExpression(asserted) || ts.isTypeAssertion(asserted)) {
|
|
7908
|
+
const from = this.mapTypeOf(this.typeOf(asserted.expression));
|
|
7909
|
+
const to = this.mapTypeOf(this.checker.getTypeFromTypeNode(asserted.type));
|
|
7910
|
+
if (from?.kind === "dyn" || from?.kind === "jsval" || (from?.kind === "record" && to?.kind === "record" && !typeEquals(from, to))) {
|
|
7911
|
+
this.noLowering("collection key assertion requiring a structural copy or dynamic conversion", asserted, "use the original reference with the same type as the collection key");
|
|
7912
|
+
}
|
|
7913
|
+
}
|
|
7914
|
+
asserted = asserted.expression;
|
|
7915
|
+
}
|
|
7916
|
+
const value = this.lowerExpr(node);
|
|
7917
|
+
const source = (value.type.kind === "union" ? this.unions.get(value.type.unionId)?.arms ?? [] : [value.type]).filter((type) => !isUnitType(type));
|
|
7918
|
+
const target = expected.kind === "union" ? this.unions.get(expected.unionId)?.arms ?? [] : [expected];
|
|
7919
|
+
const preservesIdentity = source.length > 0 && source.every((from) => target.some((to) => typeEquals(from, to) || (from.kind === "object" && to.kind === "object" && this.isSubclassOf(from.className, to.className))));
|
|
7920
|
+
if (!preservesIdentity || value.kind === "dynCheck" || value.kind === "jsExit") {
|
|
7921
|
+
this.noLowering(`collection key conversion from '${this.fmt(value.type)}' to '${this.fmt(expected)}' requiring a structural copy or dynamic conversion`, node, "use the same reference type for the key and collection; copying a key would change its identity");
|
|
7922
|
+
}
|
|
7923
|
+
return this.coerceInto(node, value, expected);
|
|
7924
|
+
}
|
|
7925
|
+
/** Lower for a known destination, then apply ordinary value coercion.
|
|
7926
|
+
* Fresh arrays and records use the destination layout directly. */
|
|
7501
7927
|
lowerExprExpecting(node, expected) {
|
|
7928
|
+
// These wrappers do not change the value or its inferred type. Keep a
|
|
7929
|
+
// fresh literal visible to destination-directed construction. Assertions
|
|
7930
|
+
// retain their own checked conversion and must not be erased here.
|
|
7931
|
+
while (ts.isParenthesizedExpression(node) || ts.isSatisfiesExpression(node))
|
|
7932
|
+
node = node.expression;
|
|
7933
|
+
if (expected) {
|
|
7934
|
+
if (ts.isConditionalExpression(node))
|
|
7935
|
+
return lowerTernary(this, node, expected);
|
|
7936
|
+
const fresh = this.emptyCollectionFor(node, expected);
|
|
7937
|
+
if (fresh)
|
|
7938
|
+
return this.coerceInto(node, fresh, expected);
|
|
7939
|
+
}
|
|
7502
7940
|
if (expected?.kind === "array") {
|
|
7503
7941
|
let x = node;
|
|
7504
7942
|
while (ts.isParenthesizedExpression(x))
|
|
7505
7943
|
x = x.expression;
|
|
7506
|
-
|
|
7944
|
+
// Fresh arrays are built for the actual destination, including
|
|
7945
|
+
// nested literals whose checker context names a wider recursive
|
|
7946
|
+
// union. Existing arrays still go through ordinary value coercion.
|
|
7947
|
+
if (ts.isArrayLiteralExpression(x)) {
|
|
7507
7948
|
return this.coerceInto(node, this.lowerArrayLiteral(x, expected), expected);
|
|
7508
7949
|
}
|
|
7509
7950
|
}
|
|
7951
|
+
if (expected?.kind === "record") {
|
|
7952
|
+
let x = node;
|
|
7953
|
+
while (ts.isParenthesizedExpression(x))
|
|
7954
|
+
x = x.expression;
|
|
7955
|
+
if (ts.isObjectLiteralExpression(x)) {
|
|
7956
|
+
return this.coerceInto(node, this.lowerObjectLiteral(x, expected), expected);
|
|
7957
|
+
}
|
|
7958
|
+
}
|
|
7959
|
+
if (expected?.kind === "union" && ts.isObjectLiteralExpression(node)) {
|
|
7960
|
+
const def = this.unions.get(expected.unionId);
|
|
7961
|
+
if (def?.discriminant) {
|
|
7962
|
+
const property = this.checker.getPropertyOfType(this.typeOf(node), def.discriminant.field);
|
|
7963
|
+
if (property && !(property.flags & (ts.SymbolFlags.Optional | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor))) {
|
|
7964
|
+
const values = literalValues(this.checker.getTypeOfSymbol(property));
|
|
7965
|
+
const arm = values && this.literalUnionArm(def.id, values);
|
|
7966
|
+
if (arm)
|
|
7967
|
+
return this.coerceInto(node, this.lowerObjectLiteral(node, arm), expected);
|
|
7968
|
+
}
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7510
7971
|
// An OBJECT LITERAL against a checked-dynamic slot in a JS file (the
|
|
7511
7972
|
// getSupportInfo options argument — a dyn-ABI param), or against the
|
|
7512
|
-
// standard
|
|
7973
|
+
// standard native option-bag types in TypeScript: the value's world IS the
|
|
7513
7974
|
// checked-dynamic tree — build the dyn literal directly.
|
|
7514
7975
|
if (expected?.kind === "dyn") {
|
|
7515
7976
|
let x = node;
|
|
7516
7977
|
while (ts.isParenthesizedExpression(x))
|
|
7517
7978
|
x = x.expression;
|
|
7979
|
+
// A fresh dense array entering a checked slot has no typed aliases.
|
|
7980
|
+
// Construct its actual storage here so identity and WeakMap lifetime
|
|
7981
|
+
// belong to the array the program keeps, rather than a typed snapshot.
|
|
7982
|
+
if (ts.isArrayLiteralExpression(x) && x.elements.every((element) => !ts.isSpreadElement(element) && !ts.isOmittedExpression(element))) {
|
|
7983
|
+
return { kind: "dynArrLit", elems: x.elements.map((element) => this.lowerExprExpecting(element, DYN)), type: DYN, loc: locOf(x) };
|
|
7984
|
+
}
|
|
7985
|
+
const contextual = this.checker.getContextualType(x);
|
|
7986
|
+
const widened = contextual ? this.checker.getBaseTypeOfLiteralType(contextual) : undefined;
|
|
7987
|
+
const parts = widened?.isUnionType() ? ts.constituentTypes(widened) : widened ? [widened] : [];
|
|
7988
|
+
const builtinOption = (name) => parts.some((part) => {
|
|
7989
|
+
const sym = part.getAliasSymbol() ?? part.getSymbol();
|
|
7990
|
+
return sym?.name === name && this.isStdlibSymbol(sym);
|
|
7991
|
+
});
|
|
7518
7992
|
if (ts.isObjectLiteralExpression(x)) {
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
? this.checker.getBaseTypeOfLiteralType(contextual)
|
|
7522
|
-
: undefined;
|
|
7523
|
-
const sym = widened?.getAliasSymbol() ?? widened?.getSymbol();
|
|
7524
|
-
const requestInit = sym?.name === "RequestInit" && this.isStdlibSymbol(sym);
|
|
7525
|
-
if (isJsSourceFile(x.getSourceFile()) || requestInit) {
|
|
7993
|
+
if (isJsSourceFile(x.getSourceFile()) || builtinOption("RequestInit") || builtinOption("ErrorOptions") || builtinOption("SpawnOptions") ||
|
|
7994
|
+
!this.mapTypeOf(this.typeOf(x))) {
|
|
7526
7995
|
return lowerDynObjectLiteral(this, x);
|
|
7527
7996
|
}
|
|
7528
7997
|
}
|
|
7529
7998
|
}
|
|
7530
|
-
//
|
|
7531
|
-
//
|
|
7532
|
-
//
|
|
7533
|
-
//
|
|
7534
|
-
//
|
|
7535
|
-
//
|
|
7999
|
+
// A fresh array can use the unique array-family destination inside a
|
|
8000
|
+
// union too. In nullable recursive fields the checker can report the
|
|
8001
|
+
// whole union as context: an identity lift of that context does not
|
|
8002
|
+
// mean the literal's independently inferred element layout fits.
|
|
8003
|
+
// Construct the elements for the selected arm before wrapping it.
|
|
8004
|
+
// When several array arms fit a fresh literal, any complete element
|
|
8005
|
+
// layout is valid: the new array has no existing aliases to preserve.
|
|
7536
8006
|
if (expected?.kind === "union") {
|
|
7537
8007
|
let x = node;
|
|
7538
8008
|
while (ts.isParenthesizedExpression(x))
|
|
7539
8009
|
x = x.expression;
|
|
7540
8010
|
if (ts.isArrayLiteralExpression(x)) {
|
|
7541
|
-
const own = this.mapTypeOf(this.checker.getContextualType(x) ?? this.typeOf(x));
|
|
7542
8011
|
// Elements beyond bare null/undefined literals can never live in
|
|
7543
8012
|
// a unit-only-element array — a checker type that degraded to one
|
|
7544
8013
|
// (`[]`-flavored inference over a populated literal) carries no
|
|
@@ -7546,26 +8015,60 @@ export class Lowerer {
|
|
|
7546
8015
|
const nonUnitElems = x.elements.some((el) => !ts.isOmittedExpression(el) &&
|
|
7547
8016
|
el.kind !== ts.SyntaxKind.NullKeyword &&
|
|
7548
8017
|
!(ts.isIdentifier(el) && el.text === "undefined"));
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
(
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
8018
|
+
const def = this.unions.get(expected.unionId);
|
|
8019
|
+
const arms = (def?.arms ?? []).filter((a) => (a.kind === "array" && !(nonUnitElems && this.unitOnlyElem(a.elem))) ||
|
|
8020
|
+
(a.kind === "record" &&
|
|
8021
|
+
!!this.shapes.get(a.shapeId)?.tuple &&
|
|
8022
|
+
this.shapes.get(a.shapeId).fields.length === x.elements.length &&
|
|
8023
|
+
!x.elements.some(ts.isSpreadElement)));
|
|
8024
|
+
let arm = arms.length === 1 ? arms[0] : undefined;
|
|
8025
|
+
if (!arm && arms.length > 1 && x.elements.length > 0 &&
|
|
8026
|
+
x.elements.every((el) => !ts.isSpreadElement(el) && !ts.isOmittedExpression(el))) {
|
|
8027
|
+
const ownType = this.mapTypeOf(this.typeOf(x));
|
|
8028
|
+
arm = arms.find((candidate) => ownType !== null && typeEquals(candidate, ownType));
|
|
8029
|
+
if (!arm) {
|
|
8030
|
+
const elements = x.elements.map((el) => tryLowerExpression(this, el));
|
|
8031
|
+
arm = arms.find((candidate) => candidate.kind === "array" &&
|
|
8032
|
+
elements.every((element) => element !== null && this.widthLiftPlan(element.type, candidate.elem) !== null));
|
|
7562
8033
|
}
|
|
7563
8034
|
}
|
|
8035
|
+
if (arm) {
|
|
8036
|
+
const built = this.lowerArrayLiteral(x, arm);
|
|
8037
|
+
return this.coerceInto(node, built, expected);
|
|
8038
|
+
}
|
|
7564
8039
|
}
|
|
7565
8040
|
}
|
|
7566
|
-
|
|
8041
|
+
let e = this.lowerExpr(node);
|
|
8042
|
+
if (expected?.kind === "union" && this.armTag(expected.unionId, UNDEFINED_T) >= 0) {
|
|
8043
|
+
// A destination that accepts undefined must retain an unchecked
|
|
8044
|
+
// read's storage value even when the checker still calls it present.
|
|
8045
|
+
e = this.runtimeOptionalSourceValue(node, e) ?? e;
|
|
8046
|
+
}
|
|
7567
8047
|
return expected ? this.coerceInto(node, e, expected) : e;
|
|
7568
8048
|
}
|
|
8049
|
+
/** An unannotated empty collection has no existing elements or aliases
|
|
8050
|
+
* that constrain its layout. An explicit type argument still wins. */
|
|
8051
|
+
emptyCollectionFor(node, expected) {
|
|
8052
|
+
let value = node;
|
|
8053
|
+
while (ts.isParenthesizedExpression(value))
|
|
8054
|
+
value = value.expression;
|
|
8055
|
+
if (!ts.isNewExpression(value) || !ts.isIdentifier(value.expression) || (value.arguments?.length ?? 0) !== 0 ||
|
|
8056
|
+
(value.typeArguments?.length ?? 0) !== 0)
|
|
8057
|
+
return null;
|
|
8058
|
+
const symbol = this.resolveValueSymbol(value.expression);
|
|
8059
|
+
if (!symbol || !this.isStdlibSymbol(symbol))
|
|
8060
|
+
return null;
|
|
8061
|
+
const kind = symbol.name === "Map" ? "map" : symbol.name === "Set" ? "set" : null;
|
|
8062
|
+
if (!kind)
|
|
8063
|
+
return null;
|
|
8064
|
+
const arms = expected.kind === "union" ? this.unions.get(expected.unionId)?.arms ?? [] : [expected];
|
|
8065
|
+
const candidates = arms.filter((arm) => arm.kind === kind);
|
|
8066
|
+
if (candidates.length !== 1)
|
|
8067
|
+
return null;
|
|
8068
|
+
const type = candidates[0];
|
|
8069
|
+
return type.kind === "map" ? { kind: "mapNew", type, loc: locOf(value) }
|
|
8070
|
+
: type.kind === "set" ? { kind: "setNew", type, loc: locOf(value) } : null;
|
|
8071
|
+
}
|
|
7569
8072
|
/** A value flowing into an index-signature VALUE slot (an overflow
|
|
7570
8073
|
* literal entry, a dynamic-keyed record write). dyn slots (`unknown`
|
|
7571
8074
|
* signatures — ModelPricing's) take a dyn conversion: dyn values pass
|
|
@@ -7623,6 +8126,22 @@ export class Lowerer {
|
|
|
7623
8126
|
* nothing evaluates; unit-typed non-literals keep the fences. */
|
|
7624
8127
|
lowerReturnValue(node) {
|
|
7625
8128
|
const expected = this.ctx.returnType;
|
|
8129
|
+
// A return slot supplies the same construction layout as an argument
|
|
8130
|
+
// or initializer. In particular, contextual callbacks can return fresh
|
|
8131
|
+
// arrays of recursive unions and nullable, unannotated collections.
|
|
8132
|
+
// Async returns still resolve a promise before converting its payload.
|
|
8133
|
+
if (!this.ctx.isAsync && expected.kind !== "void")
|
|
8134
|
+
return this.lowerExprExpecting(node, expected);
|
|
8135
|
+
// Fresh JS objects returned through a checked-native ABI use that
|
|
8136
|
+
// storage directly, just like arguments and variable initializers.
|
|
8137
|
+
// Contextual types (such as Proxy descriptors' symbol-valued fields)
|
|
8138
|
+
// must not force an intermediate record with incompatible field slots.
|
|
8139
|
+
let literal = node;
|
|
8140
|
+
while (ts.isParenthesizedExpression(literal))
|
|
8141
|
+
literal = literal.expression;
|
|
8142
|
+
if (expected.kind === "dyn" && isJsSourceFile(node.getSourceFile()) && ts.isObjectLiteralExpression(literal)) {
|
|
8143
|
+
return this.lowerExprExpecting(node, expected);
|
|
8144
|
+
}
|
|
7626
8145
|
const e = this.lowerExpr(node);
|
|
7627
8146
|
if (expected.kind === "void" && e.kind === "unitLit")
|
|
7628
8147
|
return null;
|
|
@@ -7683,14 +8202,17 @@ export class Lowerer {
|
|
|
7683
8202
|
stripUndefinedArm(t) {
|
|
7684
8203
|
if (t.kind !== "union")
|
|
7685
8204
|
return t;
|
|
8205
|
+
const cached = this.strippedUndefinedArms.get(t.unionId);
|
|
8206
|
+
if (cached && cached.unions === this.unions.revision)
|
|
8207
|
+
return cached.type;
|
|
7686
8208
|
const def = this.unions.get(t.unionId);
|
|
7687
|
-
if (!def ||
|
|
8209
|
+
if (!def || this.armTag(t.unionId, UNDEFINED_T) < 0)
|
|
7688
8210
|
return t;
|
|
7689
8211
|
const rest = def.arms.filter((a) => a.kind !== "undefinedT");
|
|
7690
|
-
if (rest.length === 1)
|
|
7691
|
-
return rest[0];
|
|
7692
8212
|
// Removing an arm keeps canonical (typeKey-sorted) order.
|
|
7693
|
-
|
|
8213
|
+
const type = rest.length === 1 ? rest[0] : { kind: "union", unionId: this.unions.transform(def, rest) };
|
|
8214
|
+
this.strippedUndefinedArms.set(t.unionId, { type, unions: this.unions.revision });
|
|
8215
|
+
return type;
|
|
7694
8216
|
}
|
|
7695
8217
|
/** The interned `T | undefined` union over a non-union arm type — the ABI
|
|
7696
8218
|
* type of a defaulted parameter, and the result type of lookups that may
|
|
@@ -7751,13 +8273,14 @@ export class Lowerer {
|
|
|
7751
8273
|
* symbol reports eagerly (nothing could ever reference it). */
|
|
7752
8274
|
collectDeferring(symbolOf, collect) {
|
|
7753
8275
|
const sink = [];
|
|
8276
|
+
const previousSink = this.diagSink;
|
|
7754
8277
|
this.diagSink = sink;
|
|
7755
8278
|
try {
|
|
7756
8279
|
collect();
|
|
7757
8280
|
return null;
|
|
7758
8281
|
}
|
|
7759
8282
|
catch (e) {
|
|
7760
|
-
this.diagSink =
|
|
8283
|
+
this.diagSink = previousSink;
|
|
7761
8284
|
const symbol = (() => {
|
|
7762
8285
|
// symbolOf queries the checker too — a second panic must not
|
|
7763
8286
|
// escape the fence that is handling the first.
|
|
@@ -7790,7 +8313,7 @@ export class Lowerer {
|
|
|
7790
8313
|
return symbol;
|
|
7791
8314
|
}
|
|
7792
8315
|
finally {
|
|
7793
|
-
this.diagSink =
|
|
8316
|
+
this.diagSink = previousSink;
|
|
7794
8317
|
}
|
|
7795
8318
|
}
|
|
7796
8319
|
/** Pushes a symbol's deferred collection diagnostics: lowering resolved
|
|
@@ -7962,7 +8485,7 @@ export class Lowerer {
|
|
|
7962
8485
|
* members ride fp.classDecls; expressions register only when their
|
|
7963
8486
|
* containing statement lowers). */
|
|
7964
8487
|
exprClasses = [];
|
|
7965
|
-
|
|
8488
|
+
exprClassInfoByName = new Map();
|
|
7966
8489
|
/** Class expressions whose collection is IN FLIGHT — the reentrancy
|
|
7967
8490
|
* guard for heritage-demanded collection (lowerClassExpressionInfo). */
|
|
7968
8491
|
collectingExprClasses = new Set();
|
|
@@ -7971,6 +8494,8 @@ export class Lowerer {
|
|
|
7971
8494
|
* BEFORE that statement (JS's order for the supported whole-initializer
|
|
7972
8495
|
* positions). */
|
|
7973
8496
|
pendingClassExprInits = [];
|
|
8497
|
+
computedClassBases = new Map();
|
|
8498
|
+
computedCallableBases = new Map();
|
|
7974
8499
|
/** Discovery hook: registers a just-collected expression class's member
|
|
7975
8500
|
* bodies as worklist units (the units map is otherwise built before
|
|
7976
8501
|
* lowering starts). Null in the emit pass. */
|
|
@@ -8016,8 +8541,8 @@ export class Lowerer {
|
|
|
8016
8541
|
* onExprClassCollected should instantiations ever need eager
|
|
8017
8542
|
* registration. */
|
|
8018
8543
|
onLateClassCollected = null;
|
|
8019
|
-
genericClassInstanceType(decl, ref) {
|
|
8020
|
-
return genericClassInstanceType(this, decl, ref);
|
|
8544
|
+
genericClassInstanceType(decl, ref, mapArgument) {
|
|
8545
|
+
return genericClassInstanceType(this, decl, ref, mapArgument);
|
|
8021
8546
|
}
|
|
8022
8547
|
findStaticOn(info, name) {
|
|
8023
8548
|
return findStaticOn(this, info, name);
|
|
@@ -8059,11 +8584,7 @@ export class Lowerer {
|
|
|
8059
8584
|
// Computed method names resolve exactly like collection did
|
|
8060
8585
|
// (classMemberNameOf — folded keys and the sym:iterator slot);
|
|
8061
8586
|
// unresolvable ones never collected, so they skip here too.
|
|
8062
|
-
const baseName =
|
|
8063
|
-
? classMemberNameOf(this, fnLike.name)
|
|
8064
|
-
: ts.isIdentifier(fnLike.name) || ts.isPrivateIdentifier(fnLike.name)
|
|
8065
|
-
? fnLike.name.text
|
|
8066
|
-
: null;
|
|
8587
|
+
const baseName = classMemberNameOf(this, fnLike.name);
|
|
8067
8588
|
if (baseName === null)
|
|
8068
8589
|
continue;
|
|
8069
8590
|
const mName = ts.isMethodDeclaration(fnLike) ? baseName : `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${baseName}`;
|
|
@@ -8090,14 +8611,10 @@ export class Lowerer {
|
|
|
8090
8611
|
superCallStmt(info, thisLocal, args, loc) {
|
|
8091
8612
|
return superCallStmt(this, info, thisLocal, args, loc);
|
|
8092
8613
|
}
|
|
8093
|
-
/** Declares the
|
|
8094
|
-
*
|
|
8614
|
+
/** Declares the this parameter in the function's dedicated binding slot.
|
|
8615
|
+
* Arrow captures use the same boxing and threading as named bindings. */
|
|
8095
8616
|
declareThis(type) {
|
|
8096
|
-
|
|
8097
|
-
const local = { id: "this.0", name: "this", type, mutable: false };
|
|
8098
|
-
ctx.locals.push(local);
|
|
8099
|
-
ctx.scopes[ctx.scopes.length - 1].set(THIS_BINDING, local);
|
|
8100
|
-
return local;
|
|
8617
|
+
return declareContextThis(this.ctx, type);
|
|
8101
8618
|
}
|
|
8102
8619
|
lowerFunction(decl) {
|
|
8103
8620
|
return lowerFunction(this, decl);
|
|
@@ -8116,26 +8633,13 @@ export class Lowerer {
|
|
|
8116
8633
|
}
|
|
8117
8634
|
/* ── scoping and captures ─────────────────────────────────────────── */
|
|
8118
8635
|
declareLocal(nameNode, name, type, mutable) {
|
|
8119
|
-
|
|
8120
|
-
const count = ctx.localCounters.get(name) ?? 0;
|
|
8121
|
-
ctx.localCounters.set(name, count + 1);
|
|
8122
|
-
const local = { id: `${name}.${count}`, name, type, mutable, source: bindingSource(nameNode) };
|
|
8123
|
-
ctx.locals.push(local);
|
|
8124
|
-
const symbol = this.checker.getSymbolAtLocation(nameNode);
|
|
8125
|
-
if (symbol)
|
|
8126
|
-
ctx.scopes[ctx.scopes.length - 1].set(symbol, local);
|
|
8127
|
-
return local;
|
|
8636
|
+
return declareContextLocal(this.ctx, name, type, mutable, this.checker.getSymbolAtLocation(nameNode), bindingSource(nameNode));
|
|
8128
8637
|
}
|
|
8129
8638
|
/** A function-scope local bound to NO ts.Symbol — the hidden ABI slot of a
|
|
8130
8639
|
* defaulted parameter (the parameter's symbol binds to the separately-
|
|
8131
8640
|
* declared body local; nothing in the source can name this one). */
|
|
8132
8641
|
declareHiddenLocal(name, type) {
|
|
8133
|
-
|
|
8134
|
-
const count = ctx.localCounters.get(name) ?? 0;
|
|
8135
|
-
ctx.localCounters.set(name, count + 1);
|
|
8136
|
-
const local = { id: `${name}.${count}`, name, type, mutable: false };
|
|
8137
|
-
ctx.locals.push(local);
|
|
8138
|
-
return local;
|
|
8642
|
+
return declareContextLocal(this.ctx, name, type, false, undefined, undefined);
|
|
8139
8643
|
}
|
|
8140
8644
|
/** Declares a callee's parameter locals from its ParamShapes and builds
|
|
8141
8645
|
* the DEFAULT-PARAM PROLOGUE. Required/optional/rest params bind their
|
|
@@ -8158,6 +8662,13 @@ export class Lowerer {
|
|
|
8158
8662
|
const decls = rawDecls.filter((p) => !isThisParameter(p));
|
|
8159
8663
|
const params = [];
|
|
8160
8664
|
const prologue = [];
|
|
8665
|
+
const defaultValue = (node, expected) => {
|
|
8666
|
+
const undefinedValue = lowerStaticallyUndefinedArgument(this, node);
|
|
8667
|
+
if (undefinedValue === null)
|
|
8668
|
+
return this.lowerExprExpecting(node, expected);
|
|
8669
|
+
const absent = { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc: locOf(node) };
|
|
8670
|
+
return defaultAfterUndefined(undefinedValue, this.coerceInto(node, absent, expected));
|
|
8671
|
+
};
|
|
8161
8672
|
decls.forEach((decl, i) => {
|
|
8162
8673
|
const shape = shapes[i];
|
|
8163
8674
|
if (ts.isArrayBindingPattern(decl.name) || ts.isObjectBindingPattern(decl.name)) {
|
|
@@ -8184,7 +8695,7 @@ export class Lowerer {
|
|
|
8184
8695
|
// dynamic dyn): the slot holds its tier's undefined directly,
|
|
8185
8696
|
// so the default test is the runtime undefined test — then
|
|
8186
8697
|
// the pattern destructures the picked value.
|
|
8187
|
-
const dflt =
|
|
8698
|
+
const dflt = defaultValue(decl.initializer, abi);
|
|
8188
8699
|
const src = this.declareHiddenLocal("%psrc", abi);
|
|
8189
8700
|
const inRef = () => ({ kind: "varRef", localId: slot.id, type: abi, loc });
|
|
8190
8701
|
const isUndef = abi.kind === "jsval"
|
|
@@ -8199,6 +8710,16 @@ export class Lowerer {
|
|
|
8199
8710
|
const pickedT = abi;
|
|
8200
8711
|
srcType = pickedT;
|
|
8201
8712
|
srcRef = () => ({ kind: "varRef", localId: src.id, type: pickedT, loc });
|
|
8713
|
+
// An empty object pattern still rejects null after applying
|
|
8714
|
+
// the default. With no property reads, nothing else performs
|
|
8715
|
+
// RequireObjectCoercible; use V8's default-expression spelling.
|
|
8716
|
+
if (abi.kind === "dyn" && ts.isObjectBindingPattern(decl.name) && decl.name.elements.length === 0) {
|
|
8717
|
+
prologue.push({
|
|
8718
|
+
kind: "exprStmt",
|
|
8719
|
+
expr: { kind: "dynDestrCheck", value: srcRef(), spelling: "(intermediate value)(intermediate value)(intermediate value)", type: DYN, loc },
|
|
8720
|
+
loc,
|
|
8721
|
+
});
|
|
8722
|
+
}
|
|
8202
8723
|
this.lowerBindingPattern(decl.name, srcRef, srcType, true, prologue);
|
|
8203
8724
|
return;
|
|
8204
8725
|
}
|
|
@@ -8228,7 +8749,7 @@ export class Lowerer {
|
|
|
8228
8749
|
}
|
|
8229
8750
|
if (!present)
|
|
8230
8751
|
this.unsupported("SC1090", decl, "this parameter form"); // defensive: abi = bodyType + undefined by construction
|
|
8231
|
-
const dflt =
|
|
8752
|
+
const dflt = defaultValue(decl.initializer, shape.bodyType);
|
|
8232
8753
|
const src = this.declareHiddenLocal("%psrc", shape.bodyType);
|
|
8233
8754
|
prologue.push({
|
|
8234
8755
|
kind: "varDecl",
|
|
@@ -8258,7 +8779,7 @@ export class Lowerer {
|
|
|
8258
8779
|
const isUndef = abi.kind === "jsval"
|
|
8259
8780
|
? { kind: "jsOp", op: "eq", args: [inRef(), { kind: "jsOp", op: "undefLit", args: [], type: JSVAL, loc }], type: BOOL, loc }
|
|
8260
8781
|
: { kind: "dynTest", test: "undefined", value: inRef(), type: BOOL, loc };
|
|
8261
|
-
const dflt =
|
|
8782
|
+
const dflt = defaultValue(decl.initializer, abi);
|
|
8262
8783
|
const body = this.declareLocal(decl.name, name, abi, true);
|
|
8263
8784
|
prologue.push({
|
|
8264
8785
|
kind: "varDecl",
|
|
@@ -8282,7 +8803,7 @@ export class Lowerer {
|
|
|
8282
8803
|
// the body keeps the full `T | undefined` union (tsc's type),
|
|
8283
8804
|
// so a present argument passes through unchanged and an omitted
|
|
8284
8805
|
// one takes the default AS IS — no narrow on either branch.
|
|
8285
|
-
const dflt =
|
|
8806
|
+
const dflt = defaultValue(decl.initializer, abi);
|
|
8286
8807
|
const body = this.declareLocal(decl.name, name, abi, true);
|
|
8287
8808
|
prologue.push({
|
|
8288
8809
|
kind: "varDecl",
|
|
@@ -8308,7 +8829,7 @@ export class Lowerer {
|
|
|
8308
8829
|
const retag = this.unionRetagHelper(abi.unionId, shape.bodyType.unionId, loc);
|
|
8309
8830
|
if (!retag)
|
|
8310
8831
|
this.unsupported("SC1090", decl, "this parameter form"); // defensive
|
|
8311
|
-
const dflt =
|
|
8832
|
+
const dflt = defaultValue(decl.initializer, shape.bodyType);
|
|
8312
8833
|
const body = this.declareLocal(decl.name, name, shape.bodyType, true);
|
|
8313
8834
|
prologue.push({
|
|
8314
8835
|
kind: "varDecl",
|
|
@@ -8331,7 +8852,7 @@ export class Lowerer {
|
|
|
8331
8852
|
// The default lowers BEFORE the body local binds, so a same-named
|
|
8332
8853
|
// outer binding referenced in it can never resolve to the fresh
|
|
8333
8854
|
// local (tsc separately rejects `x = x`).
|
|
8334
|
-
const dflt =
|
|
8855
|
+
const dflt = defaultValue(decl.initializer, shape.bodyType);
|
|
8335
8856
|
const body = this.declareLocal(decl.name, name, shape.bodyType, true);
|
|
8336
8857
|
prologue.push({
|
|
8337
8858
|
kind: "varDecl",
|
|
@@ -8364,12 +8885,7 @@ export class Lowerer {
|
|
|
8364
8885
|
/** The binding for `symbol` inside context `ctx` — a scoped local or an
|
|
8365
8886
|
* already-threaded capture entry. */
|
|
8366
8887
|
bindingIn(ctx, symbol) {
|
|
8367
|
-
|
|
8368
|
-
const local = ctx.scopes[i].get(symbol);
|
|
8369
|
-
if (local)
|
|
8370
|
-
return local;
|
|
8371
|
-
}
|
|
8372
|
-
return ctx.captureBySymbol.get(symbol) ?? null;
|
|
8888
|
+
return bindingInContext(ctx, symbol);
|
|
8373
8889
|
}
|
|
8374
8890
|
/** Resolves an identifier to a local of the CURRENT function, creating
|
|
8375
8891
|
* capture entries (and boxing the origin binding) when the name lives in
|
|
@@ -8408,7 +8924,7 @@ export class Lowerer {
|
|
|
8408
8924
|
* through arrows (function expressions/declarations reset `this` in JS;
|
|
8409
8925
|
* their bodies never see an enclosing method's binding). */
|
|
8410
8926
|
resolveThis() {
|
|
8411
|
-
return this.resolveKey(
|
|
8927
|
+
return this.resolveKey(undefined);
|
|
8412
8928
|
}
|
|
8413
8929
|
/** READ-ONLY twin of resolveLocal for PROBES (isIslandExpr): answers
|
|
8414
8930
|
* the nearest binding entry without boxing, threading, or predeclaring.
|
|
@@ -8432,75 +8948,21 @@ export class Lowerer {
|
|
|
8432
8948
|
return null;
|
|
8433
8949
|
}
|
|
8434
8950
|
resolveKey(symbol, blame) {
|
|
8435
|
-
const
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
// island handle's own retain/release (scr_jsval_*_v), untraced like
|
|
8451
|
-
// every jsval container position — engine-side back-references are
|
|
8452
|
-
// the island's documented collection stance, not the box's.
|
|
8453
|
-
if (origin.type.kind === "caught") {
|
|
8454
|
-
// A catch binding never escapes its catch (KEEP NARROW): narrow it
|
|
8455
|
-
// into a typed local and capture THAT.
|
|
8456
|
-
this.unsupported("SC1090", blame ?? this.checker.declarationsOf(symbol)[0] ?? this.entry, "closures capturing catch bindings (narrow into a typed local first)");
|
|
8457
|
-
}
|
|
8458
|
-
// The binding escapes into a nested function: it must live in a box,
|
|
8459
|
-
// shared by everyone (that's what makes mutation visible everywhere).
|
|
8460
|
-
origin.boxed = true;
|
|
8461
|
-
// Thread a capture through every function between origin and here.
|
|
8462
|
-
let parentEntry = origin;
|
|
8463
|
-
for (let j = depth + 1; j < this.fnStack.length; j++) {
|
|
8464
|
-
const ctx = this.fnStack[j];
|
|
8465
|
-
let entry = ctx.captureBySymbol.get(symbol);
|
|
8466
|
-
if (!entry) {
|
|
8467
|
-
// A context that takes NO captures (a plain declared function —
|
|
8468
|
-
// monomorphized/implicit instances lower this way) cannot carry
|
|
8469
|
-
// the binding through: the shape is a module binding whose only
|
|
8470
|
-
// storage is the init function's LOCAL (a typed-but-unmappable
|
|
8471
|
-
// const — the file-scope `new Map()` ledger idiom) read from
|
|
8472
|
-
// inside a nested instance. Fence it — in JS the statement
|
|
8473
|
-
// defers to its runtime trap like every collection failure;
|
|
8474
|
-
// asserting here was an ICE on ordinary npm-static JS.
|
|
8475
|
-
if (ctx.captures === null) {
|
|
8476
|
-
this.unsupported("SC1090", blame ?? this.checker.declarationsOf(symbol)[0] ?? this.entry, `the binding '${origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`);
|
|
8477
|
-
}
|
|
8478
|
-
const count = ctx.localCounters.get(origin.name) ?? 0;
|
|
8479
|
-
ctx.localCounters.set(origin.name, count + 1);
|
|
8480
|
-
entry = {
|
|
8481
|
-
id: `${origin.name}.${count}`,
|
|
8482
|
-
name: origin.name,
|
|
8483
|
-
type: origin.type,
|
|
8484
|
-
mutable: origin.mutable,
|
|
8485
|
-
boxed: true,
|
|
8486
|
-
...(origin.source ? { source: origin.source } : {}),
|
|
8487
|
-
// TDZ travels with the binding: reads through ANY capture of a
|
|
8488
|
-
// forward-captured const must trap while the box is empty.
|
|
8489
|
-
...(origin.tdz ? { tdz: true } : {}),
|
|
8490
|
-
};
|
|
8491
|
-
ctx.locals.push(entry);
|
|
8492
|
-
ctx.captureBySymbol.set(symbol, entry);
|
|
8493
|
-
ctx.captures.push({ localId: entry.id, name: entry.name, type: entry.type });
|
|
8494
|
-
ctx.captureSources.push(parentEntry.id);
|
|
8495
|
-
const runtimeOptionalRoot = this.runtimeOptionalRootOf(parentEntry);
|
|
8496
|
-
if (this.runtimeOptionalStorageLocals.has(runtimeOptionalRoot)) {
|
|
8497
|
-
this.runtimeOptionalRoots.set(entry, runtimeOptionalRoot);
|
|
8498
|
-
}
|
|
8499
|
-
}
|
|
8500
|
-
parentEntry = entry;
|
|
8501
|
-
}
|
|
8502
|
-
return parentEntry;
|
|
8503
|
-
}
|
|
8951
|
+
const resolved = captureContextBinding(this.fnStack, symbol, (parentEntry, entry) => {
|
|
8952
|
+
const root = this.runtimeOptionalRootOf(parentEntry);
|
|
8953
|
+
if (this.runtimeOptionalStorageLocals.has(root))
|
|
8954
|
+
this.runtimeOptionalRoots.set(entry, root);
|
|
8955
|
+
});
|
|
8956
|
+
if (resolved.error !== null) {
|
|
8957
|
+
const location = blame ?? (symbol === undefined ? undefined : this.checker.declarationsOf(symbol)[0]) ?? this.entry;
|
|
8958
|
+
const message = `the binding '${resolved.origin.name}' captured through a plain nested function (the declaration has no static storage a capture can thread — bind the value through a typed const, or read it in the declaring scope)`;
|
|
8959
|
+
this.unsupported("SC1090", location, message);
|
|
8960
|
+
}
|
|
8961
|
+
if (resolved.local !== null)
|
|
8962
|
+
return resolved.local;
|
|
8963
|
+
// This cannot be forward-declared: its parameter must already exist.
|
|
8964
|
+
if (symbol === undefined)
|
|
8965
|
+
return null;
|
|
8504
8966
|
// Nothing declared yet anywhere on the stack: the hoisted-handler shape
|
|
8505
8967
|
// — a function declared BEFORE a const it captures (`const cleanup =
|
|
8506
8968
|
// () => onSigInt; ...; const onSigInt = ...`). Pre-declare the const as
|
|
@@ -8566,21 +9028,10 @@ export class Lowerer {
|
|
|
8566
9028
|
// binding-form text.
|
|
8567
9029
|
if (symbol) {
|
|
8568
9030
|
const d = this.checker.valueDeclarationOf(symbol);
|
|
8569
|
-
if (d && ts.isVariableDeclaration(d) && ts.isVariableDeclarationList(d.parent) &&
|
|
8570
|
-
(d.parent.flags & ts.NodeFlags.Const) !== 0) {
|
|
8571
|
-
const codec = textCodecBindingClassOf(this, d.name, d.initializer);
|
|
8572
|
-
if (codec !== null) {
|
|
8573
|
-
const call = codec === "TextEncoder" ? `${name}.encode(s)` : `${name}.decode(bytes)`;
|
|
8574
|
-
const composed = codec === "TextEncoder"
|
|
8575
|
-
? "new TextEncoder().encode(s)"
|
|
8576
|
-
: "new TextDecoder().decode(bytes)";
|
|
8577
|
-
this.noLowering(`${codec} instance stored in ${name}`, node, `${call} compiles through this const; the codec object itself has no representation (the composed ${composed} form also compiles)`);
|
|
8578
|
-
}
|
|
8579
|
-
}
|
|
8580
9031
|
if (d && ts.isVariableDeclaration(d) && d.initializer === undefined) {
|
|
8581
9032
|
const t = this.checker.getTypeOfSymbol(symbol);
|
|
8582
9033
|
const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
|
|
8583
|
-
if (parts.some((p) => this.checker.getCallSignatures(p).some((s) =>
|
|
9034
|
+
if (parts.some((p) => this.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
|
|
8584
9035
|
this.unsupported("SC1030", node, `the generic-signature binding '${name}' (its type keeps type parameters and the declaration has no initializer — no function body exists to monomorphize, so nothing can pin a concrete signature)`);
|
|
8585
9036
|
}
|
|
8586
9037
|
}
|
|
@@ -8893,7 +9344,16 @@ export class Lowerer {
|
|
|
8893
9344
|
return isStdlibMember(this, access);
|
|
8894
9345
|
}
|
|
8895
9346
|
isStdlibSymbol(symbol) {
|
|
8896
|
-
|
|
9347
|
+
if (!symbol)
|
|
9348
|
+
return false;
|
|
9349
|
+
const cached = this.stdlibSymbols.get(symbol);
|
|
9350
|
+
if (cached !== undefined)
|
|
9351
|
+
return cached;
|
|
9352
|
+
// A compilation's checker declarations and library provenance are fixed.
|
|
9353
|
+
// Global alias and narrowing state remain outside this symbol-only cache.
|
|
9354
|
+
const result = isStdlibSymbol(this, symbol);
|
|
9355
|
+
this.stdlibSymbols.set(symbol, result);
|
|
9356
|
+
return result;
|
|
8897
9357
|
}
|
|
8898
9358
|
isStdlibGlobal(expr, name) {
|
|
8899
9359
|
return isStdlibGlobal(this, expr, name);
|
|
@@ -8904,8 +9364,8 @@ export class Lowerer {
|
|
|
8904
9364
|
lowerArrayLiteral(expr, expected) {
|
|
8905
9365
|
return lowerArrayLiteral(this, expr, expected);
|
|
8906
9366
|
}
|
|
8907
|
-
lowerObjectLiteral(expr) {
|
|
8908
|
-
return lowerObjectLiteral(this, expr);
|
|
9367
|
+
lowerObjectLiteral(expr, expected) {
|
|
9368
|
+
return lowerObjectLiteral(this, expr, expected);
|
|
8909
9369
|
}
|
|
8910
9370
|
lowerShorthandValue(prop) {
|
|
8911
9371
|
return lowerShorthandValue(this, prop);
|
|
@@ -9203,8 +9663,8 @@ export class Lowerer {
|
|
|
9203
9663
|
lowerFieldCompound(access, op, rhsNode, loc) {
|
|
9204
9664
|
return lowerFieldCompound(this, access, op, rhsNode, loc);
|
|
9205
9665
|
}
|
|
9206
|
-
|
|
9207
|
-
return
|
|
9666
|
+
errorConstructorArgs(args, loc, blame) {
|
|
9667
|
+
return errorConstructorArgs(this, args, loc, blame);
|
|
9208
9668
|
}
|
|
9209
9669
|
inheritsBuiltinErrorCtor(info) {
|
|
9210
9670
|
return inheritsBuiltinErrorCtor(this, info);
|
|
@@ -9235,7 +9695,7 @@ export class Lowerer {
|
|
|
9235
9695
|
const arg = this.lowerExpr(expr.arguments[0]);
|
|
9236
9696
|
return { kind: "jsOp", op: "construct", args: [ctor, arg], type: JSVAL, loc };
|
|
9237
9697
|
}
|
|
9238
|
-
const builtin = lowerAbortControllerNew(this, expr) ?? lowerResponseNew(this, expr) ?? lowerStaticReadableStreamNew(this, expr);
|
|
9698
|
+
const builtin = lowerAbortControllerNew(this, expr) ?? lowerFetchWebNew(this, expr) ?? lowerResponseNew(this, expr) ?? lowerStaticReadableStreamNew(this, expr);
|
|
9239
9699
|
return builtin ?? this.withRuntimeOptionalClassValue(expr.expression, () => lowerNew(this, expr));
|
|
9240
9700
|
}
|
|
9241
9701
|
lowerFieldRead(expr) {
|
|
@@ -9384,7 +9844,7 @@ export class Lowerer {
|
|
|
9384
9844
|
}
|
|
9385
9845
|
if (!ts.isNamespaceImport(decl))
|
|
9386
9846
|
return null;
|
|
9387
|
-
const importDecl = decl.parent
|
|
9847
|
+
const importDecl = decl.parent?.parent;
|
|
9388
9848
|
if (!ts.isImportDeclaration(importDecl) || !ts.isStringLiteral(importDecl.moduleSpecifier))
|
|
9389
9849
|
return null;
|
|
9390
9850
|
return canonicalBuiltinModule(importDecl.moduleSpecifier.text);
|
|
@@ -9404,6 +9864,16 @@ export class Lowerer {
|
|
|
9404
9864
|
builtinMemberOf(access) {
|
|
9405
9865
|
if (access.questionDotToken)
|
|
9406
9866
|
return null;
|
|
9867
|
+
// Function-owned builtin members still require import provenance. A
|
|
9868
|
+
// user object named realpathSync must retain its ordinary method call.
|
|
9869
|
+
if (access.name.text === "native") {
|
|
9870
|
+
const owner = access.expression;
|
|
9871
|
+
const imported = ts.isIdentifier(owner) ? this.builtinImportOf(owner)
|
|
9872
|
+
: ts.isPropertyAccessExpression(owner) ? this.builtinMemberOf(owner) : null;
|
|
9873
|
+
if (imported?.module === "fs" && imported.member === "realpathSync") {
|
|
9874
|
+
return { module: "fs", member: "realpathSync.native" };
|
|
9875
|
+
}
|
|
9876
|
+
}
|
|
9407
9877
|
const module = this.builtinNamespaceModuleOf(access.expression);
|
|
9408
9878
|
if (module !== null)
|
|
9409
9879
|
return { module, member: access.name.text };
|
|
@@ -9507,10 +9977,10 @@ export class Lowerer {
|
|
|
9507
9977
|
if (!expr.questionDotToken && ts.isPropertyAccessExpression(expr.expression)) {
|
|
9508
9978
|
const inner = this.builtinMemberOf(expr.expression);
|
|
9509
9979
|
if (inner && inner.module === "fs" && inner.member === "constants") {
|
|
9510
|
-
const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4 };
|
|
9980
|
+
const MODES = { F_OK: 0, X_OK: 1, W_OK: 2, R_OK: 4, COPYFILE_EXCL: 1, COPYFILE_FICLONE: 2, COPYFILE_FICLONE_FORCE: 4 };
|
|
9511
9981
|
const value = own(MODES, expr.name.text);
|
|
9512
9982
|
if (value === undefined) {
|
|
9513
|
-
this.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, and
|
|
9983
|
+
this.noLowering(`fs.constants.${expr.name.text}`, expr, "F_OK, R_OK, W_OK, X_OK, and COPYFILE_* are the lowered constants");
|
|
9514
9984
|
}
|
|
9515
9985
|
return { kind: "numLit", value, type: F64, loc };
|
|
9516
9986
|
}
|
|
@@ -9518,6 +9988,10 @@ export class Lowerer {
|
|
|
9518
9988
|
const bi = this.builtinMemberOf(expr);
|
|
9519
9989
|
if (!bi)
|
|
9520
9990
|
return null;
|
|
9991
|
+
if ((bi.module === "path" || bi.module === "path/posix" || bi.module === "path/win32") &&
|
|
9992
|
+
(bi.member === "posix" || bi.member === "win32")) {
|
|
9993
|
+
return pathModuleValue(this, `path/${bi.member}`, loc);
|
|
9994
|
+
}
|
|
9521
9995
|
// events.defaultMaxListeners READS the process-wide default (its
|
|
9522
9996
|
// write twin routes through emitter.setDefaultMaxChk).
|
|
9523
9997
|
if (bi.module === "events" && bi.member === "defaultMaxListeners") {
|
|
@@ -9544,17 +10018,16 @@ export class Lowerer {
|
|
|
9544
10018
|
if (roots)
|
|
9545
10019
|
return roots;
|
|
9546
10020
|
}
|
|
9547
|
-
//
|
|
9548
|
-
//
|
|
9549
|
-
|
|
9550
|
-
if (!isJsSourceFile(expr.getSourceFile())) {
|
|
10021
|
+
// Builtin values admitted by an explicit surface-table contract use
|
|
10022
|
+
// the same interned native closures in TypeScript and JavaScript.
|
|
10023
|
+
{
|
|
9551
10024
|
const callable = this.lowerBuiltinCallableValue(bi, loc);
|
|
9552
10025
|
if (callable)
|
|
9553
10026
|
return callable;
|
|
9554
10027
|
}
|
|
9555
10028
|
if (bi.member === "constants" && bi.module === "fs") {
|
|
9556
10029
|
// A bare `fs.constants` read (not one of the baked bits above).
|
|
9557
|
-
this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, and
|
|
10030
|
+
this.noLowering(`fs.constants`, expr, "F_OK, R_OK, W_OK, X_OK, and COPYFILE_* are the lowered constants");
|
|
9558
10031
|
}
|
|
9559
10032
|
if (builtinModuleFnOf(this, bi.module, bi.member)) {
|
|
9560
10033
|
this.unsupported("SC1090", expr, `library functions as values (call '${expr.getText()}' directly)`);
|
|
@@ -9567,9 +10040,15 @@ export class Lowerer {
|
|
|
9567
10040
|
* deliberately narrower than table membership because many table rows
|
|
9568
10041
|
* are only dispatch sentinels for call-site-specific lowering. */
|
|
9569
10042
|
lowerBuiltinCallableValue(bi, loc) {
|
|
10043
|
+
if (bi.module === "fs" && builtinModuleFnOf(this, bi.module, bi.member)?.fn === "fs.callbackCall") {
|
|
10044
|
+
return { kind: "libCall", fn: "fs.callbackValue", args: [{ kind: "strLit", value: bi.member, type: STRING, loc }], type: DYN, loc };
|
|
10045
|
+
}
|
|
9570
10046
|
const fn = builtinModuleFnOf(this, bi.module, bi.member);
|
|
9571
|
-
|
|
9572
|
-
|
|
10047
|
+
return fn ? this.lowerNativeCallableValue(fn, `${bi.module}.${bi.member}`, loc) : null;
|
|
10048
|
+
}
|
|
10049
|
+
lowerNativeCallableValue(fn, display, loc) {
|
|
10050
|
+
const valueParams = fn.valueParams;
|
|
10051
|
+
if (!valueParams)
|
|
9573
10052
|
return null;
|
|
9574
10053
|
const shapes = valueParams.map((param) => {
|
|
9575
10054
|
if (param.mode === "rest")
|
|
@@ -9593,10 +10072,10 @@ export class Lowerer {
|
|
|
9593
10072
|
name: `arg${index}`,
|
|
9594
10073
|
type,
|
|
9595
10074
|
}));
|
|
9596
|
-
const args =
|
|
9597
|
-
const
|
|
9598
|
-
if (!valueParam) {
|
|
9599
|
-
throw new InternalCompilerError(`builtin callable value '${
|
|
10075
|
+
const args = valueParams.map((valueParam, index) => {
|
|
10076
|
+
const param = params[index];
|
|
10077
|
+
if (!param || !valueParam) {
|
|
10078
|
+
throw new InternalCompilerError(`builtin callable value '${display}' has a missing value parameter`);
|
|
9600
10079
|
}
|
|
9601
10080
|
const ref = {
|
|
9602
10081
|
kind: "varRef",
|
|
@@ -9606,13 +10085,13 @@ export class Lowerer {
|
|
|
9606
10085
|
};
|
|
9607
10086
|
if (valueParam.mode !== "optional")
|
|
9608
10087
|
return ref;
|
|
9609
|
-
if (valueParam.type.kind !== "string" || param.type.kind !== "union") {
|
|
9610
|
-
throw new InternalCompilerError(`builtin callable value '${
|
|
10088
|
+
if ((valueParam.type.kind !== "string" && valueParam.type.kind !== "f64") || param.type.kind !== "union") {
|
|
10089
|
+
throw new InternalCompilerError(`builtin callable value '${display}' has an unsupported optional default`);
|
|
9611
10090
|
}
|
|
9612
10091
|
const undefTag = this.armTag(param.type.unionId, UNDEFINED_T);
|
|
9613
10092
|
const valueTag = this.armTag(param.type.unionId, valueParam.type);
|
|
9614
10093
|
if (undefTag < 0 || valueTag < 0) {
|
|
9615
|
-
throw new InternalCompilerError(`builtin callable value '${
|
|
10094
|
+
throw new InternalCompilerError(`builtin callable value '${display}' has an invalid optional ABI`);
|
|
9616
10095
|
}
|
|
9617
10096
|
return {
|
|
9618
10097
|
kind: "ternary",
|
|
@@ -9625,7 +10104,9 @@ export class Lowerer {
|
|
|
9625
10104
|
type: BOOL,
|
|
9626
10105
|
loc,
|
|
9627
10106
|
},
|
|
9628
|
-
then:
|
|
10107
|
+
then: typeof valueParam.defaultValue === "string"
|
|
10108
|
+
? { kind: "strLit", value: valueParam.defaultValue, type: STRING, loc }
|
|
10109
|
+
: { kind: "numLit", value: valueParam.defaultValue, type: F64, loc },
|
|
9629
10110
|
else_: {
|
|
9630
10111
|
kind: "unionNarrow",
|
|
9631
10112
|
unionId: param.type.unionId,
|