@scriptc/compiler 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +73 -25
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +28 -5
- package/dist/backend/build-cache.d.ts +1 -3
- package/dist/backend/build-cache.js +3 -22
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cache-root.d.ts +3 -0
- package/dist/backend/cache-root.js +23 -0
- package/dist/backend/cache-root.js.map +1 -0
- package/dist/backend/cycle-analysis.d.ts +15 -0
- package/dist/backend/cycle-analysis.js +107 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/debug-symbols.d.ts +8 -0
- package/dist/backend/debug-symbols.js +52 -0
- package/dist/backend/debug-symbols.js.map +1 -0
- package/dist/backend/executable-features.d.ts +4 -0
- package/dist/backend/executable-features.js +42 -0
- package/dist/backend/executable-features.js.map +1 -0
- package/dist/backend/external-c.d.ts +5 -27
- package/dist/backend/external-c.js +5 -40
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +2 -3
- package/dist/backend/ffi-callbacks.js +2 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.d.ts +4 -9
- package/dist/backend/library-identity-markers.js +11 -49
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +5 -0
- package/dist/backend/library-pack.js +123 -0
- package/dist/backend/library-pack.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +20 -0
- package/dist/backend/link-plan-core.js +18 -0
- package/dist/backend/link-plan-core.js.map +1 -0
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js +18 -17
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/link-trace.d.ts +2 -0
- package/dist/backend/link-trace.js +24 -0
- package/dist/backend/link-trace.js.map +1 -0
- package/dist/backend/linker.js +9 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.d.ts +9 -0
- package/dist/backend/literals.js +35 -0
- package/dist/backend/literals.js.map +1 -0
- package/dist/backend/literals.test.d.ts +1 -0
- package/dist/backend/literals.test.js +53 -0
- package/dist/backend/literals.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +4 -0
- package/dist/backend/llvm/blocks.js +25 -4
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.d.ts +1 -0
- package/dist/backend/llvm/blocks.test.js +91 -0
- package/dist/backend/llvm/blocks.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +14 -8
- package/dist/backend/llvm/classes.js +70 -28
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.d.ts +32 -0
- package/dist/backend/llvm/debug-info.js +198 -0
- package/dist/backend/llvm/debug-info.js.map +1 -0
- package/dist/backend/llvm/debug-info.test.d.ts +1 -0
- package/dist/backend/llvm/debug-info.test.js +110 -0
- package/dist/backend/llvm/debug-info.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +16 -2
- package/dist/backend/llvm/dyn.js +498 -175
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +598 -1
- package/dist/backend/llvm/emitter.js +739 -409
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +32 -14
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +9 -5
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +72 -74
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +51 -30
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +43 -4
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +102 -121
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +59 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +2 -0
- package/dist/backend/llvm/lib-http2.js +215 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -0
- package/dist/backend/llvm/lib-lookup.d.ts +2 -0
- package/dist/backend/llvm/lib-lookup.js +39 -0
- package/dist/backend/llvm/lib-lookup.js.map +1 -0
- package/dist/backend/llvm/lib-network.js +25 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +21 -16
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +125 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +35 -130
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/split.js +4 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +26 -1
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +10 -25
- package/dist/backend/native-toolchain.js +89 -219
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +15 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +70 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/source-locations.d.ts +12 -0
- package/dist/backend/source-locations.js +32 -0
- package/dist/backend/source-locations.js.map +1 -0
- package/dist/backend/source-locations.test.d.ts +1 -0
- package/dist/backend/source-locations.test.js +16 -0
- package/dist/backend/source-locations.test.js.map +1 -0
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +95 -30
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +65 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +3 -3
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js +15 -3
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +33 -10
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +38 -16
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +14 -0
- package/dist/executable/prepare.js +66 -0
- package/dist/executable/prepare.js.map +1 -0
- package/dist/ffi/ffi-manifest.d.ts +11 -4
- package/dist/ffi/ffi-manifest.js +170 -58
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.d.ts +1 -0
- package/dist/ffi/ffi-manifest.test.js +111 -0
- package/dist/ffi/ffi-manifest.test.js.map +1 -0
- package/dist/format-integer.d.ts +3 -0
- package/dist/format-integer.js +14 -0
- package/dist/format-integer.js.map +1 -0
- package/dist/frontend/analysis.d.ts +5 -0
- package/dist/frontend/analysis.js +88 -0
- package/dist/frontend/analysis.js.map +1 -0
- package/dist/frontend/arguments-usage.d.ts +4 -0
- package/dist/frontend/arguments-usage.js +40 -0
- package/dist/frontend/arguments-usage.js.map +1 -0
- package/dist/frontend/binding-source.d.ts +4 -0
- package/dist/frontend/binding-source.js +18 -0
- package/dist/frontend/binding-source.js.map +1 -0
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-lexer.d.ts +4 -25
- package/dist/frontend/cjs-lexer.js +6 -806
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/cjs-resolve.d.ts +5 -0
- package/dist/frontend/cjs-resolve.js +429 -0
- package/dist/frontend/cjs-resolve.js.map +1 -0
- package/dist/frontend/cjs-syntax.d.ts +26 -0
- package/dist/frontend/cjs-syntax.js +806 -0
- package/dist/frontend/cjs-syntax.js.map +1 -0
- package/dist/frontend/comptime-node.d.ts +4 -0
- package/dist/frontend/comptime-node.js +16 -0
- package/dist/frontend/comptime-node.js.map +1 -0
- package/dist/frontend/comptime-node.test.d.ts +1 -0
- package/dist/frontend/comptime-node.test.js +37 -0
- package/dist/frontend/comptime-node.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +3 -4
- package/dist/frontend/dts-paths.js +15 -8
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +2 -2
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/helper-tokens.d.ts +1 -0
- package/dist/frontend/helper-tokens.js +147 -0
- package/dist/frontend/helper-tokens.js.map +1 -0
- package/dist/frontend/helper-tokens.test.d.ts +1 -0
- package/dist/frontend/helper-tokens.test.js +35 -0
- package/dist/frontend/helper-tokens.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
- package/dist/frontend/inferred-js-diagnostics.js +69 -0
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +5 -2
- package/dist/frontend/input-tracker.js +24 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +23 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +32 -24
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.d.ts +4 -0
- package/dist/frontend/literal-values.js +21 -0
- package/dist/frontend/literal-values.js.map +1 -0
- package/dist/frontend/literal-values.test.d.ts +1 -0
- package/dist/frontend/literal-values.test.js +91 -0
- package/dist/frontend/literal-values.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
- package/dist/frontend/lowering/abstract-equality.js +3 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -1
- package/dist/frontend/lowering/array-values.js +43 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
- package/dist/frontend/lowering/class-callbacks.js +63 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +9 -0
- package/dist/frontend/lowering/class-descriptors.js +73 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +41 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +803 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +92 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +64 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +10 -0
- package/dist/frontend/lowering/class-method-values.js +170 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +16 -0
- package/dist/frontend/lowering/class-prototypes.js +134 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +164 -155
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +39 -16
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +11 -0
- package/dist/frontend/lowering/error-methods.js +78 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +49 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +124 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +485 -185
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
- package/dist/frontend/lowering/expressions/optional-chains.js +27 -14
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +93 -0
- package/dist/frontend/lowering/function-context.js +103 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +10 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +105 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +2 -1
- package/dist/frontend/lowering/lib-boundary.js +59 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +12 -0
- package/dist/frontend/lowering/lower-builtin-values.js +139 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +27 -41
- package/dist/frontend/lowering/lower-builtins.js +553 -346
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +22 -26
- package/dist/frontend/lowering/lower-calls.js +1373 -380
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +83 -45
- package/dist/frontend/lowering/lower-classes.js +952 -339
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +27 -32
- package/dist/frontend/lowering/lower-containers.js +796 -151
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +35 -11
- package/dist/frontend/lowering/lower-exprs.js +1785 -790
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +77 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +5 -8
- package/dist/frontend/lowering/lower-island.js +34 -23
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +252 -38
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +10 -14
- package/dist/frontend/lowering/lower-stmts.js +731 -532
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +19 -10
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +113 -189
- package/dist/frontend/lowering/lowerer.js +1033 -663
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +26 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +9 -4
- package/dist/frontend/lowering/surfaces.js +98 -35
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +10 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +77 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +5 -4
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +1 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +43 -19
- package/dist/frontend/program.js +556 -197
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.d.ts +1 -0
- package/dist/frontend/program.test.js +202 -0
- package/dist/frontend/program.test.js.map +1 -0
- package/dist/frontend/provenance-core.d.ts +9 -0
- package/dist/frontend/provenance-core.js +435 -0
- package/dist/frontend/provenance-core.js.map +1 -0
- package/dist/frontend/provenance.d.ts +0 -4
- package/dist/frontend/provenance.js +4 -459
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +3 -1
- package/dist/frontend/resolve.js +6 -3
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +4 -3
- package/dist/frontend/runtime-resolve.js +22 -18
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +53 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.d.ts +5 -0
- package/dist/frontend/services-node.js +19 -0
- package/dist/frontend/services-node.js.map +1 -0
- package/dist/frontend/services-node.test.d.ts +1 -0
- package/dist/frontend/services-node.test.js +70 -0
- package/dist/frontend/services-node.test.js.map +1 -0
- package/dist/frontend/services.d.ts +44 -0
- package/dist/frontend/services.js +90 -0
- package/dist/frontend/services.js.map +1 -0
- package/dist/frontend/services.test.d.ts +1 -0
- package/dist/frontend/services.test.js +174 -0
- package/dist/frontend/services.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +3 -3
- package/dist/frontend/ts7/adapter.js +14 -31
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/api.d.ts +16 -0
- package/dist/frontend/ts7/api.js +24 -0
- package/dist/frontend/ts7/api.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
- package/dist/frontend/ts7/ast-bytes.js +137 -0
- package/dist/frontend/ts7/ast-bytes.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-bytes.test.js +73 -0
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
- package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-guards.test.js +43 -0
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +194 -0
- package/dist/frontend/ts7/ast-node.js +448 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -0
- package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-node.test.js +266 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -0
- package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
- package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
- package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-text.d.ts +6 -0
- package/dist/frontend/ts7/ast-text.js +124 -0
- package/dist/frontend/ts7/ast-text.js.map +1 -0
- package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-text.test.js +38 -0
- package/dist/frontend/ts7/ast-text.test.js.map +1 -0
- package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
- package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
- package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.d.ts +42 -0
- package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
- package/dist/frontend/ts7/ast-types.generated.js +5 -0
- package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.js +3 -0
- package/dist/frontend/ts7/ast-types.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +58 -0
- package/dist/frontend/ts7/ast-wire.js +267 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire.test.js +151 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
- package/dist/frontend/ts7/ast.d.ts +14 -14
- package/dist/frontend/ts7/ast.js +21 -15
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +52 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +29 -19
- package/dist/frontend/type-mapper.js +713 -306
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.d.ts +1 -0
- package/dist/frontend/type-mapper.test.js +207 -0
- package/dist/frontend/type-mapper.test.js.map +1 -0
- package/dist/frontend/union-discriminants.d.ts +16 -0
- package/dist/frontend/union-discriminants.js +98 -0
- package/dist/frontend/union-discriminants.js.map +1 -0
- package/dist/frontend/union-discriminants.test.d.ts +1 -0
- package/dist/frontend/union-discriminants.test.js +182 -0
- package/dist/frontend/union-discriminants.test.js.map +1 -0
- package/dist/index.d.ts +7 -197
- package/dist/index.js +369 -1567
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +25 -6
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.js +67 -49
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/control-flow.d.ts +6 -0
- package/dist/ir/control-flow.js +142 -0
- package/dist/ir/control-flow.js.map +1 -0
- package/dist/ir/control-flow.test.d.ts +1 -0
- package/dist/ir/control-flow.test.js +113 -0
- package/dist/ir/control-flow.test.js.map +1 -0
- package/dist/ir/integer-loops.js +7 -18
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.js +53 -27
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +309 -164
- package/dist/ir/ir.js +588 -879
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +127 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +19 -12
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +53 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +1956 -1496
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +476 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/compiler-self-identity.d.ts +1 -1
- package/dist/library/compiler-self-identity.js +31 -15
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/compiler-self-identity.test.d.ts +1 -0
- package/dist/library/compiler-self-identity.test.js +93 -0
- package/dist/library/compiler-self-identity.test.js.map +1 -0
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +135 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +74 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +33 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +171 -18
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -531
- package/dist/backend/c/c-emitter.js +0 -1917
- package/dist/backend/c/c-emitter.js.map +0 -1
- package/dist/backend/c/exprs.d.ts +0 -15
- package/dist/backend/c/exprs.js +0 -8803
- package/dist/backend/c/exprs.js.map +0 -1
- package/dist/backend/c/island.d.ts +0 -45
- package/dist/backend/c/island.js +0 -281
- package/dist/backend/c/island.js.map +0 -1
- package/dist/backend/c/may-throw.js.map +0 -1
- package/dist/backend/c/shapes.d.ts +0 -142
- package/dist/backend/c/shapes.js +0 -603
- package/dist/backend/c/shapes.js.map +0 -1
- package/dist/backend/c/stmts.d.ts +0 -76
- package/dist/backend/c/stmts.js +0 -1084
- package/dist/backend/c/stmts.js.map +0 -1
- package/dist/backend/c/types.d.ts +0 -71
- package/dist/backend/c/types.js +0 -459
- package/dist/backend/c/types.js.map +0 -1
- package/dist/backend/c/types.test.js +0 -32
- package/dist/backend/c/types.test.js.map +0 -1
- package/dist/backend/c/walkers.d.ts +0 -134
- package/dist/backend/c/walkers.js +0 -1773
- package/dist/backend/c/walkers.js.map +0 -1
- /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
|
@@ -1,27 +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";
|
|
9
|
+
import { bodyReadsArguments } from "../arguments-usage.js";
|
|
7
10
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
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";
|
|
11
17
|
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr, staticImportNamespaceType } from "./lowerer.js";
|
|
12
18
|
import { enforceLibBoundary } from "./lib-boundary.js";
|
|
13
19
|
import { NARROW_FIRST, STRING_INDEX_METHODS, STR_METHODS, builtinFenceHintOf, builtinModuleFnOf } from "./surfaces.js";
|
|
14
20
|
import { ffiBindingDiag, ffiSignatureDiag, libCallbackDiag, requiresDynamicDiag } from "../../diagnostics/diagnostic.js";
|
|
15
21
|
import { mixinFnShapeOf } from "./lower-mixins.js";
|
|
16
22
|
import { dynStringReceiver, lowerArrayConstructor, lowerArrayFromCall, lowerArrayOfCall, lowerDynArrayFilterCall, lowerDynArrayFlatMapCall, lowerGroupByStaticCall, lowerIteratorHelperCall, lowerObjectAssignIndexShape, lowerObjectFromEntriesCall, lowerObjectIterOverIndexShape, lowerTupleReadMethodCall } from "./lower-containers.js";
|
|
17
|
-
import {
|
|
23
|
+
import { lowerBytesStaticCall } from "./containers/bytes.js";
|
|
18
24
|
import { lowerRegexMethodCall, lowerStringIndexCall, lowerStringMethodCall, lowerStringPaddingCall, lowerStringSplitCall } from "./containers/string-and-regexp.js";
|
|
19
|
-
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";
|
|
20
26
|
import { lowerAbsenceProbe, lowerPromiseAllTupleCall, lowerPromiseRejectCall, stringWrapperToString, templateRawTextOf } from "./lower-exprs.js";
|
|
21
27
|
import { isSafeToDiscard } from "./expressions/evaluation-safety.js";
|
|
22
28
|
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
23
29
|
import { httpClientFnBindingOf, isStreamUndefCallExpr, lowerCompatReqStreamOptionalCall, lowerHttpClientFnCall } from "./lower-server.js";
|
|
24
|
-
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";
|
|
25
32
|
import { emitterRooted, lowerEmitterMethodCall } from "./lower-event-emitter.js";
|
|
26
33
|
import { lowerConsoleInspectArg, lowerFormatCall } from "./lower-inspect.js";
|
|
27
34
|
import { STREAM_API_MEMBERS, lowerStreamMethodCall, lowerStreamModuleCall, lowerStreamStaticCall, streamSidesOf } from "./lower-stream.js";
|
|
@@ -29,10 +36,14 @@ import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUn
|
|
|
29
36
|
import { declSymbolOf } from "./lower-modules.js";
|
|
30
37
|
import { expandoMemberRead } from "./lower-expando.js";
|
|
31
38
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
32
|
-
import { countedFor, varRef } from "../../ir/build.js";
|
|
39
|
+
import { countedFor, numLit, varRef } from "../../ir/build.js";
|
|
33
40
|
import { rejectStaticThis } from "./static-this.js";
|
|
34
41
|
import { fenceNodeModuleMutationCall, lowerRequireCacheKeys } from "./lower-node-module.js";
|
|
35
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";
|
|
46
|
+
export { bodyReadsArguments };
|
|
36
47
|
/** The one func-type projection of completed parameter shapes. Typed rest
|
|
37
48
|
* parameters keep their packed array as the trailing native ABI slot and
|
|
38
49
|
* mark the value variadic so indirect call sites run completeArgs before
|
|
@@ -49,11 +60,7 @@ export function funcTypeFromParamShapes(shapes, ret) {
|
|
|
49
60
|
ret,
|
|
50
61
|
...(typedRest || dynRest || islandRest || argumentsAll ? { rest: true } : {}),
|
|
51
62
|
...(argumentsAll ? { argumentsAll: true } : {}),
|
|
52
|
-
...(typedRest
|
|
53
|
-
? { restAbi: "typed" }
|
|
54
|
-
: islandRest
|
|
55
|
-
? { restAbi: "jsval" }
|
|
56
|
-
: {}),
|
|
63
|
+
...(typedRest || islandRest ? { restAbi: typedRest ? "typed" : "jsval" } : {}),
|
|
57
64
|
};
|
|
58
65
|
}
|
|
59
66
|
/** Registers `const alias = overloadedDeclaration` as a compile-time
|
|
@@ -116,6 +123,11 @@ export const MAX_GENERIC_INSTANCES = 100;
|
|
|
116
123
|
* - `...xs: T[]`: the ABI type is the array; call sites pack the surplus.
|
|
117
124
|
*/
|
|
118
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
|
+
}
|
|
119
131
|
const moduleNs = lowerer.moduleNsParamOverrides.get(param);
|
|
120
132
|
if (moduleNs !== undefined) {
|
|
121
133
|
return { type: moduleNs, mode: param.questionToken ? "omittable" : "required" };
|
|
@@ -157,21 +169,7 @@ export function paramShape(lowerer, param) {
|
|
|
157
169
|
// default when the argument was omitted or undefined, then the
|
|
158
170
|
// pattern destructures the picked value (declareParams).
|
|
159
171
|
const raw = lowerer.irTypeOf(param.name);
|
|
160
|
-
|
|
161
|
-
// `a: any` — jsval for island values, dyn for the checked-dynamic
|
|
162
|
-
// dyn): the slot holds its tier's undefined DIRECTLY, so the ABI
|
|
163
|
-
// is the slot itself — no synthesized union; the prologue tests
|
|
164
|
-
// undefined at runtime (declareParams).
|
|
165
|
-
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
166
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
167
|
-
}
|
|
168
|
-
const bodyType = lowerer.stripUndefinedArm(raw);
|
|
169
|
-
lowerer.checkDefaultParamBodyType(param, bodyType);
|
|
170
|
-
const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
|
|
171
|
-
if (!abi) {
|
|
172
|
-
lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
|
|
173
|
-
}
|
|
174
|
-
return { type: abi, mode: "omittable", bodyType };
|
|
172
|
+
return defaultParameterShape(lowerer, param, raw);
|
|
175
173
|
}
|
|
176
174
|
return { type: lowerer.runtimeOptionalBindingType(param.name, lowerer.irTypeOf(param.name)), mode: "required" };
|
|
177
175
|
}
|
|
@@ -205,41 +203,12 @@ export function paramShape(lowerer, param) {
|
|
|
205
203
|
}
|
|
206
204
|
if (param.initializer) {
|
|
207
205
|
const raw = lowerer.irTypeOf(param.name);
|
|
208
|
-
|
|
209
|
-
// — tsc types x any; jsval for island values, dyn for the checked-
|
|
210
|
-
// dynamic dyn): the slot holds its tier's undefined directly, so
|
|
211
|
-
// the ABI is the slot itself and the prologue's default test is the
|
|
212
|
-
// runtime undefined test (declareParams).
|
|
213
|
-
if (raw.kind === "dyn" || raw.kind === "jsval") {
|
|
214
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
215
|
-
}
|
|
216
|
-
// A default that may ITSELF be undefined (`x = process.env.FOO`):
|
|
217
|
-
// tsc keeps undefined in the body's type, so there is nothing to
|
|
218
|
-
// narrow — the ABI union IS the body type and the prologue passes a
|
|
219
|
-
// present argument through unchanged (declareParams's pass-through
|
|
220
|
-
// branch). The generic strip-and-narrow below would demand a
|
|
221
|
-
// `string`-typed default and fence on the union re-tag.
|
|
222
|
-
if (lowerer.bareUndefinedArmedUnion(raw)) {
|
|
223
|
-
const initT = lowerer.mapTypeOf(lowerer.typeOf(param.initializer));
|
|
224
|
-
if (initT && (initT.kind === "undefinedT" || lowerer.bareUndefinedArmedUnion(initT))) {
|
|
225
|
-
return { type: raw, mode: "omittable", bodyType: raw };
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const bodyType = lowerer.stripUndefinedArm(raw);
|
|
229
|
-
lowerer.checkDefaultParamBodyType(param, bodyType);
|
|
230
|
-
// A UNION body type (`tlds: string | string[] = "localhost"`) arms
|
|
231
|
-
// the ABI with undefined ON TOP of the body's arms; the prologue
|
|
232
|
-
// re-tags a present argument back into the body union (undefined
|
|
233
|
-
// sorts last among arm typeKeys in practice, so the mapping is
|
|
234
|
-
// usually the identity prefix — the interned retag helper handles
|
|
235
|
-
// any order).
|
|
236
|
-
const abi = bodyType.kind === "union" ? lowerer.withUndefinedArmOf(bodyType) : lowerer.withUndefinedArm(bodyType);
|
|
237
|
-
if (!abi) {
|
|
238
|
-
lowerer.badType(param.name, lowerer.typeOf(param.name)); // defensive: unknown union id
|
|
239
|
-
}
|
|
240
|
-
return { type: abi, mode: "omittable", bodyType };
|
|
206
|
+
return defaultParameterShape(lowerer, param, raw);
|
|
241
207
|
}
|
|
242
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
|
+
}
|
|
243
212
|
if (param.questionToken && !lowerer.bareUndefinedArmedUnion(type) && type.kind !== "dyn" && type.kind !== "jsval") {
|
|
244
213
|
// `x?: unknown` where unknown came from an annotation: undefined is
|
|
245
214
|
// absorbed into the hole type, so no undefined ARM exists — but a
|
|
@@ -267,7 +236,7 @@ export function paramShapes(lowerer, params, signature, blameOf) {
|
|
|
267
236
|
return params.map((declParam, i) => {
|
|
268
237
|
const symbol = signature.getParameters()[i];
|
|
269
238
|
const tsType = symbol ? lowerer.checker.getTypeOfSymbol(symbol) : lowerer.typeOf(declParam.name);
|
|
270
|
-
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);
|
|
271
240
|
if (!mapped || mapped.kind === "void")
|
|
272
241
|
lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
|
|
273
242
|
if (declParam.dotDotDotToken) {
|
|
@@ -275,30 +244,46 @@ export function paramShapes(lowerer, params, signature, blameOf) {
|
|
|
275
244
|
lowerer.badType(blameOf?.(declParam, i) ?? declParam.name, tsType);
|
|
276
245
|
return { type: mapped, mode: "rest" };
|
|
277
246
|
}
|
|
278
|
-
if (declParam.initializer)
|
|
279
|
-
|
|
280
|
-
return { type: mapped, mode: "omittable", bodyType: mapped };
|
|
281
|
-
}
|
|
282
|
-
const bodyType = lowerer.stripUndefinedArm(mapped);
|
|
283
|
-
lowerer.checkDefaultParamBodyType(declParam, bodyType);
|
|
284
|
-
return { type: lowerer.withUndefinedArm(bodyType), mode: "omittable", bodyType };
|
|
285
|
-
}
|
|
247
|
+
if (declParam.initializer)
|
|
248
|
+
return defaultParameterShape(lowerer, declParam, mapped);
|
|
286
249
|
if (declParam.questionToken && !lowerer.bareUndefinedArmedUnion(mapped)) {
|
|
287
250
|
lowerer.unsupported("SC1090", declParam, `optional parameters of type '${lowerer.fmt(mapped)}'`);
|
|
288
251
|
}
|
|
289
252
|
return { type: mapped, mode: declParam.questionToken ? "omittable" : "required" };
|
|
290
253
|
});
|
|
291
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
|
+
}
|
|
292
278
|
/** The fences on a defaulted parameter's body type: it becomes the value
|
|
293
279
|
* arm of the synthesized `T | undefined` ABI union, so it must be a valid
|
|
294
|
-
* single arm.
|
|
280
|
+
* single arm. Functions, Maps and Sets are valid: the ABI union's test is
|
|
295
281
|
* the prologue's own undefined-tag check (never a user narrowing, which
|
|
296
|
-
* is what keeps
|
|
282
|
+
* is what keeps containers out of unions with data siblings), so `runner: Runner =
|
|
297
283
|
* defaultRunner` and `skip: Set<string> = new Set()` arm like any ref
|
|
298
284
|
* kind — the nullable-callback union shape, built by the compiler. */
|
|
299
285
|
export function checkDefaultParamBodyType(lowerer, param, bodyType) {
|
|
300
286
|
if (bodyType.kind === "void" ||
|
|
301
|
-
bodyType.kind === "map" ||
|
|
302
287
|
bodyType.kind === "regex" ||
|
|
303
288
|
bodyType.kind === "date" ||
|
|
304
289
|
bodyType.kind === "dyn" ||
|
|
@@ -334,7 +319,62 @@ export function completeArgs(lowerer, argNodes, shapes, loc, blame,
|
|
|
334
319
|
* coercion an ordinary argument gets (coerceInto against its shape,
|
|
335
320
|
* DYN conversion in a dyn rest, element coercion in a typed rest). */
|
|
336
321
|
leading) {
|
|
337
|
-
|
|
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);
|
|
338
378
|
const sources = leading?.map((ir) => ({ ir })) ?? [];
|
|
339
379
|
for (const arg of argNodes) {
|
|
340
380
|
if (!ts.isSpreadElement(arg)) {
|
|
@@ -397,9 +437,20 @@ leading) {
|
|
|
397
437
|
lowerer.unsupported("SC1090", source, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
|
|
398
438
|
}
|
|
399
439
|
const slotType = i < restAt ? positional[i].type : DYN;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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);
|
|
403
454
|
const saved = lowerer.declareHiddenLocal("%callArg", slotType);
|
|
404
455
|
stmts.push({ kind: "varDecl", localId: saved.id, init: value, loc: value.loc });
|
|
405
456
|
return { kind: "varRef", localId: saved.id, type: slotType, loc: value.loc };
|
|
@@ -407,7 +458,7 @@ leading) {
|
|
|
407
458
|
const fixed = positional.map((shape, i) => {
|
|
408
459
|
if (i < passed.length)
|
|
409
460
|
return passed[i];
|
|
410
|
-
if (shape.mode === "omittable")
|
|
461
|
+
if (shape.mode === "omittable" || lowerer.bareUndefinedArmedUnion(shape.type))
|
|
411
462
|
return shape.callDefault ?? lowerer.undefinedArgFor(shape.type, loc, blame);
|
|
412
463
|
if (shape.type.kind === "dyn")
|
|
413
464
|
return { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc };
|
|
@@ -432,9 +483,19 @@ leading) {
|
|
|
432
483
|
// completion has no home for that. Spreads fill REST slots only.
|
|
433
484
|
lowerer.unsupported("SC1090", arg, "spread arguments into fixed parameter positions (a spread can only fill a rest parameter)");
|
|
434
485
|
}
|
|
435
|
-
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
|
+
}
|
|
436
496
|
return lowerer.lowerExprExpecting(arg, shape.type);
|
|
437
|
-
|
|
497
|
+
}
|
|
498
|
+
if (shape.mode !== "omittable" && !lowerer.bareUndefinedArmedUnion(shape.type)) {
|
|
438
499
|
// A missing argument for a CHECKED-DYNAMIC param (an implicit-any
|
|
439
500
|
// JS signature called short — `mustCall(fn)` with `expected`
|
|
440
501
|
// omitted): JS fills undefined, and the dyn slot holds exactly
|
|
@@ -688,7 +749,9 @@ export function requireExactArityValue(lowerer, blame, contextual, shapes, funcT
|
|
|
688
749
|
// slot): judge by the expression's OWN completed type; the slot's
|
|
689
750
|
// coercion still enforces (or adapts) the flow it lands in.
|
|
690
751
|
if (mappedFn?.kind !== "func" && contextual) {
|
|
691
|
-
|
|
752
|
+
const ownType = lowerer.typeOf(contextual);
|
|
753
|
+
mappedFn = lowerer.mapTypeOf(ownType) ??
|
|
754
|
+
(isJsSourceFile(contextual.getSourceFile()) ? dynFallbackType(lowerer, contextual, ownType) : null);
|
|
692
755
|
}
|
|
693
756
|
if (mappedFn && typeEquals(mappedFn, funcType))
|
|
694
757
|
return;
|
|
@@ -808,6 +871,10 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
808
871
|
if (!sig)
|
|
809
872
|
lowerer.unsupported("SC1090", decl, "this function form");
|
|
810
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;
|
|
811
878
|
// A body that always throws infers `never` — as a RETURN type that is
|
|
812
879
|
// void with a stronger guarantee (`() => never` is assignable to
|
|
813
880
|
// `() => void`), and throw-only callbacks are ordinary code
|
|
@@ -815,10 +882,34 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
815
882
|
if (retTsType.flags & ts.TypeFlags.Never)
|
|
816
883
|
return VOID;
|
|
817
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
|
+
}
|
|
818
908
|
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
819
909
|
!hasExplicitJsDocReturn(decl) &&
|
|
820
910
|
mappedReturn !== null &&
|
|
821
911
|
promiseCarriesDyn(lowerer, mappedReturn) &&
|
|
912
|
+
!decl.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
822
913
|
decl.parameters.some((param) => {
|
|
823
914
|
const mapped = lowerer.mapTypeOf(lowerer.typeOf(param.name));
|
|
824
915
|
return mapped === null || mapped.kind === "dyn";
|
|
@@ -850,14 +941,19 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
850
941
|
// checked-dynamic (or none): a lambda with RECORD-typed parameters
|
|
851
942
|
// (a reduce reducer over a typed array) legitimately returns its
|
|
852
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;
|
|
853
948
|
if (isJsSourceFile(decl.getSourceFile()) &&
|
|
854
949
|
decl.type === undefined &&
|
|
855
|
-
|
|
950
|
+
recordReturn?.kind === "record" &&
|
|
951
|
+
lowerer.dynConvertible(recordReturn) &&
|
|
856
952
|
decl.parameters.every((p) => {
|
|
857
953
|
const mt = lowerer.mapTypeOf(lowerer.typeOf(p));
|
|
858
954
|
return mt === null || mt.kind === "dyn";
|
|
859
955
|
})) {
|
|
860
|
-
return DYN;
|
|
956
|
+
return asyncReturn ? { kind: "promise", inner: DYN } : DYN;
|
|
861
957
|
}
|
|
862
958
|
const returnType = lowerer.mapTypeOf(retTsType);
|
|
863
959
|
if (!returnType) {
|
|
@@ -882,7 +978,7 @@ export function declaredReturnType(lowerer, decl, blame) {
|
|
|
882
978
|
* other unmappable type (the caller's badType reports those). */
|
|
883
979
|
function fenceGenericSignatureResult(lowerer, blame, t) {
|
|
884
980
|
const parts = t.isUnionType() ? ts.constituentTypes(t) : [t];
|
|
885
|
-
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))) {
|
|
886
982
|
return;
|
|
887
983
|
}
|
|
888
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)`);
|
|
@@ -959,7 +1055,7 @@ export function collectSignatureInner(lowerer, decl) {
|
|
|
959
1055
|
if (!params.some((sh) => sh.mode === "rest" || sh.mode === "dynRest" || sh.mode === "islandRest") &&
|
|
960
1056
|
isJsSourceFile(decl.getSourceFile()) &&
|
|
961
1057
|
bodyReadsArguments(decl)) {
|
|
962
|
-
if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile())) {
|
|
1058
|
+
if (decl.parameters.length > 0 && !isNodeEsmFile(decl.getSourceFile(), lowerer.program)) {
|
|
963
1059
|
lowerer.unsupported("SC1090", decl, "parameterized 'arguments' outside an ES module (sloppy-mode parameter aliases)");
|
|
964
1060
|
}
|
|
965
1061
|
params.push({ type: DYN, mode: decl.parameters.length > 0 ? "arguments" : "dynRest" });
|
|
@@ -1191,7 +1287,7 @@ export function inferTypeParamBindings(lowerer, expr, info, rsig, tsBindings) {
|
|
|
1191
1287
|
return;
|
|
1192
1288
|
const taT = lowerer.checker.getTypeFromTypeNode(ta);
|
|
1193
1289
|
const mapped = lowerer.mapTypeOf(taT);
|
|
1194
|
-
if (mapped
|
|
1290
|
+
if (mapped) {
|
|
1195
1291
|
bindings.set(tp, mapped);
|
|
1196
1292
|
tsBindings?.set(tp, taT);
|
|
1197
1293
|
}
|
|
@@ -1211,7 +1307,7 @@ function bindDefaultTypeParams(lowerer, typeParams, typeParamDecls, bindings, ts
|
|
|
1211
1307
|
return;
|
|
1212
1308
|
const defT = lowerer.checker.getTypeFromTypeNode(tpDecl.defaultType);
|
|
1213
1309
|
const mapped = lowerer.mapTypeOf(defT);
|
|
1214
|
-
if (mapped
|
|
1310
|
+
if (mapped) {
|
|
1215
1311
|
bindings.set(tp, mapped);
|
|
1216
1312
|
tsBindings?.set(tp, defT);
|
|
1217
1313
|
}
|
|
@@ -1253,7 +1349,10 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1253
1349
|
}
|
|
1254
1350
|
if (!bindings.has(sym)) {
|
|
1255
1351
|
const mapped = lowerer.mapTypeOf(inst);
|
|
1256
|
-
|
|
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)
|
|
1257
1356
|
bindings.set(sym, mapped);
|
|
1258
1357
|
}
|
|
1259
1358
|
}
|
|
@@ -1268,10 +1367,20 @@ function unifySignatureBindings(lowerer, info, rsig, bindings, tsBindings) {
|
|
|
1268
1367
|
// unbound type parameter surfaces as a mapping diagnostic later).
|
|
1269
1368
|
if (declared.isUnionType()) {
|
|
1270
1369
|
const unitFlags = ts.TypeFlags.Undefined | ts.TypeFlags.Null;
|
|
1271
|
-
const
|
|
1272
|
-
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];
|
|
1273
1374
|
if (dParts.length === 1 && iParts.length === 1)
|
|
1274
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
|
+
}
|
|
1275
1384
|
return;
|
|
1276
1385
|
}
|
|
1277
1386
|
// Instantiations of the SAME generic ALIAS (Partial<T> vs
|
|
@@ -1424,16 +1533,21 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1424
1533
|
fnCtx.generator = generatorMeta(lowerer, inst.returnType);
|
|
1425
1534
|
}
|
|
1426
1535
|
lowerer.fnStack.push(fnCtx);
|
|
1536
|
+
lowerer.localClassInstantiations.push({ owner: decl, name: inst.name });
|
|
1427
1537
|
try {
|
|
1428
|
-
//
|
|
1429
|
-
//
|
|
1430
|
-
//
|
|
1431
|
-
// are transparent (they inherit the method's `this`); this-binding
|
|
1432
|
-
// 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.
|
|
1433
1541
|
if (info.member?.kind === "static" && decl.body) {
|
|
1434
|
-
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);
|
|
1435
1543
|
}
|
|
1436
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
|
+
}
|
|
1437
1551
|
if (cls && info.member.kind === "method") {
|
|
1438
1552
|
// Instance methods take `this` as param 0, exactly like plain
|
|
1439
1553
|
// `%C.method` functions (lowerClassMethodMemberInner).
|
|
@@ -1445,7 +1559,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1445
1559
|
// threaded — a default mentioning T resolves like any body expression.
|
|
1446
1560
|
const declared = lowerer.declareParams(decl.parameters, inst.params);
|
|
1447
1561
|
params.push(...declared.params);
|
|
1448
|
-
const body = [...declared.prologue];
|
|
1562
|
+
const body = [...receiverInit, ...declared.prologue];
|
|
1449
1563
|
const bodyBlock = blockBodyOf(decl);
|
|
1450
1564
|
if (bodyBlock) {
|
|
1451
1565
|
body.push(...lowerer.lowerStmts(bodyBlock.statements));
|
|
@@ -1488,6 +1602,8 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1488
1602
|
}
|
|
1489
1603
|
const fn = {
|
|
1490
1604
|
name: inst.name,
|
|
1605
|
+
sourceName: info.baseName,
|
|
1606
|
+
...(!isAsync && !decl.asteriskToken && (ts.isFunctionDeclaration(decl) || ts.isFunctionExpression(decl)) ? { ownsPrototype: true } : {}),
|
|
1491
1607
|
params,
|
|
1492
1608
|
returnType: bodyReturn,
|
|
1493
1609
|
locals: lowerer.ctx.locals,
|
|
@@ -1507,6 +1623,7 @@ export function lowerGenericInstance(lowerer, info, inst) {
|
|
|
1507
1623
|
lowerer.typeParamTsBindings = prevTsBindings;
|
|
1508
1624
|
lowerer.implicitParamTypes = prevImplicit;
|
|
1509
1625
|
lowerer.instantiationContext = prevContext;
|
|
1626
|
+
lowerer.localClassInstantiations.pop();
|
|
1510
1627
|
lowerer.suppressStats = prevSuppress;
|
|
1511
1628
|
}
|
|
1512
1629
|
}
|
|
@@ -1529,7 +1646,6 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1529
1646
|
// returning — JS answers undefined.
|
|
1530
1647
|
const last = body[body.length - 1];
|
|
1531
1648
|
const mayFallThrough = !last || !(last.kind === "return" || last.kind === "throw" || last.kind === "rethrow" || last.kind === "runtimeFence");
|
|
1532
|
-
const valued = infer.entries.filter((e) => e.stmt.kind === "return" && e.stmt.value !== null && e.stmt.value !== undefined);
|
|
1533
1649
|
const sawBare = mayFallThrough || infer.entries.some((e) => e.stmt.kind === "return" && (e.stmt.value === null || e.stmt.value === undefined));
|
|
1534
1650
|
let final;
|
|
1535
1651
|
if (inst.returnPinned) {
|
|
@@ -1537,16 +1653,19 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1537
1653
|
}
|
|
1538
1654
|
else {
|
|
1539
1655
|
const distinct = [];
|
|
1540
|
-
for (const e of
|
|
1541
|
-
if (
|
|
1542
|
-
|
|
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);
|
|
1543
1662
|
}
|
|
1544
1663
|
if (distinct.length === 0) {
|
|
1545
1664
|
final = DYN; // no valued return: JS completes with undefined — the dyn undefined, today's slot
|
|
1546
1665
|
}
|
|
1547
1666
|
else if (distinct.length === 1) {
|
|
1548
1667
|
const t = distinct[0];
|
|
1549
|
-
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);
|
|
1550
1669
|
}
|
|
1551
1670
|
else {
|
|
1552
1671
|
final = DYN; // disagreeing returns: the checked-dynamic join
|
|
@@ -1557,23 +1676,24 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1557
1676
|
for (const e of infer.entries) {
|
|
1558
1677
|
if (e.stmt.kind !== "return")
|
|
1559
1678
|
continue;
|
|
1560
|
-
|
|
1679
|
+
// Write through the recorded statement. A narrowed local can acquire a
|
|
1680
|
+
// different record layout and copy it in the native compiler.
|
|
1561
1681
|
const diagsBefore = lowerer.diags.length;
|
|
1562
1682
|
try {
|
|
1563
|
-
if (
|
|
1683
|
+
if (e.stmt.value === null || e.stmt.value === undefined) {
|
|
1564
1684
|
if (final.kind === "dyn")
|
|
1565
|
-
|
|
1685
|
+
e.stmt.value = dynUndefinedExpr(e.stmt.loc);
|
|
1566
1686
|
else if (final.kind === "union") {
|
|
1567
|
-
const wrapped = lowerer.wrappedUndefined(final,
|
|
1687
|
+
const wrapped = lowerer.wrappedUndefined(final, e.stmt.loc);
|
|
1568
1688
|
if (!wrapped) {
|
|
1569
1689
|
lowerer.unsupported("SC1090", e.node ?? decl, `bare 'return' in a function whose inferred return type is '${lowerer.fmt(final)}'`);
|
|
1570
1690
|
}
|
|
1571
|
-
|
|
1691
|
+
e.stmt.value = wrapped;
|
|
1572
1692
|
}
|
|
1573
1693
|
// void final: bare return stands as-is
|
|
1574
1694
|
}
|
|
1575
|
-
else if (!typeEquals(
|
|
1576
|
-
|
|
1695
|
+
else if (!typeEquals(e.stmt.value.type, final)) {
|
|
1696
|
+
e.stmt.value = lowerer.coerceInto(e.node ?? decl, e.stmt.value, final);
|
|
1577
1697
|
}
|
|
1578
1698
|
}
|
|
1579
1699
|
catch (err) {
|
|
@@ -1588,7 +1708,7 @@ function resolveInferredReturn(lowerer, inst, infer, body, decl) {
|
|
|
1588
1708
|
lowerer.diags.push(...ice);
|
|
1589
1709
|
lowerer.runtimeFences.push(...captured.filter((d) => d.code !== "SC9001"));
|
|
1590
1710
|
const first = captured.find((d) => d.code !== "SC9001");
|
|
1591
|
-
const mutable =
|
|
1711
|
+
const mutable = e.stmt;
|
|
1592
1712
|
delete mutable["value"];
|
|
1593
1713
|
mutable["kind"] = "runtimeFence";
|
|
1594
1714
|
mutable["code"] = first?.code ?? "SC1090";
|
|
@@ -1846,10 +1966,12 @@ function broadPromiseParam(lowerer, type) {
|
|
|
1846
1966
|
}
|
|
1847
1967
|
/** The implicit-type-parameter slots of a JS function-like: parallel to
|
|
1848
1968
|
* decl.parameters, the param SYMBOL where the slot is a bindable
|
|
1849
|
-
* implicit
|
|
1850
|
-
* rest/optional/defaulted, never written), null elsewhere.
|
|
1851
|
-
*
|
|
1852
|
-
|
|
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) {
|
|
1853
1975
|
if (!decl.body)
|
|
1854
1976
|
return null;
|
|
1855
1977
|
if (decl.asteriskToken)
|
|
@@ -1875,7 +1997,9 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1875
1997
|
const broadFunction = lowerer.checker.typeToString(t) === "Function";
|
|
1876
1998
|
const broadArray = lowerer.checkerAnyArrayType(t);
|
|
1877
1999
|
const broadPromise = broadPromiseParam(lowerer, t);
|
|
1878
|
-
|
|
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)
|
|
1879
2003
|
return null;
|
|
1880
2004
|
const sym = lowerer.checker.getSymbolAtLocation(param.name);
|
|
1881
2005
|
if (!sym)
|
|
@@ -1894,6 +2018,11 @@ export function implicitAnyParamSymbolsOf(lowerer, decl) {
|
|
|
1894
2018
|
* selects return INFERENCE with DYN as the recursion pin. */
|
|
1895
2019
|
function implicitDeclaredReturn(lowerer, info) {
|
|
1896
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;
|
|
1897
2026
|
const broadCallbackSymbols = new Set(info.decl.parameters.flatMap((param, index) => {
|
|
1898
2027
|
const symbol = info.implicitParams?.[index];
|
|
1899
2028
|
return symbol !== null && symbol !== undefined &&
|
|
@@ -1913,7 +2042,10 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1913
2042
|
expression = expression.expression;
|
|
1914
2043
|
if (ts.isCallExpression(expression) &&
|
|
1915
2044
|
ts.isIdentifier(expression.expression) &&
|
|
1916
|
-
|
|
2045
|
+
(() => {
|
|
2046
|
+
const symbol = lowerer.checker.getSymbolAtLocation(expression.expression);
|
|
2047
|
+
return symbol !== undefined && broadCallbackSymbols.has(symbol);
|
|
2048
|
+
})()) {
|
|
1917
2049
|
returnsBroadCallback = true;
|
|
1918
2050
|
return "stop";
|
|
1919
2051
|
}
|
|
@@ -1928,7 +2060,12 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1928
2060
|
const retTs = lowerer.checker.getReturnTypeOfSignature(declSig);
|
|
1929
2061
|
if (retTs.flags & ts.TypeFlags.Any)
|
|
1930
2062
|
return null;
|
|
2063
|
+
if (retTs.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined))
|
|
2064
|
+
return DYN;
|
|
1931
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;
|
|
1932
2069
|
const elem = lowerer.checker.getTypeArguments(retTs)[0];
|
|
1933
2070
|
// An implicit-any parameter poisons an inferred array result to
|
|
1934
2071
|
// any[] even when this instance's body produces one concrete
|
|
@@ -1939,6 +2076,11 @@ function implicitDeclaredReturn(lowerer, info) {
|
|
|
1939
2076
|
return null;
|
|
1940
2077
|
}
|
|
1941
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;
|
|
1942
2084
|
if (mapped !== null && promiseCarriesDyn(lowerer, mapped) && !hasExplicitJsDocReturn(info.decl))
|
|
1943
2085
|
return null;
|
|
1944
2086
|
return mapped;
|
|
@@ -1970,6 +2112,30 @@ function bindableImplicitIr(t) {
|
|
|
1970
2112
|
t.kind !== "void" && t.kind !== "dyn" && t.kind !== "jsval" &&
|
|
1971
2113
|
t.kind !== "caught" && t.kind !== "undefinedT" && t.kind !== "nullT");
|
|
1972
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
|
+
}
|
|
1973
2139
|
/** The instance a CALL of an implicit-any function-like names: each
|
|
1974
2140
|
* bindable implicit param takes the call's WIDENED argument checker type
|
|
1975
2141
|
* when it maps statically (DYN otherwise — today's slot), typed params
|
|
@@ -1992,19 +2158,52 @@ export function implicitCallInstance(lowerer, call, info) {
|
|
|
1992
2158
|
bound = declared.type;
|
|
1993
2159
|
const arg = call.arguments[i];
|
|
1994
2160
|
if (arg && !ts.isSpreadElement(arg)) {
|
|
1995
|
-
const
|
|
1996
|
-
if (
|
|
2161
|
+
const stored = storedImplicitArgumentType(lowerer, arg);
|
|
2162
|
+
if (stored?.kind === "dyn") {
|
|
1997
2163
|
bound = DYN;
|
|
1998
2164
|
argTypes.set(sym, lowerer.checker.getUnknownType());
|
|
1999
2165
|
shapes.push({ type: bound, mode: "required" });
|
|
2000
2166
|
return;
|
|
2001
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
|
+
}
|
|
2002
2176
|
// The argument's own checker type, literal-widened ('add' binds
|
|
2003
2177
|
// string) — typeOf consults the ACTIVE instance's bindings, so a
|
|
2004
2178
|
// bound param forwarded into another implicit call transitively
|
|
2005
2179
|
// instantiates it (this._initCommandGroup(command)).
|
|
2006
2180
|
const t = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(arg));
|
|
2007
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
|
+
}
|
|
2008
2207
|
if (ts.isArrowFunction(arg) &&
|
|
2009
2208
|
arg.type === undefined &&
|
|
2010
2209
|
mapped?.kind === "func" &&
|
|
@@ -2029,15 +2228,32 @@ export function implicitCallInstance(lowerer, call, info) {
|
|
|
2029
2228
|
/** The all-dyn DEFAULT instance — today's compiled body exactly: what a
|
|
2030
2229
|
* VALUE reference of an implicit-any function names (indirect calls
|
|
2031
2230
|
* carry no per-site types to bind). */
|
|
2032
|
-
function implicitDefaultInstance(lowerer, blame, info) {
|
|
2231
|
+
export function implicitDefaultInstance(lowerer, blame, info) {
|
|
2033
2232
|
const shapes = info.decl.parameters.map((param, i) => info.implicitParams[i] ? { type: DYN, mode: "required" } : lowerer.paramShape(param));
|
|
2034
|
-
|
|
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);
|
|
2035
2244
|
}
|
|
2036
2245
|
function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
2037
2246
|
const key = shapes.map((s) => typeKey(s.type)).join(",");
|
|
2038
2247
|
let inst = info.instances.get(key);
|
|
2039
|
-
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;
|
|
2040
2255
|
return inst;
|
|
2256
|
+
}
|
|
2041
2257
|
if (info.instances.size >= MAX_GENERIC_INSTANCES) {
|
|
2042
2258
|
lowerer.unsupported("SC1090", blame, `unbounded implicit-any instantiation ('${info.baseName}' exceeded ` +
|
|
2043
2259
|
`${MAX_GENERIC_INSTANCES} instances — polymorphic recursion?)`);
|
|
@@ -2063,11 +2279,15 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
|
2063
2279
|
...(declared === null ? { implicitInferReturn: true } : {}),
|
|
2064
2280
|
};
|
|
2065
2281
|
info.instances.set(key, inst);
|
|
2066
|
-
//
|
|
2067
|
-
//
|
|
2068
|
-
//
|
|
2069
|
-
|
|
2070
|
-
//
|
|
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;
|
|
2071
2291
|
try {
|
|
2072
2292
|
// Implicit-any instances lower EAGERLY at the call site so their
|
|
2073
2293
|
// inferred return type is available immediately. They therefore do
|
|
@@ -2085,8 +2305,20 @@ function internImplicitInstance(lowerer, blame, info, shapes, argTypes) {
|
|
|
2085
2305
|
catch (e) {
|
|
2086
2306
|
if (!(e instanceof PoisonError))
|
|
2087
2307
|
throw e;
|
|
2088
|
-
inst.implicitState = "
|
|
2089
|
-
|
|
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;
|
|
2090
2322
|
}
|
|
2091
2323
|
inst.implicitState = "done";
|
|
2092
2324
|
return inst;
|
|
@@ -2192,11 +2424,11 @@ export function implicitLocalFnInfoOf(lowerer, decl, fnNode) {
|
|
|
2192
2424
|
const implicit = implicitAnyParamSymbolsOf(lowerer, fnNode);
|
|
2193
2425
|
if (!implicit)
|
|
2194
2426
|
lowerer.unsupported("SC1090", fnNode, "this function form"); // defensive: the probe proved it
|
|
2195
|
-
const stmt = decl.parent
|
|
2427
|
+
const stmt = decl.parent?.parent;
|
|
2196
2428
|
const info = {
|
|
2197
2429
|
decl: fnNode,
|
|
2198
2430
|
baseName: name,
|
|
2199
|
-
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()}`),
|
|
2200
2432
|
typeParams: [],
|
|
2201
2433
|
instances: new Map(),
|
|
2202
2434
|
implicitParams: implicit,
|
|
@@ -2407,6 +2639,7 @@ function makeTimerArgsThunk(lowerer, cbNode, argNodes, what, loc) {
|
|
|
2407
2639
|
kind: "dynCall",
|
|
2408
2640
|
callee: { kind: "varRef", localId: "f.0", type: DYN, loc },
|
|
2409
2641
|
calleeName: "callback",
|
|
2642
|
+
receiver: { kind: "libCall", fn: "dyn.this", args: [], type: DYN, loc },
|
|
2410
2643
|
args: args.map((_, i) => ({ kind: "varRef", localId: `a${i}.0`, type: DYN, loc })),
|
|
2411
2644
|
type: DYN,
|
|
2412
2645
|
loc,
|
|
@@ -2571,7 +2804,12 @@ export function lowerTimersMemberCall(lowerer, expr, member, loc) {
|
|
|
2571
2804
|
return null;
|
|
2572
2805
|
}
|
|
2573
2806
|
function ffiSourceParams(binding) {
|
|
2574
|
-
|
|
2807
|
+
const params = [];
|
|
2808
|
+
for (const param of binding.params) {
|
|
2809
|
+
if (!isFfiContextParam(param))
|
|
2810
|
+
params.push(param);
|
|
2811
|
+
}
|
|
2812
|
+
return params;
|
|
2575
2813
|
}
|
|
2576
2814
|
function ffiParamDisplay(param) {
|
|
2577
2815
|
return isFfiCallbackParam(param)
|
|
@@ -2588,7 +2826,11 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2588
2826
|
const signatures = lowerer.checker.getCallSignatures(callbackType);
|
|
2589
2827
|
if (signatures.length !== 1)
|
|
2590
2828
|
return null;
|
|
2591
|
-
const nativeParams =
|
|
2829
|
+
const nativeParams = [];
|
|
2830
|
+
for (const param of descriptor.callback.params) {
|
|
2831
|
+
if (!isFfiContextParam(param))
|
|
2832
|
+
nativeParams.push(param);
|
|
2833
|
+
}
|
|
2592
2834
|
let nativeIndex = 0;
|
|
2593
2835
|
const params = signatures[0].getParameters();
|
|
2594
2836
|
for (let i = 0; i < params.length; i++) {
|
|
@@ -2606,12 +2848,13 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2606
2848
|
}
|
|
2607
2849
|
if (nativeClass === "bytes")
|
|
2608
2850
|
continue;
|
|
2609
|
-
const
|
|
2851
|
+
const wide = nativeClass === "i64" || nativeClass === "u64" || nativeClass === "pointer";
|
|
2852
|
+
const domain = wide ? "bigint" : nativeClass === "bool"
|
|
2610
2853
|
? "boolean"
|
|
2611
2854
|
: nativeClass === "cstring" || nativeClass === "string"
|
|
2612
2855
|
? "string"
|
|
2613
2856
|
: "number";
|
|
2614
|
-
const coversDomain = nativeClass === "bool"
|
|
2857
|
+
const coversDomain = wide ? (paramType.flags & ts.TypeFlags.BigInt) !== 0 : nativeClass === "bool"
|
|
2615
2858
|
? (paramType.flags & ts.TypeFlags.Boolean) !== 0
|
|
2616
2859
|
: nativeClass === "cstring" || nativeClass === "string"
|
|
2617
2860
|
? (paramType.flags & ts.TypeFlags.String) !== 0
|
|
@@ -2634,8 +2877,9 @@ function ffiCallbackInputDiagnostic(lowerer, descriptor, callbackType) {
|
|
|
2634
2877
|
function ffiReturnDomainDiagnostic(lowerer, nativeClass, returnType) {
|
|
2635
2878
|
if (nativeClass === "void")
|
|
2636
2879
|
return null;
|
|
2637
|
-
const
|
|
2638
|
-
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"
|
|
2639
2883
|
? (returnType.flags & ts.TypeFlags.Boolean) !== 0
|
|
2640
2884
|
: (returnType.flags & ts.TypeFlags.Number) !== 0;
|
|
2641
2885
|
return coversDomain
|
|
@@ -2743,7 +2987,7 @@ function libraryCallbackOwnsFile(lowerer, file) {
|
|
|
2743
2987
|
export function validateFfiImports(lowerer) {
|
|
2744
2988
|
const diagnostics = [];
|
|
2745
2989
|
const symbolsByName = new Map();
|
|
2746
|
-
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));
|
|
2747
2991
|
const candidates = new Map();
|
|
2748
2992
|
if (configuredNames.size === 0)
|
|
2749
2993
|
return { diagnostics, symbolsByName };
|
|
@@ -2773,6 +3017,8 @@ export function validateFfiImports(lowerer) {
|
|
|
2773
3017
|
});
|
|
2774
3018
|
}
|
|
2775
3019
|
for (const binding of lowerer.ffiImports) {
|
|
3020
|
+
if (binding.library !== undefined)
|
|
3021
|
+
continue;
|
|
2776
3022
|
const bySymbol = candidates.get(binding.name);
|
|
2777
3023
|
if (bySymbol === undefined || bySymbol.size === 0) {
|
|
2778
3024
|
// A native-manifest binding with no declaration is a broken build
|
|
@@ -2820,6 +3066,8 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2820
3066
|
if (!ts.isIdentifier(expr.expression))
|
|
2821
3067
|
return null;
|
|
2822
3068
|
const binding = lowerer.ffiImportsByName.get(expr.expression.text);
|
|
3069
|
+
if (binding?.library !== undefined)
|
|
3070
|
+
return null;
|
|
2823
3071
|
if (binding === undefined) {
|
|
2824
3072
|
// LIBRARY mode with a declared callback surface: a CALL of a
|
|
2825
3073
|
// program-authored signature-only ambient function that names no
|
|
@@ -2853,7 +3101,8 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2853
3101
|
lowerer.pushDiag(signatureFlavor(binding.name, detail, loc));
|
|
2854
3102
|
throw new PoisonError();
|
|
2855
3103
|
};
|
|
2856
|
-
const symbol = lowerer.resolveValueSymbol(expr.expression)
|
|
3104
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
3105
|
+
if (!symbol)
|
|
2857
3106
|
bindingError("the call has no resolved TypeScript symbol");
|
|
2858
3107
|
if (lowerer.ffiBindingSymbols !== null) {
|
|
2859
3108
|
const validSymbols = lowerer.ffiBindingSymbols.get(binding.name);
|
|
@@ -2936,7 +3185,7 @@ export function lowerFfiCall(lowerer, expr) {
|
|
|
2936
3185
|
}
|
|
2937
3186
|
// An inline function value at a RELEASE site can never match:
|
|
2938
3187
|
// lifted lambdas always carry a captures list (even an empty one),
|
|
2939
|
-
// so
|
|
3188
|
+
// so the backend creates a fresh closure per evaluation of the
|
|
2940
3189
|
// expression — the release argument is a pointer no registration
|
|
2941
3190
|
// holds, a guaranteed runtime trap. Declared functions stay valid
|
|
2942
3191
|
// here — their value is the interned immortal closure (captures
|
|
@@ -3143,6 +3392,18 @@ export function lowerCall(lowerer, expr) {
|
|
|
3143
3392
|
}
|
|
3144
3393
|
const consoleMember = lowerer.consoleCallMember(expr);
|
|
3145
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
|
+
};
|
|
3146
3407
|
// console.log/info/debug write stdout; console.error and console.warn
|
|
3147
3408
|
// are one stream in Node (warn IS error, info and debug ARE log) and
|
|
3148
3409
|
// write stderr with the exact same formatting. Node's formatter is
|
|
@@ -3164,13 +3425,13 @@ export function lowerCall(lowerer, expr) {
|
|
|
3164
3425
|
(ts.isStringLiteral(expr.arguments[0]) || ts.isNoSubstitutionTemplateLiteral(expr.arguments[0])) &&
|
|
3165
3426
|
/%[sdifjoOc%]/.test(expr.arguments[0].text)) {
|
|
3166
3427
|
const formatted = lowerFormatCall(lowerer, expr, loc, false);
|
|
3167
|
-
return {
|
|
3428
|
+
return withReceiver({
|
|
3168
3429
|
kind: "intrinsic",
|
|
3169
3430
|
name: stdoutMember ? "console.log" : "console.error",
|
|
3170
3431
|
args: [formatted],
|
|
3171
3432
|
type: VOID,
|
|
3172
3433
|
loc,
|
|
3173
|
-
};
|
|
3434
|
+
});
|
|
3174
3435
|
}
|
|
3175
3436
|
const args = expr.arguments.map((a) => {
|
|
3176
3437
|
const lowered = lowerer.lowerExpr(a);
|
|
@@ -3231,13 +3492,13 @@ export function lowerCall(lowerer, expr) {
|
|
|
3231
3492
|
// render fence honestly with the reason.
|
|
3232
3493
|
return lowerConsoleInspectArg(lowerer, a, lowered, surface, loc);
|
|
3233
3494
|
});
|
|
3234
|
-
return {
|
|
3495
|
+
return withReceiver({
|
|
3235
3496
|
kind: "intrinsic",
|
|
3236
3497
|
name: stdoutMember ? "console.log" : "console.error",
|
|
3237
3498
|
args,
|
|
3238
3499
|
type: VOID,
|
|
3239
3500
|
loc,
|
|
3240
|
-
};
|
|
3501
|
+
});
|
|
3241
3502
|
}
|
|
3242
3503
|
// The timer globals — setTimeout/clearTimeout, setInterval/
|
|
3243
3504
|
// clearInterval, setImmediate/clearImmediate. Provenance-checked (a
|
|
@@ -3388,25 +3649,12 @@ export function lowerCall(lowerer, expr) {
|
|
|
3388
3649
|
lowerer.noLowering(`BigInt with ${expr.arguments.length} arguments`, expr);
|
|
3389
3650
|
}
|
|
3390
3651
|
const argNode = expr.arguments[0];
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
if (arg.type.kind === "f64") {
|
|
3398
|
-
return { kind: "libCall", fn: "bigint.fromF64", args: [arg], type: BIGINT_T, loc };
|
|
3399
|
-
}
|
|
3400
|
-
if (arg.type.kind === "bool") {
|
|
3401
|
-
return {
|
|
3402
|
-
kind: "ternary",
|
|
3403
|
-
cond: arg,
|
|
3404
|
-
then: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "1", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3405
|
-
else_: { kind: "libCall", fn: "bigint.parse", args: [{ kind: "strLit", value: "0", type: STRING, loc }], type: BIGINT_T, loc },
|
|
3406
|
-
type: BIGINT_T,
|
|
3407
|
-
loc,
|
|
3408
|
-
};
|
|
3409
|
-
}
|
|
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;
|
|
3410
3658
|
lowerer.noLowering(`BigInt of ${lowerer.fmt(arg.type)} values`, argNode, "string, number, boolean, and bigint arguments are supported");
|
|
3411
3659
|
}
|
|
3412
3660
|
if (ts.isIdentifier(expr.expression) &&
|
|
@@ -3444,6 +3692,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
3444
3692
|
if (name === "Number")
|
|
3445
3693
|
return lowerNumberConstructorValue(lowerer, argNode, loc);
|
|
3446
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
|
+
}
|
|
3447
3698
|
if (name === "String")
|
|
3448
3699
|
return lowerer.ensureString(arg, argNode);
|
|
3449
3700
|
}
|
|
@@ -3461,6 +3712,29 @@ export function lowerCall(lowerer, expr) {
|
|
|
3461
3712
|
const code = lowerer.lowerExprExpecting(expr.arguments[0], STRING);
|
|
3462
3713
|
return { kind: "libCall", fn: "island.eval", args: [code], type: STRING, loc };
|
|
3463
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
|
+
}
|
|
3464
3738
|
// Island calls. A property-access callee whose receiver is an 'any'
|
|
3465
3739
|
// value is an engine method call (this = receiver, JS-exact); any other
|
|
3466
3740
|
// 'any'-typed callee is an engine function call. Arguments marshal in;
|
|
@@ -4059,6 +4333,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4059
4333
|
let callee = lowerer.lowerExpr(nsMember);
|
|
4060
4334
|
if (callee.type.kind === "record")
|
|
4061
4335
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
4336
|
+
const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
|
|
4337
|
+
if (checked)
|
|
4338
|
+
return checked;
|
|
4062
4339
|
if (callee.type.kind !== "func")
|
|
4063
4340
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
4064
4341
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
@@ -4112,6 +4389,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4112
4389
|
let callee = lowerer.lowerExpr(nameId);
|
|
4113
4390
|
if (callee.type.kind === "record")
|
|
4114
4391
|
callee = lowerer.hybridCallUnwrap(callee);
|
|
4392
|
+
const checked = lowerCheckedCallableValue(lowerer, expr, callee, loc);
|
|
4393
|
+
if (checked)
|
|
4394
|
+
return checked;
|
|
4115
4395
|
if (callee.type.kind !== "func")
|
|
4116
4396
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
4117
4397
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
@@ -4191,6 +4471,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4191
4471
|
// TestContext surface (t.test/t.skip/t.diagnostic), t.assert.*.
|
|
4192
4472
|
lowerer.lowerTestMethodCall(expr, expr.expression) ??
|
|
4193
4473
|
lowerer.lowerTimeoutMethodCall(expr, expr.expression) ??
|
|
4474
|
+
lowerArrayPrototypeBorrowCall(lowerer, expr, expr.expression) ??
|
|
4194
4475
|
lowerObjectOwnPrototypeCall(lowerer, expr, expr.expression) ??
|
|
4195
4476
|
lowerObjectPrototypeCall(lowerer, expr, expr.expression) ??
|
|
4196
4477
|
lowerStringPrototypeCall(lowerer, expr, expr.expression) ??
|
|
@@ -4198,6 +4479,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4198
4479
|
// Typed-array/Buffer receivers and the Buffer statics — before the
|
|
4199
4480
|
// island path (bytes never cross the boundary).
|
|
4200
4481
|
lowerer.lowerBytesMethodCall(expr, expr.expression) ??
|
|
4482
|
+
lowerBytesStaticCall(lowerer, expr, expr.expression) ??
|
|
4201
4483
|
lowerBufferStaticCallWithNarrowedArg(lowerer, expr, expr.expression) ??
|
|
4202
4484
|
// URL.revokeObjectURL's zero-argument contract (the one-argument
|
|
4203
4485
|
// form keeps the fence — createObjectURL does too).
|
|
@@ -4265,8 +4547,8 @@ export function lowerCall(lowerer, expr) {
|
|
|
4265
4547
|
lowerArrayFromCall(lowerer, expr, expr.expression) ??
|
|
4266
4548
|
lowerArrayOfCall(lowerer, expr, expr.expression) ??
|
|
4267
4549
|
lowerer.lowerArrayMethodCall(expr, expr.expression) ??
|
|
4268
|
-
//
|
|
4269
|
-
//
|
|
4550
|
+
// Tuple reads preserve the receiver through argument evaluation;
|
|
4551
|
+
// callbacks read each position when visited.
|
|
4270
4552
|
lowerTupleReadMethodCall(lowerer, expr, expr.expression) ??
|
|
4271
4553
|
lowerGenMethodCall(lowerer, expr, expr.expression) ??
|
|
4272
4554
|
lowerer.lowerMapMethodCall(expr, expr.expression) ??
|
|
@@ -4281,6 +4563,18 @@ export function lowerCall(lowerer, expr) {
|
|
|
4281
4563
|
lowerObjLitGenericMethodCall(lowerer, expr, expr.expression);
|
|
4282
4564
|
if (intrinsic)
|
|
4283
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
|
+
}
|
|
4284
4578
|
// A method call rooted at an initializer-less ambient `declare
|
|
4285
4579
|
// const/var` whose declared type has no mapping: Node throws the
|
|
4286
4580
|
// catchable ReferenceError at the ROOT read before the member, the
|
|
@@ -4330,6 +4624,9 @@ export function lowerCall(lowerer, expr) {
|
|
|
4330
4624
|
// The element spelling of an unsupported native Web method must fence
|
|
4331
4625
|
// before lowering the callee into a checked-dynamic keyed read.
|
|
4332
4626
|
if (ts.isElementAccessExpression(expr.expression)) {
|
|
4627
|
+
const symbolMethod = lowerClassSymbolMethodCall(lowerer, expr);
|
|
4628
|
+
if (symbolMethod)
|
|
4629
|
+
return symbolMethod;
|
|
4333
4630
|
const headersIterator = lowerer.lowerDynamicHeadersIteratorCall(expr, expr.expression);
|
|
4334
4631
|
if (headersIterator)
|
|
4335
4632
|
return headersIterator;
|
|
@@ -4345,8 +4642,41 @@ export function lowerCall(lowerer, expr) {
|
|
|
4345
4642
|
if (ts.isElementAccessExpression(expr.expression) &&
|
|
4346
4643
|
!expr.expression.questionDotToken &&
|
|
4347
4644
|
!expr.questionDotToken &&
|
|
4348
|
-
ts.isStringLiteralLike(expr.expression.argumentExpression)) {
|
|
4349
|
-
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
|
+
}
|
|
4350
4680
|
// ts7's getSymbolAtLocation does not resolve element accesses; the
|
|
4351
4681
|
// member symbol comes from the receiver's (apparent) type instead —
|
|
4352
4682
|
// same provenance answer as the dot spelling's name symbol.
|
|
@@ -4444,7 +4774,7 @@ export function lowerCall(lowerer, expr) {
|
|
|
4444
4774
|
// JS arity exactly (the thunk ignores extras). Result dyn, checked
|
|
4445
4775
|
// per use like every any-origin value.
|
|
4446
4776
|
if ((expr.arguments.length > callee.type.params.length || callee.type.rest === true) &&
|
|
4447
|
-
isJsSourceFile(expr.getSourceFile()) &&
|
|
4777
|
+
(isJsSourceFile(expr.getSourceFile()) || callee.type.rest === true && callee.type.restAbi === undefined) &&
|
|
4448
4778
|
!expr.arguments.some((a) => ts.isSpreadElement(a)) &&
|
|
4449
4779
|
canBoxFuncIntoDyn(callee.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
4450
4780
|
const args = expr.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
@@ -4455,6 +4785,29 @@ export function lowerCall(lowerer, expr) {
|
|
|
4455
4785
|
const args = completeFuncValueArgs(lowerer, expr, callee.type, loc);
|
|
4456
4786
|
return { kind: "callValue", callee, args, type: callee.type.ret, loc };
|
|
4457
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
|
+
}
|
|
4458
4811
|
function lowerRegexMethodCallWithOptionalArg(lowerer, call, access) {
|
|
4459
4812
|
const lowered = lowerer.lowerRegexMethodCall(call, access);
|
|
4460
4813
|
if (lowered?.kind !== "regexIntrinsic" || lowered.method !== "test" || call.arguments.length !== 1)
|
|
@@ -4476,9 +4829,13 @@ function optionalCallValue(lowerer, node) {
|
|
|
4476
4829
|
return lowerer.runtimeOptionalIdentifierValue(node)?.value ?? lowerAbsenceProbe(lowerer, node);
|
|
4477
4830
|
}
|
|
4478
4831
|
function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
|
|
4479
|
-
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;
|
|
4480
4837
|
if (lowered?.kind !== "bytesNew" || !lowered.source || lowered.source.type.kind !== "union")
|
|
4481
|
-
return
|
|
4838
|
+
return result;
|
|
4482
4839
|
// A callback can store a wider union than the checker sees at this use
|
|
4483
4840
|
// (including an added undefined arm). Extract the exact arm proven by
|
|
4484
4841
|
// control-flow narrowing, not merely the union with undefined removed.
|
|
@@ -4494,10 +4851,11 @@ function lowerBufferStaticCallWithNarrowedArg(lowerer, call, access) {
|
|
|
4494
4851
|
if (!helper) {
|
|
4495
4852
|
lowerer.unsupported("SC1090", call.arguments[0], "a Buffer constructor argument whose narrowed type is not a stored source arm");
|
|
4496
4853
|
}
|
|
4497
|
-
|
|
4854
|
+
const narrowedValue = {
|
|
4498
4855
|
...lowered,
|
|
4499
4856
|
source: { kind: "call", callee: helper, args: [lowered.source], type: narrowed, loc: lowered.source.loc },
|
|
4500
4857
|
};
|
|
4858
|
+
return branded ? { ...branded, args: [narrowedValue] } : narrowedValue;
|
|
4501
4859
|
}
|
|
4502
4860
|
function lowerOptionalNumberDefault(lowerer, value, dflt, loc) {
|
|
4503
4861
|
const widened = lowerer.runtimeOptionalWidening(value.type, F64);
|
|
@@ -4552,6 +4910,8 @@ function lowerStringMethodCallWithOptionalArgs(lowerer, call, access, receiver,
|
|
|
4552
4910
|
? [1]
|
|
4553
4911
|
: [];
|
|
4554
4912
|
for (const index of zeroDefaultArgs) {
|
|
4913
|
+
if (index === undefined)
|
|
4914
|
+
continue;
|
|
4555
4915
|
const value = args[index];
|
|
4556
4916
|
if (!value)
|
|
4557
4917
|
continue;
|
|
@@ -4597,6 +4957,8 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
|
|
|
4597
4957
|
}
|
|
4598
4958
|
if (arg.type.kind === "string")
|
|
4599
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 };
|
|
4600
4962
|
const optionalNumber = lowerOptionalStringNumber(lowerer, arg, loc);
|
|
4601
4963
|
if (optionalNumber)
|
|
4602
4964
|
return optionalNumber;
|
|
@@ -4607,6 +4969,61 @@ function lowerNumberConstructorValue(lowerer, argNode, loc) {
|
|
|
4607
4969
|
? "unions of numbers, booleans, strings, null, and undefined lower — narrow other arms first"
|
|
4608
4970
|
: undefined);
|
|
4609
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
|
+
}
|
|
4610
5027
|
function immediatePrimitiveWrapperToString(lowerer, node) {
|
|
4611
5028
|
const stringValue = stringWrapperToString(lowerer, node);
|
|
4612
5029
|
if (stringValue)
|
|
@@ -4629,24 +5046,6 @@ function immediatePrimitiveWrapperToString(lowerer, node) {
|
|
|
4629
5046
|
: args.length ? lowerNumberConstructorValue(lowerer, args[0], loc) : { kind: "numLit", value: 0, type: F64, loc };
|
|
4630
5047
|
return lowerer.ensureString(primitive, wrapped);
|
|
4631
5048
|
}
|
|
4632
|
-
function plainObjectCoercionReceiver(lowerer, node) {
|
|
4633
|
-
const plainLiteral = (literal) => literal.properties.every((prop) => ts.isPropertyAssignment(prop) &&
|
|
4634
|
-
(ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) || ts.isNumericLiteral(prop.name)) &&
|
|
4635
|
-
prop.name.text !== "__proto__");
|
|
4636
|
-
let value = node;
|
|
4637
|
-
while (ts.isParenthesizedExpression(value))
|
|
4638
|
-
value = value.expression;
|
|
4639
|
-
if (ts.isObjectLiteralExpression(value))
|
|
4640
|
-
return plainLiteral(value);
|
|
4641
|
-
if (!ts.isIdentifier(value))
|
|
4642
|
-
return false;
|
|
4643
|
-
const symbol = lowerer.resolveValueSymbol(value);
|
|
4644
|
-
const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
|
|
4645
|
-
if (!symbol || !decl || !ts.isVariableDeclaration(decl) || !decl.initializer ||
|
|
4646
|
-
!ts.isObjectLiteralExpression(decl.initializer) || !plainLiteral(decl.initializer))
|
|
4647
|
-
return false;
|
|
4648
|
-
return bindingNeverReassigned(lowerer, symbol, decl);
|
|
4649
|
-
}
|
|
4650
5049
|
function objectToStringTag(lowerer, type) {
|
|
4651
5050
|
switch (type.kind) {
|
|
4652
5051
|
case "undefinedT":
|
|
@@ -4667,7 +5066,7 @@ function objectToStringTag(lowerer, type) {
|
|
|
4667
5066
|
case "set": return "Set";
|
|
4668
5067
|
case "promise": return "Promise";
|
|
4669
5068
|
case "bytes":
|
|
4670
|
-
return
|
|
5069
|
+
return BYTES_ELEMENT_NAME[type.elem];
|
|
4671
5070
|
case "object":
|
|
4672
5071
|
return type.className === "%Error" || lowerer.isSubclassOf(type.className, "%Error") ? "Error" : null;
|
|
4673
5072
|
default: return null;
|
|
@@ -4689,6 +5088,10 @@ function immediateObjectTagReceiver(lowerer, node) {
|
|
|
4689
5088
|
lowerer.isStdlibSymbol(lowerer.resolveValueSymbol(value.expression) ?? undefined)) {
|
|
4690
5089
|
const name = value.expression.text;
|
|
4691
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) };
|
|
4692
5095
|
if (args.length <= 1 && !args.some(ts.isSpreadElement)) {
|
|
4693
5096
|
if (name === "String") {
|
|
4694
5097
|
const effect = stringWrapperToString(lowerer, value);
|
|
@@ -4736,6 +5139,36 @@ function immediateObjectTagReceiver(lowerer, node) {
|
|
|
4736
5139
|
}
|
|
4737
5140
|
return null;
|
|
4738
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
|
+
}
|
|
4739
5172
|
function lowerObjectOwnPrototypeCall(lowerer, call, access) {
|
|
4740
5173
|
if (lowerer.dynamic || access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
|
|
4741
5174
|
return null;
|
|
@@ -4754,10 +5187,31 @@ function lowerObjectOwnMethodCall(lowerer, call, access) {
|
|
|
4754
5187
|
const method = access.name.text;
|
|
4755
5188
|
if (lowerer.dynamic || call.questionDotToken || access.questionDotToken ||
|
|
4756
5189
|
(method !== "hasOwnProperty" && method !== "propertyIsEnumerable") ||
|
|
4757
|
-
|
|
5190
|
+
call.arguments.some(ts.isSpreadElement))
|
|
4758
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
|
+
}
|
|
4759
5197
|
return lowerObjectOwnCall(lowerer, call, access.expression, call.arguments[0], call.arguments.slice(1), method);
|
|
4760
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
|
+
}
|
|
4761
5215
|
function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, method) {
|
|
4762
5216
|
const enumerable = method === "propertyIsEnumerable";
|
|
4763
5217
|
const loc = locOf(call);
|
|
@@ -4790,14 +5244,18 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
|
|
|
4790
5244
|
stmts.push({ kind: "exprStmt", expr: effect, loc: locOf(extra) });
|
|
4791
5245
|
}
|
|
4792
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
|
+
}
|
|
4793
5251
|
if (!keyNode || rawKey?.type.kind === "undefinedT" || rawKey?.type.kind === "void") {
|
|
4794
5252
|
key = { kind: "strLit", value: "undefined", type: STRING, loc };
|
|
4795
5253
|
}
|
|
4796
5254
|
else if (rawKey?.type.kind === "nullT") {
|
|
4797
5255
|
key = { kind: "strLit", value: "null", type: STRING, loc };
|
|
4798
5256
|
}
|
|
4799
|
-
else if (key
|
|
4800
|
-
key =
|
|
5257
|
+
else if (key) {
|
|
5258
|
+
key = ownPropertyKey(lowerer, key);
|
|
4801
5259
|
}
|
|
4802
5260
|
if (!key || key.type.kind !== "string") {
|
|
4803
5261
|
lowerer.noLowering("Object.prototype." + method + " with this property key", keyNode ?? call);
|
|
@@ -4809,13 +5267,13 @@ function lowerObjectOwnCall(lowerer, call, receiverNode, keyNode, extraNodes, me
|
|
|
4809
5267
|
}
|
|
4810
5268
|
else if (type.kind === "record") {
|
|
4811
5269
|
const shape = lowerer.shapes.get(type.shapeId);
|
|
4812
|
-
if (!shape || shape.tuple ||
|
|
5270
|
+
if (!shape || shape.tuple || shapeHasAccessorSlots(shape)) {
|
|
4813
5271
|
lowerer.noLowering("Object.prototype." + method + " over this record shape", receiverNode ?? call);
|
|
4814
5272
|
}
|
|
4815
5273
|
result = { kind: "call", callee: recordHasOwnHelper(lowerer, type.shapeId, loc), args: [receiverRef, key], type: BOOL, loc };
|
|
4816
5274
|
}
|
|
4817
|
-
else if (type.kind === "dyn"
|
|
4818
|
-
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 };
|
|
4819
5277
|
}
|
|
4820
5278
|
else if (type.kind === "string" || type.kind === "array") {
|
|
4821
5279
|
const needleLocal = lowerer.declareHiddenLocal("%ownIndex", F64);
|
|
@@ -4884,6 +5342,52 @@ function lowerObjectPrototypeCall(lowerer, call, access) {
|
|
|
4884
5342
|
: { kind: "strLit", value: "[object " + tag + "]", type: STRING, loc };
|
|
4885
5343
|
return { kind: "seqExpr", stmts, result, type: STRING, loc };
|
|
4886
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
|
+
}
|
|
4887
5391
|
function lowerStringPrototypeCall(lowerer, call, access) {
|
|
4888
5392
|
if (access.name.text !== "call" || !ts.isPropertyAccessExpression(access.expression))
|
|
4889
5393
|
return null;
|
|
@@ -4926,6 +5430,9 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4926
5430
|
loc,
|
|
4927
5431
|
};
|
|
4928
5432
|
}
|
|
5433
|
+
if (receiverType.kind === "dyn") {
|
|
5434
|
+
return lowerDynamicStringPrototypeCall(lowerer, call, methodAccess, receiverValue, method);
|
|
5435
|
+
}
|
|
4929
5436
|
const padding = entry?.method === "padStart" || entry?.method === "padEnd";
|
|
4930
5437
|
const scalar = receiverType.kind === "string" || receiverType.kind === "f64" ||
|
|
4931
5438
|
receiverType.kind === "bool" || receiverType.kind === "bigint" ||
|
|
@@ -4934,10 +5441,8 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4934
5441
|
// padding uses a helper that delays conversion until every argument is ready.
|
|
4935
5442
|
const objectWithoutMethodArgs = entry?.maxArgs === 0 && call.arguments.length === 1 &&
|
|
4936
5443
|
(receiverType.kind === "record" || receiverType.kind === "array" || receiverType.kind === "object");
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
if (!scalar && !objectWithoutMethodArgs && !dynObjectWithoutMethodArgs && !(padding && receiverType.kind === "dyn")) {
|
|
4940
|
-
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);
|
|
4941
5446
|
}
|
|
4942
5447
|
if (indexMethod)
|
|
4943
5448
|
return lowerStringIndexCall(lowerer, call, indexMethod, receiverValue, receiverNode, call.arguments.slice(1));
|
|
@@ -4949,9 +5454,7 @@ function lowerStringPrototypeCall(lowerer, call, access) {
|
|
|
4949
5454
|
if (entry.method === "split") {
|
|
4950
5455
|
return lowerStringSplitCall(lowerer, call, receiverValue, receiverNode, call.arguments.slice(1));
|
|
4951
5456
|
}
|
|
4952
|
-
const receiver =
|
|
4953
|
-
? { kind: "libCall", fn: "dyn.toStringCoerce", args: [receiverValue], type: STRING, loc }
|
|
4954
|
-
: lowerer.ensureString(receiverValue, receiverNode);
|
|
5457
|
+
const receiver = lowerer.ensureString(receiverValue, receiverNode);
|
|
4955
5458
|
return lowerStringMethodCallWithOptionalArgs(lowerer, call, methodAccess, () => receiver, call.arguments.slice(1));
|
|
4956
5459
|
}
|
|
4957
5460
|
function lowerScalarUnionNumber(lowerer, arg, node, loc) {
|
|
@@ -5125,13 +5628,18 @@ function spreadNeedsRuntimeArity(lowerer, shapes, argNodes) {
|
|
|
5125
5628
|
position += tuple.fields.length;
|
|
5126
5629
|
continue;
|
|
5127
5630
|
}
|
|
5128
|
-
if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest")
|
|
5129
|
-
return
|
|
5631
|
+
if (restAt < 0 || position < restAt || shapes[restAt].mode !== "rest") {
|
|
5632
|
+
return !canCompleteRuntimeSpread(lowerer, shapes);
|
|
5633
|
+
}
|
|
5130
5634
|
}
|
|
5131
5635
|
position++;
|
|
5132
5636
|
}
|
|
5133
5637
|
return false;
|
|
5134
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
|
+
}
|
|
5135
5643
|
/** METHOD calls on dyn receivers (`pkg.name.replace(...)`, `rawName.split`,
|
|
5136
5644
|
* `ws.packages.filter(...)` — JSON.parse-derived values): validate the
|
|
5137
5645
|
* receiver's dyn kind, extract, and ride the STATIC method machinery — the
|
|
@@ -5169,6 +5677,27 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5169
5677
|
// tsc types the return by the evolved shape, the binding lowered
|
|
5170
5678
|
// dyn): probe the lowering and claim exactly the dyn results.
|
|
5171
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
|
+
}
|
|
5172
5701
|
if (probed?.type.kind !== "dyn")
|
|
5173
5702
|
return null;
|
|
5174
5703
|
recv = probed;
|
|
@@ -5176,11 +5705,30 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5176
5705
|
// A checker-`any` receiver that already lowered to a real STRING (the
|
|
5177
5706
|
// chained form — `cfg.host.trim().toLowerCase()`, where the first step
|
|
5178
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
|
+
}
|
|
5179
5713
|
if (recv.type.kind === "string") {
|
|
5180
5714
|
return lowerRegexMethodCall(lowerer, call, access, () => recv) ?? lowerStringMethodCall(lowerer, call, access, () => recv);
|
|
5181
5715
|
}
|
|
5182
5716
|
if (recv.type.kind !== "dyn")
|
|
5183
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
|
+
})();
|
|
5184
5732
|
// Typed-destination filter first (validated extraction into a real
|
|
5185
5733
|
// T[]); an untyped destination falls through to the runtime dispatch
|
|
5186
5734
|
// below (the survivors stay dyn values).
|
|
@@ -5196,34 +5744,21 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5196
5744
|
// these, "the receiver is a string, or the call throws V8's TypeError"
|
|
5197
5745
|
// IS Node's semantics for every possible dyn value. Shared names would
|
|
5198
5746
|
// need a receiver-kind dispatch — they keep the fence.
|
|
5199
|
-
if (DYN_STRING_ONLY_METHODS.has(access.name.text)) {
|
|
5747
|
+
if (DYN_STRING_ONLY_METHODS.has(access.name.text) && !ownCallable) {
|
|
5200
5748
|
const checked = () => dynStringReceiver(lowerer, recv, access);
|
|
5201
5749
|
return lowerRegexMethodCall(lowerer, call, access, checked) ?? lowerStringMethodCall(lowerer, call, access, checked);
|
|
5202
5750
|
}
|
|
5203
|
-
//
|
|
5204
|
-
//
|
|
5205
|
-
// decode per the encoding — a stream chunk's common consumption —
|
|
5206
|
-
// and strings/numbers/booleans/arrays/objects answer JS-exactly).
|
|
5207
|
-
// The optional argument is a literal encoding (meaningful for bytes;
|
|
5208
|
-
// JS ignores extra toString arguments on the other kinds, and so
|
|
5209
|
-
// 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.
|
|
5210
5753
|
if (access.name.text === "toString" && call.arguments.length <= 1) {
|
|
5211
|
-
const
|
|
5212
|
-
? bufEncoding(lowerer, "toString", call.arguments[0])
|
|
5213
|
-
: "utf8";
|
|
5214
|
-
// The source spelling rides along for the ONE receiver whose
|
|
5215
|
-
// prototype lacks toString: a null-prototype dictionary throws
|
|
5216
|
-
// Node's "<spelling> is not a function" at runtime.
|
|
5754
|
+
const argument = call.arguments[0];
|
|
5217
5755
|
return {
|
|
5218
|
-
kind: "libCall",
|
|
5219
|
-
fn: "dyn.toString",
|
|
5220
|
-
args: [
|
|
5756
|
+
kind: "libCall", fn: "dyn.toString", args: [
|
|
5221
5757
|
recv,
|
|
5222
|
-
|
|
5758
|
+
argument ? lowerer.lowerExprExpecting(argument, DYN)
|
|
5759
|
+
: dynUndefinedExpr(locOf(call)),
|
|
5223
5760
|
{ kind: "strLit", value: access.getText(), type: STRING, loc: locOf(call) },
|
|
5224
|
-
],
|
|
5225
|
-
type: STRING,
|
|
5226
|
-
loc: locOf(call),
|
|
5761
|
+
], type: STRING, loc: locOf(call),
|
|
5227
5762
|
};
|
|
5228
5763
|
}
|
|
5229
5764
|
// SHARED prototype names with a runtime dispatch (scr_dyn_invoke):
|
|
@@ -5254,17 +5789,6 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5254
5789
|
// its name overlaps a primitive prototype (`colors.bold(...)`): the
|
|
5255
5790
|
// source value was compiled from that object shape, while genuinely
|
|
5256
5791
|
// untyped/any receivers retain the runtime-kind ambiguity and fence.
|
|
5257
|
-
const ownCallable = !checkerUntyped && (() => {
|
|
5258
|
-
const prop = lowerer.checker.getPropertyOfType(recvTs, access.name.text);
|
|
5259
|
-
if (prop === undefined)
|
|
5260
|
-
return false;
|
|
5261
|
-
// getPropertyOfType includes inherited Object.prototype members.
|
|
5262
|
-
// Those are not stored members of a checked-dynamic object, so
|
|
5263
|
-
// dynKeyGet cannot stand in for JavaScript's prototype lookup. Only
|
|
5264
|
-
// an authored declaration can justify the own-member path.
|
|
5265
|
-
const authored = lowerer.checker.declarationsOf(prop).some((decl) => !lowerer.isStdlibFile(decl.getSourceFile()));
|
|
5266
|
-
return authored && lowerer.checker.getCallSignatures(lowerer.checker.getTypeOfSymbol(prop)).length > 0;
|
|
5267
|
-
})();
|
|
5268
5792
|
if (DYN_PROTO_METHOD_NAMES.has(access.name.text) && !ownCallable)
|
|
5269
5793
|
return null;
|
|
5270
5794
|
// Optional forms (`obj.cb?.()`, `obj?.cb()`) belong to the chain
|
|
@@ -5275,15 +5799,20 @@ function lowerDynReceiverMethodCall(lowerer, call, access) {
|
|
|
5275
5799
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
5276
5800
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
5277
5801
|
}
|
|
5802
|
+
const receiverLocal = lowerer.declareHiddenLocal("%dynCallReceiver", DYN);
|
|
5803
|
+
const receiver = { kind: "varRef", localId: receiverLocal.id, type: DYN, loc };
|
|
5278
5804
|
const member = {
|
|
5279
5805
|
kind: "dynKeyGet",
|
|
5280
5806
|
key: { kind: "strLit", value: access.name.text, type: STRING, loc: locOf(access) },
|
|
5281
|
-
value:
|
|
5807
|
+
value: receiver,
|
|
5282
5808
|
type: DYN,
|
|
5283
5809
|
loc: locOf(access),
|
|
5284
5810
|
};
|
|
5285
5811
|
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
5286
|
-
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
|
+
};
|
|
5287
5816
|
}
|
|
5288
5817
|
/** Prototype method names of the checked-dynamic tree-representable kinds (String, Array,
|
|
5289
5818
|
* Object, Function, Number prototypes): a dyn receiver call on one of
|
|
@@ -5310,7 +5839,8 @@ const DYN_PROTO_METHOD_NAMES = new Set([
|
|
|
5310
5839
|
* is-not-a-function where the kind's prototype lacks the name, and
|
|
5311
5840
|
* fences LOUDLY on real-but-unimplemented pairs. */
|
|
5312
5841
|
const DYN_DISPATCH_METHODS = new Set([
|
|
5313
|
-
"
|
|
5842
|
+
"segment", "containing", "resolvedOptions", "test", "exec",
|
|
5843
|
+
"apply", "bind", "call",
|
|
5314
5844
|
"push", "pop", "shift", "unshift", "slice", "at",
|
|
5315
5845
|
"indexOf", "lastIndexOf", "includes", "join", "concat", "reverse", "sort",
|
|
5316
5846
|
"forEach", "map", "filter", "some", "every", "find", "findIndex",
|
|
@@ -5328,7 +5858,7 @@ const DYN_DISPATCH_METHODS = new Set([
|
|
|
5328
5858
|
"setEncoding", "setDefaultEncoding", "setTimeout", "read", "isPaused",
|
|
5329
5859
|
"writeHead", "setHeader", "getHeader", "hasHeader", "removeHeader",
|
|
5330
5860
|
"getHeaders", "getHeaderNames", "appendHeader", "flushHeaders",
|
|
5331
|
-
"append", "delete", "get", "getSetCookie", "has", "set",
|
|
5861
|
+
"add", "append", "delete", "get", "getSetCookie", "has", "set",
|
|
5332
5862
|
"writeContinue", "writeEarlyHints", "cork", "uncork", "addTrailers",
|
|
5333
5863
|
"ref", "unref", "address", "setNoDelay", "setKeepAlive", "connect",
|
|
5334
5864
|
"resetAndDestroy", "destroySoon",
|
|
@@ -5366,7 +5896,7 @@ const DYN_DISPATCH_METHODS = new Set([
|
|
|
5366
5896
|
]);
|
|
5367
5897
|
export function lowerDynDispatchMethodCall(lowerer, call, access, recv, arrayReceiver) {
|
|
5368
5898
|
const method = access.name.text;
|
|
5369
|
-
if (!DYN_DISPATCH_METHODS.has(method)
|
|
5899
|
+
if ((!DYN_DISPATCH_METHODS.has(method) && !isJsSourceFile(call.getSourceFile())) || lowerer.chainBlocked(call, access))
|
|
5370
5900
|
return null;
|
|
5371
5901
|
if (call.arguments.some((arg) => ts.isSpreadElement(arg))) {
|
|
5372
5902
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
@@ -5492,7 +6022,8 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
|
|
|
5492
6022
|
// over side-effect-free reads (the operand re-evaluates/drops, the
|
|
5493
6023
|
// `in`-operator fold discipline). dyn/caught/jsval arms have no
|
|
5494
6024
|
// static tag answer and keep the narrow-first fence.
|
|
5495
|
-
const
|
|
6025
|
+
const unionId = arg.type.unionId;
|
|
6026
|
+
const def = lowerer.unions.get(unionId);
|
|
5496
6027
|
const opaque = !def || def.arms.some((a) => a.kind === "dyn" || a.kind === "caught" || a.kind === "jsval");
|
|
5497
6028
|
const arrayTags = lowerer.arrayValueTags(arg.type.unionId);
|
|
5498
6029
|
const freeRead = arg.kind === "varRef" || arg.kind === "recordGet" || arg.kind === "fieldGet";
|
|
@@ -5504,7 +6035,7 @@ function lowerArrayIsArrayCall(lowerer, call, access) {
|
|
|
5504
6035
|
}
|
|
5505
6036
|
if (!opaque && freeRead && arrayTags.length > 1) {
|
|
5506
6037
|
return arrayTags
|
|
5507
|
-
.map((tag) => ({ kind: "unionIsTag", unionId:
|
|
6038
|
+
.map((tag) => ({ kind: "unionIsTag", unionId: unionId, tag, negated: false, value: arg, type: BOOL, loc }))
|
|
5508
6039
|
.reduce((left, right) => ({ kind: "logical", op: "||", left, right, type: BOOL, loc }));
|
|
5509
6040
|
}
|
|
5510
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)`);
|
|
@@ -5725,6 +6256,13 @@ function lowerClassHasOwnPropertyCall(lowerer, call, access) {
|
|
|
5725
6256
|
else
|
|
5726
6257
|
return null; // computed static names — the answer isn't static
|
|
5727
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
|
+
}
|
|
5728
6266
|
return { kind: "boolLit", value: own.has(key), type: BOOL, loc: locOf(call) };
|
|
5729
6267
|
}
|
|
5730
6268
|
/** Side-effect-free receiver test for the CONSTANT primitive-prototype
|
|
@@ -5939,6 +6477,12 @@ function implicitReceiverOverloadReturn(lowerer, expr) {
|
|
|
5939
6477
|
function reconcileOverloadReturn(lowerer, expr, call) {
|
|
5940
6478
|
const rsig = lowerer.checker.getResolvedSignature(expr);
|
|
5941
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
|
+
}
|
|
5942
6486
|
const resolvedOverload = rsig && rdecl &&
|
|
5943
6487
|
(ts.isFunctionDeclaration(rdecl) || ts.isMethodDeclaration(rdecl)) &&
|
|
5944
6488
|
!rdecl.body
|
|
@@ -6145,7 +6689,7 @@ export function lowerTaggedTemplate(lowerer, expr) {
|
|
|
6145
6689
|
}
|
|
6146
6690
|
function loweredTemplateStrings(lowerer, expr, cooked, loc) {
|
|
6147
6691
|
// Normal runtime construction keeps this array aligned with the current
|
|
6148
|
-
// ScrArr layout in
|
|
6692
|
+
// ScrArr layout in the backend. The old static-header IR node encoded the
|
|
6149
6693
|
// pre-sparse layout in LLVM and crashed as soon as a tag read its strings.
|
|
6150
6694
|
const type = arrayOf(STRING);
|
|
6151
6695
|
const key = `templateStringsGlobal:${loc.file}:${expr.template.getStart()}`;
|
|
@@ -6202,7 +6746,7 @@ export function isTopLevelFnSymbol(lowerer, ident) {
|
|
|
6202
6746
|
const decl = symbol ? lowerer.checker.declarationsOf(symbol)[0] : undefined;
|
|
6203
6747
|
return (!!decl &&
|
|
6204
6748
|
ts.isFunctionDeclaration(decl) &&
|
|
6205
|
-
(ts.isSourceFile(decl.parent) || lowerer.nsBlocks.get(decl.parent) === "flattened"));
|
|
6749
|
+
(ts.isSourceFile(decl.parent) || (decl.parent !== undefined && lowerer.nsBlocks.get(decl.parent) === "flattened")));
|
|
6206
6750
|
}
|
|
6207
6751
|
/** Nested `function name(...) {...}`: declare the mutable function binding
|
|
6208
6752
|
* before lowering its body, then initialize it with the lifted closure.
|
|
@@ -6244,6 +6788,22 @@ export function lowerNestedFunctionDecl(lowerer, stmt) {
|
|
|
6244
6788
|
export function lambdaSignature(lowerer, node) {
|
|
6245
6789
|
if (!node.body)
|
|
6246
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
|
+
}
|
|
6247
6807
|
if (node.typeParameters) {
|
|
6248
6808
|
// Generic function-like forms monomorphize only where a static home
|
|
6249
6809
|
// exists: top-level generic function declarations, generic methods
|
|
@@ -6269,8 +6829,8 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6269
6829
|
: lowerer.declaredReturnType(node, node);
|
|
6270
6830
|
ret = lowerer.runtimeOptionalFunctionReturnType(node, ret);
|
|
6271
6831
|
// A contextually-typed arrow/function EXPRESSION whose slot signature
|
|
6272
|
-
// returns a
|
|
6273
|
-
// 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
|
|
6274
6834
|
// an `(n) => Promise<void> | void` field must RETURN that union — the
|
|
6275
6835
|
// body's returns coerce into it per return site (arm values wrap;
|
|
6276
6836
|
// width-coercible records rebuild into their arm — the runJobs
|
|
@@ -6284,6 +6844,9 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6284
6844
|
// returns coerce; the spawn-wrapper ABI still returns a promise).
|
|
6285
6845
|
// jsval-returning bodies stay out (adoption would force validated
|
|
6286
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.
|
|
6287
6850
|
const isAsyncLike = !ts.isMethodDeclaration(node) &&
|
|
6288
6851
|
node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
6289
6852
|
const innerRet = isAsyncLike && ret.kind === "promise" ? ret.inner : ret;
|
|
@@ -6308,8 +6871,8 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6308
6871
|
? lowerer.mapTypeOf(lowerer.checker.getReturnTypeOfSignature(ctxSigs[0]))
|
|
6309
6872
|
: null;
|
|
6310
6873
|
const ctxRet = isAsyncLike && ctxRetRaw?.kind === "promise" ? ctxRetRaw.inner : ctxRetRaw;
|
|
6311
|
-
if (ctxRet?.kind === "union" &&
|
|
6312
|
-
(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))) {
|
|
6313
6876
|
ret = isAsyncLike ? { kind: "promise", inner: ctxRet } : ctxRet;
|
|
6314
6877
|
}
|
|
6315
6878
|
// A VOID slot discards the callback's result (TS's void-returning
|
|
@@ -6329,51 +6892,29 @@ export function lambdaSignature(lowerer, node) {
|
|
|
6329
6892
|
ret = VOID;
|
|
6330
6893
|
}
|
|
6331
6894
|
}
|
|
6895
|
+
ret = lowerer.contextualFunctionReturns.get(node) ?? ret;
|
|
6332
6896
|
// A plain JS function reading `arguments` receives one hidden dyn
|
|
6333
6897
|
// array. With named parameters, the array contains every actual
|
|
6334
6898
|
// argument and only ES modules are admitted: sloppy-mode arguments
|
|
6335
6899
|
// alias named parameters. Arrows inherit the enclosing `arguments`.
|
|
6336
6900
|
const hasRest = shapes.some((s) => s.mode === "rest" || s.mode === "dynRest" || s.mode === "islandRest");
|
|
6337
6901
|
const usesArguments = !hasRest &&
|
|
6338
|
-
(ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) &&
|
|
6902
|
+
(ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) &&
|
|
6339
6903
|
isJsSourceFile(node.getSourceFile()) &&
|
|
6340
6904
|
bodyReadsArguments(node);
|
|
6341
|
-
if (usesArguments
|
|
6342
|
-
if (
|
|
6343
|
-
|
|
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
|
+
}
|
|
6344
6912
|
}
|
|
6345
6913
|
shapes.push({ type: DYN, mode: "arguments" });
|
|
6346
6914
|
}
|
|
6347
6915
|
const funcType = funcTypeFromParamShapes(shapes, ret);
|
|
6348
|
-
if (usesArguments)
|
|
6349
|
-
funcType.rest = true;
|
|
6350
6916
|
return { shapes, funcType };
|
|
6351
6917
|
}
|
|
6352
|
-
/** Does this function's OWN body read `arguments`? Nested plain functions
|
|
6353
|
-
* and methods have their own `arguments` (the walk skips them); arrows
|
|
6354
|
-
* see the enclosing one (the walk descends). Exported for the lowerer's
|
|
6355
|
-
* dynFallbackType: tsgo does not synthesize the `arguments` rest
|
|
6356
|
-
* parameter into inferred signatures (5.9.3 did — its param-count
|
|
6357
|
-
* mismatch was the detector), so the 7 world asks the BODY directly. */
|
|
6358
|
-
export function bodyReadsArguments(fn) {
|
|
6359
|
-
let found = false;
|
|
6360
|
-
if (fn.body === undefined)
|
|
6361
|
-
return false;
|
|
6362
|
-
// Iterative walk (walkPreorder): function bodies can hold pathologically
|
|
6363
|
-
// deep expression chains that a recursive visit would die on.
|
|
6364
|
-
ts.walkPreorder(fn.body, (n) => {
|
|
6365
|
-
if (ts.isIdentifier(n) && n.text === "arguments" && !(ts.isPropertyAccessExpression(n.parent) && n.parent.name === n)) {
|
|
6366
|
-
found = true;
|
|
6367
|
-
return "stop";
|
|
6368
|
-
}
|
|
6369
|
-
if ((ts.isFunctionExpression(n) || ts.isFunctionDeclaration(n) || ts.isMethodDeclaration(n)) &&
|
|
6370
|
-
n !== fn) {
|
|
6371
|
-
return "skip"; // own `arguments` scope
|
|
6372
|
-
}
|
|
6373
|
-
return undefined;
|
|
6374
|
-
});
|
|
6375
|
-
return found;
|
|
6376
|
-
}
|
|
6377
6918
|
/** Lifts an arrow function / function expression / nested declaration /
|
|
6378
6919
|
* object-literal shorthand method to a module-level function and yields
|
|
6379
6920
|
* the `closure` expression creating it. */
|
|
@@ -6421,10 +6962,17 @@ export function lowerLambda(lowerer, node) {
|
|
|
6421
6962
|
lowerer.fnStack.push(fnCtx);
|
|
6422
6963
|
try {
|
|
6423
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
|
+
}
|
|
6424
6972
|
// The synthetic trailing dyn-array param carries `arguments`.
|
|
6425
6973
|
// Parameterized functions receive all actual arguments; zero-param
|
|
6426
6974
|
// functions receive the same array through their rest ABI.
|
|
6427
|
-
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")) {
|
|
6428
6976
|
const argsLocal = lowerer.declareHiddenLocal("%arguments", DYN);
|
|
6429
6977
|
params.push({ localId: argsLocal.id, name: "%arguments", type: DYN });
|
|
6430
6978
|
fnCtx.argumentsLocal = argsLocal;
|
|
@@ -6461,7 +7009,9 @@ export function lowerLambda(lowerer, node) {
|
|
|
6461
7009
|
}
|
|
6462
7010
|
}
|
|
6463
7011
|
else {
|
|
6464
|
-
|
|
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);
|
|
6465
7015
|
// An async concise body whose value is itself a promise
|
|
6466
7016
|
// (`async () => p`): the async machinery RESOLVES the returned
|
|
6467
7017
|
// thenable into the function's own promise — lowerReturnValue's
|
|
@@ -6491,6 +7041,8 @@ export function lowerLambda(lowerer, node) {
|
|
|
6491
7041
|
const ctx = lowerer.ctx;
|
|
6492
7042
|
const lifted = {
|
|
6493
7043
|
name: fnName,
|
|
7044
|
+
sourceName: jsFuncNameOf(node) ?? "<anonymous>",
|
|
7045
|
+
...(!isAsync && !isGenerator && (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) ? { ownsPrototype: true } : {}),
|
|
6494
7046
|
params,
|
|
6495
7047
|
returnType: bodyReturn,
|
|
6496
7048
|
locals: ctx.locals,
|
|
@@ -6569,9 +7121,8 @@ export function lowerLambda(lowerer, node) {
|
|
|
6569
7121
|
* becomes the catch binding, and a handler VALUE would need a
|
|
6570
7122
|
* caught-typed closure parameter, which cannot exist. finally takes
|
|
6571
7123
|
* any () => void closure (its callback sees no arguments). then takes
|
|
6572
|
-
*
|
|
6573
|
-
*
|
|
6574
|
-
* .catch); a promise-returning handler flattens through the async
|
|
7124
|
+
* a fulfillment handler and optionally a rejection handler; a
|
|
7125
|
+
* promise-returning handler flattens through the async
|
|
6575
7126
|
* return path, a receiver rejection passes through untouched (the
|
|
6576
7127
|
* wrapper's await re-throws it), and a handler throw rejects the
|
|
6577
7128
|
* result — the spec's onFulfilled rules by construction. Null for
|
|
@@ -6670,9 +7221,9 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
6670
7221
|
};
|
|
6671
7222
|
const passthrough = call.arguments.length === 0 ||
|
|
6672
7223
|
(call.arguments.length === 1 && isAbsentHandler(call.arguments[0]));
|
|
6673
|
-
if (call.arguments.length !== 1 && !passthrough) {
|
|
7224
|
+
if (call.arguments.length !== 1 && !passthrough && !(member === "then" && call.arguments.length === 2)) {
|
|
6674
7225
|
lowerer.noLowering(`${member} with ${call.arguments.length} arguments`, call, member === "then"
|
|
6675
|
-
? "the supported form takes
|
|
7226
|
+
? "the supported form takes a fulfillment handler and an optional rejection handler"
|
|
6676
7227
|
: `the supported form takes exactly one ${member === "catch" ? "inline handler" : "callback"}`);
|
|
6677
7228
|
}
|
|
6678
7229
|
// The receiver evaluates FIRST, in the enclosing function, like JS.
|
|
@@ -6744,6 +7295,142 @@ export function lowerPromiseMethodCall(lowerer, call, access) {
|
|
|
6744
7295
|
}
|
|
6745
7296
|
}
|
|
6746
7297
|
if (member === "then") {
|
|
7298
|
+
if (call.arguments.length === 2) {
|
|
7299
|
+
const fulfilledNode = call.arguments[0];
|
|
7300
|
+
const rejectedNode = call.arguments[1];
|
|
7301
|
+
const fulfilledAbsent = isAbsentHandler(fulfilledNode);
|
|
7302
|
+
const rejectedAbsent = isAbsentHandler(rejectedNode);
|
|
7303
|
+
const resultT = lowerer.mapTypeOf(lowerer.typeOf(call));
|
|
7304
|
+
if (resultT?.kind !== "promise") {
|
|
7305
|
+
lowerer.noLowering("then with these handlers", call, "the result must be a representable promise");
|
|
7306
|
+
}
|
|
7307
|
+
const R = resultT.inner;
|
|
7308
|
+
if (!fulfilledAbsent && inner.kind === "jsval")
|
|
7309
|
+
markJsvalHandlerParams(lowerer, fulfilledNode);
|
|
7310
|
+
if (!fulfilledAbsent && inner.kind === "moduleNs")
|
|
7311
|
+
markModuleNsHandlerParams(lowerer, fulfilledNode, inner);
|
|
7312
|
+
const boxHandler = (node, allowDirect) => {
|
|
7313
|
+
const value = lowerer.lowerExpr(node);
|
|
7314
|
+
if (allowDirect && value.type.kind === "func" && value.type.params.length <= 1 &&
|
|
7315
|
+
(value.type.params.length === 0 || (inner.kind !== "void" && typeEquals(value.type.params[0], inner)))) {
|
|
7316
|
+
return { value, direct: true, returnsPromise: value.type.ret.kind === "promise" };
|
|
7317
|
+
}
|
|
7318
|
+
if (value.type.kind === "dyn")
|
|
7319
|
+
return { value, direct: false, returnsPromise: false };
|
|
7320
|
+
if (value.type.kind === "func" && value.type.params.length <= 1 &&
|
|
7321
|
+
canBoxFuncIntoDyn(value.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
7322
|
+
return { value: { kind: "dynFrom", value, type: DYN, loc }, direct: false, returnsPromise: value.type.ret.kind === "promise" };
|
|
7323
|
+
}
|
|
7324
|
+
lowerer.unsupported("SC1090", node, "then handlers that cannot be called with one value");
|
|
7325
|
+
};
|
|
7326
|
+
// Evaluate both callback expressions before the wrapper runs, in source order.
|
|
7327
|
+
const fulfilled = fulfilledAbsent ? null : boxHandler(fulfilledNode, true);
|
|
7328
|
+
const rejected = rejectedAbsent ? null : boxHandler(rejectedNode, false);
|
|
7329
|
+
const fnName = `%fn${lowerer.lambdaCounter++}_then2`;
|
|
7330
|
+
const paramTypes = [promT, ...(fulfilled ? [fulfilled.value.type] : []), ...(rejected ? [DYN] : [])];
|
|
7331
|
+
const funcType = { kind: "func", params: paramTypes, ret: resultT };
|
|
7332
|
+
const fnCtx = newFnCtx(true, null, funcType, R);
|
|
7333
|
+
fnCtx.isAsync = true;
|
|
7334
|
+
lowerer.fnStack.push(fnCtx);
|
|
7335
|
+
try {
|
|
7336
|
+
const pLocal = lowerer.declareHiddenLocal("p", promT);
|
|
7337
|
+
const fLocal = fulfilled ? lowerer.declareHiddenLocal("f", fulfilled.value.type) : null;
|
|
7338
|
+
const rLocal = rejected ? lowerer.declareHiddenLocal("r", DYN) : null;
|
|
7339
|
+
const eLocal = lowerer.declareHiddenLocal("e", CAUGHT);
|
|
7340
|
+
const vLocal = inner.kind === "void" ? null : lowerer.declareHiddenLocal("v", inner);
|
|
7341
|
+
const awaitE = {
|
|
7342
|
+
kind: "awaitExpr",
|
|
7343
|
+
value: { kind: "varRef", localId: pLocal.id, type: promT, loc },
|
|
7344
|
+
type: inner,
|
|
7345
|
+
loc,
|
|
7346
|
+
};
|
|
7347
|
+
const tryBody = vLocal
|
|
7348
|
+
? [{ kind: "varDecl", localId: vLocal.id, init: awaitE, loc }]
|
|
7349
|
+
: [{ kind: "exprStmt", expr: awaitE, loc }];
|
|
7350
|
+
const resultOf = (value, returnsPromise = false) => {
|
|
7351
|
+
const settled = value.type.kind === "promise"
|
|
7352
|
+
? { kind: "awaitExpr", value, type: value.type.inner, loc }
|
|
7353
|
+
: returnsPromise
|
|
7354
|
+
? { kind: "libCall", fn: "async.awaitDyn", args: [value], type: DYN, loc }
|
|
7355
|
+
: value;
|
|
7356
|
+
return R.kind === "void"
|
|
7357
|
+
? [{ kind: "exprStmt", expr: settled, loc }, { kind: "return", value: null, loc }]
|
|
7358
|
+
: [{ kind: "return", value: lowerer.coerceInto(call, settled, R), loc }];
|
|
7359
|
+
};
|
|
7360
|
+
const rejectedCall = rLocal ? {
|
|
7361
|
+
kind: "dynCall",
|
|
7362
|
+
callee: { kind: "varRef", localId: rLocal.id, type: DYN, loc },
|
|
7363
|
+
calleeName: jsFuncNameOf(rejectedNode) ?? "onRejected",
|
|
7364
|
+
args: [{ kind: "caughtToDyn", value: { kind: "varRef", localId: eLocal.id, type: CAUGHT, loc }, type: DYN, loc }],
|
|
7365
|
+
type: DYN,
|
|
7366
|
+
loc,
|
|
7367
|
+
} : null;
|
|
7368
|
+
const catchBody = rejectedCall
|
|
7369
|
+
? resultOf(rejectedCall, rejected?.returnsPromise)
|
|
7370
|
+
: [{ kind: "rethrow", localId: eLocal.id, loc }];
|
|
7371
|
+
const body = [{ kind: "tryCatch", tryBody, catchBody, catchLocalId: eLocal.id, finallyBody: null, loc }];
|
|
7372
|
+
// The fulfillment callback sits after the catch so a throw from it
|
|
7373
|
+
// rejects the result instead of reaching onRejected.
|
|
7374
|
+
if (fLocal) {
|
|
7375
|
+
const settled = vLocal
|
|
7376
|
+
? { kind: "varRef", localId: vLocal.id, type: inner, loc }
|
|
7377
|
+
: dynUndefinedExpr(loc);
|
|
7378
|
+
if (fulfilled.direct && fLocal.type.kind === "func") {
|
|
7379
|
+
body.push(...resultOf({
|
|
7380
|
+
kind: "callValue",
|
|
7381
|
+
callee: { kind: "varRef", localId: fLocal.id, type: fLocal.type, loc },
|
|
7382
|
+
args: fLocal.type.params.length === 0 ? [] : [settled],
|
|
7383
|
+
type: fLocal.type.ret,
|
|
7384
|
+
loc,
|
|
7385
|
+
}));
|
|
7386
|
+
}
|
|
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
|
+
}
|
|
7392
|
+
const arg = settled.type.kind === "dyn" ? settled
|
|
7393
|
+
: { kind: "dynFrom", value: settled, type: DYN, loc };
|
|
7394
|
+
body.push(...resultOf({
|
|
7395
|
+
kind: "dynCall",
|
|
7396
|
+
callee: { kind: "varRef", localId: fLocal.id, type: DYN, loc },
|
|
7397
|
+
calleeName: jsFuncNameOf(fulfilledNode) ?? "onFulfilled",
|
|
7398
|
+
args: [arg], type: DYN, loc,
|
|
7399
|
+
}, fulfilled?.returnsPromise));
|
|
7400
|
+
}
|
|
7401
|
+
}
|
|
7402
|
+
else if (vLocal) {
|
|
7403
|
+
body.push(...resultOf({ kind: "varRef", localId: vLocal.id, type: inner, loc }));
|
|
7404
|
+
}
|
|
7405
|
+
else if (R.kind === "void") {
|
|
7406
|
+
body.push({ kind: "return", value: null, loc });
|
|
7407
|
+
}
|
|
7408
|
+
else {
|
|
7409
|
+
body.push({ kind: "return", value: lowerer.coerceInto(call, dynUndefinedExpr(loc), R), loc });
|
|
7410
|
+
}
|
|
7411
|
+
const ctx = lowerer.ctx;
|
|
7412
|
+
const lifted = {
|
|
7413
|
+
name: fnName,
|
|
7414
|
+
params: [
|
|
7415
|
+
{ localId: pLocal.id, name: pLocal.name, type: promT },
|
|
7416
|
+
...(fLocal ? [{ localId: fLocal.id, name: fLocal.name, type: fLocal.type }] : []),
|
|
7417
|
+
...(rLocal ? [{ localId: rLocal.id, name: rLocal.name, type: DYN }] : []),
|
|
7418
|
+
],
|
|
7419
|
+
returnType: R,
|
|
7420
|
+
locals: ctx.locals,
|
|
7421
|
+
captures: ctx.captures,
|
|
7422
|
+
body,
|
|
7423
|
+
loc,
|
|
7424
|
+
async: true,
|
|
7425
|
+
};
|
|
7426
|
+
lowerer.liftedFns.push(lifted);
|
|
7427
|
+
const closure = { kind: "closure", fnName, captures: ctx.captureSources, type: funcType, loc };
|
|
7428
|
+
return { kind: "callValue", callee: closure, args: [receiver, ...(fulfilled ? [fulfilled.value] : []), ...(rejected ? [rejected.value] : [])], type: resultT, loc };
|
|
7429
|
+
}
|
|
7430
|
+
finally {
|
|
7431
|
+
lowerer.fnStack.pop();
|
|
7432
|
+
}
|
|
7433
|
+
}
|
|
6747
7434
|
// The settled value is an island HANDLE: an inline handler's
|
|
6748
7435
|
// unannotated parameter binds it as jsval, whatever the checker's
|
|
6749
7436
|
// contextual type spelled (a module-namespace type has no mapping —
|
|
@@ -7567,7 +8254,8 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
|
|
|
7567
8254
|
loc,
|
|
7568
8255
|
};
|
|
7569
8256
|
const finalize = () => {
|
|
7570
|
-
const
|
|
8257
|
+
const latest = lowerer.shapes.get(argIr.shapeId);
|
|
8258
|
+
const current = latest !== undefined ? latest : shape;
|
|
7571
8259
|
const body = [
|
|
7572
8260
|
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
7573
8261
|
];
|
|
@@ -7617,10 +8305,11 @@ export function recordKeysArrayCall(lowerer, receiver, argIr, shape, loc) {
|
|
|
7617
8305
|
return { kind: "call", callee: helper, args: [receiver], type: resultT, loc };
|
|
7618
8306
|
}
|
|
7619
8307
|
/** Interned `%obj.hasOwn.<n>(r, k)` — Object.hasOwn's membership walk
|
|
7620
|
-
* over a
|
|
8308
|
+
* over a record shape: the key compares against each
|
|
7621
8309
|
* declared field name, undefined-armed fields answering by their tag
|
|
7622
8310
|
* (a key is own exactly when Object.keys would list it — the two share
|
|
7623
|
-
* 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. */
|
|
7624
8313
|
function recordHasOwnHelper(lowerer, shapeId, loc) {
|
|
7625
8314
|
const key = `obj.hasOwn:${shapeId}`;
|
|
7626
8315
|
const existing = lowerer.arrHofHelpers.get(key);
|
|
@@ -7654,7 +8343,10 @@ function recordHasOwnHelper(lowerer, shapeId, loc) {
|
|
|
7654
8343
|
loc,
|
|
7655
8344
|
});
|
|
7656
8345
|
}
|
|
7657
|
-
|
|
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 });
|
|
7658
8350
|
lowerer.liftedFns.push({
|
|
7659
8351
|
name: helper,
|
|
7660
8352
|
params: [
|
|
@@ -7834,6 +8526,42 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7834
8526
|
if (!lowerer.isStdlibGlobal(access.expression, "Object"))
|
|
7835
8527
|
return null;
|
|
7836
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
|
+
}
|
|
7837
8565
|
const cacheKeys = lowerRequireCacheKeys(lowerer, call, member);
|
|
7838
8566
|
if (cacheKeys)
|
|
7839
8567
|
return cacheKeys;
|
|
@@ -7935,23 +8663,14 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7935
8663
|
}
|
|
7936
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)");
|
|
7937
8665
|
}
|
|
7938
|
-
//
|
|
7939
|
-
//
|
|
7940
|
-
//
|
|
7941
|
-
// Object.create for engine-held prototypes. Everything else is a
|
|
7942
|
-
// NAMED fence: the compiled representations have no prototype chain,
|
|
7943
|
-
// and the own-copy stand-in would answer WRONG observably — Node's
|
|
7944
|
-
// Object.keys/inspect/JSON of the created object list NO own keys,
|
|
7945
|
-
// and mutating the prototype afterwards is visible through the
|
|
7946
|
-
// 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.
|
|
7947
8669
|
if (member === "create") {
|
|
7948
8670
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
7949
8671
|
lowerer.noLowering("Object.create with spread arguments", call);
|
|
7950
8672
|
}
|
|
7951
|
-
if (call.arguments.length
|
|
7952
|
-
lowerer.noLowering("Object.create with a properties-descriptor argument", call, "create first, then assign: const o = Object.create(null); o.k = v");
|
|
7953
|
-
}
|
|
7954
|
-
if (call.arguments.length !== 1) {
|
|
8673
|
+
if (call.arguments.length < 1 || call.arguments.length > 2) {
|
|
7955
8674
|
lowerer.noLowering(`Object.create with ${call.arguments.length} arguments`, call);
|
|
7956
8675
|
}
|
|
7957
8676
|
const loc = locOf(call);
|
|
@@ -7960,6 +8679,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7960
8679
|
protoNode = protoNode.expression;
|
|
7961
8680
|
const nullProto = protoNode.kind === ts.SyntaxKind.NullKeyword;
|
|
7962
8681
|
if (lowerer.dynamic) {
|
|
8682
|
+
if (call.arguments.length === 2)
|
|
8683
|
+
lowerer.noLowering("Object.create with properties under --dynamic", call);
|
|
7963
8684
|
// The checker types the result `any` — an ENGINE value under
|
|
7964
8685
|
// --dynamic — and the engine's own Object.create answers with
|
|
7965
8686
|
// REAL prototype semantics: reads delegate LIVE, writes shadow,
|
|
@@ -7980,15 +8701,40 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
7980
8701
|
}
|
|
7981
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");
|
|
7982
8703
|
}
|
|
7983
|
-
if (nullProto) {
|
|
8704
|
+
if (nullProto && call.arguments.length === 1) {
|
|
7984
8705
|
return { kind: "libCall", fn: "dyn.objCreateNullProto", args: [], type: DYN, loc };
|
|
7985
8706
|
}
|
|
7986
|
-
|
|
7987
|
-
|
|
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);
|
|
7988
8722
|
}
|
|
7989
8723
|
// `Object.assign(fn, { props })` whose RESULT type maps to the hybrid
|
|
7990
8724
|
// (function-with-properties) record: the chalk-shape CONSTRUCTOR.
|
|
7991
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
|
+
}
|
|
7992
8738
|
const hybrid = lowerObjectAssignHybrid(lowerer, call);
|
|
7993
8739
|
if (hybrid)
|
|
7994
8740
|
return hybrid;
|
|
@@ -8035,7 +8781,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8035
8781
|
if (tProbe?.type.kind === "dyn") {
|
|
8036
8782
|
const loc = locOf(call);
|
|
8037
8783
|
const target = lowerer.lowerExpr(call.arguments[0]);
|
|
8038
|
-
const
|
|
8784
|
+
const rawSource = lowerer.lowerExpr(call.arguments[1]);
|
|
8785
|
+
fenceSymbolFieldCopy(lowerer, call.arguments[1], rawSource.type);
|
|
8786
|
+
const source = lowerer.coerceToExpected(rawSource, DYN);
|
|
8039
8787
|
if (target.type.kind === "dyn" && source.type.kind === "dyn") {
|
|
8040
8788
|
return { kind: "libCall", fn: "dyn.assign", args: [target, source], type: DYN, loc };
|
|
8041
8789
|
}
|
|
@@ -8112,7 +8860,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8112
8860
|
const argNode = sources[i];
|
|
8113
8861
|
const spread = ts.isSpreadElement(argNode);
|
|
8114
8862
|
const srcNode = spread ? argNode.expression : argNode;
|
|
8115
|
-
const
|
|
8863
|
+
const rawSource = lowerer.lowerExpr(srcNode);
|
|
8864
|
+
fenceSymbolFieldCopy(lowerer, srcNode, rawSource.type, spread);
|
|
8865
|
+
const src = lowerer.coerceToExpected(rawSource, DYN);
|
|
8116
8866
|
if (src.type.kind !== "dyn") {
|
|
8117
8867
|
ok = false;
|
|
8118
8868
|
break;
|
|
@@ -8149,22 +8899,75 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8149
8899
|
}
|
|
8150
8900
|
return null;
|
|
8151
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
|
+
}
|
|
8152
8946
|
// Object.defineProperties over a CHECKED-DYNAMIC target (test/common's
|
|
8153
8947
|
// _mustCallInner copying name/length onto the mustCall wrapper): the
|
|
8154
|
-
// runtime turns each descriptor's `value` into
|
|
8155
|
-
// the dyn node (OBJ members; FUNC nodes carry an
|
|
8156
|
-
//
|
|
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.
|
|
8157
8951
|
// The result is the target, like JS. Typed targets keep the fence:
|
|
8158
8952
|
// static shapes have no property table to extend.
|
|
8159
8953
|
if (member === "defineProperties" && call.arguments.length === 2 &&
|
|
8160
8954
|
!call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
8161
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
|
+
}
|
|
8162
8961
|
// A FUNCTION-typed target boxes through the dyn boundary: the
|
|
8163
8962
|
// property table lives on the CLOSURE (shared by every box of this
|
|
8164
8963
|
// function value), so defining through a fresh box sticks — the
|
|
8165
8964
|
// wrapper returned later reads the same table.
|
|
8166
8965
|
if (target && target.type.kind === "func" &&
|
|
8167
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)) {
|
|
8168
8971
|
target = { kind: "dynFrom", value: target, type: DYN, loc: locOf(call.arguments[0]) };
|
|
8169
8972
|
}
|
|
8170
8973
|
if (target?.type.kind === "dyn") {
|
|
@@ -8175,12 +8978,39 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8175
8978
|
}
|
|
8176
8979
|
return null;
|
|
8177
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
|
+
}
|
|
8178
9004
|
// Object.freeze: on a FRESH literal (object or array) the result IS
|
|
8179
9005
|
// the argument — no alias exists, so the frozen bit is unobservable
|
|
8180
9006
|
// (writes through the Readonly<T> result are compile errors, and no
|
|
8181
9007
|
// other reference can write). Primitives pass through per ES2015.
|
|
8182
9008
|
// Aliased objects keep a fence: a later write through the original
|
|
8183
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
|
+
}
|
|
8184
9014
|
if (member === "freeze") {
|
|
8185
9015
|
if (call.arguments.length !== 1 || ts.isSpreadElement(call.arguments[0])) {
|
|
8186
9016
|
lowerer.noLowering(`Object.freeze with ${call.arguments.length} arguments`, call);
|
|
@@ -8190,14 +9020,18 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8190
9020
|
while (ts.isParenthesizedExpression(inner) || ts.isAsExpression(inner))
|
|
8191
9021
|
inner = inner.expression;
|
|
8192
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) };
|
|
8193
9025
|
if (ts.isObjectLiteralExpression(inner) || ts.isArrayLiteralExpression(inner)) {
|
|
8194
9026
|
return value; // fresh — freeze is identity here, honestly
|
|
8195
9027
|
}
|
|
8196
9028
|
if (value.type.kind === "string" || value.type.kind === "f64" ||
|
|
8197
|
-
value.type.kind === "bool" || value.type.kind === "symbol" ||
|
|
9029
|
+
value.type.kind === "bool" || value.type.kind === "symbol" || value.type.kind === "bigint" ||
|
|
8198
9030
|
isUnitType(value.type)) {
|
|
8199
9031
|
return value; // ES2015: freeze of a primitive is the primitive
|
|
8200
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;
|
|
8201
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");
|
|
8202
9036
|
}
|
|
8203
9037
|
// `Object.hasOwn(r, k)` over a RECORD receiver: a record's own-key set
|
|
@@ -8206,9 +9040,9 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8206
9040
|
// fields answer by their runtime tag — the explicit-undefined-is-absent
|
|
8207
9041
|
// stance: an omitted optional field holds the undefined arm and reads
|
|
8208
9042
|
// as NOT own, exactly Node's absent key (an EXPLICIT `k: undefined`
|
|
8209
|
-
// diverges — documented next to the child-env/JSON rule). Tuple
|
|
8210
|
-
//
|
|
8211
|
-
//
|
|
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
|
|
8212
9046
|
// do too.
|
|
8213
9047
|
if (member === "hasOwn" && call.arguments.length === 2 && !call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
8214
9048
|
const recvNode = call.arguments[0];
|
|
@@ -8217,33 +9051,30 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8217
9051
|
// A CHECKED-DYNAMIC receiver (the JS file-scope object-literal
|
|
8218
9052
|
// identity story): the runtime dyn probe — OBJ member presence, ARR
|
|
8219
9053
|
// index bounds, Node's ToObject TypeError on nullish.
|
|
8220
|
-
if (probed?.type.kind === "dyn") {
|
|
9054
|
+
if (probed?.type.kind === "dyn" || (probed && isDynTypedRefType(probed.type)) || (probed?.type.kind === "func" && lowerer.dynConvertible(probed.type))) {
|
|
8221
9055
|
const loc = locOf(call);
|
|
8222
|
-
const receiver = lowerer.
|
|
8223
|
-
|
|
8224
|
-
if (
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
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)
|
|
8228
9064
|
return null;
|
|
8229
9065
|
return { kind: "libCall", fn: "dyn.hasOwn", args: [receiver, key], type: BOOL, loc };
|
|
8230
9066
|
}
|
|
8231
9067
|
if (probed?.type.kind !== "record")
|
|
8232
9068
|
return null;
|
|
8233
9069
|
const shape = lowerer.shapes.get(probed.type.shapeId);
|
|
8234
|
-
if (!shape || shape.tuple ||
|
|
9070
|
+
if (!shape || shape.tuple || shapeHasAccessorSlots(shape))
|
|
8235
9071
|
return null;
|
|
8236
9072
|
const loc = locOf(call);
|
|
8237
9073
|
const receiver = lowerer.lowerExpr(recvNode);
|
|
8238
9074
|
if (receiver.type.kind !== "record")
|
|
8239
9075
|
return null; // probe/lower drift: keep the fence
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
// path's rule; symbol and composite keys keep the fence.
|
|
8243
|
-
if (key.type.kind === "f64" || key.type.kind === "bool" || key.type.kind === "dyn") {
|
|
8244
|
-
key = { kind: "toString", operand: key, type: STRING, loc: locOf(keyNode) };
|
|
8245
|
-
}
|
|
8246
|
-
if (key.type.kind !== "string")
|
|
9076
|
+
const key = ownPropertyKey(lowerer, lowerer.lowerExpr(keyNode));
|
|
9077
|
+
if (!key)
|
|
8247
9078
|
return null;
|
|
8248
9079
|
const helper = recordHasOwnHelper(lowerer, receiver.type.shapeId, loc);
|
|
8249
9080
|
return { kind: "call", callee: helper, args: [receiver, key], type: BOOL, loc };
|
|
@@ -8305,8 +9136,11 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8305
9136
|
const isDyn = probed?.type.kind === "dyn";
|
|
8306
9137
|
// Unit-typed arguments (Object.keys(null)) ride the same runtime
|
|
8307
9138
|
// walk: it throws Node's catchable TypeError.
|
|
8308
|
-
const
|
|
8309
|
-
|
|
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))) {
|
|
8310
9144
|
const fn = member === "keys" ? "dyn.objKeys" : member === "values" ? "dyn.objValues" : "dyn.objEntries";
|
|
8311
9145
|
let v = lowerer.lowerExpr(argNode);
|
|
8312
9146
|
if (v.type.kind !== "dyn")
|
|
@@ -8335,6 +9169,19 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8335
9169
|
if (shapeHasAccessorSlots(shape)) {
|
|
8336
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)`);
|
|
8337
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
|
+
}
|
|
8338
9185
|
if (shape.indexValue) {
|
|
8339
9186
|
// Index-signature (overflow-carrying) shapes: the runtime walk —
|
|
8340
9187
|
// declared fields first, then the overflow in JS own-key order
|
|
@@ -8345,7 +9192,7 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8345
9192
|
const resultT = lowerer.irTypeOf(call);
|
|
8346
9193
|
if (resultT.kind !== "array")
|
|
8347
9194
|
lowerer.badType(call, lowerer.typeOf(call)); // defensive
|
|
8348
|
-
const receiver = lowerer.lowerExpr(argNode);
|
|
9195
|
+
const receiver = objectEnumerationReceiver(lowerer, lowerer.lowerExpr(argNode), argIr, loc);
|
|
8349
9196
|
if (member === "keys") {
|
|
8350
9197
|
// The keys walk is shared with for-in (which iterates exactly the
|
|
8351
9198
|
// keys Object.keys answers — one construction, one intern key).
|
|
@@ -8387,7 +9234,8 @@ function lowerObjectStaticCall(lowerer, call, access) {
|
|
|
8387
9234
|
loc,
|
|
8388
9235
|
};
|
|
8389
9236
|
const finalize = () => {
|
|
8390
|
-
const
|
|
9237
|
+
const latest = lowerer.shapes.get(argIr.shapeId);
|
|
9238
|
+
const current = latest !== undefined ? latest : shape;
|
|
8391
9239
|
const body = [
|
|
8392
9240
|
{ kind: "varDecl", localId: "out.0", init: { kind: "arrayLit", elems: [], type: resultT, loc }, loc },
|
|
8393
9241
|
];
|
|
@@ -8541,6 +9389,8 @@ export function lowerFunction(lowerer, decl) {
|
|
|
8541
9389
|
appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(decl));
|
|
8542
9390
|
const fn = {
|
|
8543
9391
|
name: sig.name,
|
|
9392
|
+
sourceName: decl.name?.text ?? "<anonymous>",
|
|
9393
|
+
...(!sig.isAsync && !sig.generator ? { ownsPrototype: true } : {}),
|
|
8544
9394
|
params,
|
|
8545
9395
|
returnType: bodyReturn,
|
|
8546
9396
|
locals: lowerer.ctx.locals,
|
|
@@ -8665,8 +9515,27 @@ function lowerObjectAssignHybrid(lowerer, call) {
|
|
|
8665
9515
|
export function lowerRecordFieldCall(lowerer, call, access) {
|
|
8666
9516
|
if (lowerer.chainBlocked(call))
|
|
8667
9517
|
return null;
|
|
8668
|
-
|
|
8669
|
-
|
|
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
|
+
}
|
|
8670
9539
|
const target = lowerer.fieldTarget(access);
|
|
8671
9540
|
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
8672
9541
|
if (!callee)
|
|
@@ -8865,7 +9734,7 @@ function nullishValueUnitOf(lowerer, sym) {
|
|
|
8865
9734
|
// the no-storage family never claims it.
|
|
8866
9735
|
if (!decl || !ts.isVariableDeclaration(decl) || !ts.isIdentifier(decl.name) ||
|
|
8867
9736
|
decl.getSourceFile().isDeclarationFile || decl.initializer === undefined ||
|
|
8868
|
-
!ts.isVariableStatement(decl.parent
|
|
9737
|
+
!ts.isVariableStatement(decl.parent?.parent)) {
|
|
8869
9738
|
return null;
|
|
8870
9739
|
}
|
|
8871
9740
|
const unit = nullishExprUnitOf(lowerer, decl.initializer);
|
|
@@ -9051,7 +9920,7 @@ export function deadUnmappableBinding(lowerer, sym, decl) {
|
|
|
9051
9920
|
// lowerVarDeclList's contract requires a lowered statement for it, so
|
|
9052
9921
|
// the no-storage family never claims it (catch bindings sit outside a
|
|
9053
9922
|
// variable statement too and stay out the same way).
|
|
9054
|
-
if (!ts.isVariableStatement(decl.parent
|
|
9923
|
+
if (!ts.isVariableStatement(decl.parent?.parent))
|
|
9055
9924
|
return false;
|
|
9056
9925
|
const sf = decl.getSourceFile();
|
|
9057
9926
|
if (sf.isDeclarationFile || isJsSourceFile(sf))
|
|
@@ -9229,11 +10098,11 @@ export function bindingGenericFnInfoOf(lowerer, decl, fnNode) {
|
|
|
9229
10098
|
lowerer.unsupported("SC1031", param);
|
|
9230
10099
|
}
|
|
9231
10100
|
}
|
|
9232
|
-
const stmt = decl.parent
|
|
10101
|
+
const stmt = decl.parent?.parent; // declarator → list → statement (nsPathPrefix wants the statement)
|
|
9233
10102
|
const info = {
|
|
9234
10103
|
decl: fnNode,
|
|
9235
10104
|
baseName: name,
|
|
9236
|
-
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt, decl) + name),
|
|
10105
|
+
qualifiedName: lowerer.qualify(decl.getSourceFile(), nsPathPrefix(stmt ?? decl, decl) + name),
|
|
9237
10106
|
typeParams,
|
|
9238
10107
|
instances: new Map(),
|
|
9239
10108
|
};
|
|
@@ -9365,6 +10234,88 @@ function arrowSignatureOf(lowerer, node) {
|
|
|
9365
10234
|
const declaration = lowerer.checker.signatureDeclaration(signatures[0]);
|
|
9366
10235
|
return declaration !== undefined && ts.isArrowFunction(declaration) ? signatures[0] : null;
|
|
9367
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
|
+
}
|
|
9368
10319
|
/** `arrow.apply(thisArg, dynArgs)` for a fixed-arity compiled arrow. Arrows
|
|
9369
10320
|
* ignore `thisArg` and surplus arguments by language definition; declared
|
|
9370
10321
|
* parameters validate from the dynamic array in order. */
|
|
@@ -9443,7 +10394,6 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9443
10394
|
thisT.kind !== "dyn" &&
|
|
9444
10395
|
thisT.kind !== "jsval" &&
|
|
9445
10396
|
(!thisArg || ts.isIdentifier(thisArg) || ts.isLiteralExpression(thisArg) ||
|
|
9446
|
-
thisArg.kind === ts.SyntaxKind.UndefinedKeyword ||
|
|
9447
10397
|
thisArg.kind === ts.SyntaxKind.NullKeyword ||
|
|
9448
10398
|
isUnitType(thisT));
|
|
9449
10399
|
if (provablyNot) {
|
|
@@ -9482,19 +10432,25 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9482
10432
|
}
|
|
9483
10433
|
const found = objLitGenericFnNodeOf(lowerer, propSym);
|
|
9484
10434
|
if (!found) {
|
|
10435
|
+
const arrowBind = lowerInlineArrowBind(lowerer, call, access);
|
|
10436
|
+
if (arrowBind !== null)
|
|
10437
|
+
return arrowBind;
|
|
9485
10438
|
const arrowApply = lowerArrowFunctionApply(lowerer, call, access);
|
|
9486
10439
|
if (arrowApply !== null)
|
|
9487
10440
|
return arrowApply;
|
|
9488
|
-
//
|
|
9489
|
-
//
|
|
9490
|
-
// `this`/arguments object to re-route — name the working spelling
|
|
9491
|
-
// instead of a class-receiver hint (or an SC2020 recitation) no
|
|
9492
|
-
// function value can follow. Before the stdlib decline: these ARE
|
|
9493
|
-
// stdlib members (CallableFunction), but the pointed message is
|
|
9494
|
-
// the honest one.
|
|
10441
|
+
// Convertible native callables use the checked invocation boundary
|
|
10442
|
+
// for Function.prototype methods, including their call-time receiver.
|
|
9495
10443
|
if ((name === "apply" || name === "call" || name === "bind") &&
|
|
9496
10444
|
lowerer.checker.getCallSignatures(recvT).length > 0) {
|
|
9497
|
-
|
|
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)`);
|
|
9498
10454
|
}
|
|
9499
10455
|
// STANDARD-LIBRARY generic members (Promise.then, Object.
|
|
9500
10456
|
// defineProperty, Array-augmentation methods) are the lib fence's
|
|
@@ -9531,7 +10487,16 @@ function lowerObjLitGenericMethodCall(lowerer, call, access) {
|
|
|
9531
10487
|
export function lowerObjectMethodCall(lowerer, call, access) {
|
|
9532
10488
|
if (lowerer.chainBlocked(access, call))
|
|
9533
10489
|
return null;
|
|
9534
|
-
|
|
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;
|
|
9535
10500
|
if (mappedReceiver?.kind === "union") {
|
|
9536
10501
|
const dispatched = lowerUnionObjectMethodCall(lowerer, call, access, mappedReceiver) ??
|
|
9537
10502
|
lowerUnionObjectDynFieldCall(lowerer, call, access, mappedReceiver);
|
|
@@ -9544,15 +10509,16 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9544
10509
|
? (() => {
|
|
9545
10510
|
const arms = lowerer.unions.get(mappedReceiver.unionId)?.arms ?? [];
|
|
9546
10511
|
const objects = arms.filter((arm) => arm.kind === "object");
|
|
9547
|
-
|
|
9548
|
-
|
|
10512
|
+
const object = objects[0];
|
|
10513
|
+
return objects.length === 1 && object?.kind === "object" && arms.every((arm) => arm.kind === "object" || isUnitType(arm))
|
|
10514
|
+
? object
|
|
9549
10515
|
: null;
|
|
9550
10516
|
})()
|
|
9551
10517
|
: null;
|
|
9552
10518
|
if (receiverIr === null)
|
|
9553
10519
|
return null;
|
|
9554
10520
|
const lowerReceiver = () => {
|
|
9555
|
-
const receiver = lowerer.lowerExpr(access.expression);
|
|
10521
|
+
const receiver = specializedReceiver ?? lowerer.lowerExpr(access.expression);
|
|
9556
10522
|
const optional = lowerer.runtimeOptionalPropertyReceiver(access.expression, receiver, receiverIr, access.name.text);
|
|
9557
10523
|
if (optional !== null)
|
|
9558
10524
|
return optional;
|
|
@@ -9561,7 +10527,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9561
10527
|
if (helper !== null)
|
|
9562
10528
|
return { kind: "call", callee: helper, args: [receiver], type: receiverIr, loc: locOf(access.expression) };
|
|
9563
10529
|
}
|
|
9564
|
-
return receiver;
|
|
10530
|
+
return receiver.type.kind === "dyn" ? lowerer.coerceInto(access.expression, receiver, receiverIr) : receiver;
|
|
9565
10531
|
};
|
|
9566
10532
|
const info = lowerer.classes.get(receiverIr.className);
|
|
9567
10533
|
if (!info)
|
|
@@ -9588,7 +10554,7 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9588
10554
|
if (info && !found) {
|
|
9589
10555
|
const gfound = findGenericMethodOn(lowerer, info, access.name.text);
|
|
9590
10556
|
if (gfound)
|
|
9591
|
-
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound);
|
|
10557
|
+
return lowerClassGenericMethodCall(lowerer, call, access, info, gfound, lowerReceiver());
|
|
9592
10558
|
}
|
|
9593
10559
|
// A FUNC-, nullable-FUNC-, or DYN-typed FIELD in call position:
|
|
9594
10560
|
// `this.cb()` — the ctor-assigned callback field (countdown.js's
|
|
@@ -9604,13 +10570,22 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9604
10570
|
? (() => {
|
|
9605
10571
|
const arms = lowerer.unions.get(fieldType.unionId)?.arms ?? [];
|
|
9606
10572
|
const funcs = arms.filter((arm) => arm.kind === "func");
|
|
9607
|
-
|
|
9608
|
-
|
|
10573
|
+
const func = funcs[0];
|
|
10574
|
+
return funcs.length === 1 && func?.kind === "func" && arms.every((arm) => arm.kind === "func" || isUnitType(arm))
|
|
10575
|
+
? func
|
|
9609
10576
|
: null;
|
|
9610
10577
|
})()
|
|
9611
10578
|
: null;
|
|
9612
10579
|
if (fieldType && (callableType !== null || fieldType.kind === "dyn")) {
|
|
9613
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 });
|
|
9614
10589
|
let callee = target ? lowerer.fieldGetExpr(target, locOf(access), access) : null;
|
|
9615
10590
|
if (callee?.type.kind === "union" && callableType !== null) {
|
|
9616
10591
|
const helper = lowerer.narrowedArmHelper(callee.type.unionId, callableType, locOf(access));
|
|
@@ -9619,15 +10594,24 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9619
10594
|
}
|
|
9620
10595
|
}
|
|
9621
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
|
+
}
|
|
9622
10606
|
const args = completeFuncValueArgs(lowerer, call, callee.type, locOf(call));
|
|
9623
|
-
return { kind: "callValue", callee, args, type: callee.type.ret, loc
|
|
10607
|
+
return finish({ kind: "callValue", callee, receiver, args, type: callee.type.ret, loc });
|
|
9624
10608
|
}
|
|
9625
10609
|
if (callee?.type.kind === "dyn") {
|
|
9626
10610
|
if (call.arguments.some((a) => ts.isSpreadElement(a))) {
|
|
9627
10611
|
lowerer.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
9628
10612
|
}
|
|
9629
10613
|
const args = call.arguments.map((a) => lowerer.lowerExprExpecting(a, DYN));
|
|
9630
|
-
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 });
|
|
9631
10615
|
}
|
|
9632
10616
|
}
|
|
9633
10617
|
return null;
|
|
@@ -9635,18 +10619,25 @@ export function lowerObjectMethodCall(lowerer, call, access) {
|
|
|
9635
10619
|
if (!info || !found)
|
|
9636
10620
|
return null;
|
|
9637
10621
|
const method = access.name.text;
|
|
9638
|
-
if (
|
|
9639
|
-
|
|
9640
|
-
// implementation called directly (overriding it is fenced, so no
|
|
9641
|
-
// dispatch can ever be needed). Receiver BORROWED by the libCall.
|
|
10622
|
+
if (isClassCallback(lowerer, info, method)) {
|
|
10623
|
+
const loc = locOf(call);
|
|
9642
10624
|
const receiver = lowerReceiver();
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
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());
|
|
9650
10641
|
}
|
|
9651
10642
|
// An ABSTRACT nearest declaration with no concrete override below the
|
|
9652
10643
|
// static class: no implementation exists for a direct call to target.
|
|
@@ -9719,7 +10710,10 @@ function lowerUnionObjectMethodCall(lowerer, call, access, receiverT) {
|
|
|
9719
10710
|
function paramAbisEqual(left, right) {
|
|
9720
10711
|
return left.length === right.length && left.every((shape, i) => {
|
|
9721
10712
|
const other = right[i];
|
|
9722
|
-
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"));
|
|
9723
10717
|
});
|
|
9724
10718
|
}
|
|
9725
10719
|
/** The JS-class sibling of union method dispatch: every arm stores the
|
|
@@ -9744,6 +10738,8 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
|
|
|
9744
10738
|
const loc = locOf(call);
|
|
9745
10739
|
const receiver = lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), receiverT);
|
|
9746
10740
|
const key = `${receiverT.unionId}:dyn-field:${field}`;
|
|
10741
|
+
const receiverLocal = lowerer.declareHiddenLocal("%unionCallReceiver", receiverT);
|
|
10742
|
+
const receiverRef = varRef(receiverLocal.id, receiverT, loc);
|
|
9747
10743
|
let helper = lowerer.unionCallHelpers.get(key);
|
|
9748
10744
|
if (!helper) {
|
|
9749
10745
|
helper = `%union.call.${lowerer.unionCallHelpers.size}`;
|
|
@@ -9796,9 +10792,12 @@ function lowerUnionObjectDynFieldCall(lowerer, call, access, receiverT) {
|
|
|
9796
10792
|
const locals = params.map((param) => ({ id: param.localId, name: param.name, type: param.type, mutable: false }));
|
|
9797
10793
|
lowerer.liftedFns.push({ name: helper, params, returnType: DYN, locals, body, loc });
|
|
9798
10794
|
}
|
|
9799
|
-
const callee = { kind: "call", callee: helper, args: [
|
|
10795
|
+
const callee = { kind: "call", callee: helper, args: [receiverRef], type: DYN, loc };
|
|
9800
10796
|
const args = call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN));
|
|
9801
|
-
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
|
+
};
|
|
9802
10801
|
}
|
|
9803
10802
|
function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans, shapes, resultT, loc) {
|
|
9804
10803
|
const key = `${receiverT.unionId}:${method}:${shapes.map((shape) => `${shape.mode}:${typeKey(shape.type)}`).join(",")}:${typeKey(resultT)}`;
|
|
@@ -9820,13 +10819,7 @@ function unionObjectMethodHelper(lowerer, sourceCall, receiverT, method, plans,
|
|
|
9820
10819
|
};
|
|
9821
10820
|
let invoke;
|
|
9822
10821
|
if (plan.found.declarer.builtinError) {
|
|
9823
|
-
invoke =
|
|
9824
|
-
kind: "libCall",
|
|
9825
|
-
fn: "error.toString",
|
|
9826
|
-
args: [lowerer.upcastTo(concrete, plan.found.declarer.def.name)],
|
|
9827
|
-
type: STRING,
|
|
9828
|
-
loc,
|
|
9829
|
-
};
|
|
10822
|
+
invoke = errorToStringCall(lowerer, concrete);
|
|
9830
10823
|
}
|
|
9831
10824
|
else if (lowerer.overrideBelow(plan.info, method)) {
|
|
9832
10825
|
lowerer.noteVirtualEdge(plan.info, method);
|