@scriptc/compiler 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +73 -24
- 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 +107 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/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 +70 -28
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.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 +16 -2
- package/dist/backend/llvm/dyn.js +494 -165
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +596 -1
- package/dist/backend/llvm/emitter.js +695 -410
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +32 -14
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +9 -5
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +62 -74
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +51 -30
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +43 -4
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +102 -121
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +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 +21 -16
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +117 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +35 -130
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +10 -25
- package/dist/backend/native-toolchain.js +31 -211
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +5 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +70 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +95 -30
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +65 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +3 -3
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +3 -3
- 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 +63 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
- package/dist/frontend/lowering/class-descriptors.js +73 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +92 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +64 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +10 -0
- package/dist/frontend/lowering/class-method-values.js +170 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
- package/dist/frontend/lowering/class-prototypes.js +134 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +164 -155
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +39 -16
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +11 -0
- package/dist/frontend/lowering/error-methods.js +78 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +49 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +124 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +473 -178
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +20 -8
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +93 -0
- package/dist/frontend/lowering/function-context.js +103 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +10 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
- package/dist/frontend/lowering/lib-boundary.js +59 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +12 -0
- package/dist/frontend/lowering/lower-builtin-values.js +139 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
- package/dist/frontend/lowering/lower-builtins.js +539 -343
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +20 -17
- package/dist/frontend/lowering/lower-calls.js +1236 -353
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +83 -45
- package/dist/frontend/lowering/lower-classes.js +952 -339
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +27 -32
- package/dist/frontend/lowering/lower-containers.js +796 -151
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +35 -11
- package/dist/frontend/lowering/lower-exprs.js +1674 -779
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +77 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +5 -8
- package/dist/frontend/lowering/lower-island.js +34 -23
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +233 -30
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +10 -14
- package/dist/frontend/lowering/lower-stmts.js +728 -496
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +19 -10
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +113 -189
- package/dist/frontend/lowering/lowerer.js +1031 -672
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +26 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +8 -3
- package/dist/frontend/lowering/surfaces.js +61 -29
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +10 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +77 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +5 -4
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +1 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +38 -19
- package/dist/frontend/program.js +344 -169
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +87 -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 +21 -15
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +52 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +25 -17
- package/dist/frontend/type-mapper.js +465 -121
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +123 -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 +21 -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 +291 -152
- package/dist/ir/ir.js +588 -881
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +127 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +19 -12
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +53 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +1942 -1491
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +476 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +135 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +74 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +33 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +52 -18
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -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,28 +1,34 @@
|
|
|
1
|
+
import { objectEnumerationReceiver } from "./object-enumeration-receiver.js";
|
|
1
2
|
import { InternalCompilerError } from "../../errors.js";
|
|
2
3
|
/* Call lowering: the lowerCall dispatch chain, parameter-shape analysis and
|
|
3
4
|
* argument completion (optional/default/rest, explicit-undefined ≡ omission),
|
|
4
5
|
* function/lambda lowering and signature collection, and monomorphizing
|
|
5
6
|
* generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
|
|
6
7
|
import * as ts from "../ts7/adapter.js";
|
|
8
|
+
import { AstNode } from "../ts7/ast-node.js";
|
|
7
9
|
import { bodyReadsArguments } from "../arguments-usage.js";
|
|
8
10
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
11
|
+
import { lowerClassSymbolMethodCall } from "./symbol-methods.js";
|
|
12
|
+
import { errorToStringCall } from "./error-methods.js";
|
|
13
|
+
import { lowerClassPrototypeAssign } from "./class-prototypes.js";
|
|
14
|
+
import { BYTES_ELEMENT_NAME, BIGINT_T, BOOL, CAUGHT, DYN, F64, JSVAL, NULL_T, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isDynTypedRefType, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/ir.js";
|
|
15
|
+
import { isJsSourceFile, isNodeEsmFile, locOf, requireSpecOf } from "../program.js";
|
|
16
|
+
import { genResultRecord, isGenericCallableMemberType, jsOpenObjectType, typeKey } from "../type-mapper.js";
|
|
12
17
|
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
|
|
13
18
|
import { enforceLibBoundary } from "./lib-boundary.js";
|
|
14
19
|
import { NARROW_FIRST, STRING_INDEX_METHODS, STR_METHODS, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
|
15
20
|
import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
|
16
21
|
import { mixinFnShapeOf } from "./lower-mixins.js";
|
|
17
22
|
import { dynStringReceiver, lowerArrayConstructor, lowerArrayFromCall, lowerArrayOfCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
|
|
18
|
-
import {
|
|
23
|
+
import { lowerBytesStaticCall } from "./containers/bytes.js";
|
|
19
24
|
import { lowerRegexMethodCall, lowerStringIndexCall, lowerStringMethodCall, lowerStringPaddingCall, lowerStringSplitCall } from "./containers/string-and-regexp.js";
|
|
20
|
-
import { lowerChildStreamMethodCall, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerNodeModuleCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
|
|
25
|
+
import { createRequireSpecOf, lowerChildStreamMethodCall, lowerChildWriterMethodCall, lowerCreateRequireCall, lowerCryptoHashMethodCall, lowerDirentMethodCall, lowerFileHandleMethodCall, lowerImportMetaResolveCall, lowerNodeModuleCall, lowerPerfHooksCall, lowerProcStreamMethodCall, lowerReflectApplyCall, lowerRequireResolveCall, lowerWatcherMethodCall } from "./lower-builtins.js";
|
|
21
26
|
import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, stringWrapperToString, templateRawTextOf } from "./lower-exprs.js";
|
|
22
27
|
import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
|
|
23
28
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
24
29
|
import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerCompatReqStreamOptionalCall, lowerHttpClientFnCall } from "./lower-server.js";
|
|
25
|
-
import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall } from "./lower-classes.js";
|
|
30
|
+
import { EMITTER_API_MEMBERS, exactInstanceClassOf, findGenericMethodOn, lowerClassGenericMethodCall, lowerStaticMethodCall, returnsOnlyThis } from "./lower-classes.js";
|
|
31
|
+
import { classCallbackCall, isClassCallback } from "./class-callbacks.js";
|
|
26
32
|
import { emitterRooted, lowerEmitterMethodCall } from "./lower-event-emitter.js";
|
|
27
33
|
import { lowerConsoleInspectArg, lowerFormatCall } from "./lower-inspect.js";
|
|
28
34
|
import { STREAM_API_MEMBERS, lowerStreamMethodCall, lowerStreamModuleCall, lowerStreamStaticCall, streamSidesOf } from "./lower-stream.js";
|
|
@@ -30,10 +36,13 @@ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUn
|
|
|
30
36
|
import { declSymbolOf } from "./lower-modules.js";
|
|
31
37
|
import { expandoMemberRead } from "./lower-expando.js";
|
|
32
38
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
33
|
-
import { countedFor, varRef } from "../../ir/build.js";
|
|
39
|
+
import { countedFor, numLit, varRef } from "../../ir/build.js";
|
|
34
40
|
import { rejectStaticThis } from "./static-this.js";
|
|
35
41
|
import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
|
|
36
42
|
import { defaultAfterUndefined, lowerOptionalArgument, lowerStaticallyUndefinedArgument, positionNumber } from "./optional-arguments.js";
|
|
43
|
+
import { fenceSymbolFieldCopy } from "./symbol-fields.js";
|
|
44
|
+
import { lowerClassDataDescriptor, lowerClassDescriptorRead } from "./class-descriptors.js";
|
|
45
|
+
import { classStaticDataFor } from "./class-static-data.js";
|
|
37
46
|
export { bodyReadsArguments };
|
|
38
47
|
/** The one func-type projection of completed parameter shapes. Typed rest
|
|
39
48
|
* parameters keep their packed array as the trailing native ABI slot and
|
|
@@ -51,11 +60,7 @@ export function funcTypeFromParamShapes(shapes, ret) {
|
|
|
51
60
|
ret,
|
|
52
61
|
...(typedRest || dynRest || islandRest || argumentsAll ? { rest: true } : {}),
|
|
53
62
|
...(argumentsAll ? { argumentsAll: true } : {}),
|
|
54
|
-
...(typedRest
|
|
55
|
-
? { restAbi: "typed" }
|
|
56
|
-
: islandRest
|
|
57
|
-
? { restAbi: "jsval" }
|
|
58
|
-
: {}),
|
|
63
|
+
...(typedRest || islandRest ? { restAbi: typedRest ? "typed" : "jsval" } : {}),
|
|
59
64
|
};
|
|
60
65
|
}
|
|
61
66
|
/** Registers `const alias = overloadedDeclaration` as a compile-time
|
|
@@ -118,6 +123,11 @@ export const MAX_GENERIC_INSTANCES = 100;
|
|
|
118
123
|
* - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
|
|
119
124
|
*/
|
|
120
125
|
export function paramShape(lowerer, param) {
|
|
126
|
+
if (lowerer.checkedCallbackParams.has(param)) {
|
|
127
|
+
return param.initializer
|
|
128
|
+
? { type: DYN, mode: "omittable", bodyType: DYN }
|
|
129
|
+
: { type: DYN, mode: "required" };
|
|
130
|
+
}
|
|
121
131
|
const moduleNs = lowerer.moduleNsParamOverrides.get(param);
|
|
122
132
|
if (moduleNs !== undefined) {
|
|
123
133
|
return { type: moduleNs, mode: param.questionToken ? "omittable" : "required" };
|
|
@@ -159,21 +169,7 @@ export function paramShape(lowerer, param) {
|
|
|
159
169
|
// default when the argument was omitted or undefined, then the
|
|
160
170
|
// pattern destructures the picked value (declareParams).
|
|
161
171
|
const raw = lowerer.irTypeOf(param.name);
|
|
162
|
-
|
|
163
|
-
// `a: any` — jsval for island values, dyn for the checked-dynamic
|
|
164
|
-
// dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
|
|
165
|
-
// is the slot itself — no synthesized union; the prologue tests
|
|
166
|
-
// undefined at runtime (declareParams).
|
|
167
|
-
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
168
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
169
|
-
}
|
|
170
|
-
const bodyType = lowerer.stripUndefinedArm(raw);
|
|
171
|
-
lowerer.checkDefaultParamBodyType(param, bodyType);
|
|
172
|
-
const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
|
|
173
|
-
if (!abi) {
|
|
174
|
-
lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
|
|
175
|
-
}
|
|
176
|
-
return { type: abi, mode: "omittable", bodyType };
|
|
172
|
+
return defaultParameterShape(lowerer, param, raw);
|
|
177
173
|
}
|
|
178
174
|
return { type: lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name)), mode: "required" };
|
|
179
175
|
}
|
|
@@ -207,41 +203,12 @@ export function paramShape(lowerer, param) {
|
|
|
207
203
|
}
|
|
208
204
|
if (param.initializer) {
|
|
209
205
|
const raw = lowerer.irTypeOf(param.name);
|
|
210
|
-
|
|
211
|
-
// — tsc types x any; jsval for island values, dyn for the checked-
|
|
212
|
-
// dynamic dyn): the slot holds its tier's undefined directly, so
|
|
213
|
-
// the ABI is the slot itself and the prologue's default test is the
|
|
214
|
-
// runtime undefined test (declareParams).
|
|
215
|
-
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
216
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
217
|
-
}
|
|
218
|
-
// A default that may ITSELF be undefined (`x = process.env.FOO`):
|
|
219
|
-
// tsc keeps undefined in the body's type, so there is nothing to
|
|
220
|
-
// narrow — the ABI union IS the body type and the prologue passes a
|
|
221
|
-
// present argument through unchanged (declareParams's pass-through
|
|
222
|
-
// branch). The generic strip-and-narrow below would demand a
|
|
223
|
-
// `string`-typed default and fence on the union re-tag.
|
|
224
|
-
if (lowerer.bareUndefinedArmedUnion(raw)) {
|
|
225
|
-
const initT = lowerer.mapTypeOf(lowerer.typeOf(param.initializer));
|
|
226
|
-
if (initT && (initT.kind === "undefinedT" || lowerer.bareUndefinedArmedUnion(initT))) {
|
|
227
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
const bodyType = lowerer.stripUndefinedArm(raw);
|
|
231
|
-
lowerer.checkDefaultParamBodyType(param, bodyType);
|
|
232
|
-
// A UNION body type (`tlds: string | string[] = "localhost"`) arms
|
|
233
|
-
// the ABI with undefined ON TOP of the body's arms; the prologue
|
|
234
|
-
// re-tags a present argument back into the body union (undefined
|
|
235
|
-
// sorts last among arm typeKeys in practice, so the mapping is
|
|
236
|
-
// usually the identity prefix — the interned retag helper handles
|
|
237
|
-
// any order).
|
|
238
|
-
const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
|
|
239
|
-
if (!abi) {
|
|
240
|
-
lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
|
|
241
|
-
}
|
|
242
|
-
return { type: abi, mode: "omittable", bodyType };
|
|
206
|
+
return defaultParameterShape(lowerer, param, raw);
|
|
243
207
|
}
|
|
244
208
|
const type = lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name));
|
|
209
|
+
if (type.kind === "void") {
|
|
210
|
+
lowerer.unsupported("SC1090", param, "function parameters with void type");
|
|
211
|
+
}
|
|
245
212
|
if (param.questionToken && !lowerer.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
|
|
246
213
|
// `x?: unknown` where unknown came from an annotation: undefined is
|
|
247
214
|
// absorbed into the hole type, so no undefined ARM exists — but a
|
|
@@ -269,7 +236,7 @@ export function paramShapes(lowerer, params, signature, blameOf) {
|
|
|
269
236
|
return params.map((declParam, i) => {
|
|
270
237
|
const symbol = signature.getParameters()[i];
|
|
271
238
|
const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name);
|
|
272
|
-
const mapped = lowerer.runtimeOptionalBindingType(declParam.name, lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name));
|
|
239
|
+
const mapped = jsOpenObjectType(declParam, lowerer.runtimeOptionalBindingType(declParam.name, lowerer.mapTypeOf(tsType) ?? lowerer.irTypeOf(declParam.name)), lowerer.shapes, lowerer.unions);
|
|
273
240
|
if (!mapped || mapped.kind === "void")
|
|
274
241
|
lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
|
|
275
242
|
if (declParam.dotDotDotToken) {
|
|
@@ -277,30 +244,46 @@ export function paramShapes(lowerer, params, signature, blameOf) {
|
|
|
277
244
|
lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
|
|
278
245
|
return { type: mapped, mode: "rest" };
|
|
279
246
|
}
|
|
280
|
-
if (declParam.initializer)
|
|
281
|
-
|
|
282
|
-
return { type: mapped, mode: "omittable", bodyType: mapped };
|
|
283
|
-
}
|
|
284
|
-
const bodyType = lowerer.stripUndefinedArm(mapped);
|
|
285
|
-
lowerer.checkDefaultParamBodyType(declParam, bodyType);
|
|
286
|
-
return { type: lowerer.withUndefinedArm(bodyType), mode: "omittable", bodyType };
|
|
287
|
-
}
|
|
247
|
+
if (declParam.initializer)
|
|
248
|
+
return defaultParameterShape(lowerer, declParam, mapped);
|
|
288
249
|
if (declParam.questionToken && !lowerer.bareUndefinedArmedUnion(mapped)) {
|
|
289
250
|
lowerer.unsupported("SC1090", declParam, `optional parameters of type '${lowerer.fmt(mapped)}'`);
|
|
290
251
|
}
|
|
291
252
|
return { type: mapped, mode: declParam.questionToken ? "omittable" : "required" };
|
|
292
253
|
});
|
|
293
254
|
}
|
|
255
|
+
/** A default expression may itself yield undefined. Keep that arm in the
|
|
256
|
+
* body and parameter-property storage, including for literal `undefined`
|
|
257
|
+
* and void expressions: the general type mapper represents those as VOID,
|
|
258
|
+
* so checking only a mapped undefinedT silently erased a valid value.
|
|
259
|
+
* Shared by declared and instantiated signatures, including destructuring. */
|
|
260
|
+
function defaultParameterShape(lowerer, param, raw) {
|
|
261
|
+
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
262
|
+
return { type: raw, mode: "omittable", bodyType: raw };
|
|
263
|
+
}
|
|
264
|
+
if (lowerer.bareUndefinedArmedUnion(raw) && param.initializer) {
|
|
265
|
+
const initializer = lowerer.typeOf(param.initializer);
|
|
266
|
+
const parts = initializer.isUnionType() ? ts.constituentTypes(initializer) : [initializer];
|
|
267
|
+
if (parts.some((part) => (part.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Void)) !== 0)) {
|
|
268
|
+
return { type: raw, mode: "omittable", bodyType: raw };
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const bodyType = lowerer.stripUndefinedArm(raw);
|
|
272
|
+
lowerer.checkDefaultParamBodyType(param, bodyType);
|
|
273
|
+
const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
|
|
274
|
+
if (!abi)
|
|
275
|
+
lowerer.badType(param.name, lowerer.typeOf(param.name));
|
|
276
|
+
return { type: abi, mode: "omittable", bodyType };
|
|
277
|
+
}
|
|
294
278
|
/** The fences on a defaulted parameter's body type: it becomes the value
|
|
295
279
|
* arm of the synthesized `T | undefined` ABI union, so it must be a valid
|
|
296
|
-
* single arm.
|
|
280
|
+
* single arm. Functions, Maps and Sets are valid: the ABI union's test is
|
|
297
281
|
* the prologue's own undefined-tag check (never a user narrowing, which
|
|
298
|
-
* is what keeps
|
|
282
|
+
* is what keeps containers out of unions with data siblings), so `runner: Runner =
|
|
299
283
|
* defaultRunner` and `skip: Set<string> = new Set()` arm like any ref
|
|
300
284
|
* kind — the nullable-callback union shape, built by the compiler. */
|
|
301
285
|
export function checkDefaultParamBodyType(lowerer, param, bodyType) {
|
|
302
286
|
if (bodyType.kind === "void" ||
|
|
303
|
-
bodyType.kind === "map" ||
|
|
304
287
|
bodyType.kind === "regex" ||
|
|
305
288
|
bodyType.kind === "date" ||
|
|
306
289
|
bodyType.kind === "dyn" ||
|
|
@@ -336,7 +319,62 @@ export function completeArgs(lowerer, argNodes, shapes, loc, blame,
|
|
|
336
319
|
* coercion an ordinary argument gets (coerceInto against its shape,
|
|
337
320
|
* DYN conversion in a dyn rest, element coercion in a typed rest). */
|
|
338
321
|
leading) {
|
|
339
|
-
|
|
322
|
+
// Conversion eligibility can traverse the whole recursive parameter
|
|
323
|
+
// graph. Ordinary calls and fixed tuples never need that analysis.
|
|
324
|
+
if (argNodes.some((arg) => ts.isSpreadElement(arg) && !fixedTupleSpreadInfo(lowerer, arg.expression)) &&
|
|
325
|
+
canCompleteRuntimeSpread(lowerer, shapes)) {
|
|
326
|
+
// Runtime-length spreads determine the complete argument list before
|
|
327
|
+
// any parameter default runs. Build it once in source order, then
|
|
328
|
+
// extract the fixed native ABI slots; missing elements are undefined.
|
|
329
|
+
const pack = lowerer.declareHiddenLocal("%spreadArgs", DYN);
|
|
330
|
+
const ref = () => ({ kind: "varRef", localId: pack.id, type: DYN, loc });
|
|
331
|
+
const stmts = [{ kind: "varDecl", localId: pack.id, init: { kind: "dynArrLit", elems: [], type: DYN, loc }, loc }];
|
|
332
|
+
const push = (value, fn) => {
|
|
333
|
+
stmts.push({ kind: "exprStmt", expr: { kind: "libCall", fn, args: [ref(), value], type: VOID, loc: value.loc }, loc: value.loc });
|
|
334
|
+
};
|
|
335
|
+
for (const value of leading ?? [])
|
|
336
|
+
push(lowerer.coerceInto(blame, value, DYN), "dyn.packPush");
|
|
337
|
+
const spreads = argNodes.filter(ts.isSpreadElement).length;
|
|
338
|
+
argNodes.forEach((arg, index) => {
|
|
339
|
+
if (!ts.isSpreadElement(arg)) {
|
|
340
|
+
push(lowerer.lowerExprExpecting(arg, DYN), "dyn.packPush");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
let value = lowerer.lowerExpr(arg.expression);
|
|
344
|
+
if (value.type.kind === "set") {
|
|
345
|
+
value = { kind: "setIntrinsic", method: "toArray", receiver: value, args: [], type: arrayOf(value.type.elem), loc: value.loc };
|
|
346
|
+
}
|
|
347
|
+
else if (value.type.kind === "object") {
|
|
348
|
+
value = lowerer.classIteratorDrainCall(value, locOf(arg)) ?? value;
|
|
349
|
+
}
|
|
350
|
+
if (value.type.kind === "array") {
|
|
351
|
+
// Argument iteration materializes holes as present undefined
|
|
352
|
+
// before conversion to the dense checked-dynamic argument pack.
|
|
353
|
+
value = { kind: "arrayLit", elems: [value], spreads: [0], type: value.type, loc: value.loc };
|
|
354
|
+
}
|
|
355
|
+
value = lowerer.coerceInto(arg.expression, value, DYN);
|
|
356
|
+
if (spreads === 1 && index === argNodes.length - 1) {
|
|
357
|
+
stmts.push({ kind: "exprStmt", expr: {
|
|
358
|
+
kind: "libCall", fn: "dyn.packPushSpread", args: [ref(), value, { kind: "strLit", value: arg.expression.getText(), type: STRING, loc }], type: VOID, loc,
|
|
359
|
+
}, loc });
|
|
360
|
+
}
|
|
361
|
+
else
|
|
362
|
+
push(value, "dyn.packPushSpreadIter");
|
|
363
|
+
});
|
|
364
|
+
const args = shapes.map((shape, index) => {
|
|
365
|
+
if (shape.mode === "arguments")
|
|
366
|
+
return ref();
|
|
367
|
+
const value = shape.mode === "rest" || shape.mode === "dynRest"
|
|
368
|
+
? { kind: "dynInvoke", recv: ref(), method: "slice", calleeName: "arguments.slice", args: [{ kind: "dynFrom", value: { kind: "numLit", value: index, type: F64, loc }, type: DYN, loc }], type: DYN, loc }
|
|
369
|
+
: { kind: "dynKeyGet", value: ref(), key: { kind: "strLit", value: String(index), type: STRING, loc }, type: DYN, loc };
|
|
370
|
+
return lowerer.coerceInto(blame, value, shape.type);
|
|
371
|
+
});
|
|
372
|
+
// Every supported form has at least one native slot to carry the
|
|
373
|
+
// evaluation prefix, including calls whose only slot is their rest.
|
|
374
|
+
args[0] = { kind: "seqExpr", stmts, result: args[0], type: args[0].type, loc };
|
|
375
|
+
return args;
|
|
376
|
+
}
|
|
377
|
+
const isIr = (s) => s !== undefined && !(s instanceof AstNode);
|
|
340
378
|
const sources = leading?.map((ir) => ({ ir })) ?? [];
|
|
341
379
|
for (const arg of argNodes) {
|
|
342
380
|
if (!ts.isSpreadElement(arg)) {
|
|
@@ -399,9 +437,20 @@ leading) {
|
|
|
399
437
|
lowerer.unsupported("SC1090", source, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
|
|
400
438
|
}
|
|
401
439
|
const slotType = i < restAt ? positional[i].type : DYN;
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
440
|
+
let value;
|
|
441
|
+
if (isIr(source)) {
|
|
442
|
+
let ir = source.ir;
|
|
443
|
+
// Tuple-spread storage also feeds later arguments. Declare it in
|
|
444
|
+
// this shared sequence, not inside one argument's initializer,
|
|
445
|
+
// whose statement frame ends before the next field is read.
|
|
446
|
+
if (ir.kind === "seqExpr") {
|
|
447
|
+
stmts.push(...ir.stmts);
|
|
448
|
+
ir = ir.result;
|
|
449
|
+
}
|
|
450
|
+
value = lowerer.coerceInto(blame, ir, slotType);
|
|
451
|
+
}
|
|
452
|
+
else
|
|
453
|
+
value = lowerer.lowerExprExpecting(source, slotType);
|
|
405
454
|
const saved = lowerer.declareHiddenLocal("%callArg", slotType);
|
|
406
455
|
stmts.push({ kind: "varDecl", localId: saved.id, init: value, loc: value.loc });
|
|
407
456
|
return { kind: "varRef", localId: saved.id, type: slotType, loc: value.loc };
|
|
@@ -409,7 +458,7 @@ leading) {
|
|
|
409
458
|
const fixed = positional.map((shape, i) => {
|
|
410
459
|
if (i < passed.length)
|
|
411
460
|
return passed[i];
|
|
412
|
-
if (shape.mode === "omittable")
|
|
461
|
+
if (shape.mode === "omittable" || lowerer.bareUndefinedArmedUnion(shape.type))
|
|
413
462
|
return shape.callDefault ?? lowerer.undefinedArgFor(shape.type, loc, blame);
|
|
414
463
|
if (shape.type.kind === "dyn")
|
|
415
464
|
return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
|
|
@@ -434,9 +483,19 @@ leading) {
|
|
|
434
483
|
// completion has no home for that. Spreads fill REST slots only.
|
|
435
484
|
lowerer.unsupported("SC1090", arg, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
|
|
436
485
|
}
|
|
437
|
-
if (arg)
|
|
486
|
+
if (arg) {
|
|
487
|
+
let operand = arg;
|
|
488
|
+
while (ts.isParenthesizedExpression(operand))
|
|
489
|
+
operand = operand.expression;
|
|
490
|
+
if (ts.isVoidExpression(operand)) {
|
|
491
|
+
const absent = omittedArgFor(lowerer, shape.type, loc);
|
|
492
|
+
const effect = lowerStaticallyUndefinedArgument(lowerer, operand);
|
|
493
|
+
if (absent && effect)
|
|
494
|
+
return defaultAfterUndefined(effect, absent);
|
|
495
|
+
}
|
|
438
496
|
return lowerer.lowerExprExpecting(arg, shape.type);
|
|
439
|
-
|
|
497
|
+
}
|
|
498
|
+
if (shape.mode !== "omittable" && !lowerer.bareUndefinedArmedUnion(shape.type)) {
|
|
440
499
|
// A missing argument for a CHECKED-DYNAMIC param (an implicit-any
|
|
441
500
|
// JS signature called short — `mustCall(fn)` with `expected`
|
|
442
501
|
// omitted): JS fills undefined, and the dyn slot holds exactly
|
|
@@ -690,7 +749,9 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
|
|
|
690
749
|
// slot): judge by the expression's OWN completed type; the slot's
|
|
691
750
|
// coercion still enforces (or adapts) the flow it lands in.
|
|
692
751
|
if (mappedFn?.kind !== "func" && contextual) {
|
|
693
|
-
|
|
752
|
+
const ownType = lowerer.typeOf(contextual);
|
|
753
|
+
mappedFn = lowerer.mapTypeOf(ownType) ??
|
|
754
|
+
(isJsSourceFile(contextual.getSourceFile()) ? dynFallbackType(lowerer, contextual, ownType) : null);
|
|
694
755
|
}
|
|
695
756
|
if (mappedFn && typeEquals(mappedFn, funcType))
|
|
696
757
|
return;
|
|
@@ -810,6 +871,10 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
810
871
|
if (!sig)
|
|
811
872
|
lowerer.unsupported("SC1090", decl, "this function form");
|
|
812
873
|
const retTsType = lowerer.checker.getReturnTypeOfSignature(sig);
|
|
874
|
+
// An inferred null/undefined return in JS can read a mutable checked-value
|
|
875
|
+
// field. Keep the actual value instead of restricting it to the initializer.
|
|
876
|
+
if (isJsSourceFile(decl.getSourceFile()) && (retTsType.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0)
|
|
877
|
+
return DYN;
|
|
813
878
|
// A body that always throws infers `never` — as a RETURN type that is
|
|
814
879
|
// void with a stronger guarantee (`() => never` is assignable to
|
|
815
880
|
// `() => void`), and throw-only callbacks are ordinary code
|
|
@@ -817,10 +882,34 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
817
882
|
if (retTsType.flags & ts.TypeFlags.Never)
|
|
818
883
|
return VOID;
|
|
819
884
|
const mappedReturn = lowerer.mapTypeOf(retTsType);
|
|
885
|
+
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) && mappedReturn?.kind === "date")
|
|
886
|
+
return DYN;
|
|
887
|
+
// JS inference assigns Number to arithmetic over any, although the
|
|
888
|
+
// runtime operands can both be BigInts. Preserve that native result.
|
|
889
|
+
if (isJsSourceFile(decl.getSourceFile()) && !decl.type && !hasExplicitJsDocReturn(decl) &&
|
|
890
|
+
mappedReturn?.kind === "f64") {
|
|
891
|
+
let numericAnyReturn = false;
|
|
892
|
+
const numeric = new Set([ts.SyntaxKind.MinusToken, ts.SyntaxKind.AsteriskToken,
|
|
893
|
+
ts.SyntaxKind.SlashToken, ts.SyntaxKind.PercentToken, ts.SyntaxKind.AsteriskAsteriskToken]);
|
|
894
|
+
const check = (node) => {
|
|
895
|
+
if (node !== decl && ts.isFunctionLike(node))
|
|
896
|
+
return;
|
|
897
|
+
const value = ts.isReturnStatement(node) ? node.expression
|
|
898
|
+
: node === decl && ts.isArrowFunction(decl) && !ts.isBlock(decl.body) ? decl.body : undefined;
|
|
899
|
+
if (value && ts.isBinaryExpression(value) && numeric.has(value.operatorToken.kind) &&
|
|
900
|
+
[value.left, value.right].some((operand) => (lowerer.typeOf(operand).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0))
|
|
901
|
+
numericAnyReturn = true;
|
|
902
|
+
node.forEachChild(check);
|
|
903
|
+
};
|
|
904
|
+
check(decl);
|
|
905
|
+
if (numericAnyReturn)
|
|
906
|
+
return DYN;
|
|
907
|
+
}
|
|
820
908
|
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
821
909
|
!hasExplicitJsDocReturn(decl) &&
|
|
822
910
|
mappedReturn !== null &&
|
|
823
911
|
promiseCarriesDyn(lowerer, mappedReturn) &&
|
|
912
|
+
!decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
824
913
|
decl.parameters.some((param) => {
|
|
825
914
|
const mapped = lowerer.mapTypeOf(lowerer.typeOf(param.name));
|
|
826
915
|
return mapped === null || mapped.kind === "dyn";
|
|
@@ -852,14 +941,19 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
852
941
|
// checked-dynamic (or none): a lambda with RECORD-typed parameters
|
|
853
942
|
// (a reduce reducer over a typed array) legitimately returns its
|
|
854
943
|
// parameters' records and keeps the static type.
|
|
944
|
+
// Native-only members (such as Int32Array layout offsets) cannot cross
|
|
945
|
+
// that boundary; their factories keep the native record ABI.
|
|
946
|
+
const asyncReturn = decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) && mappedReturn?.kind === "promise";
|
|
947
|
+
const recordReturn = asyncReturn ? mappedReturn.inner : mappedReturn;
|
|
855
948
|
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
856
949
|
decl.type === undefined &&
|
|
857
|
-
|
|
950
|
+
recordReturn?.kind === "record" &&
|
|
951
|
+
lowerer.dynConvertible(recordReturn) &&
|
|
858
952
|
decl.parameters.every((p) => {
|
|
859
953
|
const mt = lowerer.mapTypeOf(lowerer.typeOf(p));
|
|
860
954
|
return mt === null || mt.kind === "dyn";
|
|
861
955
|
})) {
|
|
862
|
-
return DYN;
|
|
956
|
+
return asyncReturn ? { kind: "promise", inner: DYN } : DYN;
|
|
863
957
|
}
|
|
864
958
|
const returnType = lowerer.mapTypeOf(retTsType);
|
|
865
959
|
if (!returnType) {
|
|
@@ -884,7 +978,7 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
884
978
|
* other unmappable type (the caller's badType reports those). */
|
|
885
979
|
function fenceGenericSignatureResult(lowerer, blame, t) {
|
|
886
980
|
const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
|
|
887
|
-
if (!parts.some((p) => lowerer.checker.getCallSignatures(p).some((s) =>
|
|
981
|
+
if (!parts.some((p) => lowerer.checker.getCallSignatures(p).some((s) => s.getTypeParameters().length > 0))) {
|
|
888
982
|
return;
|
|
889
983
|
}
|
|
890
984
|
lowerer.unsupported("SC1090", blame, `results that are themselves generic functions ('${lowerer.checker.typeToString(t)}' keeps its type parameters — no call-site instantiation pins them, and the returned value would need the producing call's frame; restructure to one generic function taking all arguments)`);
|
|
@@ -961,7 +1055,7 @@ export function collectSignatureInner(lowerer, decl) {
|
|
|
961
1055
|
if (!params.some((sh) => sh.mode === "rest" || sh.mode === "dynRest" || sh.mode === "islandRest") &&
|
|
962
1056
|
isJsSourceFile(decl.getSourceFile()) &&
|
|
963
1057
|
bodyReadsArguments(decl)) {
|
|
964
|
-
if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile())) {
|
|
1058
|
+
if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)) {
|
|
965
1059
|
lowerer.unsupported("SC1090", decl, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
|
|
966
1060
|
}
|
|
967
1061
|
params.push({ type: DYN, mode: decl.parameters.length > 0 ? "arguments" : "dynRest" });
|
|
@@ -1193,7 +1287,7 @@ export function inferTypeParamBindings(lowerer, expr, info, rsig, tsBindings) {
|
|
|
1193
1287
|
return;
|
|
1194
1288
|
const taT = lowerer.checker.getTypeFromTypeNode(ta);
|
|
1195
1289
|
const mapped = lowerer.mapTypeOf(taT);
|
|
1196
|
-
if (mapped
|
|
1290
|
+
if (mapped) {
|
|
1197
1291
|
bindings.set(tp, mapped);
|
|
1198
1292
|
tsBindings?.set(tp, taT);
|
|
1199
1293
|
}
|
|
@@ -1213,7 +1307,7 @@ function bindDefaultTypeParams(lowerer, typeParams, typeParamDecls, bindings, ts
|
|
|
1213
1307
|
return;
|
|
1214
1308
|
const defT = lowerer.checker.getTypeFromTypeNode(tpDecl.defaultType);
|
|
1215
1309
|
const mapped = lowerer.mapTypeOf(defT);
|
|
1216
|
-
if (mapped
|
|
1310
|
+
if (mapped) {
|
|
1217
1311
|
bindings.set(tp, mapped);
|
|
1218
1312
|
tsBindings?.set(tp, defT);
|
|
1219
1313
|
}
|
|
@@ -1255,7 +1349,10 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1255
1349
|
}
|
|
1256
1350
|
if (!bindings.has(sym)) {
|
|
1257
1351
|
const mapped = lowerer.mapTypeOf(inst);
|
|
1258
|
-
|
|
1352
|
+
// A visitor's inferred T can be void. It still binds the
|
|
1353
|
+
// return convention of `(node) => T`; discarding it leaves
|
|
1354
|
+
// the callback's return type spuriously uninstantiated.
|
|
1355
|
+
if (mapped)
|
|
1259
1356
|
bindings.set(sym, mapped);
|
|
1260
1357
|
}
|
|
1261
1358
|
}
|
|
@@ -1270,10 +1367,20 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1270
1367
|
// unbound type parameter surfaces as a mapping diagnostic later).
|
|
1271
1368
|
if (declared.isUnionType()) {
|
|
1272
1369
|
const unitFlags = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
|
|
1273
|
-
const
|
|
1274
|
-
const
|
|
1370
|
+
const declaredParts = ts.constituentTypes(declared);
|
|
1371
|
+
const declaredUnits = declaredParts.reduce((flags, t) => flags | (t.flags & unitFlags), 0);
|
|
1372
|
+
const dParts = declaredParts.filter((t) => !(t.flags & unitFlags));
|
|
1373
|
+
const iParts = inst.isUnionType() ? ts.constituentTypes(inst).filter((t) => !(t.flags & declaredUnits)) : [inst];
|
|
1275
1374
|
if (dParts.length === 1 && iParts.length === 1)
|
|
1276
1375
|
unify(dParts[0], iParts[0], depth + 1);
|
|
1376
|
+
else if (dParts.length === 1 && iParts.length > 1 &&
|
|
1377
|
+
iParts.every((t) => (t.flags & unitFlags) === 0)) {
|
|
1378
|
+
// T | undefined can receive boolean | undefined: boolean itself
|
|
1379
|
+
// has two literal arms. There is still one declared data slot,
|
|
1380
|
+
// so match it against the whole remaining union. Removing null
|
|
1381
|
+
// too is safe only when no undeclared null arm remains.
|
|
1382
|
+
unify(dParts[0], lowerer.checker.getNonNullableType(inst), depth + 1);
|
|
1383
|
+
}
|
|
1277
1384
|
return;
|
|
1278
1385
|
}
|
|
1279
1386
|
// Instantiations of the SAME generic ALIAS (Partial<T> vs
|
|
@@ -1426,16 +1533,21 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1426
1533
|
fnCtx.generator = generatorMeta(lowerer, inst.returnType);
|
|
1427
1534
|
}
|
|
1428
1535
|
lowerer.fnStack.push(fnCtx);
|
|
1536
|
+
lowerer.localClassInstantiations.push({ owner: decl, name: inst.name });
|
|
1429
1537
|
try {
|
|
1430
|
-
//
|
|
1431
|
-
//
|
|
1432
|
-
//
|
|
1433
|
-
// are transparent (they inherit the method's `this`); this-binding
|
|
1434
|
-
// function forms are opaque.
|
|
1538
|
+
// Static specializations bind lexical this only when the caller
|
|
1539
|
+
// proved its exact receiver. Other instances retain the fence;
|
|
1540
|
+
// super remains unsupported. Arrows inherit the lexical receiver.
|
|
1435
1541
|
if (info.member?.kind === "static" && decl.body) {
|
|
1436
|
-
rejectStaticThis(lowerer, decl.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)
|
|
1542
|
+
rejectStaticThis(lowerer, decl.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)`, false, info.staticReceiver !== undefined);
|
|
1437
1543
|
}
|
|
1438
1544
|
const params = [];
|
|
1545
|
+
const receiverInit = [];
|
|
1546
|
+
if (info.staticReceiver) {
|
|
1547
|
+
const value = lowerer.classValueRef(info.staticReceiver, decl);
|
|
1548
|
+
const local = lowerer.declareThis(value.type);
|
|
1549
|
+
receiverInit.push({ kind: "varDecl", localId: local.id, init: value, loc: locOf(decl) });
|
|
1550
|
+
}
|
|
1439
1551
|
if (cls && info.member.kind === "method") {
|
|
1440
1552
|
// Instance methods take `this` as param 0, exactly like plain
|
|
1441
1553
|
// `%C.method` functions (lowerClassMethodMemberInner).
|
|
@@ -1447,7 +1559,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1447
1559
|
// threaded — a default mentioning T resolves like any body expression.
|
|
1448
1560
|
const declared = lowerer.declareParams(decl.parameters, inst.params);
|
|
1449
1561
|
params.push(...declared.params);
|
|
1450
|
-
const body = [...declared.prologue];
|
|
1562
|
+
const body = [...receiverInit, ...declared.prologue];
|
|
1451
1563
|
const bodyBlock = blockBodyOf(decl);
|
|
1452
1564
|
if (bodyBlock) {
|
|
1453
1565
|
body.push(...lowerer.lowerStmts(bodyBlock.statements));
|
|
@@ -1490,6 +1602,8 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1490
1602
|
}
|
|
1491
1603
|
const fn = {
|
|
1492
1604
|
name: inst.name,
|
|
1605
|
+
sourceName: info.baseName,
|
|
1606
|
+
...(!isAsync && !decl.asteriskToken && (ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ? { ownsPrototype: true } : {}),
|
|
1493
1607
|
params,
|
|
1494
1608
|
returnType: bodyReturn,
|
|
1495
1609
|
locals: lowerer.ctx.locals,
|
|
@@ -1509,6 +1623,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1509
1623
|
lowerer.typeParamTsBindings = prevTsBindings;
|
|
1510
1624
|
lowerer.implicitParamTypes = prevImplicit;
|
|
1511
1625
|
lowerer.instantiationContext = prevContext;
|
|
1626
|
+
lowerer.localClassInstantiations.pop();
|
|
1512
1627
|
lowerer.suppressStats = prevSuppress;
|
|
1513
1628
|
}
|
|
1514
1629
|
}
|
|
@@ -1531,7 +1646,6 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1531
1646
|
// returning — JS answers undefined.
|
|
1532
1647
|
const last = body[body.length - 1];
|
|
1533
1648
|
const mayFallThrough = !last || !(last.kind === "return" || last.kind === "throw" || last.kind === "rethrow" || last.kind === "runtimeFence");
|
|
1534
|
-
const valued = infer.entries.filter((e) => e.stmt.kind === "return" && e.stmt.value !== null && e.stmt.value !== undefined);
|
|
1535
1649
|
const sawBare = mayFallThrough || infer.entries.some((e) => e.stmt.kind === "return" && (e.stmt.value === null || e.stmt.value === undefined));
|
|
1536
1650
|
let final;
|
|
1537
1651
|
if (inst.returnPinned) {
|
|
@@ -1539,16 +1653,19 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1539
1653
|
}
|
|
1540
1654
|
else {
|
|
1541
1655
|
const distinct = [];
|
|
1542
|
-
for (const e of
|
|
1543
|
-
if (
|
|
1544
|
-
|
|
1656
|
+
for (const e of infer.entries) {
|
|
1657
|
+
if (e.stmt.kind !== "return" || e.stmt.value === null || e.stmt.value === undefined)
|
|
1658
|
+
continue;
|
|
1659
|
+
const type = e.stmt.value.type;
|
|
1660
|
+
if (!distinct.some((t) => typeEquals(t, type)))
|
|
1661
|
+
distinct.push(type);
|
|
1545
1662
|
}
|
|
1546
1663
|
if (distinct.length === 0) {
|
|
1547
1664
|
final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
|
|
1548
1665
|
}
|
|
1549
1666
|
else if (distinct.length === 1) {
|
|
1550
1667
|
const t = distinct[0];
|
|
1551
|
-
final = !sawBare ? t : t.kind === "dyn" ? DYN : (lowerer.withUndefinedArmOf(t) ?? DYN);
|
|
1668
|
+
final = isUnitType(t) ? DYN : !sawBare ? t : t.kind === "dyn" ? DYN : (lowerer.withUndefinedArmOf(t) ?? DYN);
|
|
1552
1669
|
}
|
|
1553
1670
|
else {
|
|
1554
1671
|
final = DYN; // disagreeing returns: the checked-dynamic join
|
|
@@ -1559,23 +1676,24 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1559
1676
|
for (const e of infer.entries) {
|
|
1560
1677
|
if (e.stmt.kind !== "return")
|
|
1561
1678
|
continue;
|
|
1562
|
-
|
|
1679
|
+
// Write through the recorded statement. A narrowed local can acquire a
|
|
1680
|
+
// different record layout and copy it in the native compiler.
|
|
1563
1681
|
const diagsBefore = lowerer.diags.length;
|
|
1564
1682
|
try {
|
|
1565
|
-
if (
|
|
1683
|
+
if (e.stmt.value === null || e.stmt.value === undefined) {
|
|
1566
1684
|
if (final.kind === "dyn")
|
|
1567
|
-
|
|
1685
|
+
e.stmt.value = dynUndefinedExpr(e.stmt.loc);
|
|
1568
1686
|
else if (final.kind === "union") {
|
|
1569
|
-
const wrapped = lowerer.wrappedUndefined(final,
|
|
1687
|
+
const wrapped = lowerer.wrappedUndefined(final, e.stmt.loc);
|
|
1570
1688
|
if (!wrapped) {
|
|
1571
1689
|
lowerer.unsupported("SC1090", e.node ?? decl, `bare 'return' in a function whose inferred return type is '${lowerer.fmt(final)}'`);
|
|
1572
1690
|
}
|
|
1573
|
-
|
|
1691
|
+
e.stmt.value = wrapped;
|
|
1574
1692
|
}
|
|
1575
1693
|
// void final: bare return stands as-is
|
|
1576
1694
|
}
|
|
1577
|
-
else if (!typeEquals(
|
|
1578
|
-
|
|
1695
|
+
else if (!typeEquals(e.stmt.value.type, final)) {
|
|
1696
|
+
e.stmt.value = lowerer.coerceInto(e.node ?? decl, e.stmt.value, final);
|
|
1579
1697
|
}
|
|
1580
1698
|
}
|
|
1581
1699
|
catch (err) {
|
|
@@ -1590,7 +1708,7 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1590
1708
|
lowerer.diags.push(...ice);
|
|
1591
1709
|
lowerer.runtimeFences.push(...captured.filter((d) => d.code !== "SC9001"));
|
|
1592
1710
|
const first = captured.find((d) => d.code !== "SC9001");
|
|
1593
|
-
const mutable =
|
|
1711
|
+
const mutable = e.stmt;
|
|
1594
1712
|
delete mutable["value"];
|
|
1595
1713
|
mutable["kind"] = "runtimeFence";
|
|
1596
1714
|
mutable["code"] = first?.code ?? "SC1090";
|
|
@@ -1848,10 +1966,12 @@ function broadPromiseParam(lowerer, type) {
|
|
|
1848
1966
|
}
|
|
1849
1967
|
/** The implicit-type-parameter slots of a JS function-like: parallel to
|
|
1850
1968
|
* decl.parameters, the param SYMBOL where the slot is a bindable
|
|
1851
|
-
* implicit
|
|
1852
|
-
* rest/optional/defaulted, never written), null elsewhere.
|
|
1853
|
-
*
|
|
1854
|
-
|
|
1969
|
+
* implicit param (identifier-named, broad inferred/JSDoc type, not
|
|
1970
|
+
* rest/optional/defaulted, never written), null elsewhere. Package JS
|
|
1971
|
+
* methods may also specialize class parameters: JSDoc names a nominal
|
|
1972
|
+
* class even when the body accepts other objects with the same members.
|
|
1973
|
+
* Null overall when nothing qualifies — the declaration keeps its ABI. */
|
|
1974
|
+
export function implicitAnyParamSymbolsOf(lowerer, decl, classParams = false) {
|
|
1855
1975
|
if (!decl.body)
|
|
1856
1976
|
return null;
|
|
1857
1977
|
if (decl.asteriskToken)
|
|
@@ -1877,7 +1997,9 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1877
1997
|
const broadFunction = lowerer.checker.typeToString(t) === "Function";
|
|
1878
1998
|
const broadArray = lowerer.checkerAnyArrayType(t);
|
|
1879
1999
|
const broadPromise = broadPromiseParam(lowerer, t);
|
|
1880
|
-
|
|
2000
|
+
const declaredKind = classParams ? lowerer.mapTypeOf(t)?.kind : undefined;
|
|
2001
|
+
const classParam = classParams && (declaredKind === "object" || declaredKind === "array");
|
|
2002
|
+
if ((t.flags & ts.TypeFlags.Any) === 0 && !broadFunction && !broadArray && !broadPromise && !classParam)
|
|
1881
2003
|
return null;
|
|
1882
2004
|
const sym = lowerer.checker.getSymbolAtLocation(param.name);
|
|
1883
2005
|
if (!sym)
|
|
@@ -1896,6 +2018,11 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1896
2018
|
* selects return INFERENCE with DYN as the recursion pin. */
|
|
1897
2019
|
function implicitDeclaredReturn(lowerer, info) {
|
|
1898
2020
|
try {
|
|
2021
|
+
// Static JS helpers can accept a structurally compatible class despite
|
|
2022
|
+
// narrower JSDoc (for example a Vector2 target documented as Vector3).
|
|
2023
|
+
// Infer their result from the specialized body as well.
|
|
2024
|
+
if (info.member?.kind === "static" && info.decl.parameters.some((param, index) => info.implicitParams?.[index] && lowerer.mapTypeOf(lowerer.typeOf(param.name))?.kind === "object"))
|
|
2025
|
+
return null;
|
|
1899
2026
|
const broadCallbackSymbols = new Set(info.decl.parameters.flatMap((param, index) => {
|
|
1900
2027
|
const symbol = info.implicitParams?.[index];
|
|
1901
2028
|
return symbol !== null && symbol !== undefined &&
|
|
@@ -1915,7 +2042,10 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1915
2042
|
expression = expression.expression;
|
|
1916
2043
|
if (ts.isCallExpression(expression) &&
|
|
1917
2044
|
ts.isIdentifier(expression.expression) &&
|
|
1918
|
-
|
|
2045
|
+
(() => {
|
|
2046
|
+
const symbol = lowerer.checker.getSymbolAtLocation(expression.expression);
|
|
2047
|
+
return symbol !== undefined && broadCallbackSymbols.has(symbol);
|
|
2048
|
+
})()) {
|
|
1919
2049
|
returnsBroadCallback = true;
|
|
1920
2050
|
return "stop";
|
|
1921
2051
|
}
|
|
@@ -1930,7 +2060,12 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1930
2060
|
const retTs = lowerer.checker.getReturnTypeOfSignature(declSig);
|
|
1931
2061
|
if (retTs.flags & ts.TypeFlags.Any)
|
|
1932
2062
|
return null;
|
|
2063
|
+
if (retTs.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
2064
|
+
return DYN;
|
|
1933
2065
|
if (lowerer.checker.isArrayType(retTs)) {
|
|
2066
|
+
if (info.decl.parameters.some((param, index) => info.implicitParams?.[index] &&
|
|
2067
|
+
lowerer.mapTypeOf(lowerer.typeOf(param.name))?.kind === "array"))
|
|
2068
|
+
return null;
|
|
1934
2069
|
const elem = lowerer.checker.getTypeArguments(retTs)[0];
|
|
1935
2070
|
// An implicit-any parameter poisons an inferred array result to
|
|
1936
2071
|
// any[] even when this instance's body produces one concrete
|
|
@@ -1941,6 +2076,11 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1941
2076
|
return null;
|
|
1942
2077
|
}
|
|
1943
2078
|
const mapped = lowerer.mapTypeOf(retTs);
|
|
2079
|
+
// Inferred variadic results carry runtime argument packs. Their
|
|
2080
|
+
// factory must retain the lowered callable rather than extracting a
|
|
2081
|
+
// fixed native signature from a checked value.
|
|
2082
|
+
if (mapped?.kind === "func" && mapped.rest === true && mapped.restAbi === undefined && !hasExplicitJsDocReturn(info.decl))
|
|
2083
|
+
return null;
|
|
1944
2084
|
if (mapped !== null && promiseCarriesDyn(lowerer, mapped) && !hasExplicitJsDocReturn(info.decl))
|
|
1945
2085
|
return null;
|
|
1946
2086
|
return mapped;
|
|
@@ -1972,6 +2112,30 @@ function bindableImplicitIr(t) {
|
|
|
1972
2112
|
t.kind !== "void" && t.kind !== "dyn" && t.kind !== "jsval" &&
|
|
1973
2113
|
t.kind !== "caught" && t.kind !== "undefinedT" && t.kind !== "nullT");
|
|
1974
2114
|
}
|
|
2115
|
+
/** A represented binding or direct callable result can be wider than the
|
|
2116
|
+
* checker's inferred shape. Preserve that boundary when specializing JS. */
|
|
2117
|
+
function storedImplicitArgumentType(lowerer, arg) {
|
|
2118
|
+
while (ts.isParenthesizedExpression(arg))
|
|
2119
|
+
arg = arg.expression;
|
|
2120
|
+
if (ts.isAwaitExpression(arg)) {
|
|
2121
|
+
const awaited = storedImplicitArgumentType(lowerer, arg.expression);
|
|
2122
|
+
return awaited?.kind === "promise" ? awaited.inner : awaited;
|
|
2123
|
+
}
|
|
2124
|
+
if (ts.isObjectLiteralExpression(arg) && isJsSourceFile(arg.getSourceFile()) && arg.properties.some((property) => !ts.isSpreadAssignment(property) && property.name !== undefined && ts.isComputedPropertyName(property.name) &&
|
|
2125
|
+
lowerer.foldedStringKeyOf(property.name.expression) === null))
|
|
2126
|
+
return DYN;
|
|
2127
|
+
if (ts.isIdentifier(arg))
|
|
2128
|
+
return lowerer.peekLocal(arg)?.type ?? lowerer.globalOf(arg)?.type ?? null;
|
|
2129
|
+
if (ts.isCallExpression(arg) && ts.isIdentifier(arg.expression)) {
|
|
2130
|
+
const callee = storedImplicitArgumentType(lowerer, arg.expression);
|
|
2131
|
+
if (callee?.kind === "dyn")
|
|
2132
|
+
return DYN;
|
|
2133
|
+
if (callee?.kind === "func")
|
|
2134
|
+
return callee.ret;
|
|
2135
|
+
return lowerer.fnSigOf(arg.expression)?.returnType ?? null;
|
|
2136
|
+
}
|
|
2137
|
+
return null;
|
|
2138
|
+
}
|
|
1975
2139
|
/** The instance a CALL of an implicit-any function-like names: each
|
|
1976
2140
|
* bindable implicit param takes the call's WIDENED argument checker type
|
|
1977
2141
|
* when it maps statically (DYN otherwise — today's slot), typed params
|
|
@@ -1994,19 +2158,52 @@ export function implicitCallInstance(lowerer, call, info) {
|
|
|
1994
2158
|
bound = declared.type;
|
|
1995
2159
|
const arg = call.arguments[i];
|
|
1996
2160
|
if (arg && !ts.isSpreadElement(arg)) {
|
|
1997
|
-
const
|
|
1998
|
-
if (
|
|
2161
|
+
const stored = storedImplicitArgumentType(lowerer, arg);
|
|
2162
|
+
if (stored?.kind === "dyn") {
|
|
1999
2163
|
bound = DYN;
|
|
2000
2164
|
argTypes.set(sym, lowerer.checker.getUnknownType());
|
|
2001
2165
|
shapes.push({ type: bound, mode: "required" });
|
|
2002
2166
|
return;
|
|
2003
2167
|
}
|
|
2168
|
+
// A represented native array must keep its storage when a direct
|
|
2169
|
+
// inferred helper receives it. Re-boxing a checker-any array would
|
|
2170
|
+
// copy it, losing writes (and attempting to read unfilled slots).
|
|
2171
|
+
if (stored?.kind === "array") {
|
|
2172
|
+
argTypes.set(sym, lowerer.typeOf(arg));
|
|
2173
|
+
shapes.push({ type: stored, mode: "required" });
|
|
2174
|
+
return;
|
|
2175
|
+
}
|
|
2004
2176
|
// The argument's own checker type, literal-widened ('add' binds
|
|
2005
2177
|
// string) — typeOf consults the ACTIVE instance's bindings, so a
|
|
2006
2178
|
// bound param forwarded into another implicit call transitively
|
|
2007
2179
|
// instantiates it (this._initCommandGroup(command)).
|
|
2008
2180
|
const t = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(arg));
|
|
2009
2181
|
const mapped = lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, arg, t);
|
|
2182
|
+
// JavaScript arguments-based callables travel as checked functions.
|
|
2183
|
+
// Specializing a parameter to the inferred rest signature would
|
|
2184
|
+
// require extracting a native variadic ABI that the value does not
|
|
2185
|
+
// expose. Its checked invocation preserves the complete argument pack.
|
|
2186
|
+
if (mapped?.kind === "func" && mapped.rest === true && mapped.restAbi === undefined) {
|
|
2187
|
+
argTypes.set(sym, lowerer.checker.getUnknownType());
|
|
2188
|
+
shapes.push({ type: DYN, mode: "required" });
|
|
2189
|
+
return;
|
|
2190
|
+
}
|
|
2191
|
+
// JS inference can absorb heterogeneous loop values into `{}`.
|
|
2192
|
+
// That checker supertype is not an empty-record runtime layout:
|
|
2193
|
+
// preserve represented arms through the checked boundary instead
|
|
2194
|
+
// of specializing a call to a union that would discard them.
|
|
2195
|
+
const mappedArms = mapped?.kind === "union" ? lowerer.unions.get(mapped.unionId)?.arms ?? [] : mapped ? [mapped] : [];
|
|
2196
|
+
const hasTopObject = mappedArms.some((arm) => {
|
|
2197
|
+
const shape = arm.kind === "record" ? lowerer.shapes.get(arm.shapeId) : undefined;
|
|
2198
|
+
return shape && !shape.tuple && !shape.indexValue && shape.fields.length === 0;
|
|
2199
|
+
});
|
|
2200
|
+
if (stored?.kind === "union" && hasTopObject && lowerer.dynConvertible(stored) &&
|
|
2201
|
+
lowerer.unions.get(stored.unionId)?.arms.some((arm) => !isUnitType(arm) &&
|
|
2202
|
+
!mappedArms.some((target) => lowerer.widthLiftPlan(arm, target) !== null))) {
|
|
2203
|
+
argTypes.set(sym, lowerer.checker.getUnknownType());
|
|
2204
|
+
shapes.push({ type: DYN, mode: "required" });
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2010
2207
|
if (ts.isArrowFunction(arg) &&
|
|
2011
2208
|
arg.type === undefined &&
|
|
2012
2209
|
mapped?.kind === "func" &&
|
|
@@ -2031,15 +2228,32 @@ export function implicitCallInstance(lowerer, call, info) {
|
|
|
2031
2228
|
/** The all-dyn DEFAULT instance — today's compiled body exactly: what a
|
|
2032
2229
|
* VALUE reference of an implicit-any function names (indirect calls
|
|
2033
2230
|
* carry no per-site types to bind). */
|
|
2034
|
-
function implicitDefaultInstance(lowerer, blame, info) {
|
|
2231
|
+
export function implicitDefaultInstance(lowerer, blame, info) {
|
|
2035
2232
|
const shapes = info.decl.parameters.map((param, i) => info.implicitParams[i] ? { type: DYN, mode: "required" } : lowerer.paramShape(param));
|
|
2036
|
-
|
|
2233
|
+
const argTypes = new Map();
|
|
2234
|
+
// Newly bindable nominal class parameters must not retain their JSDoc
|
|
2235
|
+
// receiver type in the checked fallback. Keep existing broad JS inference.
|
|
2236
|
+
for (let i = 0; i < info.decl.parameters.length; i++) {
|
|
2237
|
+
const symbol = info.implicitParams?.[i];
|
|
2238
|
+
const kind = lowerer.mapTypeOf(lowerer.typeOf(info.decl.parameters[i].name))?.kind;
|
|
2239
|
+
if (symbol && (kind === "object" || kind === "array")) {
|
|
2240
|
+
argTypes.set(symbol, lowerer.checker.getUnknownType());
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
return internImplicitInstance(lowerer, blame, info, shapes, argTypes);
|
|
2037
2244
|
}
|
|
2038
2245
|
function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
2039
2246
|
const key = shapes.map((s) => typeKey(s.type)).join(",");
|
|
2040
2247
|
let inst = info.instances.get(key);
|
|
2041
|
-
if (inst)
|
|
2248
|
+
if (inst?.implicitState === "failed")
|
|
2249
|
+
lowerer.unsupported("SC1090", blame, `the failed specialization of '${info.baseName}'`);
|
|
2250
|
+
if (inst) {
|
|
2251
|
+
// A recursive caller has observed this ABI before inference settles.
|
|
2252
|
+
// Keep the promised return slot and coerce the completed body's returns.
|
|
2253
|
+
if (inst.implicitState === "lowering")
|
|
2254
|
+
inst.returnPinned = true;
|
|
2042
2255
|
return inst;
|
|
2256
|
+
}
|
|
2043
2257
|
if (info.instances.size >= MAX_GENERIC_INSTANCES) {
|
|
2044
2258
|
lowerer.unsupported("SC1090", blame, `unbounded implicit-any instantiation ('${info.baseName}' exceeded ` +
|
|
2045
2259
|
`${MAX_GENERIC_INSTANCES} instances — polymorphic recursion?)`);
|
|
@@ -2065,11 +2279,15 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
|
2065
2279
|
...(declared === null ? { implicitInferReturn: true } : {}),
|
|
2066
2280
|
};
|
|
2067
2281
|
info.instances.set(key, inst);
|
|
2068
|
-
//
|
|
2069
|
-
//
|
|
2070
|
-
//
|
|
2071
|
-
|
|
2072
|
-
//
|
|
2282
|
+
// Eager lowering settles the return ABI before callers use it. A failed
|
|
2283
|
+
// JS body must still have a throwing implementation: later references
|
|
2284
|
+
// (including recursive ones) can already hold its cached signature.
|
|
2285
|
+
const diagsBefore = lowerer.diags.length;
|
|
2286
|
+
// The instance is cached even when a receiver probe requested it.
|
|
2287
|
+
// Its body must retain statement fences instead of dropping failures
|
|
2288
|
+
// into that probe's temporary diagnostic sink and caching empty code.
|
|
2289
|
+
const previousSink = lowerer.diagSink;
|
|
2290
|
+
lowerer.diagSink = null;
|
|
2073
2291
|
try {
|
|
2074
2292
|
// Implicit-any instances lower EAGERLY at the call site so their
|
|
2075
2293
|
// inferred return type is available immediately. They therefore do
|
|
@@ -2087,8 +2305,20 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
|
2087
2305
|
catch (e) {
|
|
2088
2306
|
if (!(e instanceof PoisonError))
|
|
2089
2307
|
throw e;
|
|
2090
|
-
inst.implicitState = "
|
|
2091
|
-
|
|
2308
|
+
inst.implicitState = "failed";
|
|
2309
|
+
const types = shapes.map((shape) => shape.type);
|
|
2310
|
+
if (info.member?.kind === "method")
|
|
2311
|
+
types.unshift({ kind: "object", className: info.member.cls.def.name });
|
|
2312
|
+
const fn = lowerer.deferToRuntimeFence(diagsBefore, info.decl, {
|
|
2313
|
+
kind: "function", name: inst.name, returnType: inst.returnType,
|
|
2314
|
+
params: types.map((type, index) => ({ localId: `p.${index}`, name: `p${index}`, type })),
|
|
2315
|
+
});
|
|
2316
|
+
if (!fn)
|
|
2317
|
+
throw e;
|
|
2318
|
+
lowerer.implicitFns.push(fn);
|
|
2319
|
+
}
|
|
2320
|
+
finally {
|
|
2321
|
+
lowerer.diagSink = previousSink;
|
|
2092
2322
|
}
|
|
2093
2323
|
inst.implicitState = "done";
|
|
2094
2324
|
return inst;
|
|
@@ -2194,11 +2424,11 @@ export function implicitLocalFnInfoOf(lowerer, decl, fnNode) {
|
|
|
2194
2424
|
const implicit = implicitAnyParamSymbolsOf(lowerer, fnNode);
|
|
2195
2425
|
if (!implicit)
|
|
2196
2426
|
lowerer.unsupported("SC1090", fnNode, "this function form"); // defensive: the probe proved it
|
|
2197
|
-
const stmt = decl.parent
|
|
2427
|
+
const stmt = decl.parent?.parent;
|
|
2198
2428
|
const info = {
|
|
2199
2429
|
decl: fnNode,
|
|
2200
2430
|
baseName: name,
|
|
2201
|
-
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + `${name}%l${decl.getStart()}`),
|
|
2431
|
+
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + `${name}%l${decl.getStart()}`),
|
|
2202
2432
|
typeParams: [],
|
|
2203
2433
|
instances: new Map(),
|
|
2204
2434
|
implicitParams: implicit,
|
|
@@ -2409,6 +2639,7 @@ function makeTimerArgsThunk(lowerer, cbNode, argNodes, what, loc) {
|
|
|
2409
2639
|
kind: "dynCall",
|
|
2410
2640
|
callee: { kind: "varRef", localId: "f.0", type: DYN, loc },
|
|
2411
2641
|
calleeName: "callback",
|
|
2642
|
+
receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
|
|
2412
2643
|
args: args.map((_, i) => ({ kind: "varRef", localId: `a${i}.0`, type: DYN, loc })),
|
|
2413
2644
|
type: DYN,
|
|
2414
2645
|
loc,
|
|
@@ -2573,7 +2804,12 @@ export function lowerTimersMemberCall(lowerer, expr, member, loc) {
|
|
|
2573
2804
|
return null;
|
|
2574
2805
|
}
|
|
2575
2806
|
function ffiSourceParams(binding) {
|
|
2576
|
-
|
|
2807
|
+
const params = [];
|
|
2808
|
+
for (const param of binding.params) {
|
|
2809
|
+
if (!isFfiContextParam(param))
|
|
2810
|
+
params.push(param);
|
|
2811
|
+
}
|
|
2812
|
+
return params;
|
|
2577
2813
|
}
|
|
2578
2814
|
function ffiParamDisplay(param) {
|
|
2579
2815
|
return isFfiCallbackParam(param)
|
|
@@ -2590,7 +2826,11 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2590
2826
|
const signatures = lowerer.checker.getCallSignatures(callbackType);
|
|
2591
2827
|
if (signatures.length !== 1)
|
|
2592
2828
|
return null;
|
|
2593
|
-
const nativeParams =
|
|
2829
|
+
const nativeParams = [];
|
|
2830
|
+
for (const param of descriptor.callback.params) {
|
|
2831
|
+
if (!isFfiContextParam(param))
|
|
2832
|
+
nativeParams.push(param);
|
|
2833
|
+
}
|
|
2594
2834
|
let nativeIndex = 0;
|
|
2595
2835
|
const params = signatures[0].getParameters();
|
|
2596
2836
|
for (let i = 0; i < params.length; i++) {
|
|
@@ -2608,12 +2848,13 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2608
2848
|
}
|
|
2609
2849
|
if (nativeClass === "bytes")
|
|
2610
2850
|
continue;
|
|
2611
|
-
const
|
|
2851
|
+
const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
|
|
2852
|
+
const domain = wide ? "bigint" : nativeClass === "bool"
|
|
2612
2853
|
? "boolean"
|
|
2613
2854
|
: nativeClass === "cstring" || nativeClass === "string"
|
|
2614
2855
|
? "string"
|
|
2615
2856
|
: "number";
|
|
2616
|
-
const coversDomain = nativeClass === "bool"
|
|
2857
|
+
const coversDomain = wide ? (paramType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
|
|
2617
2858
|
? (paramType.flags & ts.TypeFlags.Boolean) !== 0
|
|
2618
2859
|
: nativeClass === "cstring" || nativeClass === "string"
|
|
2619
2860
|
? (paramType.flags & ts.TypeFlags.String) !== 0
|
|
@@ -2636,8 +2877,9 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2636
2877
|
function ffiReturnDomainDiagnostic(lowerer, nativeClass, returnType) {
|
|
2637
2878
|
if (nativeClass === "void")
|
|
2638
2879
|
return null;
|
|
2639
|
-
const
|
|
2640
|
-
const
|
|
2880
|
+
const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
|
|
2881
|
+
const domain = wide ? "bigint" : nativeClass === "bool" ? "boolean" : "number";
|
|
2882
|
+
const coversDomain = wide ? (returnType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
|
|
2641
2883
|
? (returnType.flags & ts.TypeFlags.Boolean) !== 0
|
|
2642
2884
|
: (returnType.flags & ts.TypeFlags.Number) !== 0;
|
|
2643
2885
|
return coversDomain
|
|
@@ -2745,7 +2987,7 @@ function libraryCallbackOwnsFile(lowerer, file) {
|
|
|
2745
2987
|
export function validateFfiImports(lowerer) {
|
|
2746
2988
|
const diagnostics = [];
|
|
2747
2989
|
const symbolsByName = new Map();
|
|
2748
|
-
const configuredNames = new Set(lowerer.ffiImports.map((binding) => binding.name));
|
|
2990
|
+
const configuredNames = new Set(lowerer.ffiImports.filter(binding => binding.library === undefined).map((binding) => binding.name));
|
|
2749
2991
|
const candidates = new Map();
|
|
2750
2992
|
if (configuredNames.size === 0)
|
|
2751
2993
|
return { diagnostics, symbolsByName };
|
|
@@ -2775,6 +3017,8 @@ export function validateFfiImports(lowerer) {
|
|
|
2775
3017
|
});
|
|
2776
3018
|
}
|
|
2777
3019
|
for (const binding of lowerer.ffiImports) {
|
|
3020
|
+
if (binding.library !== undefined)
|
|
3021
|
+
continue;
|
|
2778
3022
|
const bySymbol = candidates.get(binding.name);
|
|
2779
3023
|
if (bySymbol === undefined || bySymbol.size === 0) {
|
|
2780
3024
|
// A native-manifest binding with no declaration is a broken build
|
|
@@ -2822,6 +3066,8 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2822
3066
|
if (!ts.isIdentifier(expr.expression))
|
|
2823
3067
|
return null;
|
|
2824
3068
|
const binding = lowerer.ffiImportsByName.get(expr.expression.text);
|
|
3069
|
+
if (binding?.library !== undefined)
|
|
3070
|
+
return null;
|
|
2825
3071
|
if (binding === undefined) {
|
|
2826
3072
|
// LIBRARY mode with a declared callback surface: a CALL of a
|
|
2827
3073
|
// program-authored signature-only ambient function that names no
|
|
@@ -2855,7 +3101,8 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2855
3101
|
lowerer.pushDiag(signatureFlavor(binding.name, detail, loc));
|
|
2856
3102
|
throw new PoisonError();
|
|
2857
3103
|
};
|
|
2858
|
-
const symbol = lowerer.resolveValueSymbol(expr.expression)
|
|
3104
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
3105
|
+
if (!symbol)
|
|
2859
3106
|
bindingError("the call has no resolved TypeScript symbol");
|
|
2860
3107
|
if (lowerer.ffiBindingSymbols !== null) {
|
|
2861
3108
|
const validSymbols = lowerer.ffiBindingSymbols.get(binding.name);
|
|
@@ -2938,7 +3185,7 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2938
3185
|
}
|
|
2939
3186
|
// An inline function value at a RELEASE site can never match:
|
|
2940
3187
|
// lifted lambdas always carry a captures list (even an empty one),
|
|
2941
|
-
// so
|
|
3188
|
+
// so the backend creates a fresh closure per evaluation of the
|
|
2942
3189
|
// expression — the release argument is a pointer no registration
|
|
2943
3190
|
// holds, a guaranteed runtime trap. Declared functions stay valid
|
|
2944
3191
|
// here — their value is the interned immortal closure (captures
|
|
@@ -3145,6 +3392,18 @@ export function lowerCall(lowerer, expr) {
|
|
|
3145
3392
|
}
|
|
3146
3393
|
const consoleMember = lowerer.consoleCallMember(expr);
|
|
3147
3394
|
if (consoleMember !== null) {
|
|
3395
|
+
// A namespace returned by user code must evaluate before the log
|
|
3396
|
+
// arguments. Only the global and literal builtin require plumbing
|
|
3397
|
+
// have no receiver evaluation to preserve.
|
|
3398
|
+
const access = ts.isPropertyAccessExpression(expr.expression) ? expr.expression : null;
|
|
3399
|
+
const created = access && ts.isCallExpression(access.expression) ? createRequireSpecOf(lowerer, access.expression) : null;
|
|
3400
|
+
const receiver = access && !lowerer.isStdlibGlobal(access.expression, "console") &&
|
|
3401
|
+
requireSpecOf(access.expression) === null &&
|
|
3402
|
+
created?.spec !== "node:console" && created?.spec !== "console"
|
|
3403
|
+
? lowerer.lowerExpr(access.expression) : null;
|
|
3404
|
+
const withReceiver = (result) => receiver === null ? result : {
|
|
3405
|
+
kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc }], result, type: result.type, loc,
|
|
3406
|
+
};
|
|
3148
3407
|
// console.log/info/debug write stdout; console.error and console.warn
|
|
3149
3408
|
// are one stream in Node (warn IS error, info and debug ARE log) and
|
|
3150
3409
|
// write stderr with the exact same formatting. Node's formatter is
|
|
@@ -3166,13 +3425,13 @@ export function lowerCall(lowerer, expr) {
|
|
|
3166
3425
|
(ts.isStringLiteral(expr.arguments[0]) || ts.isNoSubstitutionTemplateLiteral(expr.arguments[0])) &&
|
|
3167
3426
|
/%[sdifjoOc%]/.test(expr.arguments[0].text)) {
|
|
3168
3427
|
const formatted = lowerFormatCall(lowerer, expr, loc, false);
|
|
3169
|
-
return {
|
|
3428
|
+
return withReceiver({
|
|
3170
3429
|
kind: "intrinsic",
|
|
3171
3430
|
name: stdoutMember ? "console.log" : "console.error",
|
|
3172
3431
|
args: [formatted],
|
|
3173
3432
|
type: VOID,
|
|
3174
3433
|
loc,
|
|
3175
|
-
};
|
|
3434
|
+
});
|
|
3176
3435
|
}
|
|
3177
3436
|
const args = expr.arguments.map((a) => {
|
|
3178
3437
|
const lowered = lowerer.lowerExpr(a);
|
|
@@ -3233,13 +3492,13 @@ export function lowerCall(lowerer, expr) {
|
|
|
3233
3492
|
// render fence honestly with the reason.
|
|
3234
3493
|
return lowerConsoleInspectArg(lowerer, a, lowered, surface, loc);
|
|
3235
3494
|
});
|
|
3236
|
-
return {
|
|
3495
|
+
return withReceiver({
|
|
3237
3496
|
kind: "intrinsic",
|
|
3238
3497
|
name: stdoutMember ? "console.log" : "console.error",
|
|
3239
3498
|
args,
|
|
3240
3499
|
type: VOID,
|
|
3241
3500
|
loc,
|
|
3242
|
-
};
|
|
3501
|
+
});
|
|
3243
3502
|
}
|
|
3244
3503
|
// The timer globals — setTimeout/clearTimeout, setInterval/
|
|
3245
3504
|
// clearInterval, setImmediate/clearImmediate. Provenance-checked (a
|
|
@@ -3390,25 +3649,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3390
3649
|
lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
|
|
3391
3650
|
}
|
|
3392
3651
|
const argNode = expr.arguments[0];
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
if (arg.type.kind === "f64") {
|
|
3400
|
-
return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
|
|
3401
|
-
}
|
|
3402
|
-
if (arg.type.kind === "bool") {
|
|
3403
|
-
return {
|
|
3404
|
-
kind: "ternary",
|
|
3405
|
-
cond: arg,
|
|
3406
|
-
then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3407
|
-
else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3408
|
-
type: BIGINT_T,
|
|
3409
|
-
loc,
|
|
3410
|
-
};
|
|
3411
|
-
}
|
|
3652
|
+
// Captured optional storage can change after TypeScript's guard.
|
|
3653
|
+
// BigInt consumes the stored value, including its nullish tag.
|
|
3654
|
+
const arg = optionalCallValue(lowerer, argNode) ?? lowerer.lowerExpr(argNode);
|
|
3655
|
+
const converted = lowerBigIntConstructorValue(lowerer, arg, loc);
|
|
3656
|
+
if (converted)
|
|
3657
|
+
return converted;
|
|
3412
3658
|
lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
|
|
3413
3659
|
}
|
|
3414
3660
|
if (ts.isIdentifier(expr.expression) &&
|
|
@@ -3446,6 +3692,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3446
3692
|
if (name === "Number")
|
|
3447
3693
|
return lowerNumberConstructorValue(lowerer, argNode, loc);
|
|
3448
3694
|
const arg = lowerer.lowerExpr(argNode);
|
|
3695
|
+
if (name === "String" && arg.type.kind === "dyn") {
|
|
3696
|
+
return { kind: "libCall", fn: "dyn.stringConstructor", args: [arg], type: STRING, loc };
|
|
3697
|
+
}
|
|
3449
3698
|
if (name === "String")
|
|
3450
3699
|
return lowerer.ensureString(arg, argNode);
|
|
3451
3700
|
}
|
|
@@ -3463,6 +3712,29 @@ export function lowerCall(lowerer, expr) {
|
|
|
3463
3712
|
const code = lowerer.lowerExprExpecting(expr.arguments[0], STRING);
|
|
3464
3713
|
return { kind: "libCall", fn: "island.eval", args: [code], type: STRING, loc };
|
|
3465
3714
|
}
|
|
3715
|
+
// Computed calls preserve their evaluated receiver just like dotted
|
|
3716
|
+
// calls, including when the property is keyed by a native symbol.
|
|
3717
|
+
if (ts.isElementAccessExpression(expr.expression) && !lowerer.chainBlocked(expr, expr.expression)) {
|
|
3718
|
+
const access = expr.expression;
|
|
3719
|
+
lowerer.fenceStaticResponseMember(access, "call");
|
|
3720
|
+
lowerer.fenceStaticHeadersMember(access, "call");
|
|
3721
|
+
lowerer.fenceStaticReadableStreamMember(access, "call");
|
|
3722
|
+
const source = tryLowerExpression(lowerer, access.expression);
|
|
3723
|
+
if (source && (source.type.kind === "dyn" || isDynTypedRefType(source.type) &&
|
|
3724
|
+
lowerer.foldedStringKeyOf(access.argumentExpression) === null &&
|
|
3725
|
+
lowerer.mapTypeOf(lowerer.typeOf(access.argumentExpression))?.kind !== "symbol")) {
|
|
3726
|
+
const local = lowerer.declareHiddenLocal("%computedReceiver", DYN);
|
|
3727
|
+
const receiver = varRef(local.id, DYN, loc);
|
|
3728
|
+
const key = lowerer.lowerExprExpecting(access.argumentExpression, DYN);
|
|
3729
|
+
const callee = { kind: "dynKeyGet", value: receiver, key, type: DYN, loc };
|
|
3730
|
+
const args = expr.arguments.map((arg) => lowerer.lowerExprExpecting(ts.isSpreadElement(arg) ? arg.expression : arg, DYN));
|
|
3731
|
+
const spreads = expr.arguments.flatMap((arg, index) => ts.isSpreadElement(arg) ? [{ arg: index, what: arg.expression.getText() }] : []);
|
|
3732
|
+
return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: lowerer.coerceToExpected(source, DYN), loc }], result: {
|
|
3733
|
+
kind: "dynCall", callee, receiver, calleeName: access.getText(), args,
|
|
3734
|
+
...(spreads.length > 0 ? { spreads } : {}), type: DYN, loc,
|
|
3735
|
+
}, type: DYN, loc };
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3466
3738
|
// Island calls. A property-access callee whose receiver is an 'any'
|
|
3467
3739
|
// value is an engine method call (this = receiver, JS-exact); any other
|
|
3468
3740
|
// 'any'-typed callee is an engine function call. Arguments marshal in;
|
|
@@ -4061,6 +4333,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4061
4333
|
let callee = lowerer.lowerExpr(nsMember);
|
|
4062
4334
|
if (callee.type.kind === "record")
|
|
4063
4335
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
4336
|
+
const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
|
|
4337
|
+
if (checked)
|
|
4338
|
+
return checked;
|
|
4064
4339
|
if (callee.type.kind !== "func")
|
|
4065
4340
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
4066
4341
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
@@ -4114,6 +4389,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4114
4389
|
let callee = lowerer.lowerExpr(nameId);
|
|
4115
4390
|
if (callee.type.kind === "record")
|
|
4116
4391
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
4392
|
+
const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
|
|
4393
|
+
if (checked)
|
|
4394
|
+
return checked;
|
|
4117
4395
|
if (callee.type.kind !== "func")
|
|
4118
4396
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
4119
4397
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
@@ -4193,6 +4471,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4193
4471
|
// TestContext surface (t.test/t.skip/t.diagnostic), t.assert.*.
|
|
4194
4472
|
lowerer.lowerTestMethodCall(expr, expr.expression) ??
|
|
4195
4473
|
lowerer.lowerTimeoutMethodCall(expr, expr.expression) ??
|
|
4474
|
+
lowerArrayPrototypeBorrowCall(lowerer, expr, expr.expression) ??
|
|
4196
4475
|
lowerObjectOwnPrototypeCall(lowerer, expr, expr.expression) ??
|
|
4197
4476
|
lowerObjectPrototypeCall(lowerer, expr, expr.expression) ??
|
|
4198
4477
|
lowerStringPrototypeCall(lowerer, expr, expr.expression) ??
|
|
@@ -4200,6 +4479,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4200
4479
|
// Typed-array/Buffer receivers and the Buffer statics — before the
|
|
4201
4480
|
// island path (bytes never cross the boundary).
|
|
4202
4481
|
lowerer.lowerBytesMethodCall(expr, expr.expression) ??
|
|
4482
|
+
lowerBytesStaticCall(lowerer, expr, expr.expression) ??
|
|
4203
4483
|
lowerBufferStaticCallWithNarrowedArg(lowerer, expr, expr.expression) ??
|
|
4204
4484
|
// URL.revokeObjectURL's zero-argument contract (the one-argument
|
|
4205
4485
|
// form keeps the fence — createObjectURL does too).
|
|
@@ -4267,8 +4547,8 @@ export function lowerCall(lowerer, expr) {
|
|
|
4267
4547
|
lowerArrayFromCall(lowerer, expr, expr.expression) ??
|
|
4268
4548
|
lowerArrayOfCall(lowerer, expr, expr.expression) ??
|
|
4269
4549
|
lowerer.lowerArrayMethodCall(expr, expr.expression) ??
|
|
4270
|
-
//
|
|
4271
|
-
//
|
|
4550
|
+
// Tuple reads preserve the receiver through argument evaluation;
|
|
4551
|
+
// callbacks read each position when visited.
|
|
4272
4552
|
lowerTupleReadMethodCall(lowerer, expr, expr.expression) ??
|
|
4273
4553
|
lowerGenMethodCall(lowerer, expr, expr.expression) ??
|
|
4274
4554
|
lowerer.lowerMapMethodCall(expr, expr.expression) ??
|
|
@@ -4283,6 +4563,18 @@ export function lowerCall(lowerer, expr) {
|
|
|
4283
4563
|
lowerObjLitGenericMethodCall(lowerer, expr, expr.expression);
|
|
4284
4564
|
if (intrinsic)
|
|
4285
4565
|
return intrinsic;
|
|
4566
|
+
const accessorTarget = lowerer.fieldTarget(expr.expression);
|
|
4567
|
+
if (accessorTarget?.container === "accessor") {
|
|
4568
|
+
const callee = lowerer.fieldGetExpr(accessorTarget, locOf(expr.expression), expr.expression);
|
|
4569
|
+
if (callee.type.kind === "func") {
|
|
4570
|
+
const args = completeFuncValueArgs(lowerer, expr, callee.type, locOf(expr));
|
|
4571
|
+
return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(expr) };
|
|
4572
|
+
}
|
|
4573
|
+
if (callee.type.kind === "dyn" && !expr.arguments.some((arg) => ts.isSpreadElement(arg))) {
|
|
4574
|
+
const args = expr.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
4575
|
+
return { kind: "dynCall", callee, calleeName: expr.expression.getText(), args, type: DYN, loc: locOf(expr) };
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4286
4578
|
// A method call rooted at an initializer-less ambient `declare
|
|
4287
4579
|
// const/var` whose declared type has no mapping: Node throws the
|
|
4288
4580
|
// catchable ReferenceError at the ROOT read before the member, the
|
|
@@ -4332,6 +4624,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4332
4624
|
// The element spelling of an unsupported native Web method must fence
|
|
4333
4625
|
// before lowering the callee into a checked-dynamic keyed read.
|
|
4334
4626
|
if (ts.isElementAccessExpression(expr.expression)) {
|
|
4627
|
+
const symbolMethod = lowerClassSymbolMethodCall(lowerer, expr);
|
|
4628
|
+
if (symbolMethod)
|
|
4629
|
+
return symbolMethod;
|
|
4335
4630
|
const headersIterator = lowerer.lowerDynamicHeadersIteratorCall(expr, expr.expression);
|
|
4336
4631
|
if (headersIterator)
|
|
4337
4632
|
return headersIterator;
|
|
@@ -4347,8 +4642,41 @@ export function lowerCall(lowerer, expr) {
|
|
|
4347
4642
|
if (ts.isElementAccessExpression(expr.expression) &&
|
|
4348
4643
|
!expr.expression.questionDotToken &&
|
|
4349
4644
|
!expr.questionDotToken &&
|
|
4350
|
-
ts.isStringLiteralLike(expr.expression.argumentExpression)) {
|
|
4351
|
-
const memberName = expr.expression.argumentExpression
|
|
4645
|
+
(ts.isStringLiteralLike(expr.expression.argumentExpression) || ts.isNumericLiteral(expr.expression.argumentExpression))) {
|
|
4646
|
+
const memberName = ts.isNumericLiteral(expr.expression.argumentExpression)
|
|
4647
|
+
? String(Number(expr.expression.argumentExpression.text))
|
|
4648
|
+
: expr.expression.argumentExpression.text;
|
|
4649
|
+
const receiverType = lowerer.mapTypeOf(lowerer.typeOf(expr.expression.expression));
|
|
4650
|
+
if (receiverType?.kind === "object") {
|
|
4651
|
+
const info = lowerer.classes.get(receiverType.className);
|
|
4652
|
+
const found = info ? lowerer.findMethodOn(info, memberName) : null;
|
|
4653
|
+
if (info && found) {
|
|
4654
|
+
if (found.declarer.builtinError)
|
|
4655
|
+
return errorToStringCall(lowerer, lowerer.lowerExpr(expr.expression.expression));
|
|
4656
|
+
const virtual = lowerer.overrideBelow(info, memberName);
|
|
4657
|
+
if (found.sig.abstract === true && !virtual) {
|
|
4658
|
+
lowerer.unsupported("SC1090", expr, `calls of the abstract method '${memberName}' with no concrete implementation below the receiver's static class`);
|
|
4659
|
+
}
|
|
4660
|
+
if (virtual)
|
|
4661
|
+
lowerer.noteVirtualEdge(info, memberName);
|
|
4662
|
+
else
|
|
4663
|
+
lowerer.noteEdge(`%${found.declarer.def.name}.${memberName}`);
|
|
4664
|
+
const receiver = lowerer.lowerExpr(expr.expression.expression);
|
|
4665
|
+
const args = lowerer.completeArgs(expr.arguments, found.sig.params, locOf(expr), expr);
|
|
4666
|
+
const callArgs = [lowerer.upcastTo(receiver, virtual ? info.def.name : found.declarer.def.name), ...args];
|
|
4667
|
+
const loc = locOf(expr);
|
|
4668
|
+
if (virtual) {
|
|
4669
|
+
return reconcileOverloadReturn(lowerer, expr, {
|
|
4670
|
+
kind: "virtualCall", className: info.def.name, method: memberName,
|
|
4671
|
+
args: callArgs, type: found.sig.ret, loc,
|
|
4672
|
+
});
|
|
4673
|
+
}
|
|
4674
|
+
return reconcileOverloadReturn(lowerer, expr, {
|
|
4675
|
+
kind: "call", callee: `%${found.declarer.def.name}.${memberName}`,
|
|
4676
|
+
args: callArgs, type: found.sig.ret, loc,
|
|
4677
|
+
});
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4352
4680
|
// ts7's getSymbolAtLocation does not resolve element accesses; the
|
|
4353
4681
|
// member symbol comes from the receiver's (apparent) type instead —
|
|
4354
4682
|
// same provenance answer as the dot spelling's name symbol.
|
|
@@ -4446,7 +4774,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4446
4774
|
// JS arity exactly (the thunk ignores extras). Result dyn, checked
|
|
4447
4775
|
// per use like every any-origin value.
|
|
4448
4776
|
if ((expr.arguments.length > callee.type.params.length || callee.type.rest === true) &&
|
|
4449
|
-
isJsSourceFile(expr.getSourceFile()) &&
|
|
4777
|
+
(isJsSourceFile(expr.getSourceFile()) || callee.type.rest === true && callee.type.restAbi === undefined) &&
|
|
4450
4778
|
!expr.arguments.some((a) => ts.isSpreadElement(a)) &&
|
|
4451
4779
|
canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
4452
4780
|
const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
@@ -4457,6 +4785,29 @@ export function lowerCall(lowerer, expr) {
|
|
|
4457
4785
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
4458
4786
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
4459
4787
|
}
|
|
4788
|
+
/** Exported checked and variadic callables use the same runtime-arity ABI
|
|
4789
|
+
* whether the caller spells a bare import or a namespace member. */
|
|
4790
|
+
function lowerCheckedCallableValue(lowerer, call, value, loc) {
|
|
4791
|
+
let callee = value;
|
|
4792
|
+
if (callee.type.kind !== "dyn") {
|
|
4793
|
+
if (callee.type.kind !== "func" ||
|
|
4794
|
+
!(callee.type.rest === true && callee.type.restAbi === undefined ||
|
|
4795
|
+
isJsSourceFile(call.getSourceFile()) && call.arguments.length > callee.type.params.length) ||
|
|
4796
|
+
!lowerer.dynConvertible(callee.type))
|
|
4797
|
+
return null;
|
|
4798
|
+
callee = { kind: "dynFrom", value: callee, type: DYN, loc };
|
|
4799
|
+
}
|
|
4800
|
+
if (call.arguments.some(ts.isSpreadElement)) {
|
|
4801
|
+
const spread = lowerSpreadArgsCall(lowerer, call, callee, loc);
|
|
4802
|
+
if (spread)
|
|
4803
|
+
return spread;
|
|
4804
|
+
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
4805
|
+
}
|
|
4806
|
+
return {
|
|
4807
|
+
kind: "dynCall", callee, calleeName: call.expression.getText(),
|
|
4808
|
+
args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc,
|
|
4809
|
+
};
|
|
4810
|
+
}
|
|
4460
4811
|
function lowerRegexMethodCallWithOptionalArg(lowerer, call, access) {
|
|
4461
4812
|
const lowered = lowerer.lowerRegexMethodCall(call, access);
|
|
4462
4813
|
if (lowered?.kind !== "regexIntrinsic" || lowered.method !== "test" || call.arguments.length !== 1)
|
|
@@ -4478,9 +4829,13 @@ function optionalCallValue(lowerer, node) {
|
|
|
4478
4829
|
return lowerer.runtimeOptionalIdentifierValue(node)?.value ?? lowerAbsenceProbe(lowerer, node);
|
|
4479
4830
|
}
|
|
4480
4831
|
function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
|
|
4481
|
-
const
|
|
4832
|
+
const result = lowerer.lowerBufferStaticCall(call, access);
|
|
4833
|
+
// The Buffer brand wraps the constructor result. Normalize its source
|
|
4834
|
+
// before restoring that wrapper so narrowed unions never reach bytesNew.
|
|
4835
|
+
const branded = result?.kind === "libCall" && result.fn === "buffer.brand" ? result : null;
|
|
4836
|
+
const lowered = branded ? branded.args[0] : result;
|
|
4482
4837
|
if (lowered?.kind !== "bytesNew" || !lowered.source || lowered.source.type.kind !== "union")
|
|
4483
|
-
return
|
|
4838
|
+
return result;
|
|
4484
4839
|
// A callback can store a wider union than the checker sees at this use
|
|
4485
4840
|
// (including an added undefined arm). Extract the exact arm proven by
|
|
4486
4841
|
// control-flow narrowing, not merely the union with undefined removed.
|
|
@@ -4496,10 +4851,11 @@ function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
|
|
|
4496
4851
|
if (!helper) {
|
|
4497
4852
|
lowerer.unsupported("SC1090", call.arguments[0], "a Buffer constructor argument whose narrowed type is not a stored source arm");
|
|
4498
4853
|
}
|
|
4499
|
-
|
|
4854
|
+
const narrowedValue = {
|
|
4500
4855
|
...lowered,
|
|
4501
4856
|
source: { kind: "call", callee: helper, args: [lowered.source], type: narrowed, loc: lowered.source.loc },
|
|
4502
4857
|
};
|
|
4858
|
+
return branded ? { ...branded, args: [narrowedValue] } : narrowedValue;
|
|
4503
4859
|
}
|
|
4504
4860
|
function lowerOptionalNumberDefault(lowerer, value, dflt, loc) {
|
|
4505
4861
|
const widened = lowerer.runtimeOptionalWidening(value.type, F64);
|
|
@@ -4554,6 +4910,8 @@ function lowerStringMethodCallWithOptionalArgs(lowerer, call, access, receiver,
|
|
|
4554
4910
|
? [1]
|
|
4555
4911
|
: [];
|
|
4556
4912
|
for (const index of zeroDefaultArgs) {
|
|
4913
|
+
if (index === undefined)
|
|
4914
|
+
continue;
|
|
4557
4915
|
const value = args[index];
|
|
4558
4916
|
if (!value)
|
|
4559
4917
|
continue;
|
|
@@ -4599,6 +4957,8 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
|
|
|
4599
4957
|
}
|
|
4600
4958
|
if (arg.type.kind === "string")
|
|
4601
4959
|
return { kind: "libCall", fn: "num.fromString", args: [arg], type: F64, loc };
|
|
4960
|
+
if (arg.type.kind === "dyn")
|
|
4961
|
+
return { kind: "libCall", fn: "dyn.numberConstructor", args: [arg], type: F64, loc };
|
|
4602
4962
|
const optionalNumber = lowerOptionalStringNumber(lowerer, arg, loc);
|
|
4603
4963
|
if (optionalNumber)
|
|
4604
4964
|
return optionalNumber;
|
|
@@ -4609,6 +4969,61 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
|
|
|
4609
4969
|
? "unions of numbers, booleans, strings, null, and undefined lower — narrow other arms first"
|
|
4610
4970
|
: undefined);
|
|
4611
4971
|
}
|
|
4972
|
+
/** A runtime-optional local retains its full tagged storage even after a
|
|
4973
|
+
* checker guard. Dispatch BigInt by the actual value, including nullish
|
|
4974
|
+
* TypeErrors, rather than interpreting that storage as the narrowed arm. */
|
|
4975
|
+
function lowerBigIntConstructorValue(lowerer, arg, loc) {
|
|
4976
|
+
if (arg.type.kind === "bigint")
|
|
4977
|
+
return arg;
|
|
4978
|
+
if (arg.type.kind === "string")
|
|
4979
|
+
return { kind: "libCall", fn: "bigint.parse", args: [arg], type: BIGINT_T, loc };
|
|
4980
|
+
if (arg.type.kind === "f64")
|
|
4981
|
+
return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
|
|
4982
|
+
if (arg.type.kind === "bool") {
|
|
4983
|
+
return {
|
|
4984
|
+
kind: "ternary", cond: arg,
|
|
4985
|
+
then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
|
|
4986
|
+
else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
|
|
4987
|
+
type: BIGINT_T, loc,
|
|
4988
|
+
};
|
|
4989
|
+
}
|
|
4990
|
+
if (isUnitType(arg.type)) {
|
|
4991
|
+
const name = arg.type.kind === "nullT" ? "null" : "undefined";
|
|
4992
|
+
return defaultAfterUndefined(arg, nodeThrowExpr(1, "", `Cannot convert ${name} to a BigInt`, BIGINT_T, loc));
|
|
4993
|
+
}
|
|
4994
|
+
if (arg.type.kind !== "union")
|
|
4995
|
+
return null;
|
|
4996
|
+
const unionId = arg.type.unionId;
|
|
4997
|
+
const arms = lowerer.unions.get(unionId)?.arms;
|
|
4998
|
+
if (!arms || !arms.every((arm) => arm.kind === "bigint" || arm.kind === "string" || arm.kind === "f64" || arm.kind === "bool" || isUnitType(arm)))
|
|
4999
|
+
return null;
|
|
5000
|
+
const key = `bigint.scalar:${unionId}`;
|
|
5001
|
+
let helper = lowerer.widthHelpers.get(key);
|
|
5002
|
+
if (!helper) {
|
|
5003
|
+
helper = `%bigint.scalar.${lowerer.widthHelpers.size}`;
|
|
5004
|
+
lowerer.widthHelpers.set(key, helper);
|
|
5005
|
+
const value = varRef("value.0", arg.type, loc);
|
|
5006
|
+
const body = [];
|
|
5007
|
+
arms.forEach((arm, tag) => {
|
|
5008
|
+
const narrowed = isUnitType(arm)
|
|
5009
|
+
? { kind: "unitLit", unit: arm.kind === "nullT" ? "null" : "undefined", type: arm, loc }
|
|
5010
|
+
: { kind: "unionNarrow", unionId, tag, value, type: arm, loc };
|
|
5011
|
+
const converted = lowerBigIntConstructorValue(lowerer, narrowed, loc);
|
|
5012
|
+
if (!converted)
|
|
5013
|
+
throw new InternalCompilerError("BigInt scalar union has an unsupported arm");
|
|
5014
|
+
const ret = { kind: "return", value: converted, loc };
|
|
5015
|
+
body.push(tag === arms.length - 1 ? ret : {
|
|
5016
|
+
kind: "if", cond: { kind: "unionIsTag", unionId, tag, negated: false, value, type: BOOL, loc },
|
|
5017
|
+
then: [ret], else_: null, loc,
|
|
5018
|
+
});
|
|
5019
|
+
});
|
|
5020
|
+
lowerer.liftedFns.push({
|
|
5021
|
+
name: helper, params: [{ localId: "value.0", name: "value", type: arg.type }],
|
|
5022
|
+
returnType: BIGINT_T, locals: [{ id: "value.0", name: "value", type: arg.type, mutable: false }], body, loc,
|
|
5023
|
+
});
|
|
5024
|
+
}
|
|
5025
|
+
return { kind: "call", callee: helper, args: [arg], type: BIGINT_T, loc };
|
|
5026
|
+
}
|
|
4612
5027
|
function immediatePrimitiveWrapperToString(lowerer, node) {
|
|
4613
5028
|
const stringValue = stringWrapperToString(lowerer, node);
|
|
4614
5029
|
if (stringValue)
|
|
@@ -4631,24 +5046,6 @@ function immediatePrimitiveWrapperToString(lowerer, node) {
|
|
|
4631
5046
|
: args.length ? lowerNumberConstructorValue(lowerer, args[0], loc) : { kind: "numLit", value: 0, type: F64, loc };
|
|
4632
5047
|
return lowerer.ensureString(primitive, wrapped);
|
|
4633
5048
|
}
|
|
4634
|
-
function plainObjectCoercionReceiver(lowerer, node) {
|
|
4635
|
-
const plainLiteral = (literal) => literal.properties.every((prop) => ts.isPropertyAssignment(prop) &&
|
|
4636
|
-
(ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) || ts.isNumericLiteral(prop.name)) &&
|
|
4637
|
-
prop.name.text !== "__proto__");
|
|
4638
|
-
let value = node;
|
|
4639
|
-
while (ts.isParenthesizedExpression(value))
|
|
4640
|
-
value = value.expression;
|
|
4641
|
-
if (ts.isObjectLiteralExpression(value))
|
|
4642
|
-
return plainLiteral(value);
|
|
4643
|
-
if (!ts.isIdentifier(value))
|
|
4644
|
-
return false;
|
|
4645
|
-
const symbol = lowerer.resolveValueSymbol(value);
|
|
4646
|
-
const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
|
|
4647
|
-
if (!symbol || !decl || !ts.isVariableDeclaration(decl) || !decl.initializer ||
|
|
4648
|
-
!ts.isObjectLiteralExpression(decl.initializer) || !plainLiteral(decl.initializer))
|
|
4649
|
-
return false;
|
|
4650
|
-
return bindingNeverReassigned(lowerer, symbol, decl);
|
|
4651
|
-
}
|
|
4652
5049
|
function objectToStringTag(lowerer, type) {
|
|
4653
5050
|
switch (type.kind) {
|
|
4654
5051
|
case "undefinedT":
|
|
@@ -4669,7 +5066,7 @@ function objectToStringTag(lowerer, type) {
|
|
|
4669
5066
|
case "set": return "Set";
|
|
4670
5067
|
case "promise": return "Promise";
|
|
4671
5068
|
case "bytes":
|
|
4672
|
-
return
|
|
5069
|
+
return BYTES_ELEMENT_NAME[type.elem];
|
|
4673
5070
|
case "object":
|
|
4674
5071
|
return type.className === "%Error" || lowerer.isSubclassOf(type.className, "%Error") ? "Error" : null;
|
|
4675
5072
|
default: return null;
|
|
@@ -4691,6 +5088,10 @@ function immediateObjectTagReceiver(lowerer, node) {
|
|
|
4691
5088
|
lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(value.expression) ?? undefined)) {
|
|
4692
5089
|
const name = value.expression.text;
|
|
4693
5090
|
const args = value.arguments ?? [];
|
|
5091
|
+
// JavaScript dates use checked native handles, so their IR type alone
|
|
5092
|
+
// cannot recover the tag through an immediate Object(...) wrapper.
|
|
5093
|
+
if (name === "Date")
|
|
5094
|
+
return { tag: "Date", effect: lowerer.lowerExpr(value) };
|
|
4694
5095
|
if (args.length <= 1 && !args.some(ts.isSpreadElement)) {
|
|
4695
5096
|
if (name === "String") {
|
|
4696
5097
|
const effect = stringWrapperToString(lowerer, value);
|
|
@@ -4738,6 +5139,36 @@ function immediateObjectTagReceiver(lowerer, node) {
|
|
|
4738
5139
|
}
|
|
4739
5140
|
return null;
|
|
4740
5141
|
}
|
|
5142
|
+
const ARRAY_BORROW_METHODS = new Set([
|
|
5143
|
+
"at", "every", "filter", "find", "findIndex", "findLast", "findLastIndex", "forEach", "includes",
|
|
5144
|
+
"indexOf", "lastIndexOf", "map", "reduce", "reduceRight", "slice", "some",
|
|
5145
|
+
]);
|
|
5146
|
+
function lowerArrayPrototypeBorrowCall(lowerer, call, access) {
|
|
5147
|
+
if (lowerer.dynamic || !isJsSourceFile(call.getSourceFile()) || call.questionDotToken ||
|
|
5148
|
+
access.questionDotToken || access.name.text !== "call" ||
|
|
5149
|
+
!ts.isPropertyAccessExpression(access.expression) ||
|
|
5150
|
+
call.arguments.some(ts.isSpreadElement))
|
|
5151
|
+
return null;
|
|
5152
|
+
const method = access.expression;
|
|
5153
|
+
if (method.questionDotToken || !ARRAY_BORROW_METHODS.has(method.name.text) ||
|
|
5154
|
+
!ts.isPropertyAccessExpression(method.expression) ||
|
|
5155
|
+
method.expression.questionDotToken || method.expression.name.text !== "prototype" ||
|
|
5156
|
+
!lowerer.isStdlibGlobal(method.expression.expression, "Array") ||
|
|
5157
|
+
!lowerer.isStdlibMember(method))
|
|
5158
|
+
return null;
|
|
5159
|
+
const loc = locOf(call);
|
|
5160
|
+
const receiver = call.arguments[0]
|
|
5161
|
+
? lowerer.lowerExprExpecting(call.arguments[0], DYN)
|
|
5162
|
+
: { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
|
|
5163
|
+
const args = call.arguments.slice(1).map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
5164
|
+
return {
|
|
5165
|
+
kind: "libCall", fn: "dyn.arrayProtoCall", args: [
|
|
5166
|
+
receiver,
|
|
5167
|
+
{ kind: "strLit", value: method.name.text, type: STRING, loc },
|
|
5168
|
+
{ kind: "dynArrLit", elems: args, type: DYN, loc },
|
|
5169
|
+
], type: DYN, loc,
|
|
5170
|
+
};
|
|
5171
|
+
}
|
|
4741
5172
|
function lowerObjectOwnPrototypeCall(lowerer, call, access) {
|
|
4742
5173
|
if (lowerer.dynamic || access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
|
|
4743
5174
|
return null;
|
|
@@ -4756,10 +5187,31 @@ function lowerObjectOwnMethodCall(lowerer, call, access) {
|
|
|
4756
5187
|
const method = access.name.text;
|
|
4757
5188
|
if (lowerer.dynamic || call.questionDotToken || access.questionDotToken ||
|
|
4758
5189
|
(method !== "hasOwnProperty" && method !== "propertyIsEnumerable") ||
|
|
4759
|
-
|
|
5190
|
+
call.arguments.some(ts.isSpreadElement))
|
|
4760
5191
|
return null;
|
|
5192
|
+
if (!lowerer.isStdlibMember(access)) {
|
|
5193
|
+
const receiver = tryLowerExpression(lowerer, access.expression);
|
|
5194
|
+
if (receiver?.type.kind !== "dyn")
|
|
5195
|
+
return null;
|
|
5196
|
+
}
|
|
4761
5197
|
return lowerObjectOwnCall(lowerer, call, access.expression, call.arguments[0], call.arguments.slice(1), method);
|
|
4762
5198
|
}
|
|
5199
|
+
/** ToPropertyKey for the scalar keys represented by native own-key
|
|
5200
|
+
* probes. A lowered array-loop key may carry an undefined arm even when
|
|
5201
|
+
* its checker type is string; that arm spells "undefined" at runtime. */
|
|
5202
|
+
function ownPropertyKey(lowerer, key) {
|
|
5203
|
+
if (key.type.kind === "string")
|
|
5204
|
+
return key;
|
|
5205
|
+
if (key.type.kind === "bigint") {
|
|
5206
|
+
return { kind: "libCall", fn: "bigint.toString", args: [key, numLit(10, key.loc)], type: STRING, loc: key.loc };
|
|
5207
|
+
}
|
|
5208
|
+
const scalar = (type) => type.kind === "string" || type.kind === "f64" || type.kind === "bool" || isUnitType(type);
|
|
5209
|
+
if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn" ||
|
|
5210
|
+
(key.type.kind === "union" && lowerer.unions.get(key.type.unionId)?.arms.every(scalar))) {
|
|
5211
|
+
return { kind: "toString", operand: key, type: STRING, loc: key.loc };
|
|
5212
|
+
}
|
|
5213
|
+
return null;
|
|
5214
|
+
}
|
|
4763
5215
|
function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, method) {
|
|
4764
5216
|
const enumerable = method === "propertyIsEnumerable";
|
|
4765
5217
|
const loc = locOf(call);
|
|
@@ -4792,14 +5244,18 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
|
|
|
4792
5244
|
stmts.push({ kind: "exprStmt", expr: effect, loc: locOf(extra) });
|
|
4793
5245
|
}
|
|
4794
5246
|
let key = keyRef;
|
|
5247
|
+
if (receiverRef.type.kind === "dyn" && keyRef && (keyRef.type.kind === "symbol" || keyRef.type.kind === "dyn")) {
|
|
5248
|
+
const result = { kind: "libCall", fn: enumerable ? "dyn.propertyIsEnumerableComputed" : "dyn.hasOwnComputed", args: [receiverRef, lowerer.coerceToExpected(keyRef, DYN)], type: BOOL, loc };
|
|
5249
|
+
return { kind: "seqExpr", stmts, result, type: BOOL, loc };
|
|
5250
|
+
}
|
|
4795
5251
|
if (!keyNode || rawKey?.type.kind === "undefinedT" || rawKey?.type.kind === "void") {
|
|
4796
5252
|
key = { kind: "strLit", value: "undefined", type: STRING, loc };
|
|
4797
5253
|
}
|
|
4798
5254
|
else if (rawKey?.type.kind === "nullT") {
|
|
4799
5255
|
key = { kind: "strLit", value: "null", type: STRING, loc };
|
|
4800
5256
|
}
|
|
4801
|
-
else if (key
|
|
4802
|
-
key =
|
|
5257
|
+
else if (key) {
|
|
5258
|
+
key = ownPropertyKey(lowerer, key);
|
|
4803
5259
|
}
|
|
4804
5260
|
if (!key || key.type.kind !== "string") {
|
|
4805
5261
|
lowerer.noLowering("Object.prototype." + method + " with this property key", keyNode ?? call);
|
|
@@ -4811,13 +5267,13 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
|
|
|
4811
5267
|
}
|
|
4812
5268
|
else if (type.kind === "record") {
|
|
4813
5269
|
const shape = lowerer.shapes.get(type.shapeId);
|
|
4814
|
-
if (!shape || shape.tuple ||
|
|
5270
|
+
if (!shape || shape.tuple || shapeHasAccessorSlots(shape)) {
|
|
4815
5271
|
lowerer.noLowering("Object.prototype." + method + " over this record shape", receiverNode ?? call);
|
|
4816
5272
|
}
|
|
4817
5273
|
result = { kind: "call", callee: recordHasOwnHelper(lowerer, type.shapeId, loc), args: [receiverRef, key], type: BOOL, loc };
|
|
4818
5274
|
}
|
|
4819
|
-
else if (type.kind === "dyn"
|
|
4820
|
-
result = { kind: "libCall", fn: "dyn.hasOwn", args: [receiverRef, key], type: BOOL, loc };
|
|
5275
|
+
else if (type.kind === "dyn") {
|
|
5276
|
+
result = { kind: "libCall", fn: enumerable ? "dyn.propertyIsEnumerable" : "dyn.hasOwn", args: [receiverRef, key], type: BOOL, loc };
|
|
4821
5277
|
}
|
|
4822
5278
|
else if (type.kind === "string" || type.kind === "array") {
|
|
4823
5279
|
const needleLocal = lowerer.declareHiddenLocal("%ownIndex", F64);
|
|
@@ -4886,6 +5342,52 @@ function lowerObjectPrototypeCall(lowerer, call, access) {
|
|
|
4886
5342
|
: { kind: "strLit", value: "[object " + tag + "]", type: STRING, loc };
|
|
4887
5343
|
return { kind: "seqExpr", stmts, result, type: STRING, loc };
|
|
4888
5344
|
}
|
|
5345
|
+
/** Function.call evaluates all arguments before RequireObjectCoercible and
|
|
5346
|
+
* ToString. Stabilize them before reusing the ordinary string method lowering,
|
|
5347
|
+
* so a boxed nullish receiver or a coercion hook cannot reorder effects. */
|
|
5348
|
+
function lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiver, method) {
|
|
5349
|
+
const loc = locOf(call);
|
|
5350
|
+
const receiverLocal = lowerer.declareHiddenLocal("%stringCallReceiver", receiver.type);
|
|
5351
|
+
const stmts = [{ kind: "varDecl", localId: receiverLocal.id, init: receiver, loc }];
|
|
5352
|
+
const receiverRef = varRef(receiverLocal.id, receiver.type, loc);
|
|
5353
|
+
const converted = {
|
|
5354
|
+
kind: "ternary",
|
|
5355
|
+
cond: { kind: "dynTest", test: "nullish", value: receiverRef, type: BOOL, loc },
|
|
5356
|
+
then: nodeThrowExpr(1, "", `String.prototype.${method} called on null or undefined`, STRING, loc),
|
|
5357
|
+
else_: { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverRef], type: STRING, loc },
|
|
5358
|
+
type: STRING, loc,
|
|
5359
|
+
};
|
|
5360
|
+
const overrides = [];
|
|
5361
|
+
try {
|
|
5362
|
+
for (const node of call.arguments.slice(1)) {
|
|
5363
|
+
const undefinedValue = lowerStaticallyUndefinedArgument(lowerer, node);
|
|
5364
|
+
const value = undefinedValue ?? lowerer.lowerExpr(node);
|
|
5365
|
+
let ref;
|
|
5366
|
+
if (undefinedValue || isUnitType(value.type) || value.type.kind === "void") {
|
|
5367
|
+
stmts.push({ kind: "exprStmt", expr: value, loc: value.loc });
|
|
5368
|
+
const nullUnit = !undefinedValue && value.type.kind === "nullT";
|
|
5369
|
+
ref = { kind: "unitLit", unit: nullUnit ? "null" : "undefined", type: nullUnit ? value.type : UNDEFINED_T, loc: value.loc };
|
|
5370
|
+
}
|
|
5371
|
+
else {
|
|
5372
|
+
const local = lowerer.declareHiddenLocal("%stringCallArg", value.type);
|
|
5373
|
+
stmts.push({ kind: "varDecl", localId: local.id, init: value, loc: value.loc });
|
|
5374
|
+
ref = varRef(local.id, value.type, value.loc);
|
|
5375
|
+
}
|
|
5376
|
+
overrides.push({ node, previous: lowerer.chainRecvByNode.get(node) });
|
|
5377
|
+
lowerer.chainRecvByNode.set(node, ref);
|
|
5378
|
+
}
|
|
5379
|
+
const result = lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => converted, call.arguments.slice(1));
|
|
5380
|
+
return result ? { kind: "seqExpr", stmts, result, type: result.type, loc } : null;
|
|
5381
|
+
}
|
|
5382
|
+
finally {
|
|
5383
|
+
for (const override of overrides) {
|
|
5384
|
+
if (override.previous)
|
|
5385
|
+
lowerer.chainRecvByNode.set(override.node, override.previous);
|
|
5386
|
+
else
|
|
5387
|
+
lowerer.chainRecvByNode.delete(override.node);
|
|
5388
|
+
}
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
4889
5391
|
function lowerStringPrototypeCall(lowerer, call, access) {
|
|
4890
5392
|
if (access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
|
|
4891
5393
|
return null;
|
|
@@ -4928,6 +5430,9 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4928
5430
|
loc,
|
|
4929
5431
|
};
|
|
4930
5432
|
}
|
|
5433
|
+
if (receiverType.kind === "dyn") {
|
|
5434
|
+
return lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiverValue, method);
|
|
5435
|
+
}
|
|
4931
5436
|
const padding = entry?.method === "padStart" || entry?.method === "padEnd";
|
|
4932
5437
|
const scalar = receiverType.kind === "string" || receiverType.kind === "f64" ||
|
|
4933
5438
|
receiverType.kind === "bool" || receiverType.kind === "bigint" ||
|
|
@@ -4936,10 +5441,8 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4936
5441
|
// padding uses a helper that delays conversion until every argument is ready.
|
|
4937
5442
|
const objectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
|
|
4938
5443
|
(receiverType.kind === "record" || receiverType.kind === "array" || receiverType.kind === "object");
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
if (!scalar && !objectWithoutMethodArgs && !dynObjectWithoutMethodArgs && !(padding && receiverType.kind === "dyn")) {
|
|
4942
|
-
return lowerer.noLowering(`String.prototype.${methodAccess.name.text}.call with ${lowerer.fmt(receiverType)} receivers`, call);
|
|
5444
|
+
if (!scalar && !objectWithoutMethodArgs) {
|
|
5445
|
+
lowerer.noLowering(`String.prototype.${methodAccess.name.text}.call with ${lowerer.fmt(receiverType)} receivers`, call);
|
|
4943
5446
|
}
|
|
4944
5447
|
if (indexMethod)
|
|
4945
5448
|
return lowerStringIndexCall(lowerer, call, indexMethod, receiverValue, receiverNode, call.arguments.slice(1));
|
|
@@ -4951,9 +5454,7 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4951
5454
|
if (entry.method === "split") {
|
|
4952
5455
|
return lowerStringSplitCall(lowerer, call, receiverValue, receiverNode, call.arguments.slice(1));
|
|
4953
5456
|
}
|
|
4954
|
-
const receiver =
|
|
4955
|
-
? { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverValue], type: STRING, loc }
|
|
4956
|
-
: lowerer.ensureString(receiverValue, receiverNode);
|
|
5457
|
+
const receiver = lowerer.ensureString(receiverValue, receiverNode);
|
|
4957
5458
|
return lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => receiver, call.arguments.slice(1));
|
|
4958
5459
|
}
|
|
4959
5460
|
function lowerScalarUnionNumber(lowerer, arg, node, loc) {
|
|
@@ -5127,13 +5628,18 @@ function spreadNeedsRuntimeArity(lowerer, shapes, argNodes) {
|
|
|
5127
5628
|
position += tuple.fields.length;
|
|
5128
5629
|
continue;
|
|
5129
5630
|
}
|
|
5130
|
-
if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest")
|
|
5131
|
-
return
|
|
5631
|
+
if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest") {
|
|
5632
|
+
return !canCompleteRuntimeSpread(lowerer, shapes);
|
|
5633
|
+
}
|
|
5132
5634
|
}
|
|
5133
5635
|
position++;
|
|
5134
5636
|
}
|
|
5135
5637
|
return false;
|
|
5136
5638
|
}
|
|
5639
|
+
function canCompleteRuntimeSpread(lowerer, shapes) {
|
|
5640
|
+
return shapes.length > 0 && shapes.every((shape) => shape.mode !== "islandRest" && shape.callDefault === undefined &&
|
|
5641
|
+
canDynCheckTo(shape.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)));
|
|
5642
|
+
}
|
|
5137
5643
|
/** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
|
|
5138
5644
|
* `ws.packages.filter(...)` — JSON.parse-derived values): validate the
|
|
5139
5645
|
* receiver's dyn kind, extract, and ride the STATIC method machinery — the
|
|
@@ -5171,6 +5677,27 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5171
5677
|
// tsc types the return by the evolved shape, the binding lowered
|
|
5172
5678
|
// dyn): probe the lowering and claim exactly the dyn results.
|
|
5173
5679
|
const probed = tryLowerExpression(lowerer, access.expression);
|
|
5680
|
+
if (isJsSourceFile(call.getSourceFile()) && probed?.type.kind === "func" &&
|
|
5681
|
+
!["call", "apply", "bind", "toString", "valueOf", "constructor"].includes(access.name.text) &&
|
|
5682
|
+
canBoxFuncIntoDyn(probed.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
5683
|
+
const loc = locOf(call);
|
|
5684
|
+
const fnName = jsFuncNameOf(access.expression);
|
|
5685
|
+
const boxed = { kind: "dynFrom", value: probed, type: DYN, loc, ...(fnName !== null ? { fnName } : {}) };
|
|
5686
|
+
const local = lowerer.declareHiddenLocal("%callableReceiver", DYN);
|
|
5687
|
+
const receiver = { kind: "varRef", localId: local.id, type: DYN, loc };
|
|
5688
|
+
const member = {
|
|
5689
|
+
kind: "dynKeyGet", value: receiver,
|
|
5690
|
+
key: { kind: "strLit", value: access.name.text, type: STRING, loc }, type: DYN, loc,
|
|
5691
|
+
};
|
|
5692
|
+
if (call.arguments.some(ts.isSpreadElement)) {
|
|
5693
|
+
lowerer.unsupported("SC1090", call, "spread arguments in callable property calls");
|
|
5694
|
+
}
|
|
5695
|
+
return {
|
|
5696
|
+
kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: boxed, loc }],
|
|
5697
|
+
result: { kind: "dynCall", callee: member, receiver, calleeName: access.getText(),
|
|
5698
|
+
args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc }, type: DYN, loc,
|
|
5699
|
+
};
|
|
5700
|
+
}
|
|
5174
5701
|
if (probed?.type.kind !== "dyn")
|
|
5175
5702
|
return null;
|
|
5176
5703
|
recv = probed;
|
|
@@ -5178,11 +5705,30 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5178
5705
|
// A checker-`any` receiver that already lowered to a real STRING (the
|
|
5179
5706
|
// chained form — `cfg.host.trim().toLowerCase()`, where the first step
|
|
5180
5707
|
// extracted): no validation needed, ride the string tables directly.
|
|
5708
|
+
if (recv.type.kind === "union" && lowerer.stripUndefinedArm(recv.type).kind === "string") {
|
|
5709
|
+
const present = lowerer.runtimeOptionalPropertyReceiver(access.expression, recv, STRING, access.name.text);
|
|
5710
|
+
if (present)
|
|
5711
|
+
recv = present;
|
|
5712
|
+
}
|
|
5181
5713
|
if (recv.type.kind === "string") {
|
|
5182
5714
|
return lowerRegexMethodCall(lowerer, call, access, () => recv) ?? lowerStringMethodCall(lowerer, call, access, () => recv);
|
|
5183
5715
|
}
|
|
5184
5716
|
if (recv.type.kind !== "dyn")
|
|
5185
5717
|
return null;
|
|
5718
|
+
if (lowerer.mapTypeOf(recvTs)?.kind === "classval") {
|
|
5719
|
+
return lowerStaticMethodCall(lowerer, call, access);
|
|
5720
|
+
}
|
|
5721
|
+
const ownCallable = !checkerUntyped && (() => {
|
|
5722
|
+
const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
|
|
5723
|
+
if (prop === undefined)
|
|
5724
|
+
return false;
|
|
5725
|
+
// getPropertyOfType includes inherited Object.prototype members.
|
|
5726
|
+
// Those are not stored members of a checked-dynamic object, so
|
|
5727
|
+
// dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
|
|
5728
|
+
// an authored declaration can justify the own-member path.
|
|
5729
|
+
const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
|
|
5730
|
+
return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
|
|
5731
|
+
})();
|
|
5186
5732
|
// Typed-destination filter first (validated extraction into a real
|
|
5187
5733
|
// T[]); an untyped destination falls through to the runtime dispatch
|
|
5188
5734
|
// below (the survivors stay dyn values).
|
|
@@ -5198,34 +5744,21 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5198
5744
|
// these, "the receiver is a string, or the call throws V8's TypeError"
|
|
5199
5745
|
// IS Node's semantics for every possible dyn value. Shared names would
|
|
5200
5746
|
// need a receiver-kind dispatch — they keep the fence.
|
|
5201
|
-
if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
|
|
5747
|
+
if (DYN_STRING_ONLY_METHODS.has(access.name.text) && !ownCallable) {
|
|
5202
5748
|
const checked = () => dynStringReceiver(lowerer, recv, access);
|
|
5203
5749
|
return lowerRegexMethodCall(lowerer, call, access, checked) ?? lowerStringMethodCall(lowerer, call, access, checked);
|
|
5204
5750
|
}
|
|
5205
|
-
//
|
|
5206
|
-
//
|
|
5207
|
-
// decode per the encoding — a stream chunk's common consumption —
|
|
5208
|
-
// and strings/numbers/booleans/arrays/objects answer JS-exactly).
|
|
5209
|
-
// The optional argument is a literal encoding (meaningful for bytes;
|
|
5210
|
-
// JS ignores extra toString arguments on the other kinds, and so
|
|
5211
|
-
// does the runtime dispatch).
|
|
5751
|
+
// The argument is a radix for bigint and an encoding for Buffer.
|
|
5752
|
+
// Preserve its runtime value so receiver dispatch can choose correctly.
|
|
5212
5753
|
if (access.name.text === "toString" && call.arguments.length <= 1) {
|
|
5213
|
-
const
|
|
5214
|
-
? bufEncoding(lowerer, "toString", call.arguments[0])
|
|
5215
|
-
: "utf8";
|
|
5216
|
-
// The source spelling rides along for the ONE receiver whose
|
|
5217
|
-
// prototype lacks toString: a null-prototype dictionary throws
|
|
5218
|
-
// Node's "<spelling> is not a function" at runtime.
|
|
5754
|
+
const argument = call.arguments[0];
|
|
5219
5755
|
return {
|
|
5220
|
-
kind: "libCall",
|
|
5221
|
-
fn: "dyn.toString",
|
|
5222
|
-
args: [
|
|
5756
|
+
kind: "libCall", fn: "dyn.toString", args: [
|
|
5223
5757
|
recv,
|
|
5224
|
-
|
|
5758
|
+
argument ? lowerer.lowerExprExpecting(argument, DYN)
|
|
5759
|
+
: dynUndefinedExpr(locOf(call)),
|
|
5225
5760
|
{ kind: "strLit", value: access.getText(), type: STRING, loc: locOf(call) },
|
|
5226
|
-
],
|
|
5227
|
-
type: STRING,
|
|
5228
|
-
loc: locOf(call),
|
|
5761
|
+
], type: STRING, loc: locOf(call),
|
|
5229
5762
|
};
|
|
5230
5763
|
}
|
|
5231
5764
|
// SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
|
|
@@ -5256,17 +5789,6 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5256
5789
|
// its name overlaps a primitive prototype (`colors.bold(...)`): the
|
|
5257
5790
|
// source value was compiled from that object shape, while genuinely
|
|
5258
5791
|
// untyped/any receivers retain the runtime-kind ambiguity and fence.
|
|
5259
|
-
const ownCallable = !checkerUntyped && (() => {
|
|
5260
|
-
const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
|
|
5261
|
-
if (prop === undefined)
|
|
5262
|
-
return false;
|
|
5263
|
-
// getPropertyOfType includes inherited Object.prototype members.
|
|
5264
|
-
// Those are not stored members of a checked-dynamic object, so
|
|
5265
|
-
// dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
|
|
5266
|
-
// an authored declaration can justify the own-member path.
|
|
5267
|
-
const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
|
|
5268
|
-
return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
|
|
5269
|
-
})();
|
|
5270
5792
|
if (DYN_PROTO_METHOD_NAMES.has(access.name.text) && !ownCallable)
|
|
5271
5793
|
return null;
|
|
5272
5794
|
// Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
|
|
@@ -5277,15 +5799,20 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5277
5799
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
5278
5800
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
5279
5801
|
}
|
|
5802
|
+
const receiverLocal = lowerer.declareHiddenLocal("%dynCallReceiver", DYN);
|
|
5803
|
+
const receiver = { kind: "varRef", localId: receiverLocal.id, type: DYN, loc };
|
|
5280
5804
|
const member = {
|
|
5281
5805
|
kind: "dynKeyGet",
|
|
5282
5806
|
key: { kind: "strLit", value: access.name.text, type: STRING, loc: locOf(access) },
|
|
5283
|
-
value:
|
|
5807
|
+
value: receiver,
|
|
5284
5808
|
type: DYN,
|
|
5285
5809
|
loc: locOf(access),
|
|
5286
5810
|
};
|
|
5287
5811
|
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
5288
|
-
return {
|
|
5812
|
+
return {
|
|
5813
|
+
kind: "seqExpr", stmts: [{ kind: "varDecl", localId: receiverLocal.id, init: recv, loc }],
|
|
5814
|
+
result: { kind: "dynCall", callee: member, receiver, calleeName: access.getText(), args, type: DYN, loc }, type: DYN, loc,
|
|
5815
|
+
};
|
|
5289
5816
|
}
|
|
5290
5817
|
/** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
|
|
5291
5818
|
* Object, Function, Number prototypes): a dyn receiver call on one of
|
|
@@ -5312,7 +5839,8 @@ const DYN_PROTO_METHOD_NAMES = new Set([
|
|
|
5312
5839
|
* is-not-a-function where the kind's prototype lacks the name, and
|
|
5313
5840
|
* fences LOUDLY on real-but-unimplemented pairs. */
|
|
5314
5841
|
const DYN_DISPATCH_METHODS = new Set([
|
|
5315
|
-
"
|
|
5842
|
+
"segment", "containing", "resolvedOptions", "test", "exec",
|
|
5843
|
+
"apply", "bind", "call",
|
|
5316
5844
|
"push", "pop", "shift", "unshift", "slice", "at",
|
|
5317
5845
|
"indexOf", "lastIndexOf", "includes", "join", "concat", "reverse", "sort",
|
|
5318
5846
|
"forEach", "map", "filter", "some", "every", "find", "findIndex",
|
|
@@ -5330,7 +5858,7 @@ const DYN_DISPATCH_METHODS = new Set([
|
|
|
5330
5858
|
"setEncoding", "setDefaultEncoding", "setTimeout", "read", "isPaused",
|
|
5331
5859
|
"writeHead", "setHeader", "getHeader", "hasHeader", "removeHeader",
|
|
5332
5860
|
"getHeaders", "getHeaderNames", "appendHeader", "flushHeaders",
|
|
5333
|
-
"append", "delete", "get", "getSetCookie", "has", "set",
|
|
5861
|
+
"add", "append", "delete", "get", "getSetCookie", "has", "set",
|
|
5334
5862
|
"writeContinue", "writeEarlyHints", "cork", "uncork", "addTrailers",
|
|
5335
5863
|
"ref", "unref", "address", "setNoDelay", "setKeepAlive", "connect",
|
|
5336
5864
|
"resetAndDestroy", "destroySoon",
|
|
@@ -5368,7 +5896,7 @@ const DYN_DISPATCH_METHODS = new Set([
|
|
|
5368
5896
|
]);
|
|
5369
5897
|
export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayReceiver) {
|
|
5370
5898
|
const method = access.name.text;
|
|
5371
|
-
if (!DYN_DISPATCH_METHODS.has(method)
|
|
5899
|
+
if ((!DYN_DISPATCH_METHODS.has(method) && !isJsSourceFile(call.getSourceFile())) || lowerer.chainBlocked(call, access))
|
|
5372
5900
|
return null;
|
|
5373
5901
|
if (call.arguments.some((arg) => ts.isSpreadElement(arg))) {
|
|
5374
5902
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
@@ -5494,7 +6022,8 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
|
|
|
5494
6022
|
// over side-effect-free reads (the operand re-evaluates/drops, the
|
|
5495
6023
|
// `in`-operator fold discipline). dyn/caught/jsval arms have no
|
|
5496
6024
|
// static tag answer and keep the narrow-first fence.
|
|
5497
|
-
const
|
|
6025
|
+
const unionId = arg.type.unionId;
|
|
6026
|
+
const def = lowerer.unions.get(unionId);
|
|
5498
6027
|
const opaque = !def || def.arms.some((a) => a.kind === "dyn" || a.kind === "caught" || a.kind === "jsval");
|
|
5499
6028
|
const arrayTags = lowerer.arrayValueTags(arg.type.unionId);
|
|
5500
6029
|
const freeRead = arg.kind === "varRef" || arg.kind === "recordGet" || arg.kind === "fieldGet";
|
|
@@ -5506,7 +6035,7 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
|
|
|
5506
6035
|
}
|
|
5507
6036
|
if (!opaque && freeRead && arrayTags.length > 1) {
|
|
5508
6037
|
return arrayTags
|
|
5509
|
-
.map((tag) => ({ kind: "unionIsTag", unionId:
|
|
6038
|
+
.map((tag) => ({ kind: "unionIsTag", unionId: unionId, tag, negated: false, value: arg, type: BOOL, loc }))
|
|
5510
6039
|
.reduce((left, right) => ({ kind: "logical", op: "||", left, right, type: BOOL, loc }));
|
|
5511
6040
|
}
|
|
5512
6041
|
lowerer.unsupported("SC1090", argNode, `Array.isArray on '${lowerer.fmt(arg.type)}' values (narrow first: check a discriminant field, or compare with '!== undefined'/'!== null' for unit arms)`);
|
|
@@ -5727,6 +6256,13 @@ function lowerClassHasOwnPropertyCall(lowerer, call, access) {
|
|
|
5727
6256
|
else
|
|
5728
6257
|
return null; // computed static names — the answer isn't static
|
|
5729
6258
|
}
|
|
6259
|
+
if (!own.has(key)) {
|
|
6260
|
+
const loc = locOf(call);
|
|
6261
|
+
const data = classStaticDataFor(lowerer, info, key, loc);
|
|
6262
|
+
if (data)
|
|
6263
|
+
return { kind: "libCall", fn: "dyn.hasOwn", args: [data,
|
|
6264
|
+
{ kind: "strLit", value: key, type: STRING, loc }], type: BOOL, loc };
|
|
6265
|
+
}
|
|
5730
6266
|
return { kind: "boolLit", value: own.has(key), type: BOOL, loc: locOf(call) };
|
|
5731
6267
|
}
|
|
5732
6268
|
/** Side-effect-free receiver test for the CONSTANT primitive-prototype
|
|
@@ -5941,6 +6477,12 @@ function implicitReceiverOverloadReturn(lowerer, expr) {
|
|
|
5941
6477
|
function reconcileOverloadReturn(lowerer, expr, call) {
|
|
5942
6478
|
const rsig = lowerer.checker.getResolvedSignature(expr);
|
|
5943
6479
|
const rdecl = rsig ? lowerer.checker.signatureDeclaration(rsig) : undefined;
|
|
6480
|
+
// Fluent JS overrides share the base's return ABI, but their result
|
|
6481
|
+
// still has the receiver's subclass layout at the call site.
|
|
6482
|
+
if (call.type.kind === "object" && rdecl && ts.isMethodDeclaration(rdecl) &&
|
|
6483
|
+
isJsSourceFile(rdecl.getSourceFile()) && returnsOnlyThis(rdecl)) {
|
|
6484
|
+
call = lowerer.maybeNarrow(call, expr);
|
|
6485
|
+
}
|
|
5944
6486
|
const resolvedOverload = rsig && rdecl &&
|
|
5945
6487
|
(ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
|
|
5946
6488
|
!rdecl.body
|
|
@@ -6147,7 +6689,7 @@ export function lowerTaggedTemplate(lowerer, expr) {
|
|
|
6147
6689
|
}
|
|
6148
6690
|
function loweredTemplateStrings(lowerer, expr, cooked, loc) {
|
|
6149
6691
|
// Normal runtime construction keeps this array aligned with the current
|
|
6150
|
-
// ScrArr layout in
|
|
6692
|
+
// ScrArr layout in the backend. The old static-header IR node encoded the
|
|
6151
6693
|
// pre-sparse layout in LLVM and crashed as soon as a tag read its strings.
|
|
6152
6694
|
const type = arrayOf(STRING);
|
|
6153
6695
|
const key = `templateStringsGlobal:${loc.file}:${expr.template.getStart()}`;
|
|
@@ -6204,7 +6746,7 @@ export function isTopLevelFnSymbol(lowerer, ident) {
|
|
|
6204
6746
|
const decl = symbol ? lowerer.checker.declarationsOf(symbol)[0] : undefined;
|
|
6205
6747
|
return (!!decl &&
|
|
6206
6748
|
ts.isFunctionDeclaration(decl) &&
|
|
6207
|
-
(ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
|
|
6749
|
+
(ts.isSourceFile(decl.parent) || (decl.parent !== undefined && lowerer.nsBlocks.get(decl.parent) === "flattened")));
|
|
6208
6750
|
}
|
|
6209
6751
|
/** Nested `function name(...) {...}`: declare the mutable function binding
|
|
6210
6752
|
* before lowering its body, then initialize it with the lifted closure.
|
|
@@ -6246,6 +6788,22 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
|
6246
6788
|
export function lambdaSignature(lowerer, node) {
|
|
6247
6789
|
if (!node.body)
|
|
6248
6790
|
lowerer.unsupported("SC1090", node, "function overload signatures");
|
|
6791
|
+
// A JS replacement of a native stream's write method receives the
|
|
6792
|
+
// actual call tuple, including overloads and omitted arguments. Node's
|
|
6793
|
+
// contextual overload signature cannot define this closure's ABI.
|
|
6794
|
+
if (isJsSourceFile(node.getSourceFile()) && !node.type &&
|
|
6795
|
+
(ts.isFunctionExpression(node) || ts.isArrowFunction(node)) &&
|
|
6796
|
+
node.parameters.every((param) => !param.type && !param.dotDotDotToken && !param.initializer) &&
|
|
6797
|
+
ts.isBinaryExpression(node.parent) && node.parent.right === node &&
|
|
6798
|
+
node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
6799
|
+
ts.isPropertyAccessExpression(node.parent.left) && node.parent.left.name.text === "write" &&
|
|
6800
|
+
lowerer.isStdlibMember(node.parent.left)) {
|
|
6801
|
+
const receiver = lowerer.lowerExpr(node.parent.left.expression);
|
|
6802
|
+
if (receiver.type.kind === "dyn") {
|
|
6803
|
+
const shapes = node.parameters.map(() => ({ type: DYN, mode: "required" }));
|
|
6804
|
+
return { shapes, funcType: funcTypeFromParamShapes(shapes, DYN) };
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6249
6807
|
if (node.typeParameters) {
|
|
6250
6808
|
// Generic function-like forms monomorphize only where a static home
|
|
6251
6809
|
// exists: top-level generic function declarations, generic methods
|
|
@@ -6271,8 +6829,8 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6271
6829
|
: lowerer.declaredReturnType(node, node);
|
|
6272
6830
|
ret = lowerer.runtimeOptionalFunctionReturnType(node, ret);
|
|
6273
6831
|
// A contextually-typed arrow/function EXPRESSION whose slot signature
|
|
6274
|
-
// returns a
|
|
6275
|
-
// return as its ABI: `(n) => work()` (inferring Promise<void>) against
|
|
6832
|
+
// returns a composite type the inferred return doesn't spell adopts
|
|
6833
|
+
// the slot's return as its ABI: `(n) => work()` (inferring Promise<void>) against
|
|
6276
6834
|
// an `(n) => Promise<void> | void` field must RETURN that union — the
|
|
6277
6835
|
// body's returns coerce into it per return site (arm values wrap;
|
|
6278
6836
|
// width-coercible records rebuild into their arm — the runJobs
|
|
@@ -6286,6 +6844,9 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6286
6844
|
// returns coerce; the spawn-wrapper ABI still returns a promise).
|
|
6287
6845
|
// jsval-returning bodies stay out (adoption would force validated
|
|
6288
6846
|
// exits the writer never asked for).
|
|
6847
|
+
// Array and record returns also need the destination during literal
|
|
6848
|
+
// construction: a callback building IrStmt[] must wrap each element at
|
|
6849
|
+
// that recursive layout instead of first inferring narrower arrays.
|
|
6289
6850
|
const isAsyncLike = !ts.isMethodDeclaration(node) &&
|
|
6290
6851
|
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
6291
6852
|
const innerRet = isAsyncLike && ret.kind === "promise" ? ret.inner : ret;
|
|
@@ -6310,8 +6871,8 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6310
6871
|
? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(ctxSigs[0]))
|
|
6311
6872
|
: null;
|
|
6312
6873
|
const ctxRet = isAsyncLike && ctxRetRaw?.kind === "promise" ? ctxRetRaw.inner : ctxRetRaw;
|
|
6313
|
-
if (ctxRet?.kind === "union" &&
|
|
6314
|
-
(innerRet.kind
|
|
6874
|
+
if ((ctxRet?.kind === "union" || ctxRet?.kind === "array" || ctxRet?.kind === "record") &&
|
|
6875
|
+
(innerRet.kind !== "void" || (ctxRet.kind === "union" && lowerer.armTag(ctxRet.unionId, UNDEFINED_T) >= 0))) {
|
|
6315
6876
|
ret = isAsyncLike ? { kind: "promise", inner: ctxRet } : ctxRet;
|
|
6316
6877
|
}
|
|
6317
6878
|
// A VOID slot discards the callback's result (TS's void-returning
|
|
@@ -6331,24 +6892,27 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6331
6892
|
ret = VOID;
|
|
6332
6893
|
}
|
|
6333
6894
|
}
|
|
6895
|
+
ret = lowerer.contextualFunctionReturns.get(node) ?? ret;
|
|
6334
6896
|
// A plain JS function reading `arguments` receives one hidden dyn
|
|
6335
6897
|
// array. With named parameters, the array contains every actual
|
|
6336
6898
|
// argument and only ES modules are admitted: sloppy-mode arguments
|
|
6337
6899
|
// alias named parameters. Arrows inherit the enclosing `arguments`.
|
|
6338
6900
|
const hasRest = shapes.some((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
|
|
6339
6901
|
const usesArguments = !hasRest &&
|
|
6340
|
-
(ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) &&
|
|
6902
|
+
(ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
|
|
6341
6903
|
isJsSourceFile(node.getSourceFile()) &&
|
|
6342
6904
|
bodyReadsArguments(node);
|
|
6343
|
-
if (usesArguments
|
|
6344
|
-
if (
|
|
6345
|
-
|
|
6905
|
+
if (usesArguments) {
|
|
6906
|
+
if (node.parameters.length > 0 || ts.isMethodDeclaration(node)) {
|
|
6907
|
+
const classMethod = ts.isMethodDeclaration(node) &&
|
|
6908
|
+
(ts.isClassDeclaration(node.parent) || ts.isClassExpression(node.parent));
|
|
6909
|
+
if (!classMethod && !isNodeEsmFile(node.getSourceFile(), lowerer.program)) {
|
|
6910
|
+
lowerer.unsupported("SC1090", node, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
|
|
6911
|
+
}
|
|
6346
6912
|
}
|
|
6347
6913
|
shapes.push({ type: DYN, mode: "arguments" });
|
|
6348
6914
|
}
|
|
6349
6915
|
const funcType = funcTypeFromParamShapes(shapes, ret);
|
|
6350
|
-
if (usesArguments)
|
|
6351
|
-
funcType.rest = true;
|
|
6352
6916
|
return { shapes, funcType };
|
|
6353
6917
|
}
|
|
6354
6918
|
/** Lifts an arrow function / function expression / nested declaration /
|
|
@@ -6398,10 +6962,17 @@ export function lowerLambda(lowerer, node) {
|
|
|
6398
6962
|
lowerer.fnStack.push(fnCtx);
|
|
6399
6963
|
try {
|
|
6400
6964
|
const { params, prologue } = lowerer.declareParams(node.parameters, shapes);
|
|
6965
|
+
// Checked JavaScript functions take their receiver from the call site.
|
|
6966
|
+
// Store it as this function's binding so escaping arrows capture it,
|
|
6967
|
+
// and a method nested inside another method never captures its owner.
|
|
6968
|
+
if (isJsSourceFile(node.getSourceFile()) && !ts.isArrowFunction(node)) {
|
|
6969
|
+
const receiver = lowerer.declareThis(DYN);
|
|
6970
|
+
prologue.unshift({ kind: "varDecl", localId: receiver.id, init: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc }, loc });
|
|
6971
|
+
}
|
|
6401
6972
|
// The synthetic trailing dyn-array param carries `arguments`.
|
|
6402
6973
|
// Parameterized functions receive all actual arguments; zero-param
|
|
6403
6974
|
// functions receive the same array through their rest ABI.
|
|
6404
|
-
if (funcType.rest && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
|
|
6975
|
+
if (funcType.rest && funcType.restAbi === undefined && !shapes.some((s) => s.mode === "dynRest" || s.mode === "islandRest")) {
|
|
6405
6976
|
const argsLocal = lowerer.declareHiddenLocal("%arguments", DYN);
|
|
6406
6977
|
params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
|
|
6407
6978
|
fnCtx.argumentsLocal = argsLocal;
|
|
@@ -6438,7 +7009,9 @@ export function lowerLambda(lowerer, node) {
|
|
|
6438
7009
|
}
|
|
6439
7010
|
}
|
|
6440
7011
|
else {
|
|
6441
|
-
|
|
7012
|
+
// Concise and block bodies use the same destination layout for
|
|
7013
|
+
// fresh literals. Async bodies must inspect promises first.
|
|
7014
|
+
let value = isAsync ? lowerer.lowerExpr(bodyExpr) : lowerer.lowerExprExpecting(bodyExpr, bodyReturn);
|
|
6442
7015
|
// An async concise body whose value is itself a promise
|
|
6443
7016
|
// (`async () => p`): the async machinery RESOLVES the returned
|
|
6444
7017
|
// thenable into the function's own promise — lowerReturnValue's
|
|
@@ -6468,6 +7041,8 @@ export function lowerLambda(lowerer, node) {
|
|
|
6468
7041
|
const ctx = lowerer.ctx;
|
|
6469
7042
|
const lifted = {
|
|
6470
7043
|
name: fnName,
|
|
7044
|
+
sourceName: jsFuncNameOf(node) ?? "<anonymous>",
|
|
7045
|
+
...(!isAsync && !isGenerator && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) ? { ownsPrototype: true } : {}),
|
|
6471
7046
|
params,
|
|
6472
7047
|
returnType: bodyReturn,
|
|
6473
7048
|
locals: ctx.locals,
|
|
@@ -6810,10 +7385,12 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
6810
7385
|
}));
|
|
6811
7386
|
}
|
|
6812
7387
|
else {
|
|
7388
|
+
if (settled.type.kind !== "dyn" &&
|
|
7389
|
+
!canConvertToDyn(settled.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
7390
|
+
lowerer.unsupported("SC1090", fulfilledNode, "then fulfillment values that cannot cross the checked-dynamic boundary");
|
|
7391
|
+
}
|
|
6813
7392
|
const arg = settled.type.kind === "dyn" ? settled
|
|
6814
|
-
:
|
|
6815
|
-
? { kind: "dynFrom", value: settled, type: DYN, loc }
|
|
6816
|
-
: lowerer.unsupported("SC1090", fulfilledNode, "then fulfillment values that cannot cross the checked-dynamic boundary");
|
|
7393
|
+
: { kind: "dynFrom", value: settled, type: DYN, loc };
|
|
6817
7394
|
body.push(...resultOf({
|
|
6818
7395
|
kind: "dynCall",
|
|
6819
7396
|
callee: { kind: "varRef", localId: fLocal.id, type: DYN, loc },
|
|
@@ -7677,7 +8254,8 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
|
|
|
7677
8254
|
loc,
|
|
7678
8255
|
};
|
|
7679
8256
|
const finalize = () => {
|
|
7680
|
-
const
|
|
8257
|
+
const latest = lowerer.shapes.get(argIr.shapeId);
|
|
8258
|
+
const current = latest !== undefined ? latest : shape;
|
|
7681
8259
|
const body = [
|
|
7682
8260
|
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
7683
8261
|
];
|
|
@@ -7727,10 +8305,11 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
|
|
|
7727
8305
|
return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
|
|
7728
8306
|
}
|
|
7729
8307
|
/** Interned `%obj.hasOwn.<n>(r, k)` — Object.hasOwn's membership walk
|
|
7730
|
-
* over a
|
|
8308
|
+
* over a record shape: the key compares against each
|
|
7731
8309
|
* declared field name, undefined-armed fields answering by their tag
|
|
7732
8310
|
* (a key is own exactly when Object.keys would list it — the two share
|
|
7733
|
-
* the guard), everything else true
|
|
8311
|
+
* the guard), everything else true. Unmatched keys probe the overflow
|
|
8312
|
+
* map when present, so explicit undefined values remain own keys. */
|
|
7734
8313
|
function recordHasOwnHelper(lowerer, shapeId, loc) {
|
|
7735
8314
|
const key = `obj.hasOwn:${shapeId}`;
|
|
7736
8315
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
@@ -7764,7 +8343,10 @@ function recordHasOwnHelper(lowerer, shapeId, loc) {
|
|
|
7764
8343
|
loc,
|
|
7765
8344
|
});
|
|
7766
8345
|
}
|
|
7767
|
-
|
|
8346
|
+
const fallback = shape.indexValue
|
|
8347
|
+
? { kind: "recordOvfHas", obj: rRef, shapeId, key: kRef, type: BOOL, loc }
|
|
8348
|
+
: { kind: "boolLit", value: false, type: BOOL, loc };
|
|
8349
|
+
body.push({ kind: "return", value: fallback, loc });
|
|
7768
8350
|
lowerer.liftedFns.push({
|
|
7769
8351
|
name: helper,
|
|
7770
8352
|
params: [
|
|
@@ -7944,6 +8526,42 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7944
8526
|
if (!lowerer.isStdlibGlobal(access.expression, "Object"))
|
|
7945
8527
|
return null;
|
|
7946
8528
|
const member = access.name.text;
|
|
8529
|
+
if ((member === "getOwnPropertyNames" || member === "getOwnPropertySymbols" || member === "getOwnPropertyDescriptors") && call.arguments.length === 1 &&
|
|
8530
|
+
!call.arguments.some(ts.isSpreadElement) && !lowerer.dynamic) {
|
|
8531
|
+
let object = lowerer.lowerExpr(call.arguments[0]);
|
|
8532
|
+
if (object.type.kind === "string" || object.type.kind === "f64" ||
|
|
8533
|
+
object.type.kind === "bool" || isUnitType(object.type))
|
|
8534
|
+
object = { kind: "dynFrom", value: object, type: DYN, loc: locOf(call) };
|
|
8535
|
+
if (object.type.kind === "dyn")
|
|
8536
|
+
return { kind: "libCall", fn: member === "getOwnPropertyNames" ? "dyn.getOwnPropertyNames" : member === "getOwnPropertySymbols" ? "dyn.getOwnPropertySymbols" : "dyn.getOwnPropertyDescriptors", args: [object], type: DYN, loc: locOf(call) };
|
|
8537
|
+
}
|
|
8538
|
+
if ((member === "getPrototypeOf" || member === "setPrototypeOf") &&
|
|
8539
|
+
call.arguments.length === (member === "getPrototypeOf" ? 1 : 2) &&
|
|
8540
|
+
!call.arguments.some(ts.isSpreadElement) && !lowerer.dynamic) {
|
|
8541
|
+
let object = lowerer.lowerExpr(call.arguments[0]);
|
|
8542
|
+
if (object.type.kind === "func") {
|
|
8543
|
+
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
8544
|
+
object = { kind: "dynFrom", value: object, type: DYN, loc: locOf(call),
|
|
8545
|
+
...(fnName !== null ? { fnName } : {}) };
|
|
8546
|
+
}
|
|
8547
|
+
if (object.type.kind === "dyn") {
|
|
8548
|
+
const loc = locOf(call);
|
|
8549
|
+
if (member === "getPrototypeOf")
|
|
8550
|
+
return { kind: "libCall", fn: "dyn.getPrototype", args: [object], type: DYN, loc };
|
|
8551
|
+
const prototype = lowerer.lowerExprExpecting(call.arguments[1], DYN);
|
|
8552
|
+
if (prototype.type.kind === "dyn")
|
|
8553
|
+
return { kind: "libCall", fn: "dyn.setPrototype", args: [object, prototype], type: DYN, loc };
|
|
8554
|
+
}
|
|
8555
|
+
}
|
|
8556
|
+
if (member === "getOwnPropertyDescriptor" && call.arguments.length === 2) {
|
|
8557
|
+
const [receiver, key] = call.arguments;
|
|
8558
|
+
if (receiver && key && ts.isPropertyAccessExpression(receiver) && receiver.name.text === "prototype" &&
|
|
8559
|
+
lowerer.isStdlibGlobal(receiver.expression, "ArrayBuffer") && ts.isStringLiteral(key) && key.text === "byteLength") {
|
|
8560
|
+
const loc = locOf(call);
|
|
8561
|
+
const getter = lowerer.lowerNativeCallableValue({ fn: "arrayBuffer.byteLengthGetter", params: [], result: F64, valueParams: [] }, "get ArrayBuffer.prototype.byteLength", loc);
|
|
8562
|
+
return { kind: "libCall", fn: "arrayBuffer.byteLengthDescriptor", args: [lowerer.coerceToExpected(getter, DYN)], type: DYN, loc };
|
|
8563
|
+
}
|
|
8564
|
+
}
|
|
7947
8565
|
const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
|
|
7948
8566
|
if (cacheKeys)
|
|
7949
8567
|
return cacheKeys;
|
|
@@ -8045,23 +8663,14 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8045
8663
|
}
|
|
8046
8664
|
lowerer.noLowering(`Object.is over '${lowerer.fmt(left.type)}' and '${lowerer.fmt(right.type)}' operands`, call, "the operands must share one comparable kind (numbers, strings, booleans, units, one union shape, or one reference type)");
|
|
8047
8665
|
}
|
|
8048
|
-
//
|
|
8049
|
-
//
|
|
8050
|
-
//
|
|
8051
|
-
// Object.create for engine-held prototypes. Everything else is a
|
|
8052
|
-
// NAMED fence: the compiled representations have no prototype chain,
|
|
8053
|
-
// and the own-copy stand-in would answer WRONG observably — Node's
|
|
8054
|
-
// Object.keys/inspect/JSON of the created object list NO own keys,
|
|
8055
|
-
// and mutating the prototype afterwards is visible through the
|
|
8056
|
-
// created object (live delegation), which no copy can honor.
|
|
8666
|
+
// Native checked objects retain a live prototype and can install an
|
|
8667
|
+
// own-property descriptor table during creation. Engine-held values
|
|
8668
|
+
// use the engine's Object.create path below.
|
|
8057
8669
|
if (member === "create") {
|
|
8058
8670
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
8059
8671
|
lowerer.noLowering("Object.create with spread arguments", call);
|
|
8060
8672
|
}
|
|
8061
|
-
if (call.arguments.length
|
|
8062
|
-
lowerer.noLowering("Object.create with a properties-descriptor argument", call, "create first, then assign: const o = Object.create(null); o.k = v");
|
|
8063
|
-
}
|
|
8064
|
-
if (call.arguments.length !== 1) {
|
|
8673
|
+
if (call.arguments.length < 1 || call.arguments.length > 2) {
|
|
8065
8674
|
lowerer.noLowering(`Object.create with ${call.arguments.length} arguments`, call);
|
|
8066
8675
|
}
|
|
8067
8676
|
const loc = locOf(call);
|
|
@@ -8070,6 +8679,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8070
8679
|
protoNode = protoNode.expression;
|
|
8071
8680
|
const nullProto = protoNode.kind === ts.SyntaxKind.NullKeyword;
|
|
8072
8681
|
if (lowerer.dynamic) {
|
|
8682
|
+
if (call.arguments.length === 2)
|
|
8683
|
+
lowerer.noLowering("Object.create with properties under --dynamic", call);
|
|
8073
8684
|
// The checker types the result `any` — an ENGINE value under
|
|
8074
8685
|
// --dynamic — and the engine's own Object.create answers with
|
|
8075
8686
|
// REAL prototype semantics: reads delegate LIVE, writes shadow,
|
|
@@ -8090,15 +8701,40 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8090
8701
|
}
|
|
8091
8702
|
lowerer.noLowering(`Object.create over '${lowerer.fmt(proto.type)}' prototypes`, call, "prototype reads delegate LIVE in Node (mutating the prototype shows through the created object), which the boundary's deep copy cannot honor — only null and engine-held ('any') prototypes lower");
|
|
8092
8703
|
}
|
|
8093
|
-
if (nullProto) {
|
|
8704
|
+
if (nullProto && call.arguments.length === 1) {
|
|
8094
8705
|
return { kind: "libCall", fn: "dyn.objCreateNullProto", args: [], type: DYN, loc };
|
|
8095
8706
|
}
|
|
8096
|
-
|
|
8097
|
-
|
|
8707
|
+
let proto = nullProto
|
|
8708
|
+
? { kind: "dynFrom", value: { kind: "unitLit", unit: "null", type: NULL_T, loc }, type: DYN, loc }
|
|
8709
|
+
: ts.isObjectLiteralExpression(protoNode)
|
|
8710
|
+
? lowerer.lowerExprExpecting(protoNode, DYN)
|
|
8711
|
+
: lowerer.lowerExpr(protoNode);
|
|
8712
|
+
if (isUnitType(proto.type) || proto.type.kind === "f64" || proto.type.kind === "bool" || proto.type.kind === "string")
|
|
8713
|
+
proto = { kind: "dynFrom", value: proto, type: DYN, loc };
|
|
8714
|
+
if (proto.type.kind === "dyn") {
|
|
8715
|
+
if (call.arguments.length === 1)
|
|
8716
|
+
return { kind: "libCall", fn: "dyn.objCreate", args: [proto], type: DYN, loc };
|
|
8717
|
+
const descriptors = lowerer.lowerExprExpecting(call.arguments[1], DYN);
|
|
8718
|
+
if (descriptors.type.kind === "dyn")
|
|
8719
|
+
return { kind: "libCall", fn: "dyn.objCreateWithProperties", args: [proto, descriptors], type: DYN, loc };
|
|
8720
|
+
}
|
|
8721
|
+
lowerer.noLowering(`Object.create over '${lowerer.fmt(proto.type)}' prototypes`, call);
|
|
8098
8722
|
}
|
|
8099
8723
|
// `Object.assign(fn, { props })` whose RESULT type maps to the hybrid
|
|
8100
8724
|
// (function-with-properties) record: the chalk-shape CONSTRUCTOR.
|
|
8101
8725
|
if (member === "assign") {
|
|
8726
|
+
const prototype = lowerClassPrototypeAssign(lowerer, call);
|
|
8727
|
+
if (prototype)
|
|
8728
|
+
return prototype;
|
|
8729
|
+
if (isJsSourceFile(call.getSourceFile()) && call.arguments.length > 0 && !call.arguments.some(ts.isSpreadElement)) {
|
|
8730
|
+
const target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
8731
|
+
if (target?.type.kind === "func" && lowerer.dynConvertible(target.type)) {
|
|
8732
|
+
const loc = locOf(call);
|
|
8733
|
+
return { kind: "libCall", fn: "dyn.assignAll", args: [lowerer.coerceToExpected(target, DYN),
|
|
8734
|
+
{ kind: "dynArrLit", elems: call.arguments.slice(1).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc },
|
|
8735
|
+
], type: DYN, loc };
|
|
8736
|
+
}
|
|
8737
|
+
}
|
|
8102
8738
|
const hybrid = lowerObjectAssignHybrid(lowerer, call);
|
|
8103
8739
|
if (hybrid)
|
|
8104
8740
|
return hybrid;
|
|
@@ -8145,7 +8781,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8145
8781
|
if (tProbe?.type.kind === "dyn") {
|
|
8146
8782
|
const loc = locOf(call);
|
|
8147
8783
|
const target = lowerer.lowerExpr(call.arguments[0]);
|
|
8148
|
-
const
|
|
8784
|
+
const rawSource = lowerer.lowerExpr(call.arguments[1]);
|
|
8785
|
+
fenceSymbolFieldCopy(lowerer, call.arguments[1], rawSource.type);
|
|
8786
|
+
const source = lowerer.coerceToExpected(rawSource, DYN);
|
|
8149
8787
|
if (target.type.kind === "dyn" && source.type.kind === "dyn") {
|
|
8150
8788
|
return { kind: "libCall", fn: "dyn.assign", args: [target, source], type: DYN, loc };
|
|
8151
8789
|
}
|
|
@@ -8222,7 +8860,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8222
8860
|
const argNode = sources[i];
|
|
8223
8861
|
const spread = ts.isSpreadElement(argNode);
|
|
8224
8862
|
const srcNode = spread ? argNode.expression : argNode;
|
|
8225
|
-
const
|
|
8863
|
+
const rawSource = lowerer.lowerExpr(srcNode);
|
|
8864
|
+
fenceSymbolFieldCopy(lowerer, srcNode, rawSource.type, spread);
|
|
8865
|
+
const src = lowerer.coerceToExpected(rawSource, DYN);
|
|
8226
8866
|
if (src.type.kind !== "dyn") {
|
|
8227
8867
|
ok = false;
|
|
8228
8868
|
break;
|
|
@@ -8259,22 +8899,75 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8259
8899
|
}
|
|
8260
8900
|
return null;
|
|
8261
8901
|
}
|
|
8902
|
+
if ((member === "defineProperty" && call.arguments.length === 3) ||
|
|
8903
|
+
(member === "getOwnPropertyDescriptor" && call.arguments.length === 2)) {
|
|
8904
|
+
if (call.arguments.some((a) => ts.isSpreadElement(a)))
|
|
8905
|
+
return null;
|
|
8906
|
+
let target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
8907
|
+
if (target && member === "defineProperty") {
|
|
8908
|
+
const native = lowerClassDataDescriptor(lowerer, call, member, target);
|
|
8909
|
+
if (native)
|
|
8910
|
+
return native;
|
|
8911
|
+
}
|
|
8912
|
+
if (target && member === "getOwnPropertyDescriptor" && isDynTypedRefType(target.type)) {
|
|
8913
|
+
const descriptor = lowerClassDescriptorRead(lowerer, call, target);
|
|
8914
|
+
if (descriptor)
|
|
8915
|
+
return descriptor;
|
|
8916
|
+
target = lowerer.coerceToExpected(target, DYN);
|
|
8917
|
+
}
|
|
8918
|
+
// Error.cause owns a live data-property slot shared with its checked
|
|
8919
|
+
// view. Other native fields do not yet synchronize descriptor edits.
|
|
8920
|
+
const keyNode = call.arguments[1];
|
|
8921
|
+
if (target?.type.kind === "object" && target.type.className !== "%DOMException" && lowerer.errorHierarchyClassOf(target.type.className) &&
|
|
8922
|
+
ts.isStringLiteral(keyNode) && keyNode.text === "cause") {
|
|
8923
|
+
target = lowerer.coerceToExpected(target, DYN);
|
|
8924
|
+
}
|
|
8925
|
+
if (target?.type.kind === "func" && lowerer.dynConvertible(target.type)) {
|
|
8926
|
+
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
8927
|
+
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
|
|
8928
|
+
}
|
|
8929
|
+
const descriptorPrimitive = member === "getOwnPropertyDescriptor" && target &&
|
|
8930
|
+
(target.type.kind === "bool" || target.type.kind === "f64" || target.type.kind === "string");
|
|
8931
|
+
if (!target || (target.type.kind !== "dyn" && !isUnitType(target.type) && !descriptorPrimitive))
|
|
8932
|
+
return null;
|
|
8933
|
+
if (target.type.kind !== "dyn")
|
|
8934
|
+
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
|
|
8935
|
+
const key = lowerer.lowerExprExpecting(call.arguments[1], DYN);
|
|
8936
|
+
if (key.type.kind !== "dyn")
|
|
8937
|
+
return null;
|
|
8938
|
+
if (member === "getOwnPropertyDescriptor") {
|
|
8939
|
+
return { kind: "libCall", fn: "dyn.getOwnPropertyDescriptor", args: [target, key], type: DYN, loc: locOf(call) };
|
|
8940
|
+
}
|
|
8941
|
+
const descriptor = lowerer.lowerExprExpecting(call.arguments[2], DYN);
|
|
8942
|
+
if (descriptor.type.kind !== "dyn")
|
|
8943
|
+
return null;
|
|
8944
|
+
return { kind: "libCall", fn: "dyn.defineProperty", args: [target, key, descriptor], type: DYN, loc: locOf(call) };
|
|
8945
|
+
}
|
|
8262
8946
|
// Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
|
|
8263
8947
|
// _mustCallInner copying name/length onto the mustCall wrapper): the
|
|
8264
|
-
// runtime turns each descriptor's `value` into
|
|
8265
|
-
// the dyn node (OBJ members; FUNC nodes carry an
|
|
8266
|
-
//
|
|
8948
|
+
// runtime turns each descriptor's `value` into an own property on
|
|
8949
|
+
// the dyn node (OBJ members preserve attributes; FUNC nodes carry an
|
|
8950
|
+
// own-property table). Accessors use the target as their receiver.
|
|
8267
8951
|
// The result is the target, like JS. Typed targets keep the fence:
|
|
8268
8952
|
// static shapes have no property table to extend.
|
|
8269
8953
|
if (member === "defineProperties" && call.arguments.length === 2 &&
|
|
8270
8954
|
!call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
8271
8955
|
let target = tryLowerExpression(lowerer, call.arguments[0]);
|
|
8956
|
+
if (target) {
|
|
8957
|
+
const native = lowerClassDataDescriptor(lowerer, call, member, target);
|
|
8958
|
+
if (native)
|
|
8959
|
+
return native;
|
|
8960
|
+
}
|
|
8272
8961
|
// A FUNCTION-typed target boxes through the dyn boundary: the
|
|
8273
8962
|
// property table lives on the CLOSURE (shared by every box of this
|
|
8274
8963
|
// function value), so defining through a fresh box sticks — the
|
|
8275
8964
|
// wrapper returned later reads the same table.
|
|
8276
8965
|
if (target && target.type.kind === "func" &&
|
|
8277
8966
|
canBoxFuncIntoDyn(target.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
8967
|
+
const fnName = jsFuncNameOf(call.arguments[0]);
|
|
8968
|
+
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]), ...(fnName !== null ? { fnName } : {}) };
|
|
8969
|
+
}
|
|
8970
|
+
if (target && isUnitType(target.type)) {
|
|
8278
8971
|
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
|
|
8279
8972
|
}
|
|
8280
8973
|
if (target?.type.kind === "dyn") {
|
|
@@ -8285,12 +8978,39 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8285
8978
|
}
|
|
8286
8979
|
return null;
|
|
8287
8980
|
}
|
|
8981
|
+
if (["preventExtensions", "isExtensible", "seal", "isSealed"].includes(member) &&
|
|
8982
|
+
call.arguments.length === 1 && !ts.isSpreadElement(call.arguments[0])) {
|
|
8983
|
+
const value = lowerer.lowerExpr(call.arguments[0]);
|
|
8984
|
+
if (value.type.kind === "string" || value.type.kind === "f64" ||
|
|
8985
|
+
value.type.kind === "bool" || value.type.kind === "symbol" || isUnitType(value.type)) {
|
|
8986
|
+
if (member === "preventExtensions" || member === "seal")
|
|
8987
|
+
return value;
|
|
8988
|
+
const loc = locOf(call);
|
|
8989
|
+
const answer = { kind: "boolLit", value: member !== "isExtensible", type: BOOL, loc };
|
|
8990
|
+
return isSafeToDiscard(value) ? answer : {
|
|
8991
|
+
kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: value, loc: value.loc }],
|
|
8992
|
+
result: answer, type: BOOL, loc,
|
|
8993
|
+
};
|
|
8994
|
+
}
|
|
8995
|
+
if (value.type.kind === "dyn") {
|
|
8996
|
+
const operation = {
|
|
8997
|
+
preventExtensions: "dyn.preventExtensions", isExtensible: "dyn.isExtensible",
|
|
8998
|
+
seal: "dyn.seal", isSealed: "dyn.isSealed",
|
|
8999
|
+
};
|
|
9000
|
+
const fn = operation[member];
|
|
9001
|
+
return { kind: "libCall", fn, args: [value], type: member.startsWith("is") ? BOOL : DYN, loc: locOf(call) };
|
|
9002
|
+
}
|
|
9003
|
+
}
|
|
8288
9004
|
// Object.freeze: on a FRESH literal (object or array) the result IS
|
|
8289
9005
|
// the argument — no alias exists, so the frozen bit is unobservable
|
|
8290
9006
|
// (writes through the Readonly<T> result are compile errors, and no
|
|
8291
9007
|
// other reference can write). Primitives pass through per ES2015.
|
|
8292
9008
|
// Aliased objects keep a fence: a later write through the original
|
|
8293
9009
|
// reference would need the runtime frozen bit (strict mode throws).
|
|
9010
|
+
if (member === "isFrozen" && call.arguments.length === 1) {
|
|
9011
|
+
const value = lowerer.lowerExprExpecting(call.arguments[0], DYN);
|
|
9012
|
+
return { kind: "libCall", fn: "dyn.isFrozen", args: [value], type: BOOL, loc: locOf(call) };
|
|
9013
|
+
}
|
|
8294
9014
|
if (member === "freeze") {
|
|
8295
9015
|
if (call.arguments.length !== 1 || ts.isSpreadElement(call.arguments[0])) {
|
|
8296
9016
|
lowerer.noLowering(`Object.freeze with ${call.arguments.length} arguments`, call);
|
|
@@ -8300,14 +9020,18 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8300
9020
|
while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
|
|
8301
9021
|
inner = inner.expression;
|
|
8302
9022
|
const value = lowerer.lowerExpr(argNode);
|
|
9023
|
+
if (value.type.kind === "dyn")
|
|
9024
|
+
return { kind: "libCall", fn: "dyn.freeze", args: [value], type: DYN, loc: locOf(call) };
|
|
8303
9025
|
if (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner)) {
|
|
8304
9026
|
return value; // fresh — freeze is identity here, honestly
|
|
8305
9027
|
}
|
|
8306
9028
|
if (value.type.kind === "string" || value.type.kind === "f64" ||
|
|
8307
|
-
value.type.kind === "bool" || value.type.kind === "symbol" ||
|
|
9029
|
+
value.type.kind === "bool" || value.type.kind === "symbol" || value.type.kind === "bigint" ||
|
|
8308
9030
|
isUnitType(value.type)) {
|
|
8309
9031
|
return value; // ES2015: freeze of a primitive is the primitive
|
|
8310
9032
|
}
|
|
9033
|
+
if (value.type.kind === "union" && lowerer.unions.get(value.type.unionId)?.arms.every((arm) => isUnitType(arm) || arm.kind === "f64" || arm.kind === "bigint" || arm.kind === "bool" || arm.kind === "string" || arm.kind === "symbol"))
|
|
9034
|
+
return value;
|
|
8311
9035
|
lowerer.noLowering("Object.freeze of a possibly-aliased value", call, "freeze of a FRESH object/array literal (and of primitives) compiles — frozen-ness is unobservable there; an aliased target's later writes would need the runtime frozen bit");
|
|
8312
9036
|
}
|
|
8313
9037
|
// `Object.hasOwn(r, k)` over a RECORD receiver: a record's own-key set
|
|
@@ -8316,9 +9040,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8316
9040
|
// fields answer by their runtime tag — the explicit-undefined-is-absent
|
|
8317
9041
|
// stance: an omitted optional field holds the undefined arm and reads
|
|
8318
9042
|
// as NOT own, exactly Node's absent key (an EXPLICIT `k: undefined`
|
|
8319
|
-
// diverges — documented next to the child-env/JSON rule). Tuple
|
|
8320
|
-
//
|
|
8321
|
-
//
|
|
9043
|
+
// diverges — documented next to the child-env/JSON rule). Tuple
|
|
9044
|
+
// and accessor-carrying shapes keep the SC2020 fence. Index-signature
|
|
9045
|
+
// records additionally probe the overflow map; non-record receivers
|
|
8322
9046
|
// do too.
|
|
8323
9047
|
if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
8324
9048
|
const recvNode = call.arguments[0];
|
|
@@ -8327,33 +9051,30 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8327
9051
|
// A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
|
|
8328
9052
|
// identity story): the runtime dyn probe — OBJ member presence, ARR
|
|
8329
9053
|
// index bounds, Node's ToObject TypeError on nullish.
|
|
8330
|
-
if (probed?.type.kind === "dyn") {
|
|
9054
|
+
if (probed?.type.kind === "dyn" || (probed && isDynTypedRefType(probed.type)) || (probed?.type.kind === "func" && lowerer.dynConvertible(probed.type))) {
|
|
8331
9055
|
const loc = locOf(call);
|
|
8332
|
-
const receiver = lowerer.
|
|
8333
|
-
|
|
8334
|
-
if (
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
9056
|
+
const receiver = lowerer.coerceToExpected(probed, DYN);
|
|
9057
|
+
const rawKey = lowerer.lowerExpr(keyNode);
|
|
9058
|
+
if (rawKey.type.kind === "dyn" || rawKey.type.kind === "symbol")
|
|
9059
|
+
return {
|
|
9060
|
+
kind: "libCall", fn: "dyn.hasOwnComputed", args: [receiver, lowerer.coerceToExpected(rawKey, DYN)], type: BOOL, loc,
|
|
9061
|
+
};
|
|
9062
|
+
const key = ownPropertyKey(lowerer, rawKey);
|
|
9063
|
+
if (!key)
|
|
8338
9064
|
return null;
|
|
8339
9065
|
return { kind: "libCall", fn: "dyn.hasOwn", args: [receiver, key], type: BOOL, loc };
|
|
8340
9066
|
}
|
|
8341
9067
|
if (probed?.type.kind !== "record")
|
|
8342
9068
|
return null;
|
|
8343
9069
|
const shape = lowerer.shapes.get(probed.type.shapeId);
|
|
8344
|
-
if (!shape || shape.tuple ||
|
|
9070
|
+
if (!shape || shape.tuple || shapeHasAccessorSlots(shape))
|
|
8345
9071
|
return null;
|
|
8346
9072
|
const loc = locOf(call);
|
|
8347
9073
|
const receiver = lowerer.lowerExpr(recvNode);
|
|
8348
9074
|
if (receiver.type.kind !== "record")
|
|
8349
9075
|
return null; // probe/lower drift: keep the fence
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
// path's rule; symbol and composite keys keep the fence.
|
|
8353
|
-
if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
|
|
8354
|
-
key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
|
|
8355
|
-
}
|
|
8356
|
-
if (key.type.kind !== "string")
|
|
9076
|
+
const key = ownPropertyKey(lowerer, lowerer.lowerExpr(keyNode));
|
|
9077
|
+
if (!key)
|
|
8357
9078
|
return null;
|
|
8358
9079
|
const helper = recordHasOwnHelper(lowerer, receiver.type.shapeId, loc);
|
|
8359
9080
|
return { kind: "call", callee: helper, args: [receiver, key], type: BOOL, loc };
|
|
@@ -8415,8 +9136,11 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8415
9136
|
const isDyn = probed?.type.kind === "dyn";
|
|
8416
9137
|
// Unit-typed arguments (Object.keys(null)) ride the same runtime
|
|
8417
9138
|
// walk: it throws Node's catchable TypeError.
|
|
8418
|
-
const
|
|
8419
|
-
|
|
9139
|
+
const isFunction = probed?.type.kind === "func" && lowerer.dynConvertible(probed.type);
|
|
9140
|
+
const isPrimitive = probed !== null && probed !== undefined &&
|
|
9141
|
+
(isUnitType(probed.type) || probed.type.kind === "string" ||
|
|
9142
|
+
probed.type.kind === "f64" || probed.type.kind === "bool");
|
|
9143
|
+
if (isDyn || isPrimitive || isFunction || (probed && isDynTypedRefType(probed.type))) {
|
|
8420
9144
|
const fn = member === "keys" ? "dyn.objKeys" : member === "values" ? "dyn.objValues" : "dyn.objEntries";
|
|
8421
9145
|
let v = lowerer.lowerExpr(argNode);
|
|
8422
9146
|
if (v.type.kind !== "dyn")
|
|
@@ -8445,6 +9169,19 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8445
9169
|
if (shapeHasAccessorSlots(shape)) {
|
|
8446
9170
|
lowerer.unsupported("SC1090", call, `Object.${member} over a shape carrying get/set accessor properties (Node lists the accessor names${member === "keys" ? "" : " and invokes the getters"} — the static key walk cannot; read the properties explicitly)`);
|
|
8447
9171
|
}
|
|
9172
|
+
// unknown[] uses the checked-dynamic array representation. Enumerate
|
|
9173
|
+
// a live view of the record so values retain their identities and the
|
|
9174
|
+
// result never pretends to be a native vector or an island array.
|
|
9175
|
+
const enumerationType = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
9176
|
+
if ((member === "values" || member === "entries") &&
|
|
9177
|
+
(enumerationType?.kind === "dyn" || enumerationType === null && isJsSourceFile(call.getSourceFile()))) {
|
|
9178
|
+
let receiver = lowerer.coerceToExpected(lowerer.lowerExpr(argNode), DYN);
|
|
9179
|
+
if (receiver.type.kind !== "dyn")
|
|
9180
|
+
lowerer.badType(argNode, lowerer.typeOf(argNode));
|
|
9181
|
+
if (receiver.kind === "dynFrom" && receiver.value.type.kind === "record")
|
|
9182
|
+
receiver = { ...receiver, liveRef: true };
|
|
9183
|
+
return { kind: "libCall", fn: member === "values" ? "dyn.objValues" : "dyn.objEntries", args: [receiver], type: DYN, loc: locOf(call) };
|
|
9184
|
+
}
|
|
8448
9185
|
if (shape.indexValue) {
|
|
8449
9186
|
// Index-signature (overflow-carrying) shapes: the runtime walk —
|
|
8450
9187
|
// declared fields first, then the overflow in JS own-key order
|
|
@@ -8455,7 +9192,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8455
9192
|
const resultT = lowerer.irTypeOf(call);
|
|
8456
9193
|
if (resultT.kind !== "array")
|
|
8457
9194
|
lowerer.badType(call, lowerer.typeOf(call)); // defensive
|
|
8458
|
-
const receiver = lowerer.lowerExpr(argNode);
|
|
9195
|
+
const receiver = objectEnumerationReceiver(lowerer, lowerer.lowerExpr(argNode), argIr, loc);
|
|
8459
9196
|
if (member === "keys") {
|
|
8460
9197
|
// The keys walk is shared with for-in (which iterates exactly the
|
|
8461
9198
|
// keys Object.keys answers — one construction, one intern key).
|
|
@@ -8497,7 +9234,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8497
9234
|
loc,
|
|
8498
9235
|
};
|
|
8499
9236
|
const finalize = () => {
|
|
8500
|
-
const
|
|
9237
|
+
const latest = lowerer.shapes.get(argIr.shapeId);
|
|
9238
|
+
const current = latest !== undefined ? latest : shape;
|
|
8501
9239
|
const body = [
|
|
8502
9240
|
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
8503
9241
|
];
|
|
@@ -8651,6 +9389,8 @@ export function lowerFunction(lowerer, decl) {
|
|
|
8651
9389
|
appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(decl));
|
|
8652
9390
|
const fn = {
|
|
8653
9391
|
name: sig.name,
|
|
9392
|
+
sourceName: decl.name?.text ?? "<anonymous>",
|
|
9393
|
+
...(!sig.isAsync && !sig.generator ? { ownsPrototype: true } : {}),
|
|
8654
9394
|
params,
|
|
8655
9395
|
returnType: bodyReturn,
|
|
8656
9396
|
locals: lowerer.ctx.locals,
|
|
@@ -8775,8 +9515,27 @@ function lowerObjectAssignHybrid(lowerer, call) {
|
|
|
8775
9515
|
export function lowerRecordFieldCall(lowerer, call, access) {
|
|
8776
9516
|
if (lowerer.chainBlocked(call))
|
|
8777
9517
|
return null;
|
|
8778
|
-
|
|
8779
|
-
|
|
9518
|
+
const stored = ts.isIdentifier(access.expression)
|
|
9519
|
+
? lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type : undefined;
|
|
9520
|
+
const receiverType = stored?.kind === "record" ? stored : lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
9521
|
+
if (receiverType?.kind !== "record" && receiverType?.kind !== "union")
|
|
9522
|
+
return null;
|
|
9523
|
+
// A union of records can share a closure-valued field. Its normal
|
|
9524
|
+
// property read performs the tag dispatch before arguments evaluate.
|
|
9525
|
+
// Class methods retain their vtable path and must not lose `this`.
|
|
9526
|
+
if (receiverType.kind === "union") {
|
|
9527
|
+
const arms = lowerer.unions.get(receiverType.unionId)?.arms;
|
|
9528
|
+
if (!arms?.every((arm) => arm.kind === "record"))
|
|
9529
|
+
return null;
|
|
9530
|
+
if (!arms.every((arm) => arm.kind === "record" &&
|
|
9531
|
+
lowerer.shapes.get(arm.shapeId)?.fields.some((field) => field.name === access.name.text && field.type.kind === "func")))
|
|
9532
|
+
return null;
|
|
9533
|
+
const callee = lowerer.lowerUnionProperty(access);
|
|
9534
|
+
if (callee?.type.kind !== "func")
|
|
9535
|
+
return null;
|
|
9536
|
+
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
9537
|
+
return { kind: "callValue", callee, args, type: callee.type.ret, loc: locOf(call) };
|
|
9538
|
+
}
|
|
8780
9539
|
const target = lowerer.fieldTarget(access);
|
|
8781
9540
|
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
8782
9541
|
if (!callee)
|
|
@@ -8975,7 +9734,7 @@ function nullishValueUnitOf(lowerer, sym) {
|
|
|
8975
9734
|
// the no-storage family never claims it.
|
|
8976
9735
|
if (!decl || !ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) ||
|
|
8977
9736
|
decl.getSourceFile().isDeclarationFile || decl.initializer === undefined ||
|
|
8978
|
-
!ts.isVariableStatement(decl.parent
|
|
9737
|
+
!ts.isVariableStatement(decl.parent?.parent)) {
|
|
8979
9738
|
return null;
|
|
8980
9739
|
}
|
|
8981
9740
|
const unit = nullishExprUnitOf(lowerer, decl.initializer);
|
|
@@ -9161,7 +9920,7 @@ export function deadUnmappableBinding(lowerer, sym, decl) {
|
|
|
9161
9920
|
// lowerVarDeclList's contract requires a lowered statement for it, so
|
|
9162
9921
|
// the no-storage family never claims it (catch bindings sit outside a
|
|
9163
9922
|
// variable statement too and stay out the same way).
|
|
9164
|
-
if (!ts.isVariableStatement(decl.parent
|
|
9923
|
+
if (!ts.isVariableStatement(decl.parent?.parent))
|
|
9165
9924
|
return false;
|
|
9166
9925
|
const sf = decl.getSourceFile();
|
|
9167
9926
|
if (sf.isDeclarationFile || isJsSourceFile(sf))
|
|
@@ -9339,11 +10098,11 @@ export function bindingGenericFnInfoOf(lowerer, decl, fnNode) {
|
|
|
9339
10098
|
lowerer.unsupported("SC1031", param);
|
|
9340
10099
|
}
|
|
9341
10100
|
}
|
|
9342
|
-
const stmt = decl.parent
|
|
10101
|
+
const stmt = decl.parent?.parent; // declarator → list → statement (nsPathPrefix wants the statement)
|
|
9343
10102
|
const info = {
|
|
9344
10103
|
decl: fnNode,
|
|
9345
10104
|
baseName: name,
|
|
9346
|
-
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + name),
|
|
10105
|
+
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + name),
|
|
9347
10106
|
typeParams,
|
|
9348
10107
|
instances: new Map(),
|
|
9349
10108
|
};
|
|
@@ -9475,6 +10234,88 @@ function arrowSignatureOf(lowerer, node) {
|
|
|
9475
10234
|
const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
|
|
9476
10235
|
return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
|
|
9477
10236
|
}
|
|
10237
|
+
/** An inline arrow has lexical `this` and no observable own properties
|
|
10238
|
+
* before binding. With no preset arguments, a fresh forwarding closure
|
|
10239
|
+
* preserves its completed ABI, defaults and captured environment. Keep
|
|
10240
|
+
* other receivers and rest/preset-argument forms on the named fence. */
|
|
10241
|
+
function lowerInlineArrowBind(lowerer, call, access) {
|
|
10242
|
+
if (access.name.text !== "bind" || call.arguments.length > 1 || call.arguments.some(ts.isSpreadElement))
|
|
10243
|
+
return null;
|
|
10244
|
+
let arrow = access.expression;
|
|
10245
|
+
while (ts.isParenthesizedExpression(arrow))
|
|
10246
|
+
arrow = arrow.expression;
|
|
10247
|
+
if (!ts.isArrowFunction(arrow))
|
|
10248
|
+
return null;
|
|
10249
|
+
const callee = lowerer.lowerExpr(access.expression);
|
|
10250
|
+
if (callee.type.kind !== "func" || callee.type.rest ||
|
|
10251
|
+
!canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
10252
|
+
return null;
|
|
10253
|
+
const type = callee.type;
|
|
10254
|
+
const loc = locOf(call);
|
|
10255
|
+
const firstDefault = arrow.parameters.findIndex((p) => p.initializer !== undefined);
|
|
10256
|
+
const length = firstDefault < 0 ? arrow.parameters.length : firstDefault;
|
|
10257
|
+
const key = `arrow.bind:${typeKey(type)}:${length}`;
|
|
10258
|
+
const existing = lowerer.arrHofHelpers.get(key);
|
|
10259
|
+
const name = existing ?? `%arrow.bind.${lowerer.arrHofHelpers.size}`;
|
|
10260
|
+
if (!existing) {
|
|
10261
|
+
lowerer.arrHofHelpers.set(key, name);
|
|
10262
|
+
lowerer.freshClosureAdapters.add(name);
|
|
10263
|
+
const impl = `${name}.impl`;
|
|
10264
|
+
const captured = { id: "f.0", name: "f", type, mutable: false, boxed: true };
|
|
10265
|
+
const params = type.params.map((type, i) => ({ localId: `p.${i}`, name: `p${i}`, type }));
|
|
10266
|
+
const invoked = {
|
|
10267
|
+
kind: "callValue",
|
|
10268
|
+
callee: { kind: "varRef", localId: captured.id, type, loc },
|
|
10269
|
+
args: params.map((p) => ({ kind: "varRef", localId: p.localId, type: p.type, loc })),
|
|
10270
|
+
type: type.ret,
|
|
10271
|
+
loc,
|
|
10272
|
+
};
|
|
10273
|
+
lowerer.liftedFns.push({
|
|
10274
|
+
name: impl,
|
|
10275
|
+
params,
|
|
10276
|
+
returnType: type.ret,
|
|
10277
|
+
captures: [{ localId: captured.id, name: captured.name, type }],
|
|
10278
|
+
locals: [captured, ...params.map((p) => ({ id: p.localId, name: p.name, type: p.type, mutable: false }))],
|
|
10279
|
+
body: [type.ret.kind === "void" ? { kind: "exprStmt", expr: invoked, loc } : { kind: "return", value: invoked, loc }],
|
|
10280
|
+
loc,
|
|
10281
|
+
});
|
|
10282
|
+
const bound = { kind: "varRef", localId: "bound.0", type, loc };
|
|
10283
|
+
const str = (value) => ({ kind: "strLit", value, type: STRING, loc });
|
|
10284
|
+
const descriptor = (value) => ({
|
|
10285
|
+
kind: "dynObjLit", fields: [{ key: str("value"), value: { kind: "dynFrom", value, type: DYN, loc } }], type: DYN, loc,
|
|
10286
|
+
});
|
|
10287
|
+
lowerer.liftedFns.push({
|
|
10288
|
+
name,
|
|
10289
|
+
params: [{ localId: captured.id, name: captured.name, type }],
|
|
10290
|
+
returnType: type,
|
|
10291
|
+
locals: [captured, { id: "bound.0", name: "bound", type, mutable: false }],
|
|
10292
|
+
body: [
|
|
10293
|
+
{ kind: "varDecl", localId: "bound.0", init: { kind: "closure", fnName: impl, captures: [captured.id], type, loc }, loc },
|
|
10294
|
+
// Store metadata on the closure so aliases and repeated dyn boxes
|
|
10295
|
+
// observe the bound name and source arity, including defaults.
|
|
10296
|
+
{ kind: "exprStmt", expr: {
|
|
10297
|
+
kind: "libCall", fn: "dyn.defineProps", args: [
|
|
10298
|
+
{ kind: "dynFrom", value: bound, type: DYN, loc },
|
|
10299
|
+
{ kind: "dynObjLit", fields: [
|
|
10300
|
+
{ key: str("name"), value: descriptor(str("bound ")) },
|
|
10301
|
+
{ key: str("length"), value: descriptor({ kind: "numLit", value: length, type: F64, loc }) },
|
|
10302
|
+
], type: DYN, loc },
|
|
10303
|
+
], type: DYN, loc,
|
|
10304
|
+
}, loc },
|
|
10305
|
+
{ kind: "return", value: bound, loc },
|
|
10306
|
+
],
|
|
10307
|
+
loc,
|
|
10308
|
+
});
|
|
10309
|
+
}
|
|
10310
|
+
const saved = lowerer.declareHiddenLocal("%bindFn", type);
|
|
10311
|
+
const stmts = [{ kind: "varDecl", localId: saved.id, init: callee, loc }];
|
|
10312
|
+
// The receiver is ignored by the arrow, but its effects and throws
|
|
10313
|
+
// happen after creating the arrow and before returning the bound value.
|
|
10314
|
+
if (call.arguments[0])
|
|
10315
|
+
stmts.push(lowerer.lowerExprStatement(call.arguments[0]));
|
|
10316
|
+
const result = { kind: "call", callee: name, args: [{ kind: "varRef", localId: saved.id, type, loc }], type, loc };
|
|
10317
|
+
return { kind: "seqExpr", stmts, result, type, loc };
|
|
10318
|
+
}
|
|
9478
10319
|
/** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
|
|
9479
10320
|
* ignore `thisArg` and surplus arguments by language definition; declared
|
|
9480
10321
|
* parameters validate from the dynamic array in order. */
|
|
@@ -9553,7 +10394,6 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9553
10394
|
thisT.kind !== "dyn" &&
|
|
9554
10395
|
thisT.kind !== "jsval" &&
|
|
9555
10396
|
(!thisArg || ts.isIdentifier(thisArg) || ts.isLiteralExpression(thisArg) ||
|
|
9556
|
-
thisArg.kind === ts.SyntaxKind.UndefinedKeyword ||
|
|
9557
10397
|
thisArg.kind === ts.SyntaxKind.NullKeyword ||
|
|
9558
10398
|
isUnitType(thisT));
|
|
9559
10399
|
if (provablyNot) {
|
|
@@ -9592,19 +10432,25 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9592
10432
|
}
|
|
9593
10433
|
const found = objLitGenericFnNodeOf(lowerer, propSym);
|
|
9594
10434
|
if (!found) {
|
|
10435
|
+
const arrowBind = lowerInlineArrowBind(lowerer, call, access);
|
|
10436
|
+
if (arrowBind !== null)
|
|
10437
|
+
return arrowBind;
|
|
9595
10438
|
const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
|
|
9596
10439
|
if (arrowApply !== null)
|
|
9597
10440
|
return arrowApply;
|
|
9598
|
-
//
|
|
9599
|
-
//
|
|
9600
|
-
// `this`/arguments object to re-route — name the working spelling
|
|
9601
|
-
// instead of a class-receiver hint (or an SC2020 recitation) no
|
|
9602
|
-
// function value can follow. Before the stdlib decline: these ARE
|
|
9603
|
-
// stdlib members (CallableFunction), but the pointed message is
|
|
9604
|
-
// the honest one.
|
|
10441
|
+
// Convertible native callables use the checked invocation boundary
|
|
10442
|
+
// for Function.prototype methods, including their call-time receiver.
|
|
9605
10443
|
if ((name === "apply" || name === "call" || name === "bind") &&
|
|
9606
10444
|
lowerer.checker.getCallSignatures(recvT).length > 0) {
|
|
9607
|
-
|
|
10445
|
+
const value = tryLowerExpression(lowerer, access.expression);
|
|
10446
|
+
if (value?.type.kind === "func" && lowerer.dynConvertible(value.type) && !call.arguments.some(ts.isSpreadElement)) {
|
|
10447
|
+
const loc = locOf(call);
|
|
10448
|
+
return {
|
|
10449
|
+
kind: "dynInvoke", recv: { kind: "dynFrom", value, type: DYN, loc }, method: name,
|
|
10450
|
+
calleeName: access.getText(), args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc,
|
|
10451
|
+
};
|
|
10452
|
+
}
|
|
10453
|
+
lowerer.unsupported("SC1090", call, `Function.prototype.${name} on a function whose signature cannot cross the checked-value boundary (call '${access.expression.getText()}(...)' directly)`);
|
|
9608
10454
|
}
|
|
9609
10455
|
// STANDARD-LIBRARY generic members (Promise.then, Object.
|
|
9610
10456
|
// defineProperty, Array-augmentation methods) are the lib fence's
|
|
@@ -9641,7 +10487,16 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9641
10487
|
export function lowerObjectMethodCall(lowerer, call, access) {
|
|
9642
10488
|
if (lowerer.chainBlocked(access, call))
|
|
9643
10489
|
return null;
|
|
9644
|
-
|
|
10490
|
+
let mappedReceiver = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
10491
|
+
// A specialized JS parameter can expose a native field whose checker
|
|
10492
|
+
// type still belongs to the unspecialized body (plane.normal.dot()).
|
|
10493
|
+
// Use the lowered receiver's representation and retain its evaluation.
|
|
10494
|
+
const probe = mappedReceiver?.kind !== "object" && (lowerer.implicitParamTypes !== null || ts.isNewExpression(access.expression) ||
|
|
10495
|
+
isJsSourceFile(call.getSourceFile()) && ts.isCallExpression(access.expression))
|
|
10496
|
+
? tryLowerExpression(lowerer, access.expression) : null;
|
|
10497
|
+
const specializedReceiver = probe?.type.kind === "object" ? probe : null;
|
|
10498
|
+
if (specializedReceiver)
|
|
10499
|
+
mappedReceiver = specializedReceiver.type;
|
|
9645
10500
|
if (mappedReceiver?.kind === "union") {
|
|
9646
10501
|
const dispatched = lowerUnionObjectMethodCall(lowerer, call, access, mappedReceiver) ??
|
|
9647
10502
|
lowerUnionObjectDynFieldCall(lowerer, call, access, mappedReceiver);
|
|
@@ -9654,15 +10509,16 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9654
10509
|
? (() => {
|
|
9655
10510
|
const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
|
|
9656
10511
|
const objects = arms.filter((arm) => arm.kind === "object");
|
|
9657
|
-
|
|
9658
|
-
|
|
10512
|
+
const object = objects[0];
|
|
10513
|
+
return objects.length === 1 && object?.kind === "object" && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
|
|
10514
|
+
? object
|
|
9659
10515
|
: null;
|
|
9660
10516
|
})()
|
|
9661
10517
|
: null;
|
|
9662
10518
|
if (receiverIr === null)
|
|
9663
10519
|
return null;
|
|
9664
10520
|
const lowerReceiver = () => {
|
|
9665
|
-
const receiver = lowerer.lowerExpr(access.expression);
|
|
10521
|
+
const receiver = specializedReceiver ?? lowerer.lowerExpr(access.expression);
|
|
9666
10522
|
const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
|
|
9667
10523
|
if (optional !== null)
|
|
9668
10524
|
return optional;
|
|
@@ -9671,7 +10527,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9671
10527
|
if (helper !== null)
|
|
9672
10528
|
return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
|
|
9673
10529
|
}
|
|
9674
|
-
return receiver;
|
|
10530
|
+
return receiver.type.kind === "dyn" ? lowerer.coerceInto(access.expression, receiver, receiverIr) : receiver;
|
|
9675
10531
|
};
|
|
9676
10532
|
const info = lowerer.classes.get(receiverIr.className);
|
|
9677
10533
|
if (!info)
|
|
@@ -9698,7 +10554,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9698
10554
|
if (info && !found) {
|
|
9699
10555
|
const gfound = findGenericMethodOn(lowerer, info, access.name.text);
|
|
9700
10556
|
if (gfound)
|
|
9701
|
-
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
|
|
10557
|
+
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound, lowerReceiver());
|
|
9702
10558
|
}
|
|
9703
10559
|
// A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
|
|
9704
10560
|
// `this.cb()` — the ctor-assigned callback field (countdown.js's
|
|
@@ -9714,13 +10570,22 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9714
10570
|
? (() => {
|
|
9715
10571
|
const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
|
|
9716
10572
|
const funcs = arms.filter((arm) => arm.kind === "func");
|
|
9717
|
-
|
|
9718
|
-
|
|
10573
|
+
const func = funcs[0];
|
|
10574
|
+
return funcs.length === 1 && func?.kind === "func" && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
|
|
10575
|
+
? func
|
|
9719
10576
|
: null;
|
|
9720
10577
|
})()
|
|
9721
10578
|
: null;
|
|
9722
10579
|
if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
|
|
9723
10580
|
const target = lowerer.fieldTarget(access);
|
|
10581
|
+
if (!target)
|
|
10582
|
+
return null;
|
|
10583
|
+
const loc = locOf(call);
|
|
10584
|
+
const receiverLocal = lowerer.declareHiddenLocal("%callReceiver", target.obj.type);
|
|
10585
|
+
const init = { kind: "varDecl", localId: receiverLocal.id, init: target.obj, loc };
|
|
10586
|
+
target.obj = { kind: "varRef", localId: receiverLocal.id, type: receiverLocal.type, loc };
|
|
10587
|
+
const receiver = lowerer.coerceToExpected(target.obj, DYN);
|
|
10588
|
+
const finish = (result) => ({ kind: "seqExpr", stmts: [init], result, type: result.type, loc });
|
|
9724
10589
|
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
9725
10590
|
if (callee?.type.kind === "union" && callableType !== null) {
|
|
9726
10591
|
const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
|
|
@@ -9729,15 +10594,24 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9729
10594
|
}
|
|
9730
10595
|
}
|
|
9731
10596
|
if (callee?.type.kind === "func") {
|
|
10597
|
+
if ((callee.type.rest === true && callee.type.restAbi === undefined || call.arguments.length > callee.type.params.length) &&
|
|
10598
|
+
isJsSourceFile(call.getSourceFile()) && lowerer.dynConvertible(callee.type)) {
|
|
10599
|
+
const boxed = { kind: "dynFrom", value: callee, type: DYN, loc };
|
|
10600
|
+
const spread = lowerSpreadArgsCall(lowerer, call, boxed, loc);
|
|
10601
|
+
if (spread?.kind === "dynCall")
|
|
10602
|
+
return finish({ ...spread, receiver });
|
|
10603
|
+
const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
10604
|
+
return finish({ kind: "dynCall", callee: boxed, receiver, calleeName: access.getText(), args, type: DYN, loc });
|
|
10605
|
+
}
|
|
9732
10606
|
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
9733
|
-
return { kind: "callValue", callee, args, type: callee.type.ret, loc
|
|
10607
|
+
return finish({ kind: "callValue", callee, receiver, args, type: callee.type.ret, loc });
|
|
9734
10608
|
}
|
|
9735
10609
|
if (callee?.type.kind === "dyn") {
|
|
9736
10610
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
9737
10611
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
9738
10612
|
}
|
|
9739
10613
|
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
9740
|
-
return { kind: "dynCall", callee, calleeName: access.getText(), args, type: DYN, loc
|
|
10614
|
+
return finish({ kind: "dynCall", callee, receiver, calleeName: access.getText(), args, type: DYN, loc });
|
|
9741
10615
|
}
|
|
9742
10616
|
}
|
|
9743
10617
|
return null;
|
|
@@ -9745,18 +10619,25 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9745
10619
|
if (!info || !found)
|
|
9746
10620
|
return null;
|
|
9747
10621
|
const method = access.name.text;
|
|
9748
|
-
if (
|
|
9749
|
-
|
|
9750
|
-
// implementation called directly (overriding it is fenced, so no
|
|
9751
|
-
// dispatch can ever be needed). Receiver BORROWED by the libCall.
|
|
10622
|
+
if (isClassCallback(lowerer, info, method)) {
|
|
10623
|
+
const loc = locOf(call);
|
|
9752
10624
|
const receiver = lowerReceiver();
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
10625
|
+
const local = lowerer.declareHiddenLocal("%callbackReceiver", receiver.type);
|
|
10626
|
+
const value = { kind: "varRef", localId: local.id, type: receiver.type, loc };
|
|
10627
|
+
const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
|
|
10628
|
+
const virtual = lowerer.overrideBelow(info, method);
|
|
10629
|
+
if (virtual)
|
|
10630
|
+
lowerer.noteVirtualEdge(info, method);
|
|
10631
|
+
else
|
|
10632
|
+
lowerer.noteEdge(`%${found.declarer.def.name}.${method}`);
|
|
10633
|
+
const fallback = virtual
|
|
10634
|
+
? { kind: "virtualCall", className: info.def.name, method, args: [lowerer.upcastTo(value, info.def.name), ...args], type: found.sig.ret, loc }
|
|
10635
|
+
: { kind: "call", callee: `%${found.declarer.def.name}.${method}`, args: [lowerer.upcastTo(value, found.declarer.def.name), ...args], type: found.sig.ret, loc };
|
|
10636
|
+
const result = classCallbackCall(lowerer, value, method, call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), fallback, loc);
|
|
10637
|
+
return { kind: "seqExpr", stmts: [{ kind: "varDecl", localId: local.id, init: receiver, loc }], result, type: result.type, loc };
|
|
10638
|
+
}
|
|
10639
|
+
if (found.declarer.builtinError) {
|
|
10640
|
+
return errorToStringCall(lowerer, lowerReceiver());
|
|
9760
10641
|
}
|
|
9761
10642
|
// An ABSTRACT nearest declaration with no concrete override below the
|
|
9762
10643
|
// static class: no implementation exists for a direct call to target.
|
|
@@ -9829,7 +10710,10 @@ function lowerUnionObjectMethodCall(lowerer, call, access, receiverT) {
|
|
|
9829
10710
|
function paramAbisEqual(left, right) {
|
|
9830
10711
|
return left.length === right.length && left.every((shape, i) => {
|
|
9831
10712
|
const other = right[i];
|
|
9832
|
-
return other !== undefined &&
|
|
10713
|
+
return other !== undefined && typeEquals(shape.type, other.type) &&
|
|
10714
|
+
(shape.mode === other.mode || shape.type.kind === "dyn" &&
|
|
10715
|
+
(shape.mode === "required" || shape.mode === "omittable") &&
|
|
10716
|
+
(other.mode === "required" || other.mode === "omittable"));
|
|
9833
10717
|
});
|
|
9834
10718
|
}
|
|
9835
10719
|
/** The JS-class sibling of union method dispatch: every arm stores the
|
|
@@ -9854,6 +10738,8 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
|
|
|
9854
10738
|
const loc = locOf(call);
|
|
9855
10739
|
const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
|
|
9856
10740
|
const key = `${receiverT.unionId}:dyn-field:${field}`;
|
|
10741
|
+
const receiverLocal = lowerer.declareHiddenLocal("%unionCallReceiver", receiverT);
|
|
10742
|
+
const receiverRef = varRef(receiverLocal.id, receiverT, loc);
|
|
9857
10743
|
let helper = lowerer.unionCallHelpers.get(key);
|
|
9858
10744
|
if (!helper) {
|
|
9859
10745
|
helper = `%union.call.${lowerer.unionCallHelpers.size}`;
|
|
@@ -9906,9 +10792,12 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
|
|
|
9906
10792
|
const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
|
|
9907
10793
|
lowerer.liftedFns.push({ name: helper, params, returnType: DYN, locals, body, loc });
|
|
9908
10794
|
}
|
|
9909
|
-
const callee = { kind: "call", callee: helper, args: [
|
|
10795
|
+
const callee = { kind: "call", callee: helper, args: [receiverRef], type: DYN, loc };
|
|
9910
10796
|
const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
9911
|
-
return {
|
|
10797
|
+
return {
|
|
10798
|
+
kind: "seqExpr", stmts: [{ kind: "varDecl", localId: receiverLocal.id, init: receiver, loc }],
|
|
10799
|
+
result: { kind: "dynCall", callee, receiver: lowerer.coerceToExpected(receiverRef, DYN), calleeName: access.getText(), args, type: DYN, loc }, type: DYN, loc,
|
|
10800
|
+
};
|
|
9912
10801
|
}
|
|
9913
10802
|
function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans, shapes, resultT, loc) {
|
|
9914
10803
|
const key = `${receiverT.unionId}:${method}:${shapes.map((shape) => `${shape.mode}:${typeKey(shape.type)}`).join(",")}:${typeKey(resultT)}`;
|
|
@@ -9930,13 +10819,7 @@ function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans,
|
|
|
9930
10819
|
};
|
|
9931
10820
|
let invoke;
|
|
9932
10821
|
if (plan.found.declarer.builtinError) {
|
|
9933
|
-
invoke =
|
|
9934
|
-
kind: "libCall",
|
|
9935
|
-
fn: "error.toString",
|
|
9936
|
-
args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name)],
|
|
9937
|
-
type: STRING,
|
|
9938
|
-
loc,
|
|
9939
|
-
};
|
|
10822
|
+
invoke = errorToStringCall(lowerer, concrete);
|
|
9940
10823
|
}
|
|
9941
10824
|
else if (lowerer.overrideBelow(plan.info, method)) {
|
|
9942
10825
|
lowerer.noteVirtualEdge(plan.info, method);
|