@scriptc/compiler 0.2.4 → 0.2.6
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 +972 -245
- package/ambient/scriptc-overrides.d.ts +5 -1
- package/ambient/scriptc.d.ts +22 -2
- package/dist/backend/build-cache.d.ts +4 -0
- package/dist/backend/build-cache.js +16 -2
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cycle-analysis.js +17 -5
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +50 -11
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/debug-symbols.js.map +1 -1
- package/dist/backend/executable-features.js +3 -1
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/external-c.d.ts +13 -6
- package/dist/backend/external-c.js +15 -3
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.js +6 -9
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +1 -1
- package/dist/backend/library-pack.js +81 -24
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/link-plan-core.d.ts +2 -0
- package/dist/backend/link-plan-core.js +10 -2
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js +7 -5
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/linker.d.ts +1 -1
- package/dist/backend/linker.js +42 -23
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.js +5 -4
- package/dist/backend/literals.js.map +1 -1
- package/dist/backend/literals.test.js +30 -5
- package/dist/backend/literals.test.js.map +1 -1
- package/dist/backend/llvm/blocks.test.js +5 -2
- package/dist/backend/llvm/blocks.test.js.map +1 -1
- package/dist/backend/llvm/borrowed-inputs.js.map +1 -1
- package/dist/backend/llvm/borrowed-receivers.js +43 -19
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
- package/dist/backend/llvm/byte-numbers.js +38 -5
- package/dist/backend/llvm/byte-numbers.js.map +1 -1
- package/dist/backend/llvm/byte-windows.d.ts +31 -0
- package/dist/backend/llvm/byte-windows.js +334 -0
- package/dist/backend/llvm/byte-windows.js.map +1 -0
- package/dist/backend/llvm/byte-windows.test.d.ts +1 -0
- package/dist/backend/llvm/byte-windows.test.js +244 -0
- package/dist/backend/llvm/byte-windows.test.js.map +1 -0
- package/dist/backend/llvm/bytes-bounds.js +73 -22
- package/dist/backend/llvm/bytes-bounds.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +5 -2
- package/dist/backend/llvm/call-lifetimes.js +72 -19
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +159 -28
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.d.ts +4 -0
- package/dist/backend/llvm/checked-value-lifetimes.js +14 -4
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +14 -1
- package/dist/backend/llvm/classes.js +94 -19
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.d.ts +1 -0
- package/dist/backend/llvm/classes.test.js +99 -0
- package/dist/backend/llvm/classes.test.js.map +1 -0
- package/dist/backend/llvm/common.js +4 -1
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +11 -0
- package/dist/backend/llvm/constant-callbacks.js +213 -0
- package/dist/backend/llvm/constant-callbacks.js.map +1 -0
- package/dist/backend/llvm/constant-callbacks.test.d.ts +1 -0
- package/dist/backend/llvm/constant-callbacks.test.js +124 -0
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -0
- package/dist/backend/llvm/counted-loops.js +10 -3
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +33 -13
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/debug-info.test.js +28 -6
- package/dist/backend/llvm/debug-info.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -1
- package/dist/backend/llvm/dyn.js +75 -56
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +28 -3
- package/dist/backend/llvm/emitter.js +506 -145
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +247 -50
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +25 -6
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js +24 -4
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +10 -4
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +110 -31
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +2 -0
- package/dist/backend/llvm/expr-containers.js +112 -41
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +1 -3
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +3 -1
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +55 -7
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js +26 -6
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +95 -19
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +44 -2
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +10 -9
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +44 -26
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +51 -14
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +34 -14
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/integer-remainder.d.ts +7 -0
- package/dist/backend/llvm/integer-remainder.js +26 -0
- package/dist/backend/llvm/integer-remainder.js.map +1 -0
- package/dist/backend/llvm/integer-values.js +15 -4
- package/dist/backend/llvm/integer-values.js.map +1 -1
- package/dist/backend/llvm/integer-views.js +23 -7
- package/dist/backend/llvm/integer-views.js.map +1 -1
- package/dist/backend/llvm/integer-views.test.js +42 -7
- package/dist/backend/llvm/integer-views.test.js.map +1 -1
- package/dist/backend/llvm/layouts.js +1 -1
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lib-abi.js +20 -4
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-connect.js +7 -1
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +35 -10
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +42 -38
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +33 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +60 -15
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +12 -5
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +97 -31
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +57 -14
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +122 -31
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +33 -14
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +21 -7
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/lib-tls.js +69 -20
- package/dist/backend/llvm/lib-tls.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +9 -2
- package/dist/backend/llvm/local-array-reads.js +176 -89
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +394 -62
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +25 -0
- package/dist/backend/llvm/local-union-storage.js +109 -0
- package/dist/backend/llvm/local-union-storage.js.map +1 -0
- package/dist/backend/llvm/local-union-storage.test.d.ts +1 -0
- package/dist/backend/llvm/local-union-storage.test.js +210 -0
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -0
- package/dist/backend/llvm/loop-array-borrows.d.ts +11 -0
- package/dist/backend/llvm/loop-array-borrows.js +70 -0
- package/dist/backend/llvm/loop-array-borrows.js.map +1 -0
- package/dist/backend/llvm/loop-array-borrows.test.d.ts +1 -0
- package/dist/backend/llvm/loop-array-borrows.test.js +145 -0
- package/dist/backend/llvm/loop-array-borrows.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +11 -2
- package/dist/backend/llvm/map-read-lifetimes.js +64 -19
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +89 -17
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/reference-effects.d.ts +5 -3
- package/dist/backend/llvm/reference-effects.js +74 -36
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-effects.test.js +92 -9
- package/dist/backend/llvm/reference-effects.test.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +4 -1
- package/dist/backend/llvm/shapes.js +82 -24
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +3 -1
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/split-loops.d.ts +48 -0
- package/dist/backend/llvm/split-loops.js +183 -0
- package/dist/backend/llvm/split-loops.js.map +1 -0
- package/dist/backend/llvm/split.js +4 -11
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +80 -8
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.d.ts +14 -0
- package/dist/backend/llvm/stack-callbacks.js +73 -0
- package/dist/backend/llvm/stack-callbacks.js.map +1 -0
- package/dist/backend/llvm/stack-captures.d.ts +25 -0
- package/dist/backend/llvm/stack-captures.js +150 -0
- package/dist/backend/llvm/stack-captures.js.map +1 -0
- package/dist/backend/llvm/stack-unions.js +14 -5
- package/dist/backend/llvm/stack-unions.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +151 -32
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.js.map +1 -1
- package/dist/backend/llvm/string-construction.test.js +32 -7
- package/dist/backend/llvm/string-construction.test.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.js +14 -8
- package/dist/backend/llvm/string-lifetimes.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +119 -29
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-slices.d.ts +20 -0
- package/dist/backend/llvm/string-slices.js +87 -0
- package/dist/backend/llvm/string-slices.js.map +1 -0
- package/dist/backend/llvm/string-slices.test.d.ts +1 -0
- package/dist/backend/llvm/string-slices.test.js +98 -0
- package/dist/backend/llvm/string-slices.test.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.d.ts +9 -0
- package/dist/backend/llvm/switch-dispatch.js +114 -0
- package/dist/backend/llvm/switch-dispatch.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.test.d.ts +1 -0
- package/dist/backend/llvm/switch-dispatch.test.js +83 -0
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -0
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +4 -14
- package/dist/backend/llvm/walkers.js +58 -313
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.js +9 -3
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.js +18 -8
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +119 -23
- package/dist/backend/may-throw.test.js.map +1 -1
- package/dist/backend/native/artifact-stamps.d.ts +39 -0
- package/dist/backend/native/artifact-stamps.js +371 -0
- package/dist/backend/native/artifact-stamps.js.map +1 -0
- package/dist/backend/native/cache-warm.d.ts +24 -0
- package/dist/backend/native/cache-warm.js +80 -0
- package/dist/backend/native/cache-warm.js.map +1 -0
- package/dist/backend/native/compiler-fingerprint.d.ts +19 -0
- package/dist/backend/native/compiler-fingerprint.js +357 -0
- package/dist/backend/native/compiler-fingerprint.js.map +1 -0
- package/dist/backend/native/contracts.d.ts +316 -0
- package/dist/backend/native/contracts.js +2 -0
- package/dist/backend/native/contracts.js.map +1 -0
- package/dist/backend/native/dependency-files.d.ts +5 -0
- package/dist/backend/native/dependency-files.js +83 -0
- package/dist/backend/native/dependency-files.js.map +1 -0
- package/dist/backend/native/driver.d.ts +50 -0
- package/dist/backend/native/driver.js +294 -0
- package/dist/backend/native/driver.js.map +1 -0
- package/dist/backend/native/executable.d.ts +18 -0
- package/dist/backend/native/executable.js +1275 -0
- package/dist/backend/native/executable.js.map +1 -0
- package/dist/backend/native/library.d.ts +2 -0
- package/dist/backend/native/library.js +614 -0
- package/dist/backend/native/library.js.map +1 -0
- package/dist/backend/native/linker-fingerprint.d.ts +8 -0
- package/dist/backend/native/linker-fingerprint.js +174 -0
- package/dist/backend/native/linker-fingerprint.js.map +1 -0
- package/dist/backend/native/object-merge.d.ts +2 -0
- package/dist/backend/native/object-merge.js +154 -0
- package/dist/backend/native/object-merge.js.map +1 -0
- package/dist/backend/native/process.d.ts +17 -0
- package/dist/backend/native/process.js +42 -0
- package/dist/backend/native/process.js.map +1 -0
- package/dist/backend/native/program-shards.d.ts +21 -0
- package/dist/backend/native/program-shards.js +99 -0
- package/dist/backend/native/program-shards.js.map +1 -0
- package/dist/backend/native/runtime-inputs.d.ts +12 -0
- package/dist/backend/native/runtime-inputs.js +165 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -0
- package/dist/backend/native/runtime-inputs.test.d.ts +1 -0
- package/dist/backend/native/runtime-inputs.test.js +64 -0
- package/dist/backend/native/runtime-inputs.test.js.map +1 -0
- package/dist/backend/native/runtime-objects.d.ts +16 -0
- package/dist/backend/native/runtime-objects.js +122 -0
- package/dist/backend/native/runtime-objects.js.map +1 -0
- package/dist/backend/native/session.d.ts +12 -0
- package/dist/backend/native/session.js +31 -0
- package/dist/backend/native/session.js.map +1 -0
- package/dist/backend/native/tool-identity.d.ts +37 -0
- package/dist/backend/native/tool-identity.js +310 -0
- package/dist/backend/native/tool-identity.js.map +1 -0
- package/dist/backend/native/trace-paths.d.ts +12 -0
- package/dist/backend/native/trace-paths.js +73 -0
- package/dist/backend/native/trace-paths.js.map +1 -0
- package/dist/backend/native/vendor.d.ts +1 -0
- package/dist/backend/native/vendor.js +12 -0
- package/dist/backend/native/vendor.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +6 -0
- package/dist/backend/native-codegen-core.js +23 -1
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +5 -1
- package/dist/backend/native-codegen.js +52 -25
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +59 -11
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +1 -0
- package/dist/backend/native-link-info-core.js +9 -5
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.js +14 -5
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +58 -13
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +17 -450
- package/dist/backend/native-toolchain.js +17 -3971
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +103 -72
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +3 -1
- package/dist/backend/native-tools.js +30 -9
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/object-localize.js +17 -14
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +59 -12
- 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 +1 -0
- package/dist/backend/runtime-pack-core.js +104 -50
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.js +5 -3
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +126 -17
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +1 -1
- package/dist/backend/runtime-pack.js +11 -12
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +51 -25
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/source-locations.js.map +1 -1
- package/dist/backend/source-locations.test.js +7 -2
- package/dist/backend/source-locations.test.js.map +1 -1
- package/dist/backend/target-diagnostics.js +44 -14
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +93 -20
- package/dist/backend/target-diagnostics.test.js.map +1 -1
- package/dist/backend/targets.js +230 -86
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +32 -18
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.js +5 -1
- package/dist/backend/toolchain-environment.js.map +1 -1
- package/dist/backend/vendor-archives.d.ts +2 -2
- package/dist/backend/vendor-archives.js +84 -35
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.js +13 -1
- package/dist/backend/vendor-inputs.js.map +1 -1
- package/dist/backend/warm-cache.d.ts +1 -1
- package/dist/backend/warm-cache.js +33 -9
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +39 -9
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/output-options.js +14 -4
- package/dist/cli/output-options.js.map +1 -1
- package/dist/cli/paths.js.map +1 -1
- package/dist/cli/wasi-runner.js.map +1 -1
- package/dist/compat/fetch-profile.js +36 -35
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/coverage/report.js +16 -17
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +112 -26
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +55 -16
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +2 -1
- package/dist/executable/executable-cache.js +79 -48
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +90 -26
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -2
- package/dist/executable/prepare.js.map +1 -1
- package/dist/ffi/ffi-manifest.js +78 -20
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.js +96 -16
- package/dist/ffi/ffi-manifest.test.js.map +1 -1
- package/dist/format-integer.js.map +1 -1
- package/dist/frontend/analysis.js +12 -2
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/arguments-usage.js.map +1 -1
- package/dist/frontend/binding-source.js +9 -3
- package/dist/frontend/binding-source.js.map +1 -1
- package/dist/frontend/builtin-modules.js +46 -2
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-resolve.js +40 -17
- package/dist/frontend/cjs-resolve.js.map +1 -1
- package/dist/frontend/cjs-syntax.js +31 -10
- package/dist/frontend/cjs-syntax.js.map +1 -1
- package/dist/frontend/comptime-node.test.js +10 -11
- package/dist/frontend/comptime-node.test.js.map +1 -1
- package/dist/frontend/dts-paths.js +7 -3
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.d.ts +5 -0
- package/dist/frontend/fork-target.js +55 -18
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/fork-target.test.d.ts +1 -0
- package/dist/frontend/fork-target.test.js +59 -0
- package/dist/frontend/fork-target.test.js.map +1 -0
- package/dist/frontend/function-completion.js +11 -6
- package/dist/frontend/function-completion.js.map +1 -1
- package/dist/frontend/helper-tokens.js +53 -6
- package/dist/frontend/helper-tokens.js.map +1 -1
- package/dist/frontend/helper-tokens.test.js +18 -2
- package/dist/frontend/helper-tokens.test.js.map +1 -1
- package/dist/frontend/inferred-js-diagnostics.js +32 -12
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -1
- package/dist/frontend/inferred-js-diagnostics.test.js +11 -15
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -1
- package/dist/frontend/input-tracker.js +11 -11
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +4 -1
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +38 -9
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.js.map +1 -1
- package/dist/frontend/literal-values.test.js +28 -8
- package/dist/frontend/literal-values.test.js.map +1 -1
- package/dist/frontend/lowering/abstract-equality.js +53 -10
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.d.ts +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +108 -106
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.js +37 -14
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/binding-analysis.d.ts +50 -0
- package/dist/frontend/lowering/binding-analysis.js +376 -0
- package/dist/frontend/lowering/binding-analysis.js.map +1 -0
- package/dist/frontend/lowering/builtin-calls.d.ts +9 -0
- package/dist/frontend/lowering/builtin-calls.js +60 -0
- package/dist/frontend/lowering/builtin-calls.js.map +1 -0
- package/dist/frontend/lowering/builtins/arguments.d.ts +43 -0
- package/dist/frontend/lowering/builtins/arguments.js +247 -0
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -0
- package/dist/frontend/lowering/builtins/async-context.d.ts +52 -0
- package/dist/frontend/lowering/builtins/async-context.js +436 -0
- package/dist/frontend/lowering/builtins/async-context.js.map +1 -0
- package/dist/frontend/lowering/builtins/atomics.d.ts +6 -0
- package/dist/frontend/lowering/builtins/atomics.js +82 -0
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -0
- package/dist/frontend/lowering/builtins/callable-aliases.d.ts +13 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js +87 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -0
- package/dist/frontend/lowering/builtins/child-process-async.d.ts +18 -0
- package/dist/frontend/lowering/builtins/child-process-async.js +245 -0
- package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -0
- package/dist/frontend/lowering/builtins/child-process-methods.d.ts +21 -0
- package/dist/frontend/lowering/builtins/child-process-methods.js +362 -0
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -0
- package/dist/frontend/lowering/builtins/child-process-sync.d.ts +4 -0
- package/dist/frontend/lowering/builtins/child-process-sync.js +639 -0
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -0
- package/dist/frontend/lowering/builtins/child-process.d.ts +55 -0
- package/dist/frontend/lowering/builtins/child-process.js +669 -0
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -0
- package/dist/frontend/lowering/builtins/compression.d.ts +7 -0
- package/dist/frontend/lowering/builtins/compression.js +115 -0
- package/dist/frontend/lowering/builtins/compression.js.map +1 -0
- package/dist/frontend/lowering/builtins/console.d.ts +10 -0
- package/dist/frontend/lowering/builtins/console.js +38 -0
- package/dist/frontend/lowering/builtins/console.js.map +1 -0
- package/dist/frontend/lowering/builtins/constants.d.ts +24 -0
- package/dist/frontend/lowering/builtins/constants.js +141 -0
- package/dist/frontend/lowering/builtins/constants.js.map +1 -0
- package/dist/frontend/lowering/builtins/crypto.d.ts +22 -0
- package/dist/frontend/lowering/builtins/crypto.js +517 -0
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -0
- package/dist/frontend/lowering/builtins/dates.d.ts +7 -0
- package/dist/frontend/lowering/builtins/dates.js +101 -0
- package/dist/frontend/lowering/builtins/dates.js.map +1 -0
- package/dist/frontend/lowering/builtins/environment.d.ts +34 -0
- package/dist/frontend/lowering/builtins/environment.js +95 -0
- package/dist/frontend/lowering/builtins/environment.js.map +1 -0
- package/dist/frontend/lowering/builtins/errors.d.ts +14 -0
- package/dist/frontend/lowering/builtins/errors.js +83 -0
- package/dist/frontend/lowering/builtins/errors.js.map +1 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +35 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +725 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -0
- package/dist/frontend/lowering/builtins/filesystem.d.ts +108 -0
- package/dist/frontend/lowering/builtins/filesystem.js +1061 -0
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -0
- package/dist/frontend/lowering/builtins/ipc.d.ts +8 -0
- package/dist/frontend/lowering/builtins/ipc.js +76 -0
- package/dist/frontend/lowering/builtins/ipc.js.map +1 -0
- package/dist/frontend/lowering/builtins/json.d.ts +12 -0
- package/dist/frontend/lowering/builtins/json.js +387 -0
- package/dist/frontend/lowering/builtins/json.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-bindings.d.ts +85 -0
- package/dist/frontend/lowering/builtins/module-bindings.js +346 -0
- package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-calls.d.ts +8 -0
- package/dist/frontend/lowering/builtins/module-calls.js +308 -0
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +38 -0
- package/dist/frontend/lowering/builtins/module-resolution.js +344 -0
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -0
- package/dist/frontend/lowering/builtins/numbers.d.ts +15 -0
- package/dist/frontend/lowering/builtins/numbers.js +124 -0
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -0
- package/dist/frontend/lowering/builtins/operating-system.d.ts +13 -0
- package/dist/frontend/lowering/builtins/operating-system.js +148 -0
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -0
- package/dist/frontend/lowering/builtins/performance.d.ts +13 -0
- package/dist/frontend/lowering/builtins/performance.js +100 -0
- package/dist/frontend/lowering/builtins/performance.js.map +1 -0
- package/dist/frontend/lowering/builtins/process.d.ts +50 -0
- package/dist/frontend/lowering/builtins/process.js +1138 -0
- package/dist/frontend/lowering/builtins/process.js.map +1 -0
- package/dist/frontend/lowering/builtins/promises.d.ts +14 -0
- package/dist/frontend/lowering/builtins/promises.js +356 -0
- package/dist/frontend/lowering/builtins/promises.js.map +1 -0
- package/dist/frontend/lowering/builtins/properties.d.ts +11 -0
- package/dist/frontend/lowering/builtins/properties.js +186 -0
- package/dist/frontend/lowering/builtins/properties.js.map +1 -0
- package/dist/frontend/lowering/builtins/querystring.d.ts +19 -0
- package/dist/frontend/lowering/builtins/querystring.js +150 -0
- package/dist/frontend/lowering/builtins/querystring.js.map +1 -0
- package/dist/frontend/lowering/builtins/readline.d.ts +13 -0
- package/dist/frontend/lowering/builtins/readline.js +138 -0
- package/dist/frontend/lowering/builtins/readline.js.map +1 -0
- package/dist/frontend/lowering/builtins/receiver-types.d.ts +5 -0
- package/dist/frontend/lowering/builtins/receiver-types.js +15 -0
- package/dist/frontend/lowering/builtins/receiver-types.js.map +1 -0
- package/dist/frontend/lowering/builtins/reflection.d.ts +13 -0
- package/dist/frontend/lowering/builtins/reflection.js +95 -0
- package/dist/frontend/lowering/builtins/reflection.js.map +1 -0
- package/dist/frontend/lowering/builtins/strings.d.ts +14 -0
- package/dist/frontend/lowering/builtins/strings.js +121 -0
- package/dist/frontend/lowering/builtins/strings.js.map +1 -0
- package/dist/frontend/lowering/builtins/text-codecs.d.ts +29 -0
- package/dist/frontend/lowering/builtins/text-codecs.js +590 -0
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -0
- package/dist/frontend/lowering/builtins/timers.d.ts +22 -0
- package/dist/frontend/lowering/builtins/timers.js +180 -0
- package/dist/frontend/lowering/builtins/timers.js.map +1 -0
- package/dist/frontend/lowering/builtins/url.d.ts +37 -0
- package/dist/frontend/lowering/builtins/url.js +596 -0
- package/dist/frontend/lowering/builtins/url.js.map +1 -0
- package/dist/frontend/lowering/builtins/util-types.d.ts +7 -0
- package/dist/frontend/lowering/builtins/util-types.js +31 -0
- package/dist/frontend/lowering/builtins/util-types.js.map +1 -0
- package/dist/frontend/lowering/builtins/workers.d.ts +5 -0
- package/dist/frontend/lowering/builtins/workers.js +65 -0
- package/dist/frontend/lowering/builtins/workers.js.map +1 -0
- package/dist/frontend/lowering/call-arguments.d.ts +72 -0
- package/dist/frontend/lowering/call-arguments.js +618 -0
- package/dist/frontend/lowering/call-arguments.js.map +1 -0
- package/dist/frontend/lowering/call-signatures.d.ts +115 -0
- package/dist/frontend/lowering/call-signatures.js +719 -0
- package/dist/frontend/lowering/call-signatures.js.map +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/checked-iterable-spread.js +53 -10
- package/dist/frontend/lowering/checked-iterable-spread.js.map +1 -1
- package/dist/frontend/lowering/checked-promise-all.js +41 -9
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
- package/dist/frontend/lowering/class-assertions.d.ts +7 -0
- package/dist/frontend/lowering/class-assertions.js +96 -0
- package/dist/frontend/lowering/class-assertions.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/class-callbacks.js +130 -27
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +1 -1
- package/dist/frontend/lowering/class-construction.js +247 -50
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.js +109 -29
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +6 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +2471 -465
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +284 -44
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +17 -5
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.js +199 -51
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +17 -0
- package/dist/frontend/lowering/class-protocols.js +126 -0
- package/dist/frontend/lowering/class-protocols.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.js +345 -86
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js +80 -17
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.js +76 -16
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/coercions/builders.d.ts +13 -0
- package/dist/frontend/lowering/coercions/builders.js +77 -0
- package/dist/frontend/lowering/coercions/builders.js.map +1 -0
- package/dist/frontend/lowering/coercions/function-adapters.d.ts +58 -0
- package/dist/frontend/lowering/coercions/function-adapters.js +430 -0
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -0
- package/dist/frontend/lowering/coercions/island.d.ts +37 -0
- package/dist/frontend/lowering/coercions/island.js +350 -0
- package/dist/frontend/lowering/coercions/island.js.map +1 -0
- package/dist/frontend/lowering/coercions/state.d.ts +14 -0
- package/dist/frontend/lowering/coercions/state.js +16 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural-plans.d.ts +40 -0
- package/dist/frontend/lowering/coercions/structural-plans.js +447 -0
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural.d.ts +63 -0
- package/dist/frontend/lowering/coercions/structural.js +616 -0
- package/dist/frontend/lowering/coercions/structural.js.map +1 -0
- package/dist/frontend/lowering/coercions/unions.d.ts +65 -0
- package/dist/frontend/lowering/coercions/unions.js +318 -0
- package/dist/frontend/lowering/coercions/unions.js.map +1 -0
- package/dist/frontend/lowering/collection-ingestion.js +355 -72
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +88 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +1611 -0
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -0
- package/dist/frontend/lowering/containers/array-construction.d.ts +42 -0
- package/dist/frontend/lowering/containers/array-construction.js +1044 -0
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -0
- package/dist/frontend/lowering/containers/array-iteration.d.ts +16 -0
- package/dist/frontend/lowering/containers/array-iteration.js +95 -0
- package/dist/frontend/lowering/containers/array-iteration.js.map +1 -0
- package/dist/frontend/lowering/containers/array-methods.d.ts +27 -0
- package/dist/frontend/lowering/containers/array-methods.js +1854 -0
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +17 -17
- package/dist/frontend/lowering/containers/bytes.js +430 -138
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.d.ts +26 -0
- package/dist/frontend/lowering/containers/callback-arguments.js +179 -0
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -0
- package/dist/frontend/lowering/containers/collection-grouping.d.ts +19 -0
- package/dist/frontend/lowering/containers/collection-grouping.js +297 -0
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -0
- package/dist/frontend/lowering/containers/collection-methods.d.ts +57 -0
- package/dist/frontend/lowering/containers/collection-methods.js +1314 -0
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/dynamic-receivers.d.ts +18 -0
- package/dist/frontend/lowering/containers/dynamic-receivers.js +114 -0
- package/dist/frontend/lowering/containers/dynamic-receivers.js.map +1 -0
- package/dist/frontend/lowering/containers/for-of.d.ts +60 -0
- package/dist/frontend/lowering/containers/for-of.js +643 -0
- package/dist/frontend/lowering/containers/for-of.js.map +1 -0
- package/dist/frontend/lowering/containers/indexed-objects.d.ts +132 -0
- package/dist/frontend/lowering/containers/indexed-objects.js +1743 -0
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -0
- package/dist/frontend/lowering/containers/iterator-helpers.d.ts +20 -0
- package/dist/frontend/lowering/containers/iterator-helpers.js +809 -0
- package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +601 -160
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +213 -63
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/crypto-tables.js +263 -64
- package/dist/frontend/lowering/crypto-tables.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +172 -68
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.test.js +41 -8
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
- package/dist/frontend/lowering/error-methods.js +339 -65
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/evaluation-safety.js +3 -2
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/global-symbols.js +2 -1
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -1
- package/dist/frontend/lowering/expressions/native-proxy.js +11 -5
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +67 -13
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +588 -165
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +68 -17
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.js +45 -18
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
- package/dist/frontend/lowering/function-context.js +5 -1
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/function-returns.d.ts +67 -0
- package/dist/frontend/lowering/function-returns.js +392 -0
- package/dist/frontend/lowering/function-returns.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +1 -1
- package/dist/frontend/lowering/generator-delegation.js +171 -39
- package/dist/frontend/lowering/generator-delegation.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +176 -36
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +271 -0
- package/dist/frontend/lowering/generic-functions.js +1730 -0
- package/dist/frontend/lowering/generic-functions.js.map +1 -0
- package/dist/frontend/lowering/import-meta.d.ts +1 -1
- package/dist/frontend/lowering/import-meta.js +37 -14
- package/dist/frontend/lowering/import-meta.js.map +1 -1
- package/dist/frontend/lowering/indexed-comparison.js +6 -2
- package/dist/frontend/lowering/indexed-comparison.js.map +1 -1
- package/dist/frontend/lowering/instantiation-path.d.ts +8 -0
- package/dist/frontend/lowering/instantiation-path.js +10 -0
- package/dist/frontend/lowering/instantiation-path.js.map +1 -0
- package/dist/frontend/lowering/instantiation-path.test.d.ts +1 -0
- package/dist/frontend/lowering/instantiation-path.test.js +23 -0
- package/dist/frontend/lowering/instantiation-path.test.js.map +1 -0
- package/dist/frontend/lowering/iterator-consumption.d.ts +9 -0
- package/dist/frontend/lowering/iterator-consumption.js +91 -0
- package/dist/frontend/lowering/iterator-consumption.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.js +40 -17
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.js +49 -11
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.d.ts +0 -19
- package/dist/frontend/lowering/lower-array-sort.js +331 -566
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +248 -43
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +71 -16
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.js +430 -77
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +39 -558
- package/dist/frontend/lowering/lower-calls.js +2628 -5669
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +248 -242
- package/dist/frontend/lowering/lower-classes.js +1820 -775
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +35 -35
- package/dist/frontend/lowering/lower-comptime.js +39 -37
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +59 -31
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.js +5 -2
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +323 -86
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.js +19 -7
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +194 -194
- package/dist/frontend/lowering/lower-exprs.js +3473 -1160
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.d.ts +23 -0
- package/dist/frontend/lowering/lower-functions.js +449 -0
- package/dist/frontend/lowering/lower-functions.js.map +1 -0
- package/dist/frontend/lowering/lower-generators.js +121 -32
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +15 -4
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +479 -89
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +79 -79
- package/dist/frontend/lowering/lower-island.js +366 -274
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-island.test.js +7 -2
- package/dist/frontend/lowering/lower-island.test.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +17 -8
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +95 -94
- package/dist/frontend/lowering/lower-modules.js +655 -329
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +91 -20
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.js +25 -8
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.js +115 -34
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +1210 -290
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +148 -148
- package/dist/frontend/lowering/lower-stmts.js +2324 -994
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js +13 -5
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +363 -91
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-system-errors.js +30 -8
- package/dist/frontend/lowering/lower-system-errors.js.map +1 -1
- package/dist/frontend/lowering/lower-test.js +40 -13
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.d.ts +31 -0
- package/dist/frontend/lowering/lower-timers.js +336 -0
- package/dist/frontend/lowering/lower-timers.js.map +1 -0
- package/dist/frontend/lowering/lower-url.d.ts +1 -1
- package/dist/frontend/lowering/lower-url.js +46 -13
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +34 -352
- package/dist/frontend/lowering/lowerer.js +1074 -2712
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +85 -17
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.js +43 -8
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.d.ts +21 -1
- package/dist/frontend/lowering/native-ffi.js +487 -18
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/object-enumeration-receiver.js +55 -10
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -1
- package/dist/frontend/lowering/object-factory-new.d.ts +1 -1
- package/dist/frontend/lowering/object-factory-new.js +36 -11
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/optional-arguments.js +49 -20
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +66 -14
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.js +3 -1
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -1
- package/dist/frontend/lowering/sanitize-class-types.js +4 -1
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -1
- package/dist/frontend/lowering/sanitize-class-types.test.js +86 -18
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -1
- package/dist/frontend/lowering/split-consumers.d.ts +7 -0
- package/dist/frontend/lowering/split-consumers.js +64 -0
- package/dist/frontend/lowering/split-consumers.js.map +1 -0
- package/dist/frontend/lowering/static-this.js +13 -6
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.js +32 -10
- package/dist/frontend/lowering/string-index.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +45 -46
- package/dist/frontend/lowering/surfaces.js +1129 -256
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.js +40 -15
- package/dist/frontend/lowering/symbol-fields.js.map +1 -1
- package/dist/frontend/lowering/symbol-methods.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.js +236 -24
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -1
- package/dist/frontend/lowering/text-decoder-encoding.test.js +84 -12
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -1
- package/dist/frontend/lowering/union-narrow.js +59 -16
- package/dist/frontend/lowering/union-narrow.js.map +1 -1
- package/dist/frontend/lowering/union-narrow.test.js +24 -7
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -1
- package/dist/frontend/lowering/union-retag.js +155 -40
- package/dist/frontend/lowering/union-retag.js.map +1 -1
- package/dist/frontend/lowering/union-retag.test.js +131 -33
- package/dist/frontend/lowering/union-retag.test.js.map +1 -1
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -1
- package/dist/frontend/lowering/unregistered-class-types.test.js +34 -8
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -1
- package/dist/frontend/module-source-candidates.d.ts +10 -0
- package/dist/frontend/module-source-candidates.js +40 -0
- package/dist/frontend/module-source-candidates.js.map +1 -0
- package/dist/frontend/module-source-candidates.test.d.ts +1 -0
- package/dist/frontend/module-source-candidates.test.js +53 -0
- package/dist/frontend/module-source-candidates.test.js.map +1 -0
- package/dist/frontend/module-syntax.js +21 -8
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/module-syntax.test.js +37 -13
- package/dist/frontend/module-syntax.test.js.map +1 -1
- package/dist/frontend/npm-fetch-analysis.js +13 -4
- package/dist/frontend/npm-fetch-analysis.js.map +1 -1
- package/dist/frontend/npm-fetch-analysis.test.js +33 -10
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -1
- package/dist/frontend/npm-fetch-node.js.map +1 -1
- package/dist/frontend/npm-fetch-syntax.js +4 -9
- package/dist/frontend/npm-fetch-syntax.js.map +1 -1
- package/dist/frontend/npm-node.js +3 -1
- package/dist/frontend/npm-node.js.map +1 -1
- package/dist/frontend/npm-static-bundled-cjs.js +88 -29
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -1
- package/dist/frontend/npm-static-bundled-cjs.test.js +29 -10
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -1
- package/dist/frontend/npm-static-declaration-syntax.js +148 -56
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -1
- package/dist/frontend/npm-static-declarations.d.ts +1 -1
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +33 -7
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.js +26 -12
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +17 -3
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.js +2 -3
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +64 -21
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.js +9 -4
- package/dist/frontend/npm-static-subtyping.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.test.js +30 -6
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -1
- package/dist/frontend/npm-static.js +15 -4
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.js +122 -36
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +30 -10
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.js.map +1 -1
- package/dist/frontend/pipeline.js +25 -8
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/pipeline.test.js +21 -7
- package/dist/frontend/pipeline.test.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +2 -0
- package/dist/frontend/program-analysis.js +2 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program-node.js +5 -3
- package/dist/frontend/program-node.js.map +1 -1
- package/dist/frontend/program.d.ts +2 -2
- package/dist/frontend/program.js +248 -127
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +27 -27
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/provenance-core.js +8 -4
- package/dist/frontend/provenance-core.js.map +1 -1
- package/dist/frontend/provenance-registry.js +1 -4
- package/dist/frontend/provenance-registry.js.map +1 -1
- package/dist/frontend/resolve.js +32 -20
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +1 -1
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/runtime-resolve.js +13 -4
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +25 -9
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.js +6 -2
- package/dist/frontend/services-node.js.map +1 -1
- package/dist/frontend/services-node.test.js +18 -6
- package/dist/frontend/services-node.test.js.map +1 -1
- package/dist/frontend/services.js +8 -4
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +6 -2
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/ts7/api.js +12 -4
- package/dist/frontend/ts7/api.js.map +1 -1
- package/dist/frontend/ts7/ast-bytes.js +10 -3
- package/dist/frontend/ts7/ast-bytes.js.map +1 -1
- package/dist/frontend/ts7/ast-bytes.test.js +23 -4
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -1
- package/dist/frontend/ts7/ast-guards.test.js +14 -5
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +6 -1
- package/dist/frontend/ts7/ast-node.js +490 -172
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +150 -36
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-text.js +13 -3
- package/dist/frontend/ts7/ast-text.js.map +1 -1
- package/dist/frontend/ts7/ast-text.test.js.map +1 -1
- package/dist/frontend/ts7/ast-types.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +5 -1
- package/dist/frontend/ts7/ast-wire.js +83 -20
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.test.js +53 -8
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -1
- package/dist/frontend/ts7/ast.d.ts +2 -1
- package/dist/frontend/ts7/ast.js +53 -30
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -1
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +8 -2
- package/dist/frontend/ts7/checker.js +46 -8
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +96 -17
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/enums.test.js +9 -4
- package/dist/frontend/ts7/enums.test.js.map +1 -1
- package/dist/frontend/ts7/native-api.js.map +1 -1
- package/dist/frontend/ts7/native-host.js.map +1 -1
- package/dist/frontend/ts7/native-process.js +9 -3
- package/dist/frontend/ts7/native-process.js.map +1 -1
- package/dist/frontend/ts7/program-adapter.js +1 -1
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +7 -0
- package/dist/frontend/ts7/program-host.js +33 -6
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/program-host.test.js +72 -11
- package/dist/frontend/ts7/program-host.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-api.js +3 -1
- package/dist/frontend/ts7/rpc-api.js.map +1 -1
- package/dist/frontend/ts7/rpc-client.js +15 -5
- package/dist/frontend/ts7/rpc-client.js.map +1 -1
- package/dist/frontend/ts7/rpc-client.test.js +26 -8
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -1
- package/dist/frontend/ts7/rpc-filesystem.test.js +43 -10
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-process.js +16 -6
- package/dist/frontend/ts7/rpc-process.js.map +1 -1
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -1
- package/dist/frontend/ts7/rpc-wire.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.js +41 -14
- package/dist/frontend/ts7/rpc-wire.js.map +1 -1
- package/dist/frontend/ts7/rpc-wire.test.js +36 -6
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.js +209 -68
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.test.js +29 -14
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.js +7 -1
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.test.js +17 -3
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.js +147 -51
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +72 -19
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-types.d.ts +2 -2
- package/dist/frontend/ts7/session-cache.js +10 -3
- package/dist/frontend/ts7/session-cache.js.map +1 -1
- package/dist/frontend/ts7/session-cache.test.js +13 -4
- package/dist/frontend/ts7/session-cache.test.js.map +1 -1
- package/dist/frontend/ts7/session-path.js +25 -10
- package/dist/frontend/ts7/session-path.js.map +1 -1
- package/dist/frontend/ts7/session-path.test.js +47 -4
- package/dist/frontend/ts7/session-path.test.js.map +1 -1
- package/dist/frontend/ts7/session-timing.js +22 -3
- package/dist/frontend/ts7/session-timing.js.map +1 -1
- package/dist/frontend/ts7/session-timing.test.js +12 -3
- package/dist/frontend/ts7/session-timing.test.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +1 -0
- package/dist/frontend/ts7/session.js +109 -35
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/ts7/session.test.js +69 -15
- package/dist/frontend/ts7/session.test.js.map +1 -1
- package/dist/frontend/ts7/source-parser.js +17 -6
- package/dist/frontend/ts7/source-parser.js.map +1 -1
- package/dist/frontend/ts7/source-parser.test.js +32 -9
- package/dist/frontend/ts7/source-parser.test.js.map +1 -1
- package/dist/frontend/tsc-codes.js +56 -11
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/tsc-codes.test.d.ts +1 -0
- package/dist/frontend/tsc-codes.test.js +16 -0
- package/dist/frontend/tsc-codes.test.js.map +1 -0
- package/dist/frontend/type-mapper.d.ts +3 -0
- package/dist/frontend/type-mapper.js +589 -206
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +108 -33
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.js +8 -2
- package/dist/frontend/union-discriminants.js.map +1 -1
- package/dist/frontend/union-discriminants.test.js +77 -20
- package/dist/frontend/union-discriminants.test.js.map +1 -1
- package/dist/frontend/worker-target.d.ts +6 -0
- package/dist/frontend/worker-target.js +108 -0
- package/dist/frontend/worker-target.js.map +1 -0
- package/dist/frontend/worker-target.test.d.ts +1 -0
- package/dist/frontend/worker-target.test.js +71 -0
- package/dist/frontend/worker-target.test.js.map +1 -0
- package/dist/index.d.ts +9 -8
- package/dist/index.js +174 -88
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +95 -38
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +91 -15
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/api.d.ts +4 -0
- package/dist/ir/api.js +6 -0
- package/dist/ir/api.js.map +1 -0
- package/dist/ir/build.d.ts +7 -0
- package/dist/ir/build.js +27 -1
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-effects.d.ts +9 -0
- package/dist/ir/builtin-effects.js +643 -0
- package/dist/ir/builtin-effects.js.map +1 -0
- package/dist/ir/builtin-signatures.d.ts +15 -0
- package/dist/ir/builtin-signatures.js +3397 -0
- package/dist/ir/builtin-signatures.js.map +1 -0
- package/dist/ir/byte-numbers.js +67 -16
- package/dist/ir/byte-numbers.js.map +1 -1
- package/dist/ir/byte-numbers.test.js +17 -4
- package/dist/ir/byte-numbers.test.js.map +1 -1
- package/dist/ir/constant-tables.js +13 -5
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +47 -7
- package/dist/ir/constant-tables.test.js.map +1 -1
- package/dist/ir/control-flow.js +2 -1
- package/dist/ir/control-flow.js.map +1 -1
- package/dist/ir/control-flow.test.js +35 -11
- package/dist/ir/control-flow.test.js.map +1 -1
- package/dist/ir/initializer-bindings.d.ts +9 -0
- package/dist/ir/initializer-bindings.js +115 -0
- package/dist/ir/initializer-bindings.js.map +1 -0
- package/dist/ir/initializer-bindings.test.d.ts +1 -0
- package/dist/ir/initializer-bindings.test.js +118 -0
- package/dist/ir/initializer-bindings.test.js.map +1 -0
- package/dist/ir/integer-loop-facts.d.ts +12 -0
- package/dist/ir/integer-loop-facts.js +137 -0
- package/dist/ir/integer-loop-facts.js.map +1 -0
- package/dist/ir/integer-loops.js +85 -30
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +76 -13
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.js +93 -21
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +199 -21
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/intrinsic-signatures.d.ts +20 -0
- package/dist/ir/intrinsic-signatures.js +57 -0
- package/dist/ir/intrinsic-signatures.js.map +1 -0
- package/dist/ir/ir.d.ts +15 -2160
- package/dist/ir/ir.js +160 -1396
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +98 -77
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/numeric-call-specialization.d.ts +8 -0
- package/dist/ir/numeric-call-specialization.js +198 -0
- package/dist/ir/numeric-call-specialization.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +221 -0
- package/dist/ir/runtime-features.js +552 -0
- package/dist/ir/runtime-features.js.map +1 -0
- package/dist/ir/runtime-features.test.d.ts +1 -0
- package/dist/ir/runtime-features.test.js +98 -0
- package/dist/ir/runtime-features.test.js.map +1 -0
- package/dist/ir/scalar-records.js +130 -40
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +146 -27
- package/dist/ir/scalar-records.test.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +7 -5
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +44 -9
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/traverse.js +156 -43
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/traverse.test.js +99 -24
- package/dist/ir/traverse.test.js.map +1 -1
- package/dist/ir/validate.d.ts +1 -31
- package/dist/ir/validate.js +869 -1910
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +697 -114
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.js +9 -10
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/cache-reset.test.js +2 -1
- package/dist/library/cache-reset.test.js.map +1 -1
- package/dist/library/compiler-self-identity.js +11 -5
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/compiler-self-identity.test.js +10 -3
- package/dist/library/compiler-self-identity.test.js.map +1 -1
- package/dist/library/fence-eval.js +24 -7
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/fence-eval.test.js +31 -7
- package/dist/library/fence-eval.test.js.map +1 -1
- package/dist/library/int-infer.js +199 -59
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +137 -61
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/ir-policy.d.ts +27 -0
- package/dist/library/ir-policy.js +234 -0
- package/dist/library/ir-policy.js.map +1 -0
- package/dist/library/library-cache.js +40 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +29 -18
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.js +68 -13
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.js +48 -20
- package/dist/library/prepare.js.map +1 -1
- package/dist/library/semantic-source.js +16 -14
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/semantic-source.test.js +9 -14
- package/dist/library/semantic-source.test.js.map +1 -1
- package/dist/library/sidecar-validate.js +53 -12
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.js +85 -24
- package/dist/library/sidecar.js.map +1 -1
- package/dist/library/trap-teaching.js +11 -2
- package/dist/library/trap-teaching.js.map +1 -1
- package/dist/native/cache.js +10 -4
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cli.js +34 -9
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +191 -54
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +134 -33
- package/dist/native/compiler.test.js.map +1 -1
- package/dist/native/comptime.js +23 -7
- package/dist/native/comptime.js.map +1 -1
- package/dist/native/comptime.test.js +26 -6
- package/dist/native/comptime.test.js.map +1 -1
- package/dist/native/executable-cache.js +77 -27
- package/dist/native/executable-cache.js.map +1 -1
- package/dist/native/executable-cache.test.js +41 -6
- package/dist/native/executable-cache.test.js.map +1 -1
- package/dist/native/file-identity.js +9 -2
- package/dist/native/file-identity.js.map +1 -1
- package/dist/native/file-identity.test.js.map +1 -1
- package/dist/native/library.js +50 -12
- package/dist/native/library.js.map +1 -1
- package/dist/native/prepare.js +121 -34
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/prepare.test.js +22 -6
- package/dist/native/prepare.test.js.map +1 -1
- package/dist/native/runtime-typescript.js +24 -11
- package/dist/native/runtime-typescript.js.map +1 -1
- package/dist/native/runtime-typescript.test.js.map +1 -1
- package/dist/native/sanitizer.js +71 -18
- package/dist/native/sanitizer.js.map +1 -1
- package/dist/native/sanitizer.test.js +78 -20
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/task.js.map +1 -1
- package/dist/native/task.test.js +7 -2
- package/dist/native/task.test.js.map +1 -1
- package/dist/native/toolchain.js +68 -26
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +59 -20
- package/dist/native/toolchain.test.js.map +1 -1
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +1 -1
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +30 -2
- package/dist/frontend/lowering/lower-builtins.d.ts +0 -601
- package/dist/frontend/lowering/lower-builtins.js +0 -8986
- package/dist/frontend/lowering/lower-builtins.js.map +0 -1
- package/dist/frontend/lowering/lower-containers.d.ts +0 -382
- package/dist/frontend/lowering/lower-containers.js +0 -7344
- package/dist/frontend/lowering/lower-containers.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { dynUndefinedExpr, nodeThrowExpr } from "../../ir/build.js";
|
|
1
2
|
import { InternalCompilerError } from "../../errors.js";
|
|
2
3
|
/* Class lowering: shape collection over the single-inheritance graph
|
|
3
4
|
* (fields, methods, accessors, overrides), constructor/member lowering with
|
|
@@ -5,23 +6,32 @@ import { InternalCompilerError } from "../../errors.js";
|
|
|
5
6
|
* accessor access, upcasts, `new` expressions, and the builtin Error
|
|
6
7
|
* hierarchy registration. */
|
|
7
8
|
import * as ts from "../ts7/adapter.js";
|
|
8
|
-
import { BOOL, DATE_T, DYN, F64, bytesOf, JSVAL, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, UNDEFINED_T, VOID, arrayOf, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, typeEquals } from "../../ir/ir.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { BOOL, DATE_T, DYN, F64, bytesOf, JSVAL, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, UNDEFINED_T, VOID, arrayOf, isSupportedMapKey, isSupportedMapValue, isSupportedSetElem, isUnitType, typeEquals, } from "../../ir/ir.js";
|
|
10
|
+
import { genericCallInstance, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, } from "./generic-functions.js";
|
|
11
|
+
import { extendInstantiationPath, MAX_INSTANTIATION_RECURSION, } from "./instantiation-path.js";
|
|
12
|
+
import { appendImplicitUndefinedReturn, hasExplicitJsDocReturn } from "./function-returns.js";
|
|
13
|
+
import { bodyReadsArguments } from "../arguments-usage.js";
|
|
14
|
+
import { generatorMeta } from "./call-signatures.js";
|
|
15
|
+
import { omittedArgFor } from "./call-arguments.js";
|
|
16
|
+
import { isGenericCallableMemberType, jsOpenObjectType, typeKey, withUnitArm, } from "../type-mapper.js";
|
|
17
|
+
import { cjsClassExprWholeExportOf, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeTypesPath, locOf, } from "../program.js";
|
|
18
|
+
import { PoisonError, dynFallbackType, newFnCtx, own } from "./lowerer.js";
|
|
19
|
+
import { lowerArrayConstructor } from "./containers/array-construction.js";
|
|
20
|
+
import { lowerMapSeedNew, lowerSetSeedNew } from "./containers/collection-methods.js";
|
|
21
|
+
import { lowerObjectConstructor } from "./containers/indexed-objects.js";
|
|
14
22
|
import { bufEncoding } from "./containers/bytes.js";
|
|
15
23
|
import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
|
|
16
|
-
import { lowerSearchParamsNew
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
24
|
+
import { lowerSearchParamsNew } from "./builtins/url.js";
|
|
25
|
+
import { lowerTextCodecNew } from "./builtins/text-codecs.js";
|
|
26
|
+
import { lowerWorkerNew } from "./builtins/workers.js";
|
|
27
|
+
import { requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
28
|
+
import { STREAM_API_MEMBERS, STREAM_PROP_MEMBERS, UNDERSCORE_METHODS, lowerStreamNew, lowerStreamSuperCall, streamCtorShape, } from "./lower-stream.js";
|
|
29
|
+
import { emitOverrideShapeReason, emitSpecSuperForward, emitterRooted, lowerEmitterSuperCall, } from "./lower-event-emitter.js";
|
|
20
30
|
import { declSymbolOf } from "./lower-modules.js";
|
|
21
|
-
import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName } from "./symbol-fields.js";
|
|
31
|
+
import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName, } from "./symbol-fields.js";
|
|
22
32
|
import { builtinFenceHintOf } from "./surfaces.js";
|
|
23
33
|
import { lowerHttpAgentNew, lowerHttpServerNew } from "./lower-server.js";
|
|
24
|
-
import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead } from "./lower-namespaces.js";
|
|
34
|
+
import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead, } from "./lower-namespaces.js";
|
|
25
35
|
import { mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
26
36
|
import { hasLexicalPrivateReference, hasStaticThis, rejectStaticThis } from "./static-this.js";
|
|
27
37
|
import { lowerUrlNew } from "./lower-url.js";
|
|
@@ -68,7 +78,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
68
78
|
visiting.add(expression);
|
|
69
79
|
if (ts.isParenthesizedExpression(expression))
|
|
70
80
|
return storedClassValueType(lowerer, expression.expression, visiting);
|
|
71
|
-
if (ts.isClassExpression(expression) &&
|
|
81
|
+
if (ts.isClassExpression(expression) &&
|
|
82
|
+
!functionLocalClass(expression) &&
|
|
83
|
+
!lowerer.collectingExprClasses.has(expression)) {
|
|
72
84
|
const info = lowerer.lowerClassExpressionInfo(expression);
|
|
73
85
|
return { kind: "classval", className: info.def.name };
|
|
74
86
|
}
|
|
@@ -87,7 +99,12 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
87
99
|
if (stored?.type.kind === "classval" && lowerer.classes.has(stored.type.className))
|
|
88
100
|
return stored.type;
|
|
89
101
|
const symbol = lowerer.resolveValueSymbol(expression);
|
|
90
|
-
const declaration = symbol &&
|
|
102
|
+
const declaration = symbol &&
|
|
103
|
+
lowerer.checker
|
|
104
|
+
.declarationsOf(symbol)
|
|
105
|
+
.find((decl) => ts.isVariableDeclaration(decl) &&
|
|
106
|
+
decl.initializer &&
|
|
107
|
+
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
91
108
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
92
109
|
const value = storedClassValueType(lowerer, declaration.initializer, visiting);
|
|
93
110
|
if (value?.kind === "classval")
|
|
@@ -100,7 +117,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
100
117
|
for (const signature of lowerer.checker.getConstructSignatures(type)) {
|
|
101
118
|
const constructor = lowerer.checker.signatureDeclaration(signature);
|
|
102
119
|
const declaration = constructor && ts.isConstructorDeclaration(constructor) ? constructor.parent : undefined;
|
|
103
|
-
if (declaration &&
|
|
120
|
+
if (declaration &&
|
|
121
|
+
ts.isClassExpression(declaration) &&
|
|
122
|
+
!functionLocalClass(declaration) &&
|
|
104
123
|
!lowerer.collectingExprClasses.has(declaration)) {
|
|
105
124
|
const info = lowerer.lowerClassExpressionInfo(declaration);
|
|
106
125
|
return { kind: "classval", className: info.def.name };
|
|
@@ -134,7 +153,12 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
134
153
|
}
|
|
135
154
|
if (ts.isIdentifier(callee)) {
|
|
136
155
|
const symbol = lowerer.resolveValueSymbol(callee);
|
|
137
|
-
const declaration = symbol &&
|
|
156
|
+
const declaration = symbol &&
|
|
157
|
+
lowerer.checker
|
|
158
|
+
.declarationsOf(symbol)
|
|
159
|
+
.find((decl) => ts.isVariableDeclaration(decl) &&
|
|
160
|
+
decl.initializer &&
|
|
161
|
+
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
138
162
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
139
163
|
callee = declaration.initializer;
|
|
140
164
|
continue;
|
|
@@ -142,13 +166,18 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
142
166
|
}
|
|
143
167
|
break;
|
|
144
168
|
}
|
|
145
|
-
if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) &&
|
|
146
|
-
|
|
169
|
+
if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) &&
|
|
170
|
+
isJsSourceFile(callee.getSourceFile()) &&
|
|
171
|
+
!callee.typeParameters?.length &&
|
|
172
|
+
!lowerer.preparingClassFactories.has(callee)) {
|
|
147
173
|
const signature = lowerer.checker.getSignatureFromDeclaration(callee);
|
|
148
174
|
let result = signature && lowerer.checker.getReturnTypeOfSignature(signature);
|
|
149
175
|
for (let i = 1; result && i < calls; i++) {
|
|
150
176
|
const signatures = lowerer.checker.getCallSignatures(result);
|
|
151
|
-
result =
|
|
177
|
+
result =
|
|
178
|
+
signatures.length === 1
|
|
179
|
+
? lowerer.checker.getReturnTypeOfSignature(signatures[0])
|
|
180
|
+
: undefined;
|
|
152
181
|
}
|
|
153
182
|
if (result && lowerer.checker.getConstructSignatures(result).length > 0) {
|
|
154
183
|
const returned = (value) => {
|
|
@@ -158,7 +187,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
158
187
|
return type.kind === "classval" ? type : null;
|
|
159
188
|
};
|
|
160
189
|
const home = callee.parent;
|
|
161
|
-
const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)
|
|
190
|
+
const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)
|
|
191
|
+
? lowerer.genericFnOf(home.name)
|
|
192
|
+
: null;
|
|
162
193
|
if (generic?.implicitParams && ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)) {
|
|
163
194
|
const factory = lowerer.lowerGenericFnValue(home.name, generic);
|
|
164
195
|
const type = returned(factory);
|
|
@@ -202,10 +233,15 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
202
233
|
break;
|
|
203
234
|
}
|
|
204
235
|
}
|
|
205
|
-
if (!factory ||
|
|
206
|
-
!
|
|
207
|
-
|
|
208
|
-
!ts.
|
|
236
|
+
if (!factory ||
|
|
237
|
+
!isJsSourceFile(factory.getSourceFile()) ||
|
|
238
|
+
factory.typeParameters?.length ||
|
|
239
|
+
!ts.isVariableDeclaration(factory.parent) ||
|
|
240
|
+
factory.parent.initializer !== factory ||
|
|
241
|
+
!ts.isVariableDeclarationList(factory.parent.parent) ||
|
|
242
|
+
!(factory.parent.parent.flags & ts.NodeFlags.Const) ||
|
|
243
|
+
!ts.isVariableStatement(factory.parent.parent.parent) ||
|
|
244
|
+
!ts.isSourceFile(factory.parent.parent.parent.parent) ||
|
|
209
245
|
lowerer.preparingClassFactories.has(factory))
|
|
210
246
|
continue;
|
|
211
247
|
if (!lowerer.preparedClassFactories.has(factory)) {
|
|
@@ -229,10 +265,10 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
229
265
|
return mapped;
|
|
230
266
|
}
|
|
231
267
|
/** The KEY symbol behind a LATE-BOUND (`__@name@id`) property: resolved
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
268
|
+
* from the argument of the element-access assignment that declared it
|
|
269
|
+
* (`this[kLimit] = v` — the declaration list holds the BinaryExpression
|
|
270
|
+
* or the ElementAccessExpression itself). Null when no declaration has
|
|
271
|
+
* that shape (well-known-symbol members like `[Symbol.iterator]`). */
|
|
236
272
|
function lateBoundKeySymOf(lowerer, p) {
|
|
237
273
|
for (const d of lowerer.checker.declarationsOf(p)) {
|
|
238
274
|
const access = ts.isBinaryExpression(d) && ts.isElementAccessExpression(d.left)
|
|
@@ -249,20 +285,20 @@ function lateBoundKeySymOf(lowerer, p) {
|
|
|
249
285
|
return null;
|
|
250
286
|
}
|
|
251
287
|
/** Symbol-slot RETURN refinement (5.9.3 ABI parity): tsgo synthesizes no
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
288
|
+
* late-bound property for a JS class's `this[k] = v` declaration (the
|
|
289
|
+
* finding-5 family), so an unannotated method whose returns read a
|
|
290
|
+
* declared symbol-keyed slot infers `any` — the checked-dynamic
|
|
291
|
+
* fallback would box a value whose static type the class layout already
|
|
292
|
+
* knows (5.9.3 inferred it through the late-bound property; runtime
|
|
293
|
+
* output was identical either way, but the method ABI carried a dyn
|
|
294
|
+
* box). Recovered here from the layout itself, under a shape that
|
|
295
|
+
* cannot mis-type: an unannotated, non-async, non-generator JS method
|
|
296
|
+
* whose LAST top-level statement is a return (no fall-through
|
|
297
|
+
* `undefined` completion), where EVERY return statement (nested
|
|
298
|
+
* functions excluded — they return elsewhere) returns `this[k]` with a
|
|
299
|
+
* statically-resolved key declared in symbolFields, and all the slots
|
|
300
|
+
* agree on one IR type. Null when the shape doesn't hold — the value
|
|
301
|
+
* stays checked-dynamic exactly as before. */
|
|
266
302
|
function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
267
303
|
if (symbolFields.size === 0)
|
|
268
304
|
return null;
|
|
@@ -308,12 +344,12 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
|
308
344
|
return out;
|
|
309
345
|
}
|
|
310
346
|
/** The builtin Error hierarchy
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
347
|
+
* as eagerly-registered ClassInfos: mapType names them the moment a lib
|
|
348
|
+
* Error type appears, so the infos must exist before any lowering. They
|
|
349
|
+
* are runtime-provided — no decl, no lowerable bodies; `new`/super()/
|
|
350
|
+
* toString reach them through dedicated error.* libCall lowerings, and
|
|
351
|
+
* user classes extend them like any base (the emitted subclass struct
|
|
352
|
+
* embeds ScrError's prefix). */
|
|
317
353
|
export function registerBuiltinErrorClasses(lowerer) {
|
|
318
354
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
319
355
|
for (const [irName, rec] of RUNTIME_ERROR_CLASSES) {
|
|
@@ -363,7 +399,10 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
363
399
|
ctor: null,
|
|
364
400
|
// Inherited constructors forward both raw arguments. The runtime
|
|
365
401
|
// applies the undefined message default and InstallErrorCause.
|
|
366
|
-
ctorParams: [
|
|
402
|
+
ctorParams: [
|
|
403
|
+
{ type: DYN, mode: "omittable" },
|
|
404
|
+
{ type: DYN, mode: "omittable" },
|
|
405
|
+
],
|
|
367
406
|
base,
|
|
368
407
|
subclasses: [],
|
|
369
408
|
throwingSetters: [],
|
|
@@ -375,14 +414,14 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
375
414
|
}
|
|
376
415
|
}
|
|
377
416
|
/** The runtime-provided node:events EventEmitter as an eagerly-registered
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
417
|
+
* ClassInfo (the error-hierarchy story): mapType names `%EventEmitter`
|
|
418
|
+
* the moment an emitter type appears, so the info must exist before any
|
|
419
|
+
* lowering. No decl, no lowerable bodies — `new`/super() reach it
|
|
420
|
+
* through emitter.* libCalls, the method surface lowers through
|
|
421
|
+
* lower-event-emitter.ts, and user classes extend it like any base (the
|
|
422
|
+
* emitted subclass struct embeds ScrEmitter's registry/name prefix —
|
|
423
|
+
* carried by the BACKEND, not by IR fields, so the fields list stays
|
|
424
|
+
* empty and subclass field layout starts right after the prefix). */
|
|
386
425
|
export function registerBuiltinEmitterClass(lowerer) {
|
|
387
426
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
388
427
|
const info = {
|
|
@@ -404,13 +443,13 @@ export function registerBuiltinEmitterClass(lowerer) {
|
|
|
404
443
|
lowerer.classes.set(RUNTIME_EMITTER_CLASS, info);
|
|
405
444
|
}
|
|
406
445
|
/** The runtime-provided node:stream classes as eagerly-registered
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
446
|
+
* ClassInfos (the emitter story): mapType names `%Readable` et al the
|
|
447
|
+
* moment a stream type appears, so the infos must exist before any
|
|
448
|
+
* lowering. Each roots at the emitter through its base chain, so the
|
|
449
|
+
* EventEmitter method surface, upcasts, and instanceof intervals apply
|
|
450
|
+
* unchanged; the stream method/property surface lowers through
|
|
451
|
+
* lower-stream.ts. No decl, no lowerable bodies, empty field lists —
|
|
452
|
+
* every instance is runtime-allocated (user `extends` is fenced). */
|
|
414
453
|
export function registerBuiltinStreamClasses(lowerer) {
|
|
415
454
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
416
455
|
for (const [irName, rec] of RUNTIME_STREAM_CLASSES) {
|
|
@@ -437,12 +476,12 @@ export function registerBuiltinStreamClasses(lowerer) {
|
|
|
437
476
|
}
|
|
438
477
|
}
|
|
439
478
|
/** The stream ClassInfo a VALUE symbol refers to (`new Readable(...)`,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
479
|
+
* `x instanceof Writable`) — any import spelling resolves to the
|
|
480
|
+
* ambient class. Provenance: a stdlib-file CLASS declaration inside the
|
|
481
|
+
* "stream" ambient module, EXCLUDING @types/node's (whose stream.Readable
|
|
482
|
+
* also types child stdio — under @types/node the childStream mapping
|
|
483
|
+
* keeps priority and the static stream classes stand down; the shipped
|
|
484
|
+
* fallback declarations are the supported surface). */
|
|
446
485
|
export function builtinStreamInfoOf(lowerer, symbol) {
|
|
447
486
|
if (!symbol)
|
|
448
487
|
return null;
|
|
@@ -454,7 +493,8 @@ export function builtinStreamInfoOf(lowerer, symbol) {
|
|
|
454
493
|
// alias plumbing (streamClassAliasDecl — both declaration walks
|
|
455
494
|
// skip it).
|
|
456
495
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
457
|
-
if (decl &&
|
|
496
|
+
if (decl &&
|
|
497
|
+
ts.isVariableDeclaration(decl) &&
|
|
458
498
|
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 &&
|
|
459
499
|
decl.initializer !== undefined &&
|
|
460
500
|
ts.isPropertyAccessExpression(decl.initializer) &&
|
|
@@ -495,8 +535,12 @@ export function builtinStreamInfoOf(lowerer, symbol) {
|
|
|
495
535
|
function jsFieldInitializerType(lowerer, type, expression) {
|
|
496
536
|
if (ts.isIdentifier(expression)) {
|
|
497
537
|
const symbol = lowerer.checker.getSymbolAtLocation(expression);
|
|
498
|
-
if (symbol &&
|
|
499
|
-
|
|
538
|
+
if (symbol &&
|
|
539
|
+
lowerer.checker
|
|
540
|
+
.declarationsOf(symbol)
|
|
541
|
+
.some((decl) => ts.isParameter(decl) &&
|
|
542
|
+
(ts.isConstructorDeclaration(decl.parent) ||
|
|
543
|
+
(lowerer.typeOf(expression).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)))
|
|
500
544
|
return DYN;
|
|
501
545
|
}
|
|
502
546
|
if (type.kind === "array" || type.kind === "record")
|
|
@@ -507,17 +551,25 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
507
551
|
if (type.kind === "f64" && isJsSourceFile(expression.getSourceFile())) {
|
|
508
552
|
const assignment = expression.parent;
|
|
509
553
|
const left = ts.isBinaryExpression(assignment) ? assignment.left : null;
|
|
510
|
-
const field = left &&
|
|
554
|
+
const field = left &&
|
|
555
|
+
ts.isPropertyAccessExpression(left) &&
|
|
556
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword
|
|
557
|
+
? left.name.text
|
|
558
|
+
: null;
|
|
511
559
|
let owner = expression.parent;
|
|
512
560
|
while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
|
|
513
561
|
owner = owner.parent;
|
|
514
562
|
if (field && owner) {
|
|
515
563
|
let acceptsUnchecked = false;
|
|
516
564
|
const scan = (node) => {
|
|
517
|
-
if (acceptsUnchecked ||
|
|
565
|
+
if (acceptsUnchecked ||
|
|
566
|
+
(node !== owner && (ts.isClassDeclaration(node) || ts.isClassExpression(node))))
|
|
518
567
|
return;
|
|
519
|
-
if (ts.isBinaryExpression(node) &&
|
|
520
|
-
|
|
568
|
+
if (ts.isBinaryExpression(node) &&
|
|
569
|
+
node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
570
|
+
ts.isPropertyAccessExpression(node.left) &&
|
|
571
|
+
node.left.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
572
|
+
node.left.name.text === field) {
|
|
521
573
|
let rhs = node.right;
|
|
522
574
|
while (ts.isParenthesizedExpression(rhs))
|
|
523
575
|
rhs = rhs.expression;
|
|
@@ -538,14 +590,17 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
538
590
|
let prototypeArgument = false;
|
|
539
591
|
for (const argument of node.arguments)
|
|
540
592
|
ts.walkPreorder(argument, (part) => {
|
|
541
|
-
if (!ts.isPropertyAccessExpression(part) ||
|
|
593
|
+
if (!ts.isPropertyAccessExpression(part) ||
|
|
594
|
+
part.expression.kind !== ts.SyntaxKind.ThisKeyword)
|
|
542
595
|
return;
|
|
543
596
|
const symbol = lowerer.checker.getSymbolAtLocation(part.name);
|
|
544
|
-
if (symbol &&
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
member
|
|
548
|
-
|
|
597
|
+
if (symbol &&
|
|
598
|
+
lowerer.checker.declarationsOf(symbol).some((decl) => {
|
|
599
|
+
const member = ts.isBinaryExpression(decl) ? decl.left : decl;
|
|
600
|
+
return (ts.isPropertyAccessExpression(member) &&
|
|
601
|
+
ts.isPropertyAccessExpression(member.expression) &&
|
|
602
|
+
member.expression.name.text === "prototype");
|
|
603
|
+
}))
|
|
549
604
|
prototypeArgument = true;
|
|
550
605
|
// JS checkers can synthesize a property declaration for prototype
|
|
551
606
|
// assignments. Keep the source ownership proof when that happens.
|
|
@@ -555,12 +610,17 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
555
610
|
if (owner && (ts.isClassDeclaration(owner) || ts.isClassExpression(owner)) && owner.name) {
|
|
556
611
|
const className = owner.name.text;
|
|
557
612
|
for (const statement of owner.getSourceFile().statements) {
|
|
558
|
-
if (!ts.isExpressionStatement(statement) ||
|
|
613
|
+
if (!ts.isExpressionStatement(statement) ||
|
|
614
|
+
!ts.isBinaryExpression(statement.expression))
|
|
559
615
|
continue;
|
|
560
616
|
const left = statement.expression.left;
|
|
561
|
-
if (statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
562
|
-
|
|
563
|
-
|
|
617
|
+
if (statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
618
|
+
ts.isPropertyAccessExpression(left) &&
|
|
619
|
+
left.name.text === part.name.text &&
|
|
620
|
+
ts.isPropertyAccessExpression(left.expression) &&
|
|
621
|
+
left.expression.name.text === "prototype" &&
|
|
622
|
+
ts.isIdentifier(left.expression.expression) &&
|
|
623
|
+
left.expression.expression.text === className)
|
|
564
624
|
prototypeArgument = true;
|
|
565
625
|
}
|
|
566
626
|
}
|
|
@@ -572,7 +632,7 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
572
632
|
}
|
|
573
633
|
if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
|
|
574
634
|
const ret = lowerer.declaredReturnType(node, node);
|
|
575
|
-
const arms = type.kind === "union" ? lowerer.unions.get(type.unionId)?.arms ?? [] : [type];
|
|
635
|
+
const arms = type.kind === "union" ? (lowerer.unions.get(type.unionId)?.arms ?? []) : [type];
|
|
576
636
|
// Inferred arithmetic may return a checked Number or BigInt. Preserve
|
|
577
637
|
// the callable when its native return ABI differs from the checker slot.
|
|
578
638
|
if (arms.some((arm) => arm.kind === "func" && !typeEquals(arm.ret, ret)))
|
|
@@ -581,13 +641,22 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
581
641
|
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
582
642
|
return withUnitArm(type, "nullT", lowerer.unions) ?? type;
|
|
583
643
|
const inferred = lowerer.typeOf(node);
|
|
584
|
-
const scalar = (inferred.flags & ts.TypeFlags.BooleanLike) !== 0
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
644
|
+
const scalar = (inferred.flags & ts.TypeFlags.BooleanLike) !== 0
|
|
645
|
+
? "bool"
|
|
646
|
+
: (inferred.flags & ts.TypeFlags.NumberLike) !== 0
|
|
647
|
+
? "f64"
|
|
648
|
+
: (inferred.flags & ts.TypeFlags.StringLike) !== 0
|
|
649
|
+
? "string"
|
|
650
|
+
: (inferred.flags & ts.TypeFlags.BigIntLike) !== 0
|
|
651
|
+
? "bigint"
|
|
652
|
+
: (inferred.flags & ts.TypeFlags.ESSymbolLike) !== 0
|
|
653
|
+
? "symbol"
|
|
654
|
+
: null;
|
|
655
|
+
if (scalar &&
|
|
656
|
+
type.kind !== "dyn" &&
|
|
657
|
+
type.kind !== scalar &&
|
|
658
|
+
!(type.kind === "union" &&
|
|
659
|
+
lowerer.unions.get(type.unionId)?.arms.some((arm) => arm.kind === scalar)))
|
|
591
660
|
return DYN;
|
|
592
661
|
for (const arm of inferred.isUnionType() ? ts.constituentTypes(inferred) : [inferred]) {
|
|
593
662
|
if ((arm.flags & ts.TypeFlags.Undefined) !== 0)
|
|
@@ -618,7 +687,10 @@ function inheritedJsFieldType(lowerer, decl, name, type) {
|
|
|
618
687
|
return type;
|
|
619
688
|
}
|
|
620
689
|
function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
621
|
-
if (!isJsSourceFile(member.getSourceFile()) ||
|
|
690
|
+
if (!isJsSourceFile(member.getSourceFile()) ||
|
|
691
|
+
member.type ||
|
|
692
|
+
member.asteriskToken ||
|
|
693
|
+
hasExplicitJsDocReturn(member))
|
|
622
694
|
return false;
|
|
623
695
|
const widened = (expression) => {
|
|
624
696
|
if (ts.isParenthesizedExpression(expression))
|
|
@@ -627,22 +699,38 @@ function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
|
627
699
|
return widened(expression.whenTrue) || widened(expression.whenFalse);
|
|
628
700
|
if (ts.isCallExpression(expression)) {
|
|
629
701
|
const callee = expression.expression;
|
|
630
|
-
const symbol = ts.isPropertyAccessExpression(callee)
|
|
631
|
-
|
|
702
|
+
const symbol = ts.isPropertyAccessExpression(callee)
|
|
703
|
+
? lowerer.checker.getSymbolAtLocation(callee.name)
|
|
704
|
+
: ts.isElementAccessExpression(callee)
|
|
705
|
+
? lowerer.checker.getPropertyOfType(lowerer.typeOf(callee.expression), lowerer.foldedStringKeyOf(callee.argumentExpression) ?? "")
|
|
632
706
|
: undefined;
|
|
633
|
-
if (symbol &&
|
|
707
|
+
if (symbol &&
|
|
708
|
+
lowerer.checker
|
|
709
|
+
.declarationsOf(symbol)
|
|
710
|
+
.some((declaration) => ts.isMethodDeclaration(declaration) &&
|
|
711
|
+
lowerer.checkedVirtualJsMethods.has(declaration)))
|
|
634
712
|
return true;
|
|
635
713
|
}
|
|
636
|
-
const name = ts.isPropertyAccessExpression(expression)
|
|
637
|
-
|
|
714
|
+
const name = ts.isPropertyAccessExpression(expression)
|
|
715
|
+
? expression.name.text
|
|
716
|
+
: ts.isElementAccessExpression(expression)
|
|
717
|
+
? lowerer.foldedStringKeyOf(expression.argumentExpression)
|
|
718
|
+
: null;
|
|
638
719
|
if (ts.isPropertyAccessExpression(expression)) {
|
|
639
720
|
const symbol = lowerer.checker.getSymbolAtLocation(expression.name);
|
|
640
|
-
if (symbol &&
|
|
721
|
+
if (symbol &&
|
|
722
|
+
lowerer.checker
|
|
723
|
+
.declarationsOf(symbol)
|
|
724
|
+
.some((declaration) => (ts.isGetAccessorDeclaration(declaration) ||
|
|
725
|
+
ts.isSetAccessorDeclaration(declaration)) &&
|
|
726
|
+
lowerer.checkedVirtualJsAccessors.has(declaration)))
|
|
641
727
|
return true;
|
|
642
728
|
}
|
|
643
|
-
if (name !== null &&
|
|
729
|
+
if (name !== null &&
|
|
730
|
+
(ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) &&
|
|
644
731
|
expression.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
645
|
-
return fields.get(name)?.kind === "dyn" ||
|
|
732
|
+
return (fields.get(name)?.kind === "dyn" ||
|
|
733
|
+
inheritedJsFieldType(lowerer, decl, name, ret).kind === "dyn");
|
|
646
734
|
}
|
|
647
735
|
return false;
|
|
648
736
|
};
|
|
@@ -659,10 +747,10 @@ function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
|
659
747
|
return result;
|
|
660
748
|
}
|
|
661
749
|
/** The undefined-armed union of a JS class property's inferred type — the
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
750
|
+
* honest slot for a field first assigned outside the constructor's top
|
|
751
|
+
* level (undefined until the write runs, Node-exact). Null when the
|
|
752
|
+
* inference is unmappable or an arm-less kind that cannot join a union
|
|
753
|
+
* (genResultRecord's list, including scalar-backed Date values). */
|
|
666
754
|
function undefArmedFieldType(lowerer, p) {
|
|
667
755
|
const t = lowerer.checker.getTypeOfSymbol(p);
|
|
668
756
|
const site = lowerer.checker.declarationsOf(p)[0];
|
|
@@ -673,7 +761,9 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
673
761
|
return null;
|
|
674
762
|
for (const declaration of lowerer.checker.declarationsOf(p)) {
|
|
675
763
|
const assignment = ts.isBinaryExpression(declaration) ? declaration : declaration.parent;
|
|
676
|
-
if (assignment &&
|
|
764
|
+
if (assignment &&
|
|
765
|
+
ts.isBinaryExpression(assignment) &&
|
|
766
|
+
assignment.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
677
767
|
mapped = jsFieldInitializerType(lowerer, mapped, assignment.right);
|
|
678
768
|
}
|
|
679
769
|
}
|
|
@@ -683,8 +773,11 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
683
773
|
const byKey = new Map();
|
|
684
774
|
const arms = mapped.kind === "union" ? (lowerer.unions.get(mapped.unionId)?.arms ?? []) : [mapped];
|
|
685
775
|
for (const a of arms) {
|
|
686
|
-
if (a.kind === "map" ||
|
|
687
|
-
a.kind === "
|
|
776
|
+
if (a.kind === "map" ||
|
|
777
|
+
a.kind === "regex" ||
|
|
778
|
+
a.kind === "date" ||
|
|
779
|
+
a.kind === "jsval" ||
|
|
780
|
+
a.kind === "generator") {
|
|
688
781
|
return null;
|
|
689
782
|
}
|
|
690
783
|
byKey.set(typeKey(a), a);
|
|
@@ -694,10 +787,10 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
694
787
|
return { kind: "union", unionId: lowerer.unions.intern(sorted) };
|
|
695
788
|
}
|
|
696
789
|
/** The emitter ClassInfo a VALUE symbol refers to (`new EventEmitter`,
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
790
|
+
* `extends EventEmitter`, `x instanceof EventEmitter`) — any import
|
|
791
|
+
* spelling (named/default/namespace member, CJS require) resolves to
|
|
792
|
+
* the ambient class. Provenance-checked like the error classes: only a
|
|
793
|
+
* stdlib-file declaration inside the "events" ambient module counts. */
|
|
701
794
|
export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
702
795
|
if (!symbol)
|
|
703
796
|
return null;
|
|
@@ -709,7 +802,8 @@ export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
|
709
802
|
// itself is alias plumbing (builtinMemberRequireDecl — both
|
|
710
803
|
// declaration walks skip it).
|
|
711
804
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
712
|
-
if (decl !== undefined &&
|
|
805
|
+
if (decl !== undefined &&
|
|
806
|
+
ts.isVariableDeclaration(decl) &&
|
|
713
807
|
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 &&
|
|
714
808
|
decl.initializer !== undefined &&
|
|
715
809
|
ts.isPropertyAccessExpression(decl.initializer) &&
|
|
@@ -737,9 +831,9 @@ export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
|
737
831
|
return declared ? (lowerer.classes.get(RUNTIME_EMITTER_CLASS) ?? null) : null;
|
|
738
832
|
}
|
|
739
833
|
/** The builtin error ClassInfo a VALUE symbol refers to (`new Error`,
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
834
|
+
* `extends TypeError`, `x instanceof RangeError`), or null. Provenance-
|
|
835
|
+
* checked: only the standard library's declarations count — a user's own
|
|
836
|
+
* `class Error` resolves through classBySymbol instead. */
|
|
743
837
|
export function builtinErrorInfoOf(lowerer, symbol) {
|
|
744
838
|
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
745
839
|
return null;
|
|
@@ -753,22 +847,34 @@ export function builtinErrorInfoOf(lowerer, symbol) {
|
|
|
753
847
|
* members with these names are fenced (collectClassShapeInner) and calls
|
|
754
848
|
* to them on emitter-rooted receivers lower through lower-event-emitter.ts. */
|
|
755
849
|
export const EMITTER_API_MEMBERS = new Set([
|
|
756
|
-
"on",
|
|
757
|
-
"
|
|
758
|
-
"
|
|
850
|
+
"on",
|
|
851
|
+
"addListener",
|
|
852
|
+
"once",
|
|
853
|
+
"prependListener",
|
|
854
|
+
"prependOnceListener",
|
|
855
|
+
"off",
|
|
856
|
+
"removeListener",
|
|
857
|
+
"removeAllListeners",
|
|
858
|
+
"emit",
|
|
859
|
+
"listenerCount",
|
|
860
|
+
"listeners",
|
|
861
|
+
"rawListeners",
|
|
862
|
+
"eventNames",
|
|
863
|
+
"setMaxListeners",
|
|
864
|
+
"getMaxListeners",
|
|
759
865
|
]);
|
|
760
866
|
/** The decorators of a class-like or member node (they live in
|
|
761
|
-
|
|
867
|
+
* `modifiers` since TS 4.8). */
|
|
762
868
|
export function decoratorNodesOf(n) {
|
|
763
869
|
return (n.modifiers ?? []).filter((m) => m.kind === ts.SyntaxKind.Decorator);
|
|
764
870
|
}
|
|
765
871
|
/** The AMBIENT name a decorator expression's evaluation throws on, or
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
872
|
+
* null. Node erases ambient declarations (`declare let dec: any`,
|
|
873
|
+
* `declare const instance: T`, `declare function dec<T>(t: T): T`), so
|
|
874
|
+
* reading the name is a ReferenceError. Factory spellings ride along —
|
|
875
|
+
* `@dec(...)` evaluates the CALLEE before any argument — and property
|
|
876
|
+
* chains throw at their ROOT (`@instance.decorate` reads `instance`
|
|
877
|
+
* first). */
|
|
772
878
|
function ambientDecoratorThrowNameOf(lowerer, dExpr) {
|
|
773
879
|
let e = dExpr;
|
|
774
880
|
while (ts.isParenthesizedExpression(e))
|
|
@@ -785,16 +891,16 @@ function ambientDecoratorThrowNameOf(lowerer, dExpr) {
|
|
|
785
891
|
return null;
|
|
786
892
|
}
|
|
787
893
|
/** The guaranteed decoration THROW of a decorated class, or null. Walks
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
894
|
+
* the class definition's evaluation-order items — class decorators
|
|
895
|
+
* (source order), the heritage expression, then per member in body
|
|
896
|
+
* order its decorators and computed key (the verified TC39/tsc-downlevel
|
|
897
|
+
* order) — and answers the first AMBIENT decorator name, provided every
|
|
898
|
+
* item BEFORE it is provably effect-free and non-throwing: bare
|
|
899
|
+
* identifier decorators over defined values (a pure read), an absent /
|
|
900
|
+
* `null` / bare-identifier heritage, literal or bare-identifier
|
|
901
|
+
* computed keys. Anything richer (factory calls over defined values,
|
|
902
|
+
* property-access reads, computed-key calls) stops the proof — the
|
|
903
|
+
* named fences answer instead. */
|
|
798
904
|
export function guaranteedDecorationThrow(lowerer, decl) {
|
|
799
905
|
const stripParens = (e) => {
|
|
800
906
|
let x = e;
|
|
@@ -819,8 +925,7 @@ export function guaranteedDecorationThrow(lowerer, decl) {
|
|
|
819
925
|
if (v !== "effectFree")
|
|
820
926
|
return v;
|
|
821
927
|
}
|
|
822
|
-
const heritage = decl.heritageClauses
|
|
823
|
-
?.find((c) => c.token === ts.SyntaxKind.ExtendsKeyword)
|
|
928
|
+
const heritage = decl.heritageClauses?.find((c) => c.token === ts.SyntaxKind.ExtendsKeyword)
|
|
824
929
|
?.types[0];
|
|
825
930
|
if (heritage) {
|
|
826
931
|
const h = stripParens(heritage.expression);
|
|
@@ -846,7 +951,36 @@ export function guaranteedDecorationThrow(lowerer, decl) {
|
|
|
846
951
|
return null;
|
|
847
952
|
}
|
|
848
953
|
export function collectClassShape(lowerer, decl) {
|
|
849
|
-
|
|
954
|
+
if (lowerer.classes.has(lowerer.classNamer(decl)) ||
|
|
955
|
+
lowerer.collectingClassDeclarations.has(decl))
|
|
956
|
+
return;
|
|
957
|
+
lowerer.collectingClassDeclarations.add(decl);
|
|
958
|
+
try {
|
|
959
|
+
collectClassShapeDeferring(lowerer, decl);
|
|
960
|
+
}
|
|
961
|
+
finally {
|
|
962
|
+
lowerer.collectingClassDeclarations.delete(decl);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
function collectClassShapeDeferring(lowerer, decl) {
|
|
966
|
+
const symbol = lowerer.collectDeferring(() => declSymbolOf(lowerer, decl), () => {
|
|
967
|
+
// A forward type reference can demand this class before collection
|
|
968
|
+
// reaches its earlier base declaration. Collect that dependency first;
|
|
969
|
+
// a later same-file base remains subject to the runtime order boundary.
|
|
970
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
971
|
+
const reference = heritage && ts.isPropertyAccessExpression(heritage) ? heritage.name : heritage;
|
|
972
|
+
const baseSymbol = reference && ts.isIdentifier(reference) ? lowerer.resolveValueSymbol(reference) : undefined;
|
|
973
|
+
const baseDeclaration = baseSymbol
|
|
974
|
+
? lowerer.checker.declarationsOf(baseSymbol).find(ts.isClassDeclaration)
|
|
975
|
+
: undefined;
|
|
976
|
+
if (baseDeclaration &&
|
|
977
|
+
!lowerer.isStdlibSymbol(baseSymbol ?? undefined) &&
|
|
978
|
+
!baseDeclaration.getSourceFile().isDeclarationFile &&
|
|
979
|
+
(baseDeclaration.getSourceFile() !== decl.getSourceFile() ||
|
|
980
|
+
baseDeclaration.getStart() < decl.getStart()))
|
|
981
|
+
lowerer.collectClassShape(baseDeclaration);
|
|
982
|
+
lowerer.collectClassShapeInner(decl);
|
|
983
|
+
});
|
|
850
984
|
// Typed receivers and module retention know the class only by its
|
|
851
985
|
// qualified IR name — index the deferral under it too.
|
|
852
986
|
if (symbol)
|
|
@@ -898,7 +1032,9 @@ export function collectClassShape(lowerer, decl) {
|
|
|
898
1032
|
}
|
|
899
1033
|
}
|
|
900
1034
|
function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
901
|
-
if (!ts.isNewExpression(initializer) ||
|
|
1035
|
+
if (!ts.isNewExpression(initializer) ||
|
|
1036
|
+
(initializer.arguments?.length ?? 0) !== 0 ||
|
|
1037
|
+
!ts.isIdentifier(initializer.expression))
|
|
902
1038
|
return null;
|
|
903
1039
|
const collection = initializer.expression.text;
|
|
904
1040
|
if (collection !== "Map" && collection !== "Set")
|
|
@@ -912,7 +1048,11 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
912
1048
|
const mappedArgument = (argument) => {
|
|
913
1049
|
const type = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(argument));
|
|
914
1050
|
const mapped = lowerer.mapTypeOf(type);
|
|
915
|
-
if (!mapped ||
|
|
1051
|
+
if (!mapped ||
|
|
1052
|
+
mapped.kind === "dyn" ||
|
|
1053
|
+
mapped.kind === "jsval" ||
|
|
1054
|
+
mapped.kind === "void" ||
|
|
1055
|
+
isUnitType(mapped))
|
|
916
1056
|
return null;
|
|
917
1057
|
return mapped;
|
|
918
1058
|
};
|
|
@@ -927,19 +1067,27 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
927
1067
|
receiver.name.text !== field) {
|
|
928
1068
|
return undefined;
|
|
929
1069
|
}
|
|
930
|
-
if (collection === "Map" &&
|
|
1070
|
+
if (collection === "Map" &&
|
|
1071
|
+
node.expression.name.text === "set" &&
|
|
1072
|
+
node.arguments.length === 2) {
|
|
931
1073
|
const key = mappedArgument(node.arguments[0]);
|
|
932
1074
|
const value = mappedArgument(node.arguments[1]);
|
|
933
|
-
if (key !== null &&
|
|
1075
|
+
if (key !== null &&
|
|
1076
|
+
value !== null &&
|
|
1077
|
+
isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) &&
|
|
1078
|
+
isSupportedMapValue(value)) {
|
|
934
1079
|
mapKeys.push(key);
|
|
935
1080
|
mapValues.push(value);
|
|
936
1081
|
}
|
|
937
1082
|
}
|
|
938
1083
|
if (collection === "Set" &&
|
|
939
|
-
(node.expression.name.text === "add" ||
|
|
1084
|
+
(node.expression.name.text === "add" ||
|
|
1085
|
+
node.expression.name.text === "has" ||
|
|
1086
|
+
node.expression.name.text === "delete") &&
|
|
940
1087
|
node.arguments.length === 1) {
|
|
941
1088
|
const element = mappedArgument(node.arguments[0]);
|
|
942
|
-
if (element !== null &&
|
|
1089
|
+
if (element !== null &&
|
|
1090
|
+
isSupportedSetElem(element, element.kind === "union" ? lowerer.unions.get(element.unionId)?.arms : undefined))
|
|
943
1091
|
setElements.push(element);
|
|
944
1092
|
}
|
|
945
1093
|
return undefined;
|
|
@@ -1008,8 +1156,10 @@ mixin) {
|
|
|
1008
1156
|
// The guaranteed-throw SHELL: declarations only (expressions
|
|
1009
1157
|
// lower their throw at the expression — lowerClassExpression),
|
|
1010
1158
|
// never instantiations/mixins (they share a family declaration).
|
|
1011
|
-
if (inst === undefined &&
|
|
1012
|
-
|
|
1159
|
+
if (inst === undefined &&
|
|
1160
|
+
mixin === undefined &&
|
|
1161
|
+
ts.isClassDeclaration(decl) &&
|
|
1162
|
+
decl.typeParameters === undefined) {
|
|
1013
1163
|
const thrown = guaranteedDecorationThrow(lowerer, decl);
|
|
1014
1164
|
if (thrown) {
|
|
1015
1165
|
const className = lowerer.classNamer(decl);
|
|
@@ -1055,9 +1205,9 @@ mixin) {
|
|
|
1055
1205
|
: ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)
|
|
1056
1206
|
? "accessor decorators"
|
|
1057
1207
|
: ts.isPropertyDeclaration(member)
|
|
1058
|
-
?
|
|
1208
|
+
? member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AccessorKeyword)
|
|
1059
1209
|
? "auto-accessor decorators"
|
|
1060
|
-
: "field decorators"
|
|
1210
|
+
: "field decorators"
|
|
1061
1211
|
: "member decorators";
|
|
1062
1212
|
lowerer.unsupported("SC1090", dec, `${kind} (the standard context object and member replacement have no static lowering — class decorators and provably-throwing ambient decorations compile)`);
|
|
1063
1213
|
}
|
|
@@ -1093,60 +1243,48 @@ mixin) {
|
|
|
1093
1243
|
lowerer.unsupported("SC1090", decl, "generic class expressions");
|
|
1094
1244
|
}
|
|
1095
1245
|
const className = inst ? inst.name : mixin ? mixin.name : lowerer.classNamer(decl); // program-wide qualified name
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
// so the base's ClassInfo already exists here. An INSTANTIATION's
|
|
1100
|
-
// base is its family (whose base is the declared one) — the heritage
|
|
1101
|
-
// clause resolved when the family collected.
|
|
1246
|
+
// Collection follows module order for runtime heritage. Ordinary
|
|
1247
|
+
// instances use the family as their storage base; generic heritage
|
|
1248
|
+
// resolves a concrete base under each instance's type bindings.
|
|
1102
1249
|
const computedBase = lowerer.computedClassBases.get(lowerer.classNamer(decl));
|
|
1103
|
-
let base = inst
|
|
1250
|
+
let base = inst
|
|
1251
|
+
? inst.family
|
|
1252
|
+
: mixin
|
|
1253
|
+
? mixin.base
|
|
1254
|
+
: (computedBase?.classInfo ?? null);
|
|
1255
|
+
let genericBase;
|
|
1104
1256
|
let callableBase;
|
|
1105
1257
|
let factoryBaseExpression;
|
|
1106
1258
|
const adoptCallableBase = (expression) => {
|
|
1107
1259
|
if (familyMode || inst || mixin)
|
|
1108
1260
|
return false;
|
|
1109
1261
|
if (lowerer.computedCallableBases.has(decl)) {
|
|
1110
|
-
callableBase = {
|
|
1262
|
+
callableBase = {
|
|
1263
|
+
expression,
|
|
1264
|
+
constructorId: `%g.${className}.base`,
|
|
1265
|
+
prototypeId: `%g.${className}.basePrototype`,
|
|
1266
|
+
};
|
|
1111
1267
|
return true;
|
|
1112
1268
|
}
|
|
1113
1269
|
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(expression));
|
|
1114
1270
|
const source = signatures.length === 1 ? lowerer.checker.signatureDeclaration(signatures[0]) : undefined;
|
|
1115
|
-
if (!source ||
|
|
1271
|
+
if (!source ||
|
|
1272
|
+
!isJsSourceFile(source.getSourceFile()) ||
|
|
1116
1273
|
!(ts.isFunctionDeclaration(source) || ts.isFunctionExpression(source)))
|
|
1117
1274
|
return false;
|
|
1118
|
-
callableBase = {
|
|
1275
|
+
callableBase = {
|
|
1276
|
+
expression,
|
|
1277
|
+
constructorId: `%g.${className}.base`,
|
|
1278
|
+
prototypeId: `%g.${className}.basePrototype`,
|
|
1279
|
+
};
|
|
1119
1280
|
return true;
|
|
1120
1281
|
};
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
for (const tp of decl.typeParameters) {
|
|
1128
|
-
const s = lowerer.checker.getSymbolAtLocation(tp.name);
|
|
1129
|
-
if (s)
|
|
1130
|
-
tpSyms.add(s);
|
|
1131
|
-
}
|
|
1132
|
-
for (const clause of decl.heritageClauses) {
|
|
1133
|
-
if (clause.token !== ts.SyntaxKind.ExtendsKeyword)
|
|
1134
|
-
continue;
|
|
1135
|
-
for (const t of clause.types) {
|
|
1136
|
-
let mentions = false;
|
|
1137
|
-
ts.walkPreorder(t, (n) => {
|
|
1138
|
-
const s = ts.isIdentifier(n) ? lowerer.checker.getSymbolAtLocation(n) : undefined;
|
|
1139
|
-
if (s && tpSyms.has(s)) {
|
|
1140
|
-
mentions = true;
|
|
1141
|
-
return "stop";
|
|
1142
|
-
}
|
|
1143
|
-
return undefined;
|
|
1144
|
-
});
|
|
1145
|
-
if (mentions) {
|
|
1146
|
-
lowerer.unsupported("SC1090", t, "generic classes whose 'extends' clause mentions their own type parameters (each instantiation would need a different base)");
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1282
|
+
const ownGenericBase = inst?.family.genericBase;
|
|
1283
|
+
if (inst && ownGenericBase) {
|
|
1284
|
+
const mapped = lowerer.mapTypeOf(lowerer.checker.getTypeAtLocation(ownGenericBase));
|
|
1285
|
+
base = mapped?.kind === "object" ? (lowerer.classes.get(mapped.className) ?? null) : null;
|
|
1286
|
+
if (!base || base.generic)
|
|
1287
|
+
lowerer.unsupported("SC1090", ownGenericBase, "a generic base whose type arguments have no concrete layout");
|
|
1150
1288
|
}
|
|
1151
1289
|
for (const clause of inst || mixin || computedBase ? [] : (decl.heritageClauses ?? [])) {
|
|
1152
1290
|
// `implements` is pure type-world: tsc checked the conformance and
|
|
@@ -1156,6 +1294,22 @@ mixin) {
|
|
|
1156
1294
|
if (clause.token === ts.SyntaxKind.ImplementsKeyword)
|
|
1157
1295
|
continue;
|
|
1158
1296
|
const t = clause.types[0];
|
|
1297
|
+
if (familyMode && t) {
|
|
1298
|
+
const reference = ts.isPropertyAccessExpression(t.expression)
|
|
1299
|
+
? t.expression.name
|
|
1300
|
+
: t.expression;
|
|
1301
|
+
const symbol = ts.isIdentifier(reference)
|
|
1302
|
+
? lowerer.resolveValueSymbol(reference)
|
|
1303
|
+
: undefined;
|
|
1304
|
+
const familyBase = symbol ? lowerer.classBySymbol.get(symbol) : undefined;
|
|
1305
|
+
if (familyBase?.generic) {
|
|
1306
|
+
if (symbol && ts.isPropertyAccessExpression(t.expression))
|
|
1307
|
+
fenceEarlyNsMemberRef(lowerer, t.expression, symbol);
|
|
1308
|
+
base = familyBase;
|
|
1309
|
+
genericBase = t;
|
|
1310
|
+
continue;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1159
1313
|
// `extends events.EventEmitter` — the namespace-member spelling of
|
|
1160
1314
|
// the ambient emitter base resolves like the named import.
|
|
1161
1315
|
if (t && ts.isPropertyAccessExpression(t.expression) && ts.isIdentifier(t.expression.name)) {
|
|
@@ -1163,8 +1317,10 @@ mixin) {
|
|
|
1163
1317
|
const resolved = memberSym && memberSym.flags & ts.SymbolFlags.Alias
|
|
1164
1318
|
? lowerer.checker.getAliasedSymbol(memberSym)
|
|
1165
1319
|
: memberSym;
|
|
1166
|
-
const globalError = !t.expression.questionDotToken &&
|
|
1167
|
-
|
|
1320
|
+
const globalError = !t.expression.questionDotToken &&
|
|
1321
|
+
lowerer.isStdlibGlobal(t.expression.expression, "globalThis")
|
|
1322
|
+
? lowerer.builtinErrorInfoOf(resolved)
|
|
1323
|
+
: null;
|
|
1168
1324
|
if (globalError && globalError.def.name !== "%DOMException") {
|
|
1169
1325
|
if (t.typeArguments)
|
|
1170
1326
|
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
@@ -1231,8 +1387,7 @@ mixin) {
|
|
|
1231
1387
|
const rebinds = memberSym !== undefined &&
|
|
1232
1388
|
lowerer.checker
|
|
1233
1389
|
.declarationsOf(memberSym)
|
|
1234
|
-
.filter((d) => ts.isBinaryExpression(d) &&
|
|
1235
|
-
d.operatorToken.kind === ts.SyntaxKind.EqualsToken).length > 1;
|
|
1390
|
+
.filter((d) => ts.isBinaryExpression(d) && d.operatorToken.kind === ts.SyntaxKind.EqualsToken).length > 1;
|
|
1236
1391
|
if (rebinds) {
|
|
1237
1392
|
lowerer.unsupported("SC1090", t, `extending the reassigned property '${t.expression.getText()}' (the runtime base is whichever assignment ran last — bind the class exactly once)`);
|
|
1238
1393
|
}
|
|
@@ -1295,8 +1450,10 @@ mixin) {
|
|
|
1295
1450
|
if (lowerer.builtinErrorInfoOf(symbol)?.def.name === "%DOMException") {
|
|
1296
1451
|
lowerer.unsupported("SC1090", t, "extending DOMException (its runtime layout carries hidden slots a subclass would overlap — extend Error and set name/code yourself)");
|
|
1297
1452
|
}
|
|
1298
|
-
const named = (symbol && lowerer.classBySymbol.get(symbol)) ??
|
|
1299
|
-
lowerer.
|
|
1453
|
+
const named = (symbol && lowerer.classBySymbol.get(symbol)) ??
|
|
1454
|
+
lowerer.builtinErrorInfoOf(symbol) ??
|
|
1455
|
+
lowerer.builtinEmitterInfoOf(symbol) ??
|
|
1456
|
+
builtinStreamInfoOf(lowerer, symbol) ??
|
|
1300
1457
|
// A const BINDING holding exactly one class (`const B = Animal`,
|
|
1301
1458
|
// `const B = class {…}`): the base is that class — extends
|
|
1302
1459
|
// through the alias is the declaration story (a general class
|
|
@@ -1314,7 +1471,8 @@ mixin) {
|
|
|
1314
1471
|
(() => {
|
|
1315
1472
|
const stored = storedClassValueType(lowerer, t.expression);
|
|
1316
1473
|
return stored?.kind === "classval" ? lowerer.classes.get(stored.className) : null;
|
|
1317
|
-
})() ??
|
|
1474
|
+
})() ??
|
|
1475
|
+
null;
|
|
1318
1476
|
// `extends Box<number>` — a GENERIC program class as the base: the
|
|
1319
1477
|
// base is the concrete INSTANTIATION, resolved through the heritage
|
|
1320
1478
|
// type (mapType registers/reuses `Box%0`).
|
|
@@ -1397,10 +1555,16 @@ mixin) {
|
|
|
1397
1555
|
const runtimePrototypeMembers = [];
|
|
1398
1556
|
// Public JS accessors need live constructor descriptors, including
|
|
1399
1557
|
// receiver-sensitive getters and setters inherited by subclasses.
|
|
1400
|
-
const checkedStatics = isJsSourceFile(decl.getSourceFile()) &&
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1558
|
+
const checkedStatics = isJsSourceFile(decl.getSourceFile()) &&
|
|
1559
|
+
((base && hasRuntimeStatics(base)) ||
|
|
1560
|
+
decl.members.some((member) => ts.isAccessor(member) &&
|
|
1561
|
+
!ts.isPrivateIdentifier(member.name) &&
|
|
1562
|
+
member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) &&
|
|
1563
|
+
!decl.members.some((member) => member.name &&
|
|
1564
|
+
ts.isPrivateIdentifier(member.name) &&
|
|
1565
|
+
ts
|
|
1566
|
+
.getModifiers(member)
|
|
1567
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
1404
1568
|
// GENERIC methods (own type parameters), instance and static: only
|
|
1405
1569
|
// the SYNTAX is checked here — parameter/return types mention the
|
|
1406
1570
|
// type parameters and cannot map yet; bodies lower per call-site
|
|
@@ -1436,7 +1600,9 @@ mixin) {
|
|
|
1436
1600
|
typeParams.push(sym);
|
|
1437
1601
|
}
|
|
1438
1602
|
for (const param of fnNode.parameters) {
|
|
1439
|
-
if (!ts.isIdentifier(param.name) &&
|
|
1603
|
+
if (!ts.isIdentifier(param.name) &&
|
|
1604
|
+
!ts.isObjectBindingPattern(param.name) &&
|
|
1605
|
+
!ts.isArrayBindingPattern(param.name)) {
|
|
1440
1606
|
lowerer.unsupported("SC1031", param);
|
|
1441
1607
|
}
|
|
1442
1608
|
}
|
|
@@ -1449,16 +1615,23 @@ mixin) {
|
|
|
1449
1615
|
});
|
|
1450
1616
|
};
|
|
1451
1617
|
for (const member of decl.members) {
|
|
1452
|
-
if ((functionLocalClass(decl) || checkedStatics) &&
|
|
1453
|
-
(
|
|
1618
|
+
if ((functionLocalClass(decl) || checkedStatics) &&
|
|
1619
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
1620
|
+
(ts.isClassStaticBlockDeclaration(member) ||
|
|
1621
|
+
ts
|
|
1622
|
+
.getModifiers(member)
|
|
1623
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) {
|
|
1454
1624
|
runtimeStatics.push(member);
|
|
1455
1625
|
continue;
|
|
1456
1626
|
}
|
|
1457
|
-
if (functionLocalClass(decl) &&
|
|
1458
|
-
(
|
|
1627
|
+
if (functionLocalClass(decl) &&
|
|
1628
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
1629
|
+
(ts.isMethodDeclaration(member) || ts.isAccessor(member)) &&
|
|
1630
|
+
member.body &&
|
|
1459
1631
|
!ts.isPrivateIdentifier(member.name)) {
|
|
1460
1632
|
runtimePrototypeMembers.push(member);
|
|
1461
|
-
if (ts.isComputedPropertyName(member.name) &&
|
|
1633
|
+
if (ts.isComputedPropertyName(member.name) &&
|
|
1634
|
+
classMemberNameOf(lowerer, member.name) === null)
|
|
1462
1635
|
continue;
|
|
1463
1636
|
}
|
|
1464
1637
|
if (ts.isClassStaticBlockDeclaration(member)) {
|
|
@@ -1507,15 +1680,20 @@ mixin) {
|
|
|
1507
1680
|
(ts.isIdentifier(member.name) || ts.isPrivateIdentifier(member.name)) &&
|
|
1508
1681
|
member.initializer &&
|
|
1509
1682
|
member.postfixToken?.kind !== ts.SyntaxKind.QuestionToken) {
|
|
1510
|
-
const initializerSymbol = ts.isIdentifier(member.initializer)
|
|
1683
|
+
const initializerSymbol = ts.isIdentifier(member.initializer)
|
|
1684
|
+
? lowerer.resolveValueSymbol(member.initializer)
|
|
1685
|
+
: null;
|
|
1511
1686
|
// Enum namespace aliases are erased; member reads fold through the checker.
|
|
1512
1687
|
if (initializerSymbol && (initializerSymbol.flags & ts.SymbolFlags.Enum) !== 0)
|
|
1513
1688
|
continue;
|
|
1514
1689
|
const type = lowerer.irTypeOf(member.name);
|
|
1515
1690
|
if (type.kind === "void")
|
|
1516
1691
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1517
|
-
if (type.kind === "dyn" &&
|
|
1518
|
-
(member.
|
|
1692
|
+
if (type.kind === "dyn" &&
|
|
1693
|
+
!isJsSourceFile(member.getSourceFile()) &&
|
|
1694
|
+
!lowerer.classImplementedProtocol(lowerer.typeOf(member.name)) &&
|
|
1695
|
+
(member.type !== undefined ||
|
|
1696
|
+
(lowerer.typeOf(member.name).flags & ts.TypeFlags.Any) === 0)) {
|
|
1519
1697
|
lowerer.unsupported("SC1090", member.name, "'unknown'-typed static fields");
|
|
1520
1698
|
}
|
|
1521
1699
|
staticFields.push({
|
|
@@ -1538,14 +1716,19 @@ mixin) {
|
|
|
1538
1716
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1539
1717
|
}
|
|
1540
1718
|
staticMethods.set(member.name.text, { params: shapes, ret: ft.ret, member });
|
|
1541
|
-
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
1542
|
-
|
|
1719
|
+
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
1720
|
+
!functionLocalClass(decl) &&
|
|
1721
|
+
inst === undefined &&
|
|
1722
|
+
decl.typeParameters === undefined) {
|
|
1543
1723
|
const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
|
|
1544
1724
|
if (implicit)
|
|
1545
1725
|
genericStatics.set(member.name.text, {
|
|
1546
|
-
decl: member,
|
|
1726
|
+
decl: member,
|
|
1727
|
+
baseName: member.name.text,
|
|
1547
1728
|
qualifiedName: `%${className}.static:${member.name.text}%implicit`,
|
|
1548
|
-
typeParams: [],
|
|
1729
|
+
typeParams: [],
|
|
1730
|
+
instances: new Map(),
|
|
1731
|
+
implicitParams: implicit,
|
|
1549
1732
|
});
|
|
1550
1733
|
}
|
|
1551
1734
|
}
|
|
@@ -1577,11 +1760,18 @@ mixin) {
|
|
|
1577
1760
|
// (every named member kind stores a PropertyName there).
|
|
1578
1761
|
const memberName = member.name;
|
|
1579
1762
|
if (errorRooted && memberName && classMemberNameOf(lowerer, memberName) === "cause") {
|
|
1580
|
-
if (ts.isPropertyDeclaration(member) &&
|
|
1763
|
+
if (ts.isPropertyDeclaration(member) &&
|
|
1764
|
+
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
|
|
1581
1765
|
if (!isJsSourceFile(member.getSourceFile()))
|
|
1582
1766
|
lowerer.unsupported("SC1090", memberName, "redeclaring Error.cause (pass the cause in the Error constructor options)");
|
|
1583
|
-
fieldOrder.push({
|
|
1584
|
-
|
|
1767
|
+
fieldOrder.push({
|
|
1768
|
+
name: "cause",
|
|
1769
|
+
type: DYN,
|
|
1770
|
+
initializer: member.initializer,
|
|
1771
|
+
...(member.initializer ? {} : { undefinedInitializer: locOf(member) }),
|
|
1772
|
+
redeclared: true,
|
|
1773
|
+
errorCause: true,
|
|
1774
|
+
});
|
|
1585
1775
|
continue;
|
|
1586
1776
|
}
|
|
1587
1777
|
lowerer.unsupported("SC1090", memberName, "Error.cause accessors");
|
|
@@ -1619,7 +1809,8 @@ mixin) {
|
|
|
1619
1809
|
// keep the fence for emit too: the runtime stream machinery emits
|
|
1620
1810
|
// 'data'/'end'/... internally, which could never route through
|
|
1621
1811
|
// the override.
|
|
1622
|
-
if (memberName &&
|
|
1812
|
+
if (memberName &&
|
|
1813
|
+
ts.isIdentifier(memberName) &&
|
|
1623
1814
|
EMITTER_API_MEMBERS.has(memberName.text) &&
|
|
1624
1815
|
(() => {
|
|
1625
1816
|
for (let c = base; c; c = c.base)
|
|
@@ -1633,7 +1824,10 @@ mixin) {
|
|
|
1633
1824
|
return true;
|
|
1634
1825
|
return false;
|
|
1635
1826
|
})();
|
|
1636
|
-
if (memberName.text === "emit" &&
|
|
1827
|
+
if (memberName.text === "emit" &&
|
|
1828
|
+
!streamRooted &&
|
|
1829
|
+
!inst &&
|
|
1830
|
+
!mixin &&
|
|
1637
1831
|
ts.isMethodDeclaration(member) &&
|
|
1638
1832
|
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
|
|
1639
1833
|
const reason = emitOverrideShapeReason(lowerer, member);
|
|
@@ -1698,20 +1892,39 @@ mixin) {
|
|
|
1698
1892
|
// get/set pair — declare the field and accessors explicitly.
|
|
1699
1893
|
lowerer.unsupported("SC1090", member, "auto-accessor fields ('accessor x')");
|
|
1700
1894
|
}
|
|
1701
|
-
if (ts.isComputedPropertyName(member.name) ||
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1895
|
+
if (ts.isComputedPropertyName(member.name) ||
|
|
1896
|
+
ts.isStringLiteralLike(member.name) ||
|
|
1897
|
+
ts.isNumericLiteral(member.name)) {
|
|
1898
|
+
const symbolKey = ts.isComputedPropertyName(member.name)
|
|
1899
|
+
? classSymbolKeyOf(lowerer, member.name.expression)
|
|
1900
|
+
: null;
|
|
1901
|
+
const stringKey = ts.isComputedPropertyName(member.name)
|
|
1902
|
+
? lowerer.foldedStringKeyOf(member.name.expression)
|
|
1903
|
+
: ts.isNumericLiteral(member.name)
|
|
1904
|
+
? String(Number(member.name.text))
|
|
1905
|
+
: member.name.text;
|
|
1705
1906
|
const fieldName = symbolKey?.fieldName ?? stringKey;
|
|
1706
|
-
if (fieldName === null ||
|
|
1907
|
+
if (fieldName === null ||
|
|
1908
|
+
(!member.initializer && !isJsSourceFile(member.getSourceFile()))) {
|
|
1707
1909
|
lowerer.unsupported("SC1090", member, "computed class fields without an initializer and a stable string, number, or module-level literal Symbol()/Symbol.for() key");
|
|
1708
1910
|
}
|
|
1709
1911
|
const declared = lowerer.typeOf(member);
|
|
1710
|
-
const inferred = member.type || !member.initializer
|
|
1711
|
-
|
|
1912
|
+
const inferred = member.type || !member.initializer
|
|
1913
|
+
? declared
|
|
1914
|
+
: lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(member.initializer));
|
|
1915
|
+
const mapped = member.initializer
|
|
1916
|
+
? (lowerer.mapTypeOf(inferred) ?? dynFallbackType(lowerer, member, inferred))
|
|
1917
|
+
: DYN;
|
|
1712
1918
|
let type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
|
|
1713
|
-
? DYN
|
|
1714
|
-
|
|
1919
|
+
? DYN
|
|
1920
|
+
: mapped
|
|
1921
|
+
? jsOpenObjectType(member, mapped, lowerer.shapes, lowerer.unions)
|
|
1922
|
+
: null;
|
|
1923
|
+
if (!type ||
|
|
1924
|
+
type.kind === "void" ||
|
|
1925
|
+
(type.kind === "dyn" &&
|
|
1926
|
+
!isJsSourceFile(member.getSourceFile()) &&
|
|
1927
|
+
!lowerer.classImplementedProtocol(inferred)))
|
|
1715
1928
|
lowerer.badType(member, inferred);
|
|
1716
1929
|
if (isJsSourceFile(member.getSourceFile())) {
|
|
1717
1930
|
type = inheritedJsFieldType(lowerer, decl, fieldName, type);
|
|
@@ -1729,11 +1942,22 @@ mixin) {
|
|
|
1729
1942
|
if (!typeEquals(previous, type)) {
|
|
1730
1943
|
lowerer.unsupported("SC1090", member.name, "redeclaring computed fields at a different type");
|
|
1731
1944
|
}
|
|
1732
|
-
fieldOrder.push({
|
|
1945
|
+
fieldOrder.push({
|
|
1946
|
+
name: fieldName,
|
|
1947
|
+
type,
|
|
1948
|
+
initializer: member.initializer,
|
|
1949
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
1950
|
+
redeclared: true,
|
|
1951
|
+
});
|
|
1733
1952
|
}
|
|
1734
1953
|
else {
|
|
1735
1954
|
fields.set(fieldName, type);
|
|
1736
|
-
fieldOrder.push({
|
|
1955
|
+
fieldOrder.push({
|
|
1956
|
+
name: fieldName,
|
|
1957
|
+
type,
|
|
1958
|
+
initializer: member.initializer,
|
|
1959
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
1960
|
+
});
|
|
1737
1961
|
}
|
|
1738
1962
|
if (symbolKey)
|
|
1739
1963
|
symbolFields.set(symbolKey.identity, fieldName);
|
|
@@ -1788,20 +2012,28 @@ mixin) {
|
|
|
1788
2012
|
if (isJsSourceFile(member.getSourceFile()) && !member.initializer) {
|
|
1789
2013
|
const constructor = decl.members.find((part) => ts.isConstructorDeclaration(part) && !!part.body);
|
|
1790
2014
|
for (const statement of constructor?.body?.statements ?? []) {
|
|
1791
|
-
if (!ts.isExpressionStatement(statement) ||
|
|
2015
|
+
if (!ts.isExpressionStatement(statement) ||
|
|
2016
|
+
!ts.isBinaryExpression(statement.expression) ||
|
|
1792
2017
|
statement.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken)
|
|
1793
2018
|
continue;
|
|
1794
2019
|
const left = statement.expression.left;
|
|
1795
|
-
if (!ts.isPropertyAccessExpression(left) ||
|
|
2020
|
+
if (!ts.isPropertyAccessExpression(left) ||
|
|
2021
|
+
left.expression.kind !== ts.SyntaxKind.ThisKeyword ||
|
|
2022
|
+
left.name.text !== member.name.text)
|
|
1796
2023
|
continue;
|
|
1797
|
-
type =
|
|
2024
|
+
type =
|
|
2025
|
+
statement.expression.right.kind === ts.SyntaxKind.NullKeyword
|
|
2026
|
+
? DYN
|
|
2027
|
+
: jsFieldInitializerType(lowerer, type, statement.expression.right);
|
|
1798
2028
|
}
|
|
1799
2029
|
}
|
|
1800
2030
|
// Unannotated JavaScript callback slots retain the original
|
|
1801
2031
|
// callable and its receiver instead of adapting its signature.
|
|
1802
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2032
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2033
|
+
!member.type &&
|
|
1803
2034
|
!/@type\b/.test(member.getSourceFile().text.slice(member.pos, member.getStart())) &&
|
|
1804
|
-
(type.kind === "func" || type.kind === "record") &&
|
|
2035
|
+
(type.kind === "func" || type.kind === "record") &&
|
|
2036
|
+
lowerer.dynConvertible(type))
|
|
1805
2037
|
type = DYN;
|
|
1806
2038
|
// JS permits reads before a constructor's first assignment even
|
|
1807
2039
|
// when its inferred field type omits undefined.
|
|
@@ -1820,7 +2052,9 @@ mixin) {
|
|
|
1820
2052
|
// Bundled JS declares fields without annotations before assigning
|
|
1821
2053
|
// them in the constructor. Use the same native checked-dynamic
|
|
1822
2054
|
// storage as implicit constructor-assigned JS fields.
|
|
1823
|
-
if (type.kind === "dyn" &&
|
|
2055
|
+
if (type.kind === "dyn" &&
|
|
2056
|
+
!isJsSourceFile(member.getSourceFile()) &&
|
|
2057
|
+
!lowerer.classImplementedProtocol(lowerer.typeOf(member.name))) {
|
|
1824
2058
|
lowerer.unsupported("SC1090", member.name, "'unknown'-typed class fields");
|
|
1825
2059
|
}
|
|
1826
2060
|
const undefinedInitializer = type.kind === "dyn" && !member.initializer ? locOf(member) : undefined;
|
|
@@ -1838,7 +2072,13 @@ mixin) {
|
|
|
1838
2072
|
// Other bare or type-changing redeclarations keep the fence.
|
|
1839
2073
|
const baseType = fields.get(member.name.text);
|
|
1840
2074
|
if ((member.initializer || type.kind === "dyn") && typeEquals(type, baseType)) {
|
|
1841
|
-
fieldOrder.push({
|
|
2075
|
+
fieldOrder.push({
|
|
2076
|
+
name: member.name.text,
|
|
2077
|
+
type,
|
|
2078
|
+
initializer: member.initializer,
|
|
2079
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
2080
|
+
redeclared: true,
|
|
2081
|
+
});
|
|
1842
2082
|
continue;
|
|
1843
2083
|
}
|
|
1844
2084
|
lowerer.unsupported("SC1090", member.name, member.initializer
|
|
@@ -1862,8 +2102,10 @@ mixin) {
|
|
|
1862
2102
|
// list checked against the constructor after the member loop
|
|
1863
2103
|
// (the constructor may be declared later in the class body).
|
|
1864
2104
|
const admitsUndefined = (type.kind === "union" &&
|
|
1865
|
-
(lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ??
|
|
1866
|
-
|
|
2105
|
+
(lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ??
|
|
2106
|
+
false)) ||
|
|
2107
|
+
type.kind === "jsval" ||
|
|
2108
|
+
type.kind === "dyn";
|
|
1867
2109
|
if (!member.initializer && !admitsUndefined) {
|
|
1868
2110
|
const opts = lowerer.program.getCompilerOptions();
|
|
1869
2111
|
const spi = opts.strictPropertyInitialization ?? opts.strict ?? false;
|
|
@@ -1883,7 +2125,12 @@ mixin) {
|
|
|
1883
2125
|
}
|
|
1884
2126
|
}
|
|
1885
2127
|
fields.set(member.name.text, type);
|
|
1886
|
-
fieldOrder.push({
|
|
2128
|
+
fieldOrder.push({
|
|
2129
|
+
name: member.name.text,
|
|
2130
|
+
type,
|
|
2131
|
+
initializer: member.initializer,
|
|
2132
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
2133
|
+
});
|
|
1887
2134
|
}
|
|
1888
2135
|
else if (ts.isConstructorDeclaration(member)) {
|
|
1889
2136
|
// A body-less constructor is an OVERLOAD SIGNATURE: type-world,
|
|
@@ -1935,7 +2182,7 @@ mixin) {
|
|
|
1935
2182
|
if (type.kind === "void")
|
|
1936
2183
|
lowerer.badType(p.name, lowerer.typeOf(p.name));
|
|
1937
2184
|
// The class-field dyn rule verbatim (KEEP NARROW).
|
|
1938
|
-
if (type.kind === "dyn") {
|
|
2185
|
+
if (type.kind === "dyn" && !lowerer.classImplementedProtocol(lowerer.typeOf(p))) {
|
|
1939
2186
|
lowerer.unsupported("SC1090", p.name, "'unknown'-typed class fields");
|
|
1940
2187
|
}
|
|
1941
2188
|
// `override x` (and any same-named inherited member) would
|
|
@@ -2027,15 +2274,18 @@ mixin) {
|
|
|
2027
2274
|
// signature carries bindable untyped params collects like a
|
|
2028
2275
|
// GENERIC method — into genericMethods, no vtable slot, one
|
|
2029
2276
|
// instance per call-site type tuple (the untyped params ARE the
|
|
2030
|
-
// type parameters; see
|
|
2277
|
+
// type parameters; see generic-functions.ts). DECLINES
|
|
2031
2278
|
// (falls through to the normal all-dyn ABI) wherever the two
|
|
2032
2279
|
// dispatch worlds could meet: an inherited declaration of the
|
|
2033
2280
|
// name (the override stays on the vtable), a shadowed field, or
|
|
2034
2281
|
// a generic-class instantiation's member.
|
|
2035
|
-
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
2282
|
+
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
2283
|
+
!functionLocalClass(decl) &&
|
|
2036
2284
|
ts.isIdentifier(member.name) &&
|
|
2037
|
-
!lowerer.virtualJsMethods.has(member) &&
|
|
2038
|
-
|
|
2285
|
+
!lowerer.virtualJsMethods.has(member) &&
|
|
2286
|
+
!lowerer.prototypeMethodAccesses.has(member.name.text) &&
|
|
2287
|
+
inst === undefined &&
|
|
2288
|
+
decl.typeParameters === undefined &&
|
|
2039
2289
|
!fields.has(member.name.text) &&
|
|
2040
2290
|
!lowerer.findMethodOn(base, member.name.text) &&
|
|
2041
2291
|
!findGenericMethodOn(lowerer, base, member.name.text)) {
|
|
@@ -2069,9 +2319,13 @@ mixin) {
|
|
|
2069
2319
|
}
|
|
2070
2320
|
// JS inference may retain only a symbol sentinel while a method
|
|
2071
2321
|
// also returns values from an untyped mutable field or local.
|
|
2072
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2322
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2323
|
+
!member.type &&
|
|
2324
|
+
!hasExplicitJsDocReturn(member) &&
|
|
2325
|
+
ft.ret.kind === "symbol")
|
|
2073
2326
|
ft.ret = DYN;
|
|
2074
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2327
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2328
|
+
lowerer.prototypeMethodAccesses.has(mName) &&
|
|
2075
2329
|
!lowerer.findMethodOn(base, mName)?.declarer.def.runtime &&
|
|
2076
2330
|
shapes.every((p) => p.mode === "required" || p.mode === "omittable")) {
|
|
2077
2331
|
for (const shape of shapes) {
|
|
@@ -2087,7 +2341,8 @@ mixin) {
|
|
|
2087
2341
|
// argument slots in the base before constructing its vtable; shorter
|
|
2088
2342
|
// bodies ignore them and omitted call arguments become undefined.
|
|
2089
2343
|
const virtualArity = lowerer.virtualJsMethodArity.get(member) ?? shapes.length;
|
|
2090
|
-
if (virtualArity > shapes.length &&
|
|
2344
|
+
if (virtualArity > shapes.length &&
|
|
2345
|
+
!bodyReadsArguments(member) &&
|
|
2091
2346
|
shapes.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
2092
2347
|
while (shapes.length < virtualArity)
|
|
2093
2348
|
shapes.push({ type: DYN, mode: "omittable" });
|
|
@@ -2121,13 +2376,18 @@ mixin) {
|
|
|
2121
2376
|
// An unannotated JS override can return a checked value into
|
|
2122
2377
|
// the inherited native ABI, just as its untyped parameters do.
|
|
2123
2378
|
// Body lowering inserts the conversion at each return.
|
|
2124
|
-
if (!member.type &&
|
|
2125
|
-
|
|
2379
|
+
if (!member.type &&
|
|
2380
|
+
ft.ret.kind === "dyn" &&
|
|
2381
|
+
overridden.sig.ret.kind !== "dyn" &&
|
|
2382
|
+
!overridden.sig.async &&
|
|
2383
|
+
!overridden.sig.gen)
|
|
2126
2384
|
ft.ret = overridden.sig.ret;
|
|
2127
2385
|
// Fluent overrides return the same native receiver. Keep the
|
|
2128
2386
|
// inherited return ABI and upcast `this` when lowering returns.
|
|
2129
|
-
if (overridden.sig.ret.kind === "object" &&
|
|
2130
|
-
|
|
2387
|
+
if (overridden.sig.ret.kind === "object" &&
|
|
2388
|
+
base &&
|
|
2389
|
+
(base.def.name === overridden.sig.ret.className ||
|
|
2390
|
+
lowerer.isSubclassOf(base.def.name, overridden.sig.ret.className)) &&
|
|
2131
2391
|
returnsOnlyThis(member))
|
|
2132
2392
|
ft.ret = overridden.sig.ret;
|
|
2133
2393
|
// An unannotated JS parameter can use the base's typed ABI.
|
|
@@ -2136,8 +2396,13 @@ mixin) {
|
|
|
2136
2396
|
for (let i = 0; i < shapes.length; i++) {
|
|
2137
2397
|
const parameter = member.parameters[i];
|
|
2138
2398
|
const inherited = overridden.sig.params[i];
|
|
2139
|
-
if (parameter &&
|
|
2140
|
-
|
|
2399
|
+
if (parameter &&
|
|
2400
|
+
inherited &&
|
|
2401
|
+
!parameter.type &&
|
|
2402
|
+
!parameter.initializer &&
|
|
2403
|
+
!parameter.dotDotDotToken &&
|
|
2404
|
+
shapes[i].type.kind === "dyn" &&
|
|
2405
|
+
inherited.type.kind !== "dyn" &&
|
|
2141
2406
|
(inherited.mode === "required" || inherited.mode === "omittable")) {
|
|
2142
2407
|
shapes[i] = { ...inherited };
|
|
2143
2408
|
}
|
|
@@ -2147,12 +2412,18 @@ mixin) {
|
|
|
2147
2412
|
// checked-value ABI slots as unused parameters, and let shorter
|
|
2148
2413
|
// calls fill them with undefined. Typed tails and rest/arguments
|
|
2149
2414
|
// readers keep the exact-signature fence.
|
|
2150
|
-
if (overridden &&
|
|
2415
|
+
if (overridden &&
|
|
2416
|
+
isJsSourceFile(member.getSourceFile()) &&
|
|
2151
2417
|
shapes.length < overridden.sig.params.length &&
|
|
2152
2418
|
!bodyReadsArguments(member) &&
|
|
2153
|
-
shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") &&
|
|
2154
|
-
|
|
2155
|
-
|
|
2419
|
+
shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") &&
|
|
2420
|
+
typeEquals(p.type, overridden.sig.params[i].type)) &&
|
|
2421
|
+
overridden.sig.params
|
|
2422
|
+
.slice(shapes.length)
|
|
2423
|
+
.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
2424
|
+
shapes.push(...overridden.sig.params
|
|
2425
|
+
.slice(shapes.length)
|
|
2426
|
+
.map((p) => ({ type: p.type, mode: "omittable" })));
|
|
2156
2427
|
}
|
|
2157
2428
|
if (overridden &&
|
|
2158
2429
|
member.asteriskToken === undefined &&
|
|
@@ -2160,7 +2431,8 @@ mixin) {
|
|
|
2160
2431
|
!overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) ||
|
|
2161
2432
|
!typeEquals(overridden.sig.ret, ft.ret))) {
|
|
2162
2433
|
const fencedJsOverride = isJsSourceFile(member.getSourceFile()) &&
|
|
2163
|
-
overridden.declarer.decl !== null &&
|
|
2434
|
+
overridden.declarer.decl !== null &&
|
|
2435
|
+
isJsSourceFile(overridden.declarer.decl.getSourceFile()) &&
|
|
2164
2436
|
overridden.sig.gen === undefined;
|
|
2165
2437
|
if (fencedJsOverride) {
|
|
2166
2438
|
// A dormant JS method must not poison the whole class. Keep
|
|
@@ -2171,8 +2443,11 @@ mixin) {
|
|
|
2171
2443
|
!member.parameters.some((parameter, index) => {
|
|
2172
2444
|
if (!parameter.initializer)
|
|
2173
2445
|
return false;
|
|
2174
|
-
const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) &&
|
|
2175
|
-
|
|
2446
|
+
const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) &&
|
|
2447
|
+
classMemberNameOf(lowerer, candidate.name) === mName);
|
|
2448
|
+
const inherited = baseMember && ts.isMethodDeclaration(baseMember)
|
|
2449
|
+
? baseMember.parameters[index]?.initializer
|
|
2450
|
+
: undefined;
|
|
2176
2451
|
if (!inherited)
|
|
2177
2452
|
return false;
|
|
2178
2453
|
const ownType = lowerer.mapTypeOf(lowerer.typeOf(parameter.initializer));
|
|
@@ -2201,7 +2476,8 @@ mixin) {
|
|
|
2201
2476
|
else
|
|
2202
2477
|
lowerer.unsupported("SC1090", member.name, message);
|
|
2203
2478
|
}
|
|
2204
|
-
if (overridden &&
|
|
2479
|
+
if (overridden &&
|
|
2480
|
+
(member.asteriskToken !== undefined || overridden.sig.gen !== undefined)) {
|
|
2205
2481
|
const message = `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`;
|
|
2206
2482
|
if (isJsSourceFile(member.getSourceFile()))
|
|
2207
2483
|
methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), message));
|
|
@@ -2223,7 +2499,9 @@ mixin) {
|
|
|
2223
2499
|
});
|
|
2224
2500
|
}
|
|
2225
2501
|
else {
|
|
2226
|
-
methods.set(mName, asyncMember
|
|
2502
|
+
methods.set(mName, asyncMember
|
|
2503
|
+
? { params: shapes, ret: ft.ret, async: true }
|
|
2504
|
+
: { params: shapes, ret: ft.ret });
|
|
2227
2505
|
}
|
|
2228
2506
|
// Overrides keep the inherited ABI exactly, so only non-override
|
|
2229
2507
|
// methods may still refine once the ctor scan runs.
|
|
@@ -2262,14 +2540,19 @@ mixin) {
|
|
|
2262
2540
|
if (!member.body && !abstractAccessor)
|
|
2263
2541
|
lowerer.unsupported("SC1090", member, "bodyless accessors");
|
|
2264
2542
|
const mName = `${isGet ? "get" : "set"}:${prop}`;
|
|
2265
|
-
if (fields.has(prop) &&
|
|
2543
|
+
if (fields.has(prop) &&
|
|
2544
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
2545
|
+
base?.fields.has(prop) &&
|
|
2266
2546
|
!fieldOrder.some((field) => field.name === prop)) {
|
|
2267
2547
|
// JS may override an inherited data field with a prototype
|
|
2268
2548
|
// accessor. Retain the base storage prefix for its constructor;
|
|
2269
2549
|
// property dispatch on this subclass selects the accessor.
|
|
2270
2550
|
fields.delete(prop);
|
|
2271
2551
|
}
|
|
2272
|
-
if (fields.has(prop) &&
|
|
2552
|
+
if (fields.has(prop) &&
|
|
2553
|
+
!((prop === "message" || prop === "name") &&
|
|
2554
|
+
base &&
|
|
2555
|
+
(base.def.name === "%Error" || lowerer.isSubclassOf(base.def.name, "%Error")))) {
|
|
2273
2556
|
// tsc rejects field/accessor mixing (TS2610/2611); defensive.
|
|
2274
2557
|
lowerer.unsupported("SC1090", member.name, "accessors sharing a name with a field");
|
|
2275
2558
|
}
|
|
@@ -2333,7 +2616,11 @@ mixin) {
|
|
|
2333
2616
|
if (paramProps.length > 0) {
|
|
2334
2617
|
for (const pp of paramProps)
|
|
2335
2618
|
fields.set(pp.name, pp.type);
|
|
2336
|
-
fieldOrder.unshift(...paramProps.map((pp) => ({
|
|
2619
|
+
fieldOrder.unshift(...paramProps.map((pp) => ({
|
|
2620
|
+
name: pp.name,
|
|
2621
|
+
type: pp.type,
|
|
2622
|
+
initializer: undefined,
|
|
2623
|
+
})));
|
|
2337
2624
|
}
|
|
2338
2625
|
// The deferred definite-assignment check: a field on the unguarded
|
|
2339
2626
|
// list passes only with an unconditional `this.x = ...` at the
|
|
@@ -2367,9 +2654,14 @@ mixin) {
|
|
|
2367
2654
|
// extraction targets one arm); union-typed `!` fields keep the
|
|
2368
2655
|
// fence.
|
|
2369
2656
|
const declared = fields.get(f.name);
|
|
2370
|
-
const armable = declared !== undefined &&
|
|
2371
|
-
declared
|
|
2372
|
-
declared.kind !== "
|
|
2657
|
+
const armable = declared !== undefined &&
|
|
2658
|
+
!isUnitType(declared) &&
|
|
2659
|
+
declared.kind !== "union" &&
|
|
2660
|
+
declared.kind !== "jsval" &&
|
|
2661
|
+
declared.kind !== "dyn" &&
|
|
2662
|
+
declared.kind !== "map" &&
|
|
2663
|
+
declared.kind !== "date" &&
|
|
2664
|
+
declared.kind !== "generator" &&
|
|
2373
2665
|
declared.kind !== "void" &&
|
|
2374
2666
|
declared.kind !== "caught";
|
|
2375
2667
|
const armed = armable ? lowerer.withUndefinedArm(declared) : null;
|
|
@@ -2436,13 +2728,18 @@ mixin) {
|
|
|
2436
2728
|
// forbids via strictPropertyInitialization — so they keep a named
|
|
2437
2729
|
// fence instead of a silent undefined.
|
|
2438
2730
|
if (isJsSourceFile(decl.getSourceFile())) {
|
|
2439
|
-
const hasAccessor = (name) => methods.has(`get:${name}`) ||
|
|
2731
|
+
const hasAccessor = (name) => methods.has(`get:${name}`) ||
|
|
2732
|
+
methods.has(`set:${name}`) ||
|
|
2440
2733
|
lowerer.findMethodOn(base, `get:${name}`) !== null ||
|
|
2441
2734
|
lowerer.findMethodOn(base, `set:${name}`) !== null;
|
|
2442
2735
|
// Named classes (declarations and self-binding expressions) resolve
|
|
2443
2736
|
// by name; the nameless default-export declaration by its module's
|
|
2444
2737
|
// default-export symbol.
|
|
2445
|
-
const classSym = decl.name
|
|
2738
|
+
const classSym = decl.name
|
|
2739
|
+
? lowerer.checker.getSymbolAtLocation(decl.name)
|
|
2740
|
+
: ts.isClassDeclaration(decl)
|
|
2741
|
+
? declSymbolOf(lowerer, decl)
|
|
2742
|
+
: undefined;
|
|
2446
2743
|
const instType = classSym ? lowerer.checker.getDeclaredTypeOfSymbol(classSym) : undefined;
|
|
2447
2744
|
// LATE-BOUND properties (the checker's `__@name@id` spelling —
|
|
2448
2745
|
// `this[kLimit] = v` where kLimit is a unique symbol const) by
|
|
@@ -2466,7 +2763,8 @@ mixin) {
|
|
|
2466
2763
|
stmt.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken
|
|
2467
2764
|
? stmt.expression.left
|
|
2468
2765
|
: null;
|
|
2469
|
-
if (lhs &&
|
|
2766
|
+
if (lhs &&
|
|
2767
|
+
ts.isPropertyAccessExpression(lhs) &&
|
|
2470
2768
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
2471
2769
|
const assign = lhs;
|
|
2472
2770
|
const name = assign.name.text;
|
|
@@ -2493,7 +2791,9 @@ mixin) {
|
|
|
2493
2791
|
// TS-annotated `unknown` fields keep their fence (KEEP NARROW
|
|
2494
2792
|
// applies where an annotation could say better).
|
|
2495
2793
|
let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, assign, t)) : null;
|
|
2496
|
-
if (t &&
|
|
2794
|
+
if (t &&
|
|
2795
|
+
(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0 &&
|
|
2796
|
+
isJsSourceFile(decl.getSourceFile()))
|
|
2497
2797
|
type = DYN;
|
|
2498
2798
|
if (type)
|
|
2499
2799
|
type = jsOpenObjectType(assign, type, lowerer.shapes, lowerer.unions);
|
|
@@ -2540,7 +2840,8 @@ mixin) {
|
|
|
2540
2840
|
// property type, through the same JS checked-dynamic fallback
|
|
2541
2841
|
// as named fields. Keys that DON'T resolve fall through to the
|
|
2542
2842
|
// late-bound fence below.
|
|
2543
|
-
if (lhs &&
|
|
2843
|
+
if (lhs &&
|
|
2844
|
+
ts.isElementAccessExpression(lhs) &&
|
|
2544
2845
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
2545
2846
|
const key = classSymbolKeyOf(lowerer, lhs.argumentExpression);
|
|
2546
2847
|
const stringKey = lowerer.foldedStringKeyOf(lhs.argumentExpression);
|
|
@@ -2566,7 +2867,11 @@ mixin) {
|
|
|
2566
2867
|
// one layout would need one printable name for two slots.
|
|
2567
2868
|
lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
|
|
2568
2869
|
}
|
|
2569
|
-
const propSym = key
|
|
2870
|
+
const propSym = key
|
|
2871
|
+
? lateBoundByKey.get(key.sym)
|
|
2872
|
+
: instType
|
|
2873
|
+
? lowerer.checker.getPropertyOfType(instType, fieldName)
|
|
2874
|
+
: undefined;
|
|
2570
2875
|
// tsgo does not synthesize the late-bound `__@name@id`
|
|
2571
2876
|
// property for a JS `this[k] = v` declaration (the finding-5
|
|
2572
2877
|
// family: no expando/late-bound synthesis in its stricter
|
|
@@ -2610,7 +2915,10 @@ mixin) {
|
|
|
2610
2915
|
continue;
|
|
2611
2916
|
if (base && (base.fields.has(p.name) || lowerer.findMethodOn(base, p.name)))
|
|
2612
2917
|
continue;
|
|
2613
|
-
const site = lowerer.checker
|
|
2918
|
+
const site = lowerer.checker
|
|
2919
|
+
.declarationsOf(p)
|
|
2920
|
+
.find((d) => ts.isPropertyAccessExpression(d) ||
|
|
2921
|
+
ts.isBinaryExpression(d) ||
|
|
2614
2922
|
ts.isElementAccessExpression(d));
|
|
2615
2923
|
if (!site)
|
|
2616
2924
|
continue;
|
|
@@ -2684,8 +2992,11 @@ mixin) {
|
|
|
2684
2992
|
const ctorParams = ctor && !mixinForwarding
|
|
2685
2993
|
? lowerer.paramShapes(ctor.parameters)
|
|
2686
2994
|
: (base?.ctorParams ?? (callableBase ? [{ type: DYN, mode: "dynRest" }] : []));
|
|
2687
|
-
if (ctor &&
|
|
2688
|
-
!
|
|
2995
|
+
if (ctor &&
|
|
2996
|
+
!mixinForwarding &&
|
|
2997
|
+
isJsSourceFile(ctor.getSourceFile()) &&
|
|
2998
|
+
!ctorParams.some((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest") &&
|
|
2999
|
+
bodyReadsArguments(ctor)) {
|
|
2689
3000
|
ctorParams.push({ type: DYN, mode: "arguments" });
|
|
2690
3001
|
}
|
|
2691
3002
|
const info = {
|
|
@@ -2708,7 +3019,9 @@ mixin) {
|
|
|
2708
3019
|
// initializers assign the prefix slot).
|
|
2709
3020
|
fields: [
|
|
2710
3021
|
...(base?.def.fields ?? []),
|
|
2711
|
-
...fieldOrder
|
|
3022
|
+
...fieldOrder
|
|
3023
|
+
.filter((f) => f.redeclared !== true)
|
|
3024
|
+
.map((f) => ({ name: f.name, type: f.type })),
|
|
2712
3025
|
],
|
|
2713
3026
|
...(methods.size > 0 ? { methods: [...methods.keys()] } : {}),
|
|
2714
3027
|
...(abstractClass ? { abstract: true } : {}),
|
|
@@ -2729,6 +3042,7 @@ mixin) {
|
|
|
2729
3042
|
ctorParams,
|
|
2730
3043
|
...(paramProps.length > 0 ? { paramProps } : {}),
|
|
2731
3044
|
base,
|
|
3045
|
+
...(genericBase ? { genericBase } : {}),
|
|
2732
3046
|
...(callableBase ? { callableBase } : {}),
|
|
2733
3047
|
...(factoryBaseExpression ? { factoryBaseExpression } : {}),
|
|
2734
3048
|
subclasses: [],
|
|
@@ -2738,7 +3052,9 @@ mixin) {
|
|
|
2738
3052
|
...(staticBlocks.length > 0 ? { staticBlocks } : {}),
|
|
2739
3053
|
...(symbolFields.size > 0 ? { symbolFields } : {}),
|
|
2740
3054
|
...(symbolMethods.size > 0 ? { symbolMethods } : {}),
|
|
2741
|
-
...(classDecoratorNodes.length > 0
|
|
3055
|
+
...(classDecoratorNodes.length > 0
|
|
3056
|
+
? { classDecorators: { nodes: classDecoratorNodes } }
|
|
3057
|
+
: {}),
|
|
2742
3058
|
...(deferredInitFields.size > 0 ? { deferredInitFields } : {}),
|
|
2743
3059
|
};
|
|
2744
3060
|
// GENERIC members get their declaring-class backlink now that the
|
|
@@ -2756,6 +3072,7 @@ mixin) {
|
|
|
2756
3072
|
}
|
|
2757
3073
|
if (inst) {
|
|
2758
3074
|
info.genericInstance = {
|
|
3075
|
+
path: inst.path,
|
|
2759
3076
|
family: inst.family,
|
|
2760
3077
|
bindings: inst.bindings,
|
|
2761
3078
|
typeArgsText: inst.typeArgsText,
|
|
@@ -2793,14 +3110,29 @@ mixin) {
|
|
|
2793
3110
|
lowerer.classes.set(className, info);
|
|
2794
3111
|
if (computedBase && !functionLocalClass(decl)) {
|
|
2795
3112
|
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2796
|
-
lowerer.globalsList.push({
|
|
3113
|
+
lowerer.globalsList.push({
|
|
3114
|
+
id: info.def.baseValueGlobal,
|
|
3115
|
+
name: `${className} base`,
|
|
3116
|
+
type: computedBase.value.type,
|
|
3117
|
+
mutable: false,
|
|
3118
|
+
});
|
|
2797
3119
|
}
|
|
2798
3120
|
if (factoryBaseExpression && !functionLocalClass(decl)) {
|
|
2799
3121
|
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2800
|
-
lowerer.globalsList.push({
|
|
3122
|
+
lowerer.globalsList.push({
|
|
3123
|
+
id: info.def.baseValueGlobal,
|
|
3124
|
+
name: `${className} base`,
|
|
3125
|
+
type: { kind: "classval", className: base.def.name },
|
|
3126
|
+
mutable: false,
|
|
3127
|
+
});
|
|
2801
3128
|
}
|
|
2802
3129
|
if (callableBase && !functionLocalClass(decl)) {
|
|
2803
|
-
lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, {
|
|
3130
|
+
lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, {
|
|
3131
|
+
id: callableBase.prototypeId,
|
|
3132
|
+
name: `${className} base prototype`,
|
|
3133
|
+
type: DYN,
|
|
3134
|
+
mutable: false,
|
|
3135
|
+
});
|
|
2804
3136
|
}
|
|
2805
3137
|
// A NAMED class binds its name (declarations in their scope, class
|
|
2806
3138
|
// expressions inside their own bodies — tsc resolves both to this
|
|
@@ -2812,29 +3144,45 @@ mixin) {
|
|
|
2812
3144
|
// classes fence at their use sites).
|
|
2813
3145
|
const classSymbol = inst || mixin
|
|
2814
3146
|
? undefined
|
|
2815
|
-
: decl.name
|
|
3147
|
+
: decl.name
|
|
3148
|
+
? lowerer.checker.getSymbolAtLocation(decl.name)
|
|
3149
|
+
: ts.isClassDeclaration(decl)
|
|
3150
|
+
? declSymbolOf(lowerer, decl)
|
|
3151
|
+
: undefined;
|
|
2816
3152
|
if (classSymbol)
|
|
2817
3153
|
lowerer.classBySymbol.set(classSymbol, info);
|
|
2818
3154
|
// Static-field storage registers with the module's globals only
|
|
2819
3155
|
// once the whole shape collected (a poisoned class never leaves a
|
|
2820
3156
|
// half-registered global behind).
|
|
2821
3157
|
for (const f of staticFields) {
|
|
2822
|
-
lowerer.globalsList.push({
|
|
3158
|
+
lowerer.globalsList.push({
|
|
3159
|
+
id: f.globalId,
|
|
3160
|
+
name: `${info.def.jsName ?? className}.${f.name}`,
|
|
3161
|
+
type: f.type,
|
|
3162
|
+
mutable: !f.readonly,
|
|
3163
|
+
});
|
|
2823
3164
|
}
|
|
2824
3165
|
}
|
|
2825
3166
|
}
|
|
2826
3167
|
/** mapType's generic-class hook: the INSTANTIATION a concrete type
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
3168
|
+
* reference (`Box<number>`) names — registered on first demand. The
|
|
3169
|
+
* instance's NAME reserves its key before the shape collects, so
|
|
3170
|
+
* self-referential layouts (`next: Box<T> | null`) re-enter here and
|
|
3171
|
+
* take the name without recursing; a poisoned collection (a field type
|
|
3172
|
+
* with no lowering under these bindings — the diagnostic carries the
|
|
3173
|
+
* instantiation context) leaves the entry poisoned and the type
|
|
3174
|
+
* unmapped, the fenced-JS-class story. Null answers (unmappable type
|
|
3175
|
+
* arguments, the instance cap, an uncollected family) make the whole
|
|
3176
|
+
* reference unmappable — per-site diagnostics own the fence. */
|
|
2836
3177
|
export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
2837
|
-
|
|
3178
|
+
let gci = lowerer.genericClassByDecl.get(decl);
|
|
3179
|
+
if (!gci && ts.isClassDeclaration(decl)) {
|
|
3180
|
+
// A method signature can reference a generic class declared later in
|
|
3181
|
+
// the same module. Resolve its family now rather than freezing the
|
|
3182
|
+
// signature at the erased family layout for the rest of the build.
|
|
3183
|
+
lowerer.collectClassShape(decl);
|
|
3184
|
+
gci = lowerer.genericClassByDecl.get(decl);
|
|
3185
|
+
}
|
|
2838
3186
|
if (!gci) {
|
|
2839
3187
|
// The family never collected (a deferred/poisoned declaration): the
|
|
2840
3188
|
// pre-generics answer — the class's own name, unregistered, so dead
|
|
@@ -2856,7 +3204,9 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2856
3204
|
const familyT = { kind: "object", className: gci.family.def.name };
|
|
2857
3205
|
// The checker appends `this` (and outer type parameters) to
|
|
2858
3206
|
// getTypeArguments — only the declaration's own count participates.
|
|
2859
|
-
const args = lowerer.checker
|
|
3207
|
+
const args = lowerer.checker
|
|
3208
|
+
.getTypeArguments(ref)
|
|
3209
|
+
.slice(0, gci.typeParams.length);
|
|
2860
3210
|
const mapped = [];
|
|
2861
3211
|
if (args.length === gci.typeParams.length) {
|
|
2862
3212
|
for (const a of args) {
|
|
@@ -2889,12 +3239,12 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2889
3239
|
lowerer.noteGenericClassInstanceDemand(existing.info);
|
|
2890
3240
|
return existing.poisoned ? null : { kind: "object", className: existing.name };
|
|
2891
3241
|
}
|
|
2892
|
-
//
|
|
2893
|
-
//
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
3242
|
+
// Recursive class fields and queued member bodies share the function
|
|
3243
|
+
// demand budget. Independent uses do not limit the family size.
|
|
3244
|
+
const path = extendInstantiationPath(lowerer.genericInstantiationPath, decl);
|
|
3245
|
+
if (!path) {
|
|
3246
|
+
lowerer.unsupported("SC1090", decl, `unbounded generic class instantiation ('${gci.baseName}' exceeded ${MAX_INSTANTIATION_RECURSION} recursive specializations on one demand path)`);
|
|
3247
|
+
}
|
|
2898
3248
|
const ordinal = gci.instances.size;
|
|
2899
3249
|
const name = `${gci.family.def.name}%${ordinal}`;
|
|
2900
3250
|
const entry = { name, info: null };
|
|
@@ -2905,10 +3255,19 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2905
3255
|
const typeArgsText = `<${rendered.length > 80 ? rendered.slice(0, 77) + "..." : rendered}>`;
|
|
2906
3256
|
const prevBindings = lowerer.typeParamBindings;
|
|
2907
3257
|
const prevContext = lowerer.instantiationContext;
|
|
3258
|
+
const previousPath = lowerer.genericInstantiationPath;
|
|
3259
|
+
lowerer.genericInstantiationPath = path;
|
|
2908
3260
|
lowerer.typeParamBindings = bindings;
|
|
2909
3261
|
lowerer.instantiationContext = `instantiating class '${gci.baseName}' with ${typeArgsText}`;
|
|
2910
3262
|
try {
|
|
2911
|
-
lowerer.collectClassShapeInner(decl, undefined, {
|
|
3263
|
+
lowerer.collectClassShapeInner(decl, undefined, {
|
|
3264
|
+
path,
|
|
3265
|
+
family: gci.family,
|
|
3266
|
+
name,
|
|
3267
|
+
bindings,
|
|
3268
|
+
typeArgsText,
|
|
3269
|
+
ordinal,
|
|
3270
|
+
});
|
|
2912
3271
|
}
|
|
2913
3272
|
catch (e) {
|
|
2914
3273
|
// Collection fenced under THESE bindings: the diagnostic (with the
|
|
@@ -2921,6 +3280,7 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2921
3280
|
finally {
|
|
2922
3281
|
lowerer.typeParamBindings = prevBindings;
|
|
2923
3282
|
lowerer.instantiationContext = prevContext;
|
|
3283
|
+
lowerer.genericInstantiationPath = previousPath;
|
|
2924
3284
|
}
|
|
2925
3285
|
const info = lowerer.classes.get(name);
|
|
2926
3286
|
if (!info) {
|
|
@@ -2934,11 +3294,11 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2934
3294
|
return { kind: "object", className: name };
|
|
2935
3295
|
}
|
|
2936
3296
|
/** Runs a member-lowering thunk under an INSTANTIATION's type-parameter
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
3297
|
+
* bindings (the generic-fn typeParamResolver mechanism) — the checker
|
|
3298
|
+
* keeps reporting the unsubstituted `T`s inside the shared body AST.
|
|
3299
|
+
* Coverage counts a generic class's statements once: only the FIRST
|
|
3300
|
+
* instantiation contributes (the lowerGenericInstance rule). A no-op
|
|
3301
|
+
* for ordinary classes. */
|
|
2942
3302
|
function withInstanceBindings(lowerer, info, fn) {
|
|
2943
3303
|
const gi = info.genericInstance;
|
|
2944
3304
|
if (!gi) {
|
|
@@ -2970,6 +3330,8 @@ function withInstanceBindings(lowerer, info, fn) {
|
|
|
2970
3330
|
const prevBindings = lowerer.typeParamBindings;
|
|
2971
3331
|
const prevContext = lowerer.instantiationContext;
|
|
2972
3332
|
const prevSuppress = lowerer.suppressStats;
|
|
3333
|
+
const previousPath = lowerer.genericInstantiationPath;
|
|
3334
|
+
lowerer.genericInstantiationPath = gi.path;
|
|
2973
3335
|
lowerer.typeParamBindings = gi.bindings;
|
|
2974
3336
|
lowerer.instantiationContext = `instantiating class '${gi.family.generic?.baseName ?? info.def.jsName ?? ""}' with ${gi.typeArgsText}`;
|
|
2975
3337
|
lowerer.suppressStats = prevSuppress || gi.ordinal > 0;
|
|
@@ -2980,14 +3342,15 @@ function withInstanceBindings(lowerer, info, fn) {
|
|
|
2980
3342
|
lowerer.typeParamBindings = prevBindings;
|
|
2981
3343
|
lowerer.instantiationContext = prevContext;
|
|
2982
3344
|
lowerer.suppressStats = prevSuppress;
|
|
3345
|
+
lowerer.genericInstantiationPath = previousPath;
|
|
2983
3346
|
}
|
|
2984
3347
|
}
|
|
2985
3348
|
/** The `%init` statements for one class's static readonly fields AND
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3349
|
+
* static blocks, interleaved in member order — emitted at the class
|
|
3350
|
+
* statement's source position (see lowerFileInit's merge), exactly when
|
|
3351
|
+
* JS evaluates static initializers and blocks. Field failures poison per
|
|
3352
|
+
* field, like fieldInitStmts; a block lowers as the block statement it
|
|
3353
|
+
* is, so its statements poison individually inside lowerStmts. */
|
|
2991
3354
|
export function lowerStaticFieldInits(lowerer, info) {
|
|
2992
3355
|
if (info.localClass)
|
|
2993
3356
|
return [];
|
|
@@ -3018,41 +3381,102 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3018
3381
|
// initializers and static blocks (verified against Node — the
|
|
3019
3382
|
// decorated result is what `this`/the class name mean inside them).
|
|
3020
3383
|
const out = [...lowerClassDecoration(lowerer, info)];
|
|
3021
|
-
const computedBase = info.decl
|
|
3384
|
+
const computedBase = info.decl
|
|
3385
|
+
? lowerer.computedClassBases.get(lowerer.classNamer(info.decl))
|
|
3386
|
+
: undefined;
|
|
3022
3387
|
if (info.factoryBaseExpression && info.def.baseValueGlobal) {
|
|
3023
3388
|
const loc = locOf(info.factoryBaseExpression);
|
|
3024
3389
|
const type = { kind: "classval", className: info.base.def.name };
|
|
3025
|
-
out.push({
|
|
3026
|
-
|
|
3390
|
+
out.push({
|
|
3391
|
+
kind: "assign",
|
|
3392
|
+
localId: info.def.baseValueGlobal,
|
|
3393
|
+
value: lowerer.lowerExprExpecting(info.factoryBaseExpression, type),
|
|
3394
|
+
loc,
|
|
3395
|
+
});
|
|
3396
|
+
out.push({
|
|
3397
|
+
kind: "exprStmt",
|
|
3398
|
+
expr: {
|
|
3399
|
+
kind: "libCall",
|
|
3400
|
+
fn: "dyn.classInherit",
|
|
3401
|
+
args: [
|
|
3027
3402
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3028
3403
|
lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type, loc }, DYN),
|
|
3029
|
-
],
|
|
3404
|
+
],
|
|
3405
|
+
type: DYN,
|
|
3406
|
+
loc,
|
|
3407
|
+
},
|
|
3408
|
+
loc,
|
|
3409
|
+
});
|
|
3030
3410
|
}
|
|
3031
3411
|
if (computedBase && info.def.baseValueGlobal) {
|
|
3032
3412
|
const loc = computedBase.value.loc;
|
|
3033
3413
|
out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: computedBase.value, loc });
|
|
3034
|
-
out.push({
|
|
3414
|
+
out.push({
|
|
3415
|
+
kind: "exprStmt",
|
|
3416
|
+
expr: {
|
|
3417
|
+
kind: "libCall",
|
|
3418
|
+
fn: "dyn.classInherit",
|
|
3419
|
+
args: [
|
|
3035
3420
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3036
|
-
lowerer.coerceToExpected({
|
|
3037
|
-
|
|
3421
|
+
lowerer.coerceToExpected({
|
|
3422
|
+
kind: "varRef",
|
|
3423
|
+
localId: info.def.baseValueGlobal,
|
|
3424
|
+
type: computedBase.value.type,
|
|
3425
|
+
loc,
|
|
3426
|
+
}, DYN),
|
|
3427
|
+
],
|
|
3428
|
+
type: DYN,
|
|
3429
|
+
loc,
|
|
3430
|
+
},
|
|
3431
|
+
loc,
|
|
3432
|
+
});
|
|
3038
3433
|
}
|
|
3039
3434
|
if (info.callableBase) {
|
|
3040
3435
|
const { expression, constructorId, prototypeId } = info.callableBase;
|
|
3041
3436
|
const loc = locOf(expression);
|
|
3042
|
-
out.push({
|
|
3437
|
+
out.push({
|
|
3438
|
+
kind: "assign",
|
|
3439
|
+
localId: constructorId,
|
|
3440
|
+
value: info.decl && lowerer.computedCallableBases.has(info.decl)
|
|
3043
3441
|
? lowerer.coerceToExpected(lowerer.computedCallableBases.get(info.decl), DYN)
|
|
3044
|
-
: lowerer.lowerExprExpecting(expression, DYN),
|
|
3045
|
-
|
|
3442
|
+
: lowerer.lowerExprExpecting(expression, DYN),
|
|
3443
|
+
loc,
|
|
3444
|
+
}, {
|
|
3445
|
+
kind: "assign",
|
|
3446
|
+
localId: prototypeId,
|
|
3447
|
+
value: {
|
|
3448
|
+
kind: "libCall",
|
|
3449
|
+
fn: "dyn.classBasePrototype",
|
|
3450
|
+
args: [{ kind: "varRef", localId: constructorId, type: DYN, loc }],
|
|
3451
|
+
type: DYN,
|
|
3452
|
+
loc,
|
|
3453
|
+
},
|
|
3454
|
+
loc,
|
|
3455
|
+
});
|
|
3046
3456
|
const prototype = classPrototypeData(lowerer, info, loc);
|
|
3047
3457
|
if (prototype)
|
|
3048
3458
|
out.push({ kind: "exprStmt", expr: prototype, loc });
|
|
3049
|
-
out.push({
|
|
3459
|
+
out.push({
|
|
3460
|
+
kind: "exprStmt",
|
|
3461
|
+
expr: {
|
|
3462
|
+
kind: "libCall",
|
|
3463
|
+
fn: "dyn.classInherit",
|
|
3464
|
+
args: [
|
|
3050
3465
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3051
3466
|
{ kind: "varRef", localId: constructorId, type: DYN, loc },
|
|
3052
|
-
],
|
|
3467
|
+
],
|
|
3468
|
+
type: DYN,
|
|
3469
|
+
loc,
|
|
3470
|
+
},
|
|
3471
|
+
loc,
|
|
3472
|
+
});
|
|
3053
3473
|
}
|
|
3054
3474
|
if (info.runtimeStatics && !info.localClass && info.decl) {
|
|
3055
|
-
out.push({
|
|
3475
|
+
out.push({
|
|
3476
|
+
kind: "exprStmt",
|
|
3477
|
+
expr: initializeRuntimeStatics(lowerer, info, classValueRef(lowerer, info, info.decl)),
|
|
3478
|
+
loc: locOf(info.decl),
|
|
3479
|
+
});
|
|
3056
3480
|
}
|
|
3057
3481
|
const items = [
|
|
3058
3482
|
...info.staticFields.map((f) => ({ pos: f.initializer.getStart(), kind: "field", f })),
|
|
@@ -3072,11 +3496,24 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3072
3496
|
try {
|
|
3073
3497
|
const previousThis = lowerer.ctx.thisLocal;
|
|
3074
3498
|
const receiver = f.initializer.kind === ts.SyntaxKind.ThisKeyword || hasStaticThis(f.initializer)
|
|
3075
|
-
? lowerer.declareHiddenLocal("%staticThis", {
|
|
3499
|
+
? lowerer.declareHiddenLocal("%staticThis", {
|
|
3500
|
+
kind: "classval",
|
|
3501
|
+
className: info.def.name,
|
|
3502
|
+
})
|
|
3503
|
+
: null;
|
|
3076
3504
|
if (receiver) {
|
|
3077
3505
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
3078
|
-
out.push({
|
|
3079
|
-
|
|
3506
|
+
out.push({
|
|
3507
|
+
kind: "varDecl",
|
|
3508
|
+
localId: receiver.id,
|
|
3509
|
+
init: {
|
|
3510
|
+
kind: "classRef",
|
|
3511
|
+
className: info.def.name,
|
|
3512
|
+
type: receiver.type,
|
|
3513
|
+
loc: locOf(f.initializer),
|
|
3514
|
+
},
|
|
3515
|
+
loc: locOf(f.initializer),
|
|
3516
|
+
});
|
|
3080
3517
|
}
|
|
3081
3518
|
let value;
|
|
3082
3519
|
try {
|
|
@@ -3095,7 +3532,9 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3095
3532
|
lowerer.stats.statementsFailed++;
|
|
3096
3533
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
3097
3534
|
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
3098
|
-
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
3535
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
3536
|
+
kind: "statement",
|
|
3537
|
+
});
|
|
3099
3538
|
if (fence)
|
|
3100
3539
|
out.push(fence);
|
|
3101
3540
|
}
|
|
@@ -3104,22 +3543,22 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3104
3543
|
return out;
|
|
3105
3544
|
}
|
|
3106
3545
|
/** Post-collection analysis of a decorated class (all shapes registered —
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3546
|
+
* a decorator's return type may name a subclass declared BELOW the
|
|
3547
|
+
* class). Classifies every class-level decorator by its checker type:
|
|
3548
|
+
* exactly one parameter, itself a classval the decorated class legally
|
|
3549
|
+
* flows into (the class, or a base sharing its completed constructor
|
|
3550
|
+
* ABI — the classval widening rule), returning void/undefined (an
|
|
3551
|
+
* effect-only decorator) or the class/a same-ABI subclass (a REPLACING
|
|
3552
|
+
* decorator, whose result rebinds the name). Everything else is a named
|
|
3553
|
+
* fence: the standard context parameter, structural sibling
|
|
3554
|
+
* replacements tsc admits but the nominal classval world cannot carry,
|
|
3555
|
+
* unions mixing the class with undefined. A replacing decorator
|
|
3556
|
+
* registers the mutable classval global the name rebinds through, and
|
|
3557
|
+
* fences the two shapes the value rebinding cannot keep exact —
|
|
3558
|
+
* subclasses of the decorated class (the compiled hierarchy is fixed at
|
|
3559
|
+
* build time; the runtime base would be the decoration result) and
|
|
3560
|
+
* namespace-nested declarations (qualified references resolve the class
|
|
3561
|
+
* directly, not through the rebound value). */
|
|
3123
3562
|
export function analyzeClassDecoration(lowerer, info) {
|
|
3124
3563
|
const cd = info.classDecorators;
|
|
3125
3564
|
if (!cd || cd.shapes !== undefined || cd.poisoned)
|
|
@@ -3237,14 +3676,14 @@ export function analyzeClassDecoration(lowerer, info) {
|
|
|
3237
3676
|
}
|
|
3238
3677
|
}
|
|
3239
3678
|
/** The decoration statements of a decorated class — the %init code that
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3679
|
+
* runs at the class statement's position, BEFORE its static field
|
|
3680
|
+
* initializers and blocks (lowerStaticFieldInits composes them; the
|
|
3681
|
+
* lower-modules interleave places the whole bundle). Verified Node
|
|
3682
|
+
* order: decorator expressions evaluate in SOURCE order (factories run
|
|
3683
|
+
* here), then applications run in REVERSE member order over the class
|
|
3684
|
+
* object, each replacing decorator's non-undefined result feeding the
|
|
3685
|
+
* next application; the final value binds the class name (the mutable
|
|
3686
|
+
* classval global) when any decorator can replace. */
|
|
3248
3687
|
function lowerClassDecoration(lowerer, info) {
|
|
3249
3688
|
const cd = info.classDecorators;
|
|
3250
3689
|
if (!cd || cd.poisoned || cd.shapes === undefined || info.decl === null)
|
|
@@ -3264,7 +3703,11 @@ function lowerClassDecoration(lowerer, info) {
|
|
|
3264
3703
|
const d = cd.nodes[i];
|
|
3265
3704
|
const shape = cd.shapes[i];
|
|
3266
3705
|
if (shape.kind === "ambientThrow") {
|
|
3267
|
-
stmts.push({
|
|
3706
|
+
stmts.push({
|
|
3707
|
+
kind: "exprStmt",
|
|
3708
|
+
expr: nsUndefRead(lowerer, shape.name, d, F64),
|
|
3709
|
+
loc: locOf(d),
|
|
3710
|
+
});
|
|
3268
3711
|
return stmts;
|
|
3269
3712
|
}
|
|
3270
3713
|
const value = lowerer.lowerExprExpecting(d.expression, shape.funcType);
|
|
@@ -3313,9 +3756,9 @@ function lowerClassDecoration(lowerer, info) {
|
|
|
3313
3756
|
}
|
|
3314
3757
|
}
|
|
3315
3758
|
/** The nearest declaration of static member `name` at or above `info` —
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3759
|
+
* the compile-time prototype-chain walk (`D.x` reads C's global when C
|
|
3760
|
+
* declared x and nothing between redeclares it; a redeclaration shadows
|
|
3761
|
+
* with its OWN storage, exactly JS). */
|
|
3319
3762
|
export function findStaticOn(lowerer, info, name) {
|
|
3320
3763
|
for (let c = info; c; c = c.base) {
|
|
3321
3764
|
const field = c.staticFields.find((s) => s.name === name);
|
|
@@ -3328,17 +3771,17 @@ export function findStaticOn(lowerer, info, name) {
|
|
|
3328
3771
|
return null;
|
|
3329
3772
|
}
|
|
3330
3773
|
/** True when some STRICT descendant of `info` redeclares static `name` —
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
export function staticShadowBelow(
|
|
3774
|
+
* the through-a-VALUE devirtualization test: a classval(info) slot can
|
|
3775
|
+
* hold any descendant, and a shadowing redeclaration means the runtime
|
|
3776
|
+
* class decides which storage answers. */
|
|
3777
|
+
export function staticShadowBelow(info, name) {
|
|
3335
3778
|
return info.subclasses.some((s) => s.staticFields.some((f) => f.name === name) ||
|
|
3336
3779
|
s.staticMethods?.has(name) === true ||
|
|
3337
3780
|
s.genericStatics?.has(name) === true ||
|
|
3338
|
-
staticShadowBelow(
|
|
3781
|
+
staticShadowBelow(s, name));
|
|
3339
3782
|
}
|
|
3340
3783
|
/** The nearest GENERIC static declaration of `name` at/above `info` —
|
|
3341
|
-
|
|
3784
|
+
* findStaticOn's twin over the genericStatics tables. */
|
|
3342
3785
|
export function findGenericStaticOn(lowerer, info, name) {
|
|
3343
3786
|
for (let c = info; c; c = c.base) {
|
|
3344
3787
|
const gs = c.genericStatics?.get(name);
|
|
@@ -3348,8 +3791,8 @@ export function findGenericStaticOn(lowerer, info, name) {
|
|
|
3348
3791
|
return null;
|
|
3349
3792
|
}
|
|
3350
3793
|
/** A static METHOD taken as a value: the zero-capture closure over its
|
|
3351
|
-
|
|
3352
|
-
|
|
3794
|
+
* module function — the declared-function-as-value rule verbatim
|
|
3795
|
+
* (interned by the backend, so `C.m === C.m` holds). */
|
|
3353
3796
|
function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
|
|
3354
3797
|
const reflected = reflectedClassStaticMethodValue(lowerer, declarer, name);
|
|
3355
3798
|
if (reflected)
|
|
@@ -3366,13 +3809,13 @@ function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
|
|
|
3366
3809
|
return { kind: "closure", fnName, captures: [], type: funcType, loc };
|
|
3367
3810
|
}
|
|
3368
3811
|
/** The class itself taken as a VALUE (`const X = C`, an argument, an
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3812
|
+
* array element, a class expression's result): the classRef over the
|
|
3813
|
+
* per-class immortal class object. The construct thunk needs a thunk-
|
|
3814
|
+
* shaped constructor, so classes whose construction is libCall-shaped —
|
|
3815
|
+
* the runtime-provided builtins and anything inheriting a builtin
|
|
3816
|
+
* constructor (Error/EventEmitter/stream chains complete their `new`
|
|
3817
|
+
* by special rules) — are named fences here. The constructor edge is
|
|
3818
|
+
* noted at every classRef: a value can always be constructed through. */
|
|
3376
3819
|
export function classValueRef(lowerer, info, blame) {
|
|
3377
3820
|
const display = info.def.name.replace(/^%|^%m\d+\./, "");
|
|
3378
3821
|
fenceDecorationThrows(lowerer, info, blame);
|
|
@@ -3395,9 +3838,12 @@ export function classValueRef(lowerer, info, blame) {
|
|
|
3395
3838
|
}
|
|
3396
3839
|
if (lowerer.inheritsBuiltinEmitterCtor(info) ||
|
|
3397
3840
|
inheritsBuiltinStreamCtor(lowerer, info) ||
|
|
3398
|
-
(() => {
|
|
3399
|
-
|
|
3400
|
-
|
|
3841
|
+
(() => {
|
|
3842
|
+
for (let c = info.base; c; c = c.base)
|
|
3843
|
+
if (c.builtinEmitter || c.builtinStream !== undefined)
|
|
3844
|
+
return true;
|
|
3845
|
+
return false;
|
|
3846
|
+
})()) {
|
|
3401
3847
|
lowerer.unsupported("SC1090", blame, `classes extending builtin bases as values ('${display}' inherits a runtime-provided constructor)`);
|
|
3402
3848
|
}
|
|
3403
3849
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
@@ -3409,20 +3855,22 @@ export function classValueRef(lowerer, info, blame) {
|
|
|
3409
3855
|
};
|
|
3410
3856
|
}
|
|
3411
3857
|
/** Constructor-ABI equality — the classval widening rule: a classval(D)
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3858
|
+
* value may flow into a classval(C) slot only when D's completed
|
|
3859
|
+
* constructor signature equals C's (same count, modes, and ABI types),
|
|
3860
|
+
* which is what keeps newValue completion against C's one signature
|
|
3861
|
+
* sound for every value legally in the slot. */
|
|
3416
3862
|
export function ctorAbiEquals(lowerer, sub, sup) {
|
|
3417
3863
|
const a = sub.ctorParams;
|
|
3418
3864
|
const b = sup.ctorParams;
|
|
3419
|
-
return a.length === b.length &&
|
|
3865
|
+
return (a.length === b.length &&
|
|
3866
|
+
a.every((p, i) => p.mode === b[i].mode && typeEquals(p.type, b[i].type)));
|
|
3420
3867
|
}
|
|
3421
3868
|
/** Writable storage for an own static field named through its exact class.
|
|
3422
3869
|
* Inherited writes create a new subclass property in JS, so they must not
|
|
3423
3870
|
* update the declaring class's global. */
|
|
3424
3871
|
export function staticFieldWriteTarget(lowerer, access) {
|
|
3425
|
-
if (access.questionDotToken ||
|
|
3872
|
+
if (access.questionDotToken ||
|
|
3873
|
+
(!ts.isIdentifier(access.expression) && access.expression.kind !== ts.SyntaxKind.ThisKeyword))
|
|
3426
3874
|
return null;
|
|
3427
3875
|
const info = lowerer.exactClassOfReceiver(access.expression);
|
|
3428
3876
|
if (!info)
|
|
@@ -3439,20 +3887,23 @@ export function staticFieldWriteTarget(lowerer, access) {
|
|
|
3439
3887
|
return { id: found.field.globalId, type: found.field.type };
|
|
3440
3888
|
}
|
|
3441
3889
|
/** `C.x` where C is a class declared in the program and x a static
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3890
|
+
* member of its chain: field reads are the module global, static
|
|
3891
|
+
* methods become interned closures, and `.name` folds to the class's
|
|
3892
|
+
* compile-time name. Null for everything else — unresolved members
|
|
3893
|
+
* fall through to the ordinary chain so the static fence or the
|
|
3894
|
+
* generic member rejection names the site. */
|
|
3447
3895
|
export function lowerStaticFieldRead(lowerer, expr) {
|
|
3448
3896
|
if (expr.name.text === "prototype")
|
|
3449
3897
|
return null;
|
|
3450
3898
|
if (expr.questionDotToken)
|
|
3451
3899
|
return null;
|
|
3452
|
-
if (!ts.isIdentifier(expr.expression) &&
|
|
3900
|
+
if (!ts.isIdentifier(expr.expression) &&
|
|
3901
|
+
expr.expression.kind !== ts.SyntaxKind.ThisKeyword &&
|
|
3453
3902
|
exactClassOfReceiver(lowerer, expr.expression) === null)
|
|
3454
3903
|
return null;
|
|
3455
|
-
const symbol = ts.isIdentifier(expr.expression)
|
|
3904
|
+
const symbol = ts.isIdentifier(expr.expression)
|
|
3905
|
+
? lowerer.resolveValueSymbol(expr.expression)
|
|
3906
|
+
: null;
|
|
3456
3907
|
const info = (symbol ? lowerer.classBySymbol.get(symbol) : undefined) ??
|
|
3457
3908
|
// A require binding over `module.exports = class {…}` (the alias
|
|
3458
3909
|
// lands on the expression's own symbol): resolve/collect on demand,
|
|
@@ -3473,8 +3924,13 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
3473
3924
|
const loc = locOf(expr);
|
|
3474
3925
|
const found = findStaticOn(lowerer, info, expr.name.text);
|
|
3475
3926
|
if (hasRuntimeStatics(info) && !found?.field)
|
|
3476
|
-
return {
|
|
3477
|
-
|
|
3927
|
+
return {
|
|
3928
|
+
kind: "dynKeyGet",
|
|
3929
|
+
value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3930
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3931
|
+
type: DYN,
|
|
3932
|
+
loc,
|
|
3933
|
+
};
|
|
3478
3934
|
// A #private static resolves only through the DECLARING class's own
|
|
3479
3935
|
// name: in JS the brand lives on that one constructor object, so
|
|
3480
3936
|
// `D.#s` (a subclass receiver) throws Node's TypeError instead of
|
|
@@ -3503,25 +3959,38 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
3503
3959
|
return { kind: "strLit", value: info.def.jsName, type: STRING, loc };
|
|
3504
3960
|
}
|
|
3505
3961
|
if (info.callableBase)
|
|
3506
|
-
return {
|
|
3507
|
-
|
|
3962
|
+
return {
|
|
3963
|
+
kind: "dynKeyGet",
|
|
3964
|
+
value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3965
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3966
|
+
type: DYN,
|
|
3967
|
+
loc,
|
|
3968
|
+
};
|
|
3508
3969
|
const data = classStaticDataFor(lowerer, info, expr.name.text, loc);
|
|
3509
3970
|
if (data) {
|
|
3510
|
-
const value = {
|
|
3971
|
+
const value = {
|
|
3972
|
+
kind: "dynKeyGet",
|
|
3973
|
+
value: data,
|
|
3974
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3975
|
+
type: DYN,
|
|
3976
|
+
loc,
|
|
3977
|
+
};
|
|
3511
3978
|
// JavaScript often assigns public statics after the class declaration.
|
|
3512
3979
|
// Their storage stays mutable and checked, while reads retain the
|
|
3513
3980
|
// checker's concrete type instead of losing the method receiver.
|
|
3514
|
-
const type = isJsSourceFile(expr.getSourceFile())
|
|
3981
|
+
const type = isJsSourceFile(expr.getSourceFile())
|
|
3982
|
+
? null
|
|
3983
|
+
: lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
3515
3984
|
return type ? lowerer.coerceToExpected(value, type) : value;
|
|
3516
3985
|
}
|
|
3517
3986
|
return null;
|
|
3518
3987
|
}
|
|
3519
3988
|
/** NamedEvaluation's answer for a class expression's `.name`: its own
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3989
|
+
* declared name, else the binding name when the expression is the
|
|
3990
|
+
* direct initializer of a variable declaration / the RHS of a simple
|
|
3991
|
+
* assignment / an object-literal property value / a default parameter —
|
|
3992
|
+
* "" everywhere else (array elements, call arguments). Verified against
|
|
3993
|
+
* Node for each shape. */
|
|
3525
3994
|
function namedEvaluationName(expr) {
|
|
3526
3995
|
if (expr.name)
|
|
3527
3996
|
return expr.name.text;
|
|
@@ -3530,7 +3999,9 @@ function namedEvaluationName(expr) {
|
|
|
3530
3999
|
p = p.parent;
|
|
3531
4000
|
if (ts.isVariableDeclaration(p) && ts.isIdentifier(p.name) && p.initializer !== undefined)
|
|
3532
4001
|
return p.name.text;
|
|
3533
|
-
if (ts.isBinaryExpression(p) &&
|
|
4002
|
+
if (ts.isBinaryExpression(p) &&
|
|
4003
|
+
p.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
4004
|
+
ts.isIdentifier(p.left))
|
|
3534
4005
|
return p.left.text;
|
|
3535
4006
|
if (ts.isPropertyAssignment(p) && ts.isIdentifier(p.name))
|
|
3536
4007
|
return p.name.text;
|
|
@@ -3567,19 +4038,28 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3567
4038
|
if (local && expr.members.some((member) => member.name && ts.isPrivateIdentifier(member.name))) {
|
|
3568
4039
|
lowerer.unsupported("SC1090", expr, "function-local classes with private brands");
|
|
3569
4040
|
}
|
|
3570
|
-
if (local &&
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
4041
|
+
if (local &&
|
|
4042
|
+
(expr.typeParameters?.length ||
|
|
4043
|
+
decoratorNodesOf(expr).length ||
|
|
4044
|
+
expr.members.some((member) => decoratorNodesOf(member).length ||
|
|
4045
|
+
(!isJsSourceFile(expr.getSourceFile()) &&
|
|
4046
|
+
(ts.isClassStaticBlockDeclaration(member) ||
|
|
4047
|
+
ts
|
|
4048
|
+
.getModifiers(member)
|
|
4049
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) ||
|
|
4050
|
+
(ts.isMethodDeclaration(member) && member.typeParameters?.length)))) {
|
|
3575
4051
|
lowerer.unsupported("SC1090", expr, "function-local classes with statics, decorators, or generic members");
|
|
3576
4052
|
}
|
|
3577
4053
|
lowerer.collectingExprClasses.add(expr);
|
|
3578
4054
|
try {
|
|
3579
|
-
if (local &&
|
|
4055
|
+
if (local &&
|
|
4056
|
+
lowerer.fnStack.length > 0 &&
|
|
4057
|
+
!lowerer.computedClassBases.has(lowerer.classNamer(expr))) {
|
|
3580
4058
|
const heritage = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
3581
|
-
if (heritage &&
|
|
3582
|
-
ts.
|
|
4059
|
+
if (heritage &&
|
|
4060
|
+
(ts.isCallExpression(heritage) ||
|
|
4061
|
+
(ts.isIdentifier(heritage) &&
|
|
4062
|
+
(lowerer.peekLocal(heritage) ?? lowerer.globalOf(heritage)) != null))) {
|
|
3583
4063
|
let value = lowerer.lowerExpr(heritage);
|
|
3584
4064
|
const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, heritage) : null;
|
|
3585
4065
|
if (known?.kind === "classval")
|
|
@@ -3601,7 +4081,10 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3601
4081
|
throw new PoisonError(); // collection poisoned and reported
|
|
3602
4082
|
if (local) {
|
|
3603
4083
|
info.def.localCaptures = [];
|
|
3604
|
-
info.def.fields.push({
|
|
4084
|
+
info.def.fields.push({
|
|
4085
|
+
name: `%classEnvironment:${info.def.name}`,
|
|
4086
|
+
type: { kind: "classval", className: info.def.name },
|
|
4087
|
+
});
|
|
3605
4088
|
info.localClass = { context: null, bodies: new Map(), captureSources: [], ready: false };
|
|
3606
4089
|
if (info.base?.localClass) {
|
|
3607
4090
|
const baseExpression = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
@@ -3619,10 +4102,17 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3619
4102
|
// drains it), which is JS's order for whole-initializer positions.
|
|
3620
4103
|
// Anything subtler (multi-declarator statements, arguments evaluated
|
|
3621
4104
|
// after other side effects) is a named fence, never a reordering.
|
|
3622
|
-
if (!local &&
|
|
4105
|
+
if (!local &&
|
|
4106
|
+
(info.callableBase ||
|
|
4107
|
+
info.def.baseValueGlobal ||
|
|
4108
|
+
info.runtimeStatics ||
|
|
4109
|
+
info.staticFields.length > 0 ||
|
|
4110
|
+
(info.staticBlocks?.length ?? 0) > 0)) {
|
|
3623
4111
|
let holder = expr.parent;
|
|
3624
|
-
while (ts.isParenthesizedExpression(holder) ||
|
|
3625
|
-
ts.
|
|
4112
|
+
while (ts.isParenthesizedExpression(holder) ||
|
|
4113
|
+
ts.isClassExpression(holder) ||
|
|
4114
|
+
ts.isHeritageClause(holder) ||
|
|
4115
|
+
ts.isExpressionWithTypeArguments(holder)) {
|
|
3626
4116
|
holder = holder.parent;
|
|
3627
4117
|
}
|
|
3628
4118
|
const wholeInit = (ts.isVariableDeclaration(holder) &&
|
|
@@ -3643,13 +4133,13 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3643
4133
|
return info;
|
|
3644
4134
|
}
|
|
3645
4135
|
/** `class {…}` in expression position: a class definition bound to no
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
4136
|
+
* statement — once the static side is a value, the expression IS the
|
|
4137
|
+
* definition plus a classRef over it. A DECORATED class expression
|
|
4138
|
+
* whose decoration provably throws (the ambient-decorator shape) never
|
|
4139
|
+
* mints a class at all: evaluating the expression IS the
|
|
4140
|
+
* ReferenceError, so it lowers to exactly that read — every evaluation
|
|
4141
|
+
* throws identically, which is why the once-evaluated restriction and
|
|
4142
|
+
* the member fences don't apply. */
|
|
3653
4143
|
export function lowerClassExpression(lowerer, expr) {
|
|
3654
4144
|
if (decoratorNodesOf(expr).length > 0 ||
|
|
3655
4145
|
expr.members.some((m) => decoratorNodesOf(m).length > 0)) {
|
|
@@ -3664,8 +4154,13 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3664
4154
|
}
|
|
3665
4155
|
}
|
|
3666
4156
|
const info = lowerClassExpressionInfo(lowerer, expr);
|
|
3667
|
-
if (!info.localClass &&
|
|
3668
|
-
|
|
4157
|
+
if (!info.localClass &&
|
|
4158
|
+
!info.expressionInitializationEmitted &&
|
|
4159
|
+
(info.callableBase ||
|
|
4160
|
+
info.def.baseValueGlobal ||
|
|
4161
|
+
info.runtimeStatics ||
|
|
4162
|
+
info.staticFields.length > 0 ||
|
|
4163
|
+
(info.staticBlocks?.length ?? 0) > 0)) {
|
|
3669
4164
|
info.expressionInitializationEmitted = true;
|
|
3670
4165
|
lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
|
|
3671
4166
|
}
|
|
@@ -3681,7 +4176,11 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3681
4176
|
info.localClass.captureSources = context.captureSources;
|
|
3682
4177
|
if (info.localClass.baseExpression && info.base) {
|
|
3683
4178
|
info.def.localBaseCapture = info.def.localCaptures.length;
|
|
3684
|
-
info.def.localCaptures.push({
|
|
4179
|
+
info.def.localCaptures.push({
|
|
4180
|
+
localId: "%base",
|
|
4181
|
+
name: "base",
|
|
4182
|
+
type: { kind: "classval", className: info.base.def.name },
|
|
4183
|
+
});
|
|
3685
4184
|
}
|
|
3686
4185
|
info.localClass.ready = true;
|
|
3687
4186
|
lowerer.onExprClassCollected?.(info);
|
|
@@ -3701,18 +4200,47 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3701
4200
|
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3702
4201
|
const boxed = { kind: "dynFrom", value: clsRef, type: DYN, loc };
|
|
3703
4202
|
info.localPrototypeData = true;
|
|
3704
|
-
return initializeRuntimeStatics(lowerer, info, {
|
|
4203
|
+
return initializeRuntimeStatics(lowerer, info, {
|
|
4204
|
+
kind: "seqExpr",
|
|
4205
|
+
stmts: [
|
|
3705
4206
|
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3706
|
-
{
|
|
3707
|
-
|
|
3708
|
-
|
|
4207
|
+
{
|
|
4208
|
+
kind: "varDecl",
|
|
4209
|
+
localId: clsLocal.id,
|
|
4210
|
+
init: { ...value, captures: info.localClass.captureSources },
|
|
4211
|
+
loc,
|
|
4212
|
+
},
|
|
4213
|
+
{
|
|
4214
|
+
kind: "exprStmt",
|
|
4215
|
+
expr: { kind: "libCall", fn: "dyn.classInherit", args: [boxed, baseRef], type: DYN, loc },
|
|
4216
|
+
loc,
|
|
4217
|
+
},
|
|
4218
|
+
{
|
|
4219
|
+
kind: "exprStmt",
|
|
4220
|
+
expr: {
|
|
4221
|
+
kind: "libCall",
|
|
4222
|
+
fn: "dyn.classPrototype",
|
|
4223
|
+
args: [
|
|
4224
|
+
boxed,
|
|
3709
4225
|
{ kind: "libCall", fn: "dyn.classBasePrototype", args: [baseRef], type: DYN, loc },
|
|
3710
|
-
],
|
|
3711
|
-
|
|
4226
|
+
],
|
|
4227
|
+
type: DYN,
|
|
4228
|
+
loc,
|
|
4229
|
+
},
|
|
4230
|
+
loc,
|
|
4231
|
+
},
|
|
4232
|
+
],
|
|
4233
|
+
result: clsRef,
|
|
4234
|
+
type: value.type,
|
|
4235
|
+
loc,
|
|
4236
|
+
});
|
|
3712
4237
|
}
|
|
3713
4238
|
if (info.localClass?.baseExpression && info.base && value.kind === "classRef") {
|
|
3714
4239
|
const loc = locOf(expr);
|
|
3715
|
-
const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, {
|
|
4240
|
+
const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, {
|
|
4241
|
+
kind: "classval",
|
|
4242
|
+
className: info.base.def.name,
|
|
4243
|
+
});
|
|
3716
4244
|
const baseLocal = lowerer.declareHiddenLocal("%classBase", base.type);
|
|
3717
4245
|
baseLocal.boxed = true;
|
|
3718
4246
|
const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
|
|
@@ -3720,26 +4248,57 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3720
4248
|
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3721
4249
|
const basePrototype = classPrototypeData(lowerer, info.base, loc, baseRef);
|
|
3722
4250
|
info.localPrototypeData = true;
|
|
3723
|
-
return initializeRuntimeStatics(lowerer, info, {
|
|
4251
|
+
return initializeRuntimeStatics(lowerer, info, {
|
|
4252
|
+
kind: "seqExpr",
|
|
4253
|
+
stmts: [
|
|
3724
4254
|
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3725
|
-
{
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
4255
|
+
{
|
|
4256
|
+
kind: "varDecl",
|
|
4257
|
+
localId: clsLocal.id,
|
|
4258
|
+
init: { ...value, captures: [...info.localClass.captureSources, baseLocal.id] },
|
|
4259
|
+
loc,
|
|
4260
|
+
},
|
|
4261
|
+
{
|
|
4262
|
+
kind: "exprStmt",
|
|
4263
|
+
expr: {
|
|
4264
|
+
kind: "libCall",
|
|
4265
|
+
fn: "dyn.classInherit",
|
|
4266
|
+
args: [
|
|
4267
|
+
{ kind: "dynFrom", value: clsRef, type: DYN, loc },
|
|
4268
|
+
{ kind: "dynFrom", value: baseRef, type: DYN, loc },
|
|
4269
|
+
],
|
|
4270
|
+
type: DYN,
|
|
4271
|
+
loc,
|
|
4272
|
+
},
|
|
4273
|
+
loc,
|
|
4274
|
+
},
|
|
4275
|
+
{
|
|
4276
|
+
kind: "exprStmt",
|
|
4277
|
+
expr: {
|
|
4278
|
+
kind: "libCall",
|
|
4279
|
+
fn: "dyn.classPrototype",
|
|
4280
|
+
args: [{ kind: "dynFrom", value: clsRef, type: DYN, loc }, basePrototype],
|
|
4281
|
+
type: DYN,
|
|
4282
|
+
loc,
|
|
4283
|
+
},
|
|
4284
|
+
loc,
|
|
4285
|
+
},
|
|
4286
|
+
],
|
|
4287
|
+
result: clsRef,
|
|
4288
|
+
type: value.type,
|
|
4289
|
+
loc,
|
|
4290
|
+
});
|
|
4291
|
+
}
|
|
4292
|
+
return info.localClass
|
|
4293
|
+
? initializeRuntimeStatics(lowerer, info, value.kind === "classRef" ? { ...value, captures: info.localClass.captureSources } : value)
|
|
4294
|
+
: value;
|
|
3736
4295
|
}
|
|
3737
4296
|
/** The EXACT class a receiver expression is statically known to BE (not
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
4297
|
+
* merely be typed by): the class name itself, or a `const` binding
|
|
4298
|
+
* whose initializer is a class expression / class name. Such receivers
|
|
4299
|
+
* can never hold a subclass at runtime, so static WRITES through them
|
|
4300
|
+
* hit the declaring class's storage exactly (the shadowing hazards of
|
|
4301
|
+
* general class values don't arise). Null for everything else. */
|
|
3743
4302
|
export function exactClassOfReceiver(lowerer, expr) {
|
|
3744
4303
|
if (ts.isPropertyAccessExpression(expr) && !expr.questionDotToken) {
|
|
3745
4304
|
const member = nsMemberIdentOf(lowerer, expr);
|
|
@@ -3750,7 +4309,9 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3750
4309
|
// receiver specialization; ordinary instance this remains an object.
|
|
3751
4310
|
if (expr.kind === ts.SyntaxKind.ThisKeyword) {
|
|
3752
4311
|
const receiver = lowerer.resolveThis();
|
|
3753
|
-
return receiver?.type.kind === "classval"
|
|
4312
|
+
return receiver?.type.kind === "classval"
|
|
4313
|
+
? (lowerer.classes.get(receiver.type.className) ?? null)
|
|
4314
|
+
: null;
|
|
3754
4315
|
}
|
|
3755
4316
|
if (!ts.isIdentifier(expr))
|
|
3756
4317
|
return null;
|
|
@@ -3765,7 +4326,9 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3765
4326
|
if (direct)
|
|
3766
4327
|
return direct.classDecorators?.valueGlobalId !== undefined ? null : direct;
|
|
3767
4328
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
3768
|
-
if (!decl ||
|
|
4329
|
+
if (!decl ||
|
|
4330
|
+
!ts.isVariableDeclaration(decl) ||
|
|
4331
|
+
decl.initializer === undefined ||
|
|
3769
4332
|
!ts.isVariableDeclarationList(decl.parent) ||
|
|
3770
4333
|
(decl.parent.flags & ts.NodeFlags.Const) === 0) {
|
|
3771
4334
|
return null;
|
|
@@ -3785,20 +4348,20 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3785
4348
|
return null;
|
|
3786
4349
|
}
|
|
3787
4350
|
/** The class a PROPERTY-ASSIGNMENT binding pins — the salsa/CJS
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
4351
|
+
* declaration forms of a class expression: `Common.I = class {…}`
|
|
4352
|
+
* (expando members of a plain object), `exports.I = class {…}` /
|
|
4353
|
+
* `module.exports.I = class {…}` (CJS member exports), and
|
|
4354
|
+
* `module.exports = class {…}` (the whole-export replacement, whose
|
|
4355
|
+
* export symbol requirer bindings alias to). The symbol arrives in two
|
|
4356
|
+
* shapes — an ALIAS resolving to the class expression's own symbol
|
|
4357
|
+
* (valueDeclaration IS the ts.ClassExpression), or the expando property
|
|
4358
|
+
* symbol whose declarations are the assignment BinaryExpressions — and
|
|
4359
|
+
* both pin the class exactly when ONE top-level assignment declares it:
|
|
4360
|
+
* a reassigned property is a dynamic binding (the runtime class is
|
|
4361
|
+
* whichever assignment ran last), so it answers null and the caller's
|
|
4362
|
+
* fence names it. Collection is on demand and idempotent
|
|
4363
|
+
* (lowerClassExpressionInfo), so resolution order between files and
|
|
4364
|
+
* passes never matters. */
|
|
3802
4365
|
export function propertyAssignedClassInfoOf(lowerer, symbol) {
|
|
3803
4366
|
if (!symbol)
|
|
3804
4367
|
return null;
|
|
@@ -3840,22 +4403,25 @@ export function propertyAssignedClassInfoOf(lowerer, symbol) {
|
|
|
3840
4403
|
return info;
|
|
3841
4404
|
}
|
|
3842
4405
|
/** The top-level `… = <this class expression>` assignment a class
|
|
3843
|
-
|
|
4406
|
+
* expression is the (paren-unwrapped) RHS of, or null. */
|
|
3844
4407
|
function enclosingTopLevelClassAssignment(expr) {
|
|
3845
4408
|
let value = expr;
|
|
3846
4409
|
while (ts.isParenthesizedExpression(value.parent))
|
|
3847
4410
|
value = value.parent;
|
|
3848
4411
|
const p = value.parent;
|
|
3849
|
-
if (!ts.isBinaryExpression(p) ||
|
|
3850
|
-
p.
|
|
4412
|
+
if (!ts.isBinaryExpression(p) ||
|
|
4413
|
+
p.operatorToken.kind !== ts.SyntaxKind.EqualsToken ||
|
|
4414
|
+
p.right !== value ||
|
|
4415
|
+
!ts.isExpressionStatement(p.parent) ||
|
|
4416
|
+
!ts.isSourceFile(p.parent.parent)) {
|
|
3851
4417
|
return null;
|
|
3852
4418
|
}
|
|
3853
4419
|
return p;
|
|
3854
4420
|
}
|
|
3855
4421
|
/** How many top-level statements of the file assign the same target as
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
4422
|
+
* `assign` (textual LHS match — `module.exports`, `exports.I`,
|
|
4423
|
+
* `Common.I`): a second assignment makes the binding dynamic, so
|
|
4424
|
+
* callers refuse to pin the first one's class. */
|
|
3859
4425
|
function countAssignmentsTo(assign) {
|
|
3860
4426
|
const sf = assign.getSourceFile();
|
|
3861
4427
|
// `exports.I` and `module.exports.I` are the SAME binding in Node
|
|
@@ -3871,7 +4437,8 @@ function countAssignmentsTo(assign) {
|
|
|
3871
4437
|
if (!ts.isExpressionStatement(stmt))
|
|
3872
4438
|
continue;
|
|
3873
4439
|
const e = stmt.expression;
|
|
3874
|
-
if (ts.isBinaryExpression(e) &&
|
|
4440
|
+
if (ts.isBinaryExpression(e) &&
|
|
4441
|
+
e.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
3875
4442
|
canon(e.left) === target) {
|
|
3876
4443
|
n++;
|
|
3877
4444
|
}
|
|
@@ -3879,14 +4446,14 @@ function countAssignmentsTo(assign) {
|
|
|
3879
4446
|
return n;
|
|
3880
4447
|
}
|
|
3881
4448
|
/** `C.m(args)` / `X.m(args)` — static method calls, on the class name
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
4449
|
+
* directly or through a class VALUE. Resolution walks the chain
|
|
4450
|
+
* (nearest declarer, the compile-time prototype chain); through a
|
|
4451
|
+
* VALUE the call devirtualizes exactly when no strict descendant
|
|
4452
|
+
* redeclares the member (values never leave the static class's
|
|
4453
|
+
* subtree). A func-typed static FIELD in call position reads the
|
|
4454
|
+
* global and calls through the value. Null when the receiver isn't a
|
|
4455
|
+
* class name/value or the member doesn't resolve (the fences name the
|
|
4456
|
+
* site downstream). */
|
|
3890
4457
|
export function lowerStaticMethodCall(lowerer, call, access) {
|
|
3891
4458
|
if (access.questionDotToken)
|
|
3892
4459
|
return null;
|
|
@@ -3896,11 +4463,25 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3896
4463
|
if (info)
|
|
3897
4464
|
return staticCallOn(lowerer, call, access, info, false);
|
|
3898
4465
|
}
|
|
4466
|
+
// Namespace exports are immutable bindings to the same declaration as
|
|
4467
|
+
// named imports. Resolve them before asking for a constructor-value ABI:
|
|
4468
|
+
// a generic family has statics but no single constructor signature.
|
|
4469
|
+
if (ts.isPropertyAccessExpression(access.expression) && !access.expression.questionDotToken) {
|
|
4470
|
+
const member = nsMemberIdentOf(lowerer, access.expression);
|
|
4471
|
+
const symbol = member ? lowerer.resolveValueSymbol(member) : null;
|
|
4472
|
+
const info = symbol ? lowerer.classBySymbol.get(symbol) : undefined;
|
|
4473
|
+
if (info && info.classDecorators?.valueGlobalId === undefined) {
|
|
4474
|
+
if (symbol)
|
|
4475
|
+
fenceEarlyNsMemberRef(lowerer, access.expression, symbol);
|
|
4476
|
+
return staticCallOn(lowerer, call, access, info, false);
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
3899
4479
|
// `module.exports.describe()` in a module whose whole export IS a
|
|
3900
4480
|
// class expression: the receiver is exactly that class (the kept
|
|
3901
4481
|
// export assignment pins it) — the direct-name rules apply.
|
|
3902
4482
|
if (!ts.isIdentifier(access.expression)) {
|
|
3903
|
-
if (!isModuleExportsAccess(access.expression) ||
|
|
4483
|
+
if (!isModuleExportsAccess(access.expression) ||
|
|
4484
|
+
!isCjsJsFile(access.getSourceFile(), lowerer.program)) {
|
|
3904
4485
|
let receiverType = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
3905
4486
|
if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile())) {
|
|
3906
4487
|
const receiver = tryLowerExpression(lowerer, access.expression);
|
|
@@ -3919,8 +4500,13 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3919
4500
|
// A typed checker projection cannot turn a replaced field into a call
|
|
3920
4501
|
// to the class that originally occupied it.
|
|
3921
4502
|
const receiver = lowerer.lowerExprExpecting(access.expression, receiverType);
|
|
3922
|
-
return {
|
|
3923
|
-
|
|
4503
|
+
return {
|
|
4504
|
+
kind: "seqExpr",
|
|
4505
|
+
stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(access.expression) }],
|
|
4506
|
+
result,
|
|
4507
|
+
type: result.type,
|
|
4508
|
+
loc: locOf(call),
|
|
4509
|
+
};
|
|
3924
4510
|
}
|
|
3925
4511
|
const whole = cjsClassExprWholeExportOf(access.getSourceFile());
|
|
3926
4512
|
if (!whole)
|
|
@@ -3949,31 +4535,42 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3949
4535
|
return staticCallOn(lowerer, call, access, info, throughValue);
|
|
3950
4536
|
}
|
|
3951
4537
|
/** True when a class-VALUE receiver can only hold `info`'s own class
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
4538
|
+
* object at runtime: the receiver provably IS the class
|
|
4539
|
+
* (exactClassOfReceiver — the name, or a const bound to the class
|
|
4540
|
+
* expression / class name), or `info` is a LEAF class, so no strict
|
|
4541
|
+
* descendant exists to flow into the slot (the static-write path's
|
|
4542
|
+
* rule — a rebindable decorated name rides this arm, since replacement
|
|
4543
|
+
* decorators fence any class with subclasses before minting the
|
|
4544
|
+
* rebindable global). Exactly then a #private static access through
|
|
4545
|
+
* the value always carries the declaring class's brand — Node's
|
|
4546
|
+
* TypeError cannot arise. */
|
|
3961
4547
|
function classValueIsExactlyOwn(lowerer, recv, info) {
|
|
3962
4548
|
return exactClassOfReceiver(lowerer, recv) === info || info.subclasses.length === 0;
|
|
3963
4549
|
}
|
|
3964
4550
|
function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
3965
4551
|
const loc = locOf(call);
|
|
3966
|
-
if (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field ||
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4552
|
+
if ((hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field) ||
|
|
4553
|
+
(info.callableBase &&
|
|
4554
|
+
!findStaticOn(lowerer, info, access.name.text) &&
|
|
4555
|
+
!findGenericStaticOn(lowerer, info, access.name.text)))
|
|
4556
|
+
return {
|
|
4557
|
+
kind: "dynInvoke",
|
|
4558
|
+
recv: lowerer.lowerExprExpecting(access.expression, DYN),
|
|
4559
|
+
method: access.name.text,
|
|
4560
|
+
calleeName: access.name.text,
|
|
4561
|
+
args: call.arguments.map((argument) => lowerer.lowerExprExpecting(argument, DYN)),
|
|
4562
|
+
type: DYN,
|
|
4563
|
+
loc,
|
|
4564
|
+
};
|
|
3970
4565
|
// #private statics: through-a-VALUE receiver the call devirtualizes
|
|
3971
4566
|
// exactly when the value can only BE the declaring class
|
|
3972
4567
|
// (classValueIsExactlyOwn — a slot that could hold a descendant at
|
|
3973
4568
|
// runtime fences, since only the declaring class object carries the
|
|
3974
4569
|
// brand in JS), and the direct spelling resolves only on the
|
|
3975
4570
|
// declaring class itself — `D.#s` is Node's TypeError.
|
|
3976
|
-
if (access.name.text.startsWith("#") &&
|
|
4571
|
+
if (access.name.text.startsWith("#") &&
|
|
4572
|
+
throughValue &&
|
|
4573
|
+
!classValueIsExactlyOwn(lowerer, access.expression, info)) {
|
|
3977
4574
|
lowerer.unsupported("SC1090", call, `calling the private static '${access.name.text}' through a class value (JS brands the declaring class object alone — call it through the class's own name)`);
|
|
3978
4575
|
}
|
|
3979
4576
|
const found = findStaticOn(lowerer, info, access.name.text);
|
|
@@ -3987,14 +4584,14 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
3987
4584
|
const gfound = findGenericStaticOn(lowerer, info, access.name.text);
|
|
3988
4585
|
if (!gfound)
|
|
3989
4586
|
return null;
|
|
3990
|
-
if (throughValue && staticShadowBelow(
|
|
4587
|
+
if (throughValue && staticShadowBelow(info, access.name.text)) {
|
|
3991
4588
|
lowerer.unsupported("SC1090", call, `calling the static member '${access.name.text}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
|
|
3992
4589
|
}
|
|
3993
4590
|
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, gfound.info, info, throughValue));
|
|
3994
4591
|
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
3995
4592
|
return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
|
|
3996
4593
|
}
|
|
3997
|
-
if (throughValue && staticShadowBelow(
|
|
4594
|
+
if (throughValue && staticShadowBelow(info, access.name.text)) {
|
|
3998
4595
|
lowerer.unsupported("SC1090", call, `calling the static member '${access.name.text}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
|
|
3999
4596
|
}
|
|
4000
4597
|
const specialized = findGenericStaticOn(lowerer, info, access.name.text);
|
|
@@ -4008,7 +4605,12 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
4008
4605
|
// call through the value (the ctor-assigned-callback pattern).
|
|
4009
4606
|
if (found.field.type.kind !== "func")
|
|
4010
4607
|
return null;
|
|
4011
|
-
const callee = {
|
|
4608
|
+
const callee = {
|
|
4609
|
+
kind: "varRef",
|
|
4610
|
+
localId: found.field.globalId,
|
|
4611
|
+
type: found.field.type,
|
|
4612
|
+
loc,
|
|
4613
|
+
};
|
|
4012
4614
|
const params = found.field.type.params;
|
|
4013
4615
|
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
4014
4616
|
for (let i = args.length; i < params.length; i++) {
|
|
@@ -4018,17 +4620,32 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
4018
4620
|
}
|
|
4019
4621
|
args.push(absent);
|
|
4020
4622
|
}
|
|
4021
|
-
return {
|
|
4623
|
+
return {
|
|
4624
|
+
kind: "callValue",
|
|
4625
|
+
callee,
|
|
4626
|
+
receiver: lowerer.lowerExprExpecting(access.expression, DYN),
|
|
4627
|
+
args,
|
|
4628
|
+
type: found.field.type.ret,
|
|
4629
|
+
loc,
|
|
4630
|
+
};
|
|
4022
4631
|
}
|
|
4023
4632
|
if (found.method.member.body && hasStaticThis(found.method.member)) {
|
|
4024
|
-
const generic = found.method.receiverInfo ??= {
|
|
4025
|
-
decl: found.method.member,
|
|
4633
|
+
const generic = (found.method.receiverInfo ??= {
|
|
4634
|
+
decl: found.method.member,
|
|
4635
|
+
baseName: access.name.text,
|
|
4026
4636
|
qualifiedName: `%${found.declarer.def.name}.static:${access.name.text}`,
|
|
4027
|
-
typeParams: [],
|
|
4028
|
-
|
|
4637
|
+
typeParams: [],
|
|
4638
|
+
instances: new Map(),
|
|
4639
|
+
member: { cls: found.declarer, kind: "static" },
|
|
4640
|
+
});
|
|
4029
4641
|
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, generic, info, throughValue));
|
|
4030
|
-
return {
|
|
4031
|
-
|
|
4642
|
+
return {
|
|
4643
|
+
kind: "call",
|
|
4644
|
+
callee: instance.name,
|
|
4645
|
+
args: lowerer.completeArgs(call.arguments, instance.params, loc, call),
|
|
4646
|
+
type: instance.returnType,
|
|
4647
|
+
loc,
|
|
4648
|
+
};
|
|
4032
4649
|
}
|
|
4033
4650
|
const fnName = `%${found.declarer.def.name}.static:${access.name.text}`;
|
|
4034
4651
|
lowerer.noteEdge(fnName);
|
|
@@ -4047,22 +4664,27 @@ function staticMethodForReceiver(lowerer, access, method, receiver, throughValue
|
|
|
4047
4664
|
if (throughValue && !classValueIsExactlyOwn(lowerer, access.expression, receiver)) {
|
|
4048
4665
|
lowerer.unsupported("SC1090", access, "receiver-dependent static methods through a polymorphic class value");
|
|
4049
4666
|
}
|
|
4050
|
-
const instances = method.receiverSpecializations ??= new Map();
|
|
4667
|
+
const instances = (method.receiverSpecializations ??= new Map());
|
|
4051
4668
|
let specialized = instances.get(receiver.def.name);
|
|
4052
4669
|
if (!specialized) {
|
|
4053
|
-
specialized = {
|
|
4054
|
-
|
|
4670
|
+
specialized = {
|
|
4671
|
+
...method,
|
|
4672
|
+
qualifiedName: `${method.qualifiedName}%on.${receiver.def.name}`,
|
|
4673
|
+
instances: new Map(),
|
|
4674
|
+
staticReceiver: receiver,
|
|
4675
|
+
receiverSpecializations: new Map(),
|
|
4676
|
+
};
|
|
4055
4677
|
instances.set(receiver.def.name, specialized);
|
|
4056
4678
|
}
|
|
4057
4679
|
return specialized;
|
|
4058
4680
|
}
|
|
4059
4681
|
/** Static member access through a class VALUE (`X.m` where X is
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4682
|
+
* classval-typed): devirtualized — the member resolves against the
|
|
4683
|
+
* static class's chain, exact when no strict descendant redeclares it
|
|
4684
|
+
* (values in the slot never leave the subtree). `X.name` is the one
|
|
4685
|
+
* genuinely dynamic member: the class.name libCall reads the runtime
|
|
4686
|
+
* class object's stored name. Null when the receiver isn't a class
|
|
4687
|
+
* value or the member doesn't resolve. */
|
|
4066
4688
|
export function lowerClassValueProperty(lowerer, expr) {
|
|
4067
4689
|
if (expr.questionDotToken)
|
|
4068
4690
|
return null;
|
|
@@ -4072,9 +4694,16 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4072
4694
|
const loc = locOf(expr);
|
|
4073
4695
|
const member = expr.name.text;
|
|
4074
4696
|
const info = lowerer.classes.get(recvT.className);
|
|
4075
|
-
if (info &&
|
|
4076
|
-
|
|
4077
|
-
|
|
4697
|
+
if (info &&
|
|
4698
|
+
((hasRuntimeStatics(info) && !findStaticOn(lowerer, info, member)?.field) ||
|
|
4699
|
+
(info.callableBase && !findStaticOn(lowerer, info, member))))
|
|
4700
|
+
return {
|
|
4701
|
+
kind: "dynKeyGet",
|
|
4702
|
+
value: lowerer.lowerExprExpecting(expr.expression, DYN),
|
|
4703
|
+
key: { kind: "strLit", value: member, type: STRING, loc },
|
|
4704
|
+
type: DYN,
|
|
4705
|
+
loc,
|
|
4706
|
+
};
|
|
4078
4707
|
// `X.name` reads the RUNTIME class object's stored name — the one
|
|
4079
4708
|
// genuinely dynamic member. It CONSUMES the receiver (no evaluation
|
|
4080
4709
|
// is discarded), so any receiver expression is fine here.
|
|
@@ -4119,7 +4748,7 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4119
4748
|
lowerer.unsupported("SC1090", expr, `reading the private static '${member}' through the subclass '${info.def.name.replace(/^%|^%m\d+\./, "")}' (JS brands the declaring class object alone — Node throws a TypeError here; spell the declaring class's name)`);
|
|
4120
4749
|
}
|
|
4121
4750
|
}
|
|
4122
|
-
if (staticShadowBelow(
|
|
4751
|
+
if (staticShadowBelow(info, member)) {
|
|
4123
4752
|
lowerer.unsupported("SC1090", expr, `reading the static member '${member}' through a class value (a subclass of '${info.def.name.replace(/^%|^%m\d+\./, "")}' redeclares it, so the runtime class decides which declaration answers)`);
|
|
4124
4753
|
}
|
|
4125
4754
|
if (found.field !== undefined) {
|
|
@@ -4128,18 +4757,21 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4128
4757
|
return staticMethodValue(lowerer, found.declarer, member, found.method, expr, loc);
|
|
4129
4758
|
}
|
|
4130
4759
|
/** An abstract method's signature — lambdaSignature minus the body check
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4760
|
+
* (an abstract declaration IS exactly a signature; tsc rejects the
|
|
4761
|
+
* async/generator/generic-with-body combinations before this runs, and
|
|
4762
|
+
* the generic case fences at the caller). */
|
|
4134
4763
|
function abstractMemberSignature(lowerer, member) {
|
|
4135
4764
|
for (const param of member.parameters) {
|
|
4136
4765
|
if (!ts.isIdentifier(param.name))
|
|
4137
4766
|
lowerer.unsupported("SC1031", param);
|
|
4138
4767
|
}
|
|
4139
|
-
return {
|
|
4768
|
+
return {
|
|
4769
|
+
shapes: lowerer.paramShapes(member.parameters),
|
|
4770
|
+
ret: lowerer.declaredReturnType(member, member.name),
|
|
4771
|
+
};
|
|
4140
4772
|
}
|
|
4141
4773
|
/** The nearest declaration of `name` at or above `info` — the method a
|
|
4142
|
-
|
|
4774
|
+
* receiver of that static class runs when nothing below overrides it. */
|
|
4143
4775
|
export function findMethodOn(lowerer, info, name) {
|
|
4144
4776
|
for (let c = info; c; c = c.base) {
|
|
4145
4777
|
const sig = c.methods.get(name);
|
|
@@ -4150,15 +4782,21 @@ export function findMethodOn(lowerer, info, name) {
|
|
|
4150
4782
|
}
|
|
4151
4783
|
/** True when `sub` is a STRICT descendant of `sup` in the class graph. */
|
|
4152
4784
|
export function isSubclassOf(lowerer, sub, sup) {
|
|
4153
|
-
|
|
4154
|
-
|
|
4785
|
+
if (sub === sup)
|
|
4786
|
+
return false;
|
|
4787
|
+
for (let c = lowerer.classes.get(sub); c; c = c.base ?? undefined) {
|
|
4788
|
+
if (c.def.name === sup && c.def.name !== sub)
|
|
4155
4789
|
return true;
|
|
4790
|
+
for (let family = c.genericInstance?.family; family; family = family.base ?? undefined) {
|
|
4791
|
+
if (family.def.name === sup)
|
|
4792
|
+
return true;
|
|
4793
|
+
}
|
|
4156
4794
|
}
|
|
4157
4795
|
return false;
|
|
4158
4796
|
}
|
|
4159
4797
|
/** In an extends-hierarchy (as base or derived): the class carries a
|
|
4160
|
-
|
|
4161
|
-
|
|
4798
|
+
* vtable and participates in dynamic instanceof; standalone classes keep
|
|
4799
|
+
* their exact pre-inheritance layout and behavior. */
|
|
4162
4800
|
export function inHierarchy(lowerer, info) {
|
|
4163
4801
|
// The runtime emitter class is ALWAYS a hierarchy member: ScrEmitter
|
|
4164
4802
|
// carries its vtable word whether or not the program subclasses it
|
|
@@ -4166,10 +4804,10 @@ export function inHierarchy(lowerer, info) {
|
|
|
4166
4804
|
return info.base !== null || info.subclasses.length > 0 || info.builtinEmitter === true;
|
|
4167
4805
|
}
|
|
4168
4806
|
/** True when some STRICT descendant of `info` declares `name` with a BODY
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4807
|
+
* — the whole-program devirtualization test: a call through this static
|
|
4808
|
+
* class can reach a distinct implementation, so it must dispatch
|
|
4809
|
+
* dynamically. Abstract re-declarations don't count (they carry no
|
|
4810
|
+
* implementation; the concrete ones below them do, via the recursion). */
|
|
4173
4811
|
export function overrideBelow(lowerer, info, name) {
|
|
4174
4812
|
return info.subclasses.some((s) => {
|
|
4175
4813
|
const m = s.methods.get(name);
|
|
@@ -4177,7 +4815,7 @@ export function overrideBelow(lowerer, info, name) {
|
|
|
4177
4815
|
});
|
|
4178
4816
|
}
|
|
4179
4817
|
/** The nearest GENERIC-method declaration of `name` at/above `info` —
|
|
4180
|
-
|
|
4818
|
+
* findMethodOn's twin over the genericMethods tables. */
|
|
4181
4819
|
export function findGenericMethodOn(lowerer, info, name) {
|
|
4182
4820
|
for (let c = info; c; c = c.base) {
|
|
4183
4821
|
const gm = c.genericMethods?.get(name);
|
|
@@ -4187,11 +4825,11 @@ export function findGenericMethodOn(lowerer, info, name) {
|
|
|
4187
4825
|
return null;
|
|
4188
4826
|
}
|
|
4189
4827
|
/** True when some STRICT descendant of `info` re-declares the generic
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
export function genericOverrideBelow(
|
|
4194
|
-
return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(
|
|
4828
|
+
* method `name` — overrideBelow's twin: generic methods have no vtable
|
|
4829
|
+
* slot, so a call that could reach an override compiles only when the
|
|
4830
|
+
* receiver's runtime class is statically exact. */
|
|
4831
|
+
export function genericOverrideBelow(info, name) {
|
|
4832
|
+
return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(s, name));
|
|
4195
4833
|
}
|
|
4196
4834
|
/** Discover inherited data writes before any base storage ABI is chosen.
|
|
4197
4835
|
* The checker does not widen a base field for assignments in JS subclasses. */
|
|
@@ -4200,7 +4838,8 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4200
4838
|
if (!isJsSourceFile(file))
|
|
4201
4839
|
continue;
|
|
4202
4840
|
ts.walkPreorder(file, (node) => {
|
|
4203
|
-
if ((!ts.isClassDeclaration(node) && !ts.isClassExpression(node)) ||
|
|
4841
|
+
if ((!ts.isClassDeclaration(node) && !ts.isClassExpression(node)) ||
|
|
4842
|
+
!node.heritageClauses?.length)
|
|
4204
4843
|
return;
|
|
4205
4844
|
const writes = new Map();
|
|
4206
4845
|
const addWrite = (name, expression) => {
|
|
@@ -4211,14 +4850,17 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4211
4850
|
writes.set(name, [expression]);
|
|
4212
4851
|
};
|
|
4213
4852
|
const scan = (part) => {
|
|
4214
|
-
if (ts.isClassDeclaration(part) ||
|
|
4215
|
-
ts.
|
|
4853
|
+
if (ts.isClassDeclaration(part) ||
|
|
4854
|
+
ts.isClassExpression(part) ||
|
|
4855
|
+
(ts.isFunctionLike(part) && !ts.isArrowFunction(part)))
|
|
4216
4856
|
return;
|
|
4217
4857
|
if (ts.isBinaryExpression(part) && part.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
4218
4858
|
const left = part.left;
|
|
4219
|
-
if (ts.isPropertyAccessExpression(left) &&
|
|
4859
|
+
if (ts.isPropertyAccessExpression(left) &&
|
|
4860
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword)
|
|
4220
4861
|
addWrite(left.name.text, part.right);
|
|
4221
|
-
else if (ts.isElementAccessExpression(left) &&
|
|
4862
|
+
else if (ts.isElementAccessExpression(left) &&
|
|
4863
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
4222
4864
|
const name = lowerer.foldedStringKeyOf(left.argumentExpression);
|
|
4223
4865
|
if (name !== null)
|
|
4224
4866
|
addWrite(name, part.right);
|
|
@@ -4230,12 +4872,16 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4230
4872
|
if (member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))
|
|
4231
4873
|
continue;
|
|
4232
4874
|
if (ts.isPropertyDeclaration(member) && member.initializer) {
|
|
4233
|
-
const name = ts.isPrivateIdentifier(member.name)
|
|
4875
|
+
const name = ts.isPrivateIdentifier(member.name)
|
|
4876
|
+
? null
|
|
4877
|
+
: classMemberNameOf(lowerer, member.name);
|
|
4234
4878
|
if (name !== null)
|
|
4235
4879
|
addWrite(name, member.initializer);
|
|
4236
4880
|
scan(member.initializer);
|
|
4237
4881
|
}
|
|
4238
|
-
if (ts.isConstructorDeclaration(member) ||
|
|
4882
|
+
if (ts.isConstructorDeclaration(member) ||
|
|
4883
|
+
ts.isMethodDeclaration(member) ||
|
|
4884
|
+
ts.isAccessor(member)) {
|
|
4239
4885
|
if (member.body)
|
|
4240
4886
|
scan(member.body);
|
|
4241
4887
|
}
|
|
@@ -4259,11 +4905,13 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4259
4905
|
let owner = declaration.parent;
|
|
4260
4906
|
while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
|
|
4261
4907
|
owner = owner.parent;
|
|
4262
|
-
if (!owner ||
|
|
4908
|
+
if (!owner ||
|
|
4909
|
+
(!ts.isClassDeclaration(owner) && !ts.isClassExpression(owner)) ||
|
|
4910
|
+
!isJsSourceFile(owner.getSourceFile()))
|
|
4263
4911
|
continue;
|
|
4264
4912
|
let fields = lowerer.inheritedJsFieldWrites.get(owner);
|
|
4265
4913
|
if (!fields)
|
|
4266
|
-
lowerer.inheritedJsFieldWrites.set(owner, fields = new Map());
|
|
4914
|
+
lowerer.inheritedJsFieldWrites.set(owner, (fields = new Map()));
|
|
4267
4915
|
const existing = fields.get(name);
|
|
4268
4916
|
if (existing)
|
|
4269
4917
|
existing.push(...expressions);
|
|
@@ -4292,24 +4940,35 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4292
4940
|
ts.walkPreorder(file, (node) => {
|
|
4293
4941
|
if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
|
|
4294
4942
|
return;
|
|
4295
|
-
const name = ts.isPropertyAccessExpression(node)
|
|
4296
|
-
|
|
4943
|
+
const name = ts.isPropertyAccessExpression(node)
|
|
4944
|
+
? node.name.text
|
|
4945
|
+
: ts.isStringLiteralLike(node.argumentExpression)
|
|
4946
|
+
? node.argumentExpression.text
|
|
4947
|
+
: null;
|
|
4297
4948
|
if (name === null)
|
|
4298
4949
|
return;
|
|
4299
4950
|
const prototype = ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "prototype";
|
|
4300
|
-
const assigned = ts.isBinaryExpression(node.parent) &&
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4951
|
+
const assigned = ts.isBinaryExpression(node.parent) &&
|
|
4952
|
+
node.parent.left === node &&
|
|
4953
|
+
node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
|
|
4954
|
+
const symbol = !assigned
|
|
4955
|
+
? undefined
|
|
4956
|
+
: ts.isPropertyAccessExpression(node)
|
|
4957
|
+
? lowerer.checker.getSymbolAtLocation(node.name)
|
|
4958
|
+
: lowerer.checker.getPropertyOfType(lowerer.typeOf(node.expression), name);
|
|
4959
|
+
if (prototype ||
|
|
4960
|
+
(symbol && lowerer.checker.declarationsOf(symbol).some(ts.isMethodDeclaration))) {
|
|
4305
4961
|
lowerer.prototypeMethodAccesses.set(name, node);
|
|
4306
4962
|
}
|
|
4307
4963
|
});
|
|
4308
4964
|
const visit = (node) => {
|
|
4309
4965
|
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
|
4310
|
-
const accessors = node.members.filter((member) => (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) &&
|
|
4966
|
+
const accessors = node.members.filter((member) => (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) &&
|
|
4967
|
+
ts.isIdentifier(member.name) &&
|
|
4311
4968
|
!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
4312
|
-
if (node.heritageClauses?.length &&
|
|
4969
|
+
if (node.heritageClauses?.length &&
|
|
4970
|
+
accessors.length &&
|
|
4971
|
+
isJsSourceFile(node.getSourceFile())) {
|
|
4313
4972
|
const symbol = lowerer.typeOf(node).getSymbol();
|
|
4314
4973
|
const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
|
|
4315
4974
|
const seen = new Set();
|
|
@@ -4324,12 +4983,15 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4324
4983
|
continue;
|
|
4325
4984
|
const property = lowerer.checker.getPropertyOfType(base, member.name.text);
|
|
4326
4985
|
for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
|
|
4327
|
-
if ((ts.isGetAccessorDeclaration(declaration) ||
|
|
4986
|
+
if ((ts.isGetAccessorDeclaration(declaration) ||
|
|
4987
|
+
ts.isSetAccessorDeclaration(declaration)) &&
|
|
4988
|
+
isJsSourceFile(declaration.getSourceFile())) {
|
|
4328
4989
|
lowerer.checkedVirtualJsAccessors.add(declaration);
|
|
4329
4990
|
lowerer.checkedVirtualJsAccessors.add(member);
|
|
4330
4991
|
for (const twin of node.members)
|
|
4331
4992
|
if ((ts.isGetAccessorDeclaration(twin) || ts.isSetAccessorDeclaration(twin)) &&
|
|
4332
|
-
ts.isIdentifier(twin.name) &&
|
|
4993
|
+
ts.isIdentifier(twin.name) &&
|
|
4994
|
+
twin.name.text === member.name.text)
|
|
4333
4995
|
lowerer.checkedVirtualJsAccessors.add(twin);
|
|
4334
4996
|
}
|
|
4335
4997
|
}
|
|
@@ -4340,7 +5002,8 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4340
5002
|
if (instance)
|
|
4341
5003
|
markAccessors(instance);
|
|
4342
5004
|
}
|
|
4343
|
-
const members = node.members.filter((member) => ts.isMethodDeclaration(member) &&
|
|
5005
|
+
const members = node.members.filter((member) => ts.isMethodDeclaration(member) &&
|
|
5006
|
+
ts.isIdentifier(member.name) &&
|
|
4344
5007
|
!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
4345
5008
|
if (node.heritageClauses?.length && members.length > 0) {
|
|
4346
5009
|
const symbol = lowerer.typeOf(node).getSymbol();
|
|
@@ -4357,14 +5020,18 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4357
5020
|
continue;
|
|
4358
5021
|
const property = lowerer.checker.getPropertyOfType(base, member.name.text);
|
|
4359
5022
|
for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
|
|
4360
|
-
if (ts.isMethodDeclaration(declaration) &&
|
|
5023
|
+
if (ts.isMethodDeclaration(declaration) &&
|
|
5024
|
+
isJsSourceFile(declaration.getSourceFile())) {
|
|
4361
5025
|
lowerer.virtualJsMethods.add(declaration);
|
|
4362
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
4363
|
-
!member.
|
|
5026
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
5027
|
+
!member.typeParameters &&
|
|
5028
|
+
!member.asteriskToken &&
|
|
5029
|
+
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
4364
5030
|
!bodyReadsArguments(member) &&
|
|
4365
5031
|
member.parameters.every((p) => !p.dotDotDotToken)) {
|
|
4366
5032
|
lowerer.virtualJsMethodArity.set(declaration, Math.max(lowerer.virtualJsMethodArity.get(declaration) ?? 0, member.parameters.length));
|
|
4367
|
-
const checked = !declaration.typeParameters &&
|
|
5033
|
+
const checked = !declaration.typeParameters &&
|
|
5034
|
+
!declaration.asteriskToken &&
|
|
4368
5035
|
!declaration.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
4369
5036
|
!bodyReadsArguments(declaration) &&
|
|
4370
5037
|
[...member.parameters, ...declaration.parameters].every((p) => !p.dotDotDotToken);
|
|
@@ -4401,7 +5068,8 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4401
5068
|
while (changed) {
|
|
4402
5069
|
changed = false;
|
|
4403
5070
|
for (const [base, derived] of families) {
|
|
4404
|
-
if (!lowerer.checkedVirtualJsValueReturns.has(base) &&
|
|
5071
|
+
if (!lowerer.checkedVirtualJsValueReturns.has(base) &&
|
|
5072
|
+
!lowerer.checkedVirtualJsValueReturns.has(derived))
|
|
4405
5073
|
continue;
|
|
4406
5074
|
for (const member of [base, derived])
|
|
4407
5075
|
if (!lowerer.checkedVirtualJsValueReturns.has(member)) {
|
|
@@ -4412,11 +5080,11 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4412
5080
|
}
|
|
4413
5081
|
}
|
|
4414
5082
|
/** The receiver's EXACT runtime class, when the expression proves it: a
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
5083
|
+
* `new C(...)` expression directly, or a const binding initialized with
|
|
5084
|
+
* one (the binding can never be reassigned to a subclass instance).
|
|
5085
|
+
* The class is read off the mapped INITIALIZER type — a `const b: Base =
|
|
5086
|
+
* new D()` receiver is exactly D, not its annotation. Distinct from
|
|
5087
|
+
* exactClassOfReceiver, which answers for CLASS-VALUE receivers. */
|
|
4420
5088
|
export function exactInstanceClassOf(lowerer, expr) {
|
|
4421
5089
|
let e = expr;
|
|
4422
5090
|
while (ts.isParenthesizedExpression(e))
|
|
@@ -4434,7 +5102,9 @@ export function exactInstanceClassOf(lowerer, expr) {
|
|
|
4434
5102
|
return null;
|
|
4435
5103
|
const symbol = lowerer.resolveValueSymbol(e);
|
|
4436
5104
|
const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
|
|
4437
|
-
if (!decl ||
|
|
5105
|
+
if (!decl ||
|
|
5106
|
+
!ts.isVariableDeclaration(decl) ||
|
|
5107
|
+
decl.initializer === undefined ||
|
|
4438
5108
|
!ts.isVariableDeclarationList(decl.parent) ||
|
|
4439
5109
|
(decl.parent.flags & ts.NodeFlags.Const) === 0) {
|
|
4440
5110
|
return null;
|
|
@@ -4445,19 +5115,19 @@ export function exactInstanceClassOf(lowerer, expr) {
|
|
|
4445
5115
|
return classOfNew(init);
|
|
4446
5116
|
}
|
|
4447
5117
|
/** `const r: Repo = new MemRepo()` where EVERY member of the annotation's
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
5118
|
+
* checker type is a generic-callable method (`interface Repo { get<T>(id:
|
|
5119
|
+
* string): T }`): the record shape maps EMPTY — generic members are
|
|
5120
|
+
* excluded (no closure slot can hold a generic function) — so the
|
|
5121
|
+
* copy-reshape width coercion would DROP the exact class the method
|
|
5122
|
+
* calls monomorphize against, and in JS the binding IS the instance (no
|
|
5123
|
+
* copy exists). The binding keeps the initializer's class
|
|
5124
|
+
* representation instead: generic-method calls resolve like class-typed
|
|
5125
|
+
* receivers (exactInstanceClassOf reads the same const+new discipline),
|
|
5126
|
+
* and uses that want the empty record width-coerce at the use site.
|
|
5127
|
+
* Const + direct `new` only — a reassignable binding or a produced
|
|
5128
|
+
* value keeps today's record story and its fences. */
|
|
4459
5129
|
export function genericIfaceBindingKeepsClass(lowerer, decl, declaredType) {
|
|
4460
|
-
if (declaredType.kind !== "record")
|
|
5130
|
+
if (declaredType.kind !== "record" && declaredType.kind !== "dyn")
|
|
4461
5131
|
return false;
|
|
4462
5132
|
if (!ts.isIdentifier(decl.name) || decl.initializer === undefined || decl.type === undefined)
|
|
4463
5133
|
return false;
|
|
@@ -4468,27 +5138,30 @@ export function genericIfaceBindingKeepsClass(lowerer, decl, declaredType) {
|
|
|
4468
5138
|
init = init.expression;
|
|
4469
5139
|
if (!ts.isNewExpression(init))
|
|
4470
5140
|
return false;
|
|
4471
|
-
const shape = lowerer.shapes.get(declaredType.shapeId);
|
|
4472
|
-
if (!shape || shape.fields.length > 0 || shape.indexValue !== undefined || shape.tuple === true)
|
|
4473
|
-
return false;
|
|
4474
5141
|
const annT = lowerer.typeOf(decl.name);
|
|
4475
5142
|
const props = lowerer.checker.getPropertiesOfType(annT);
|
|
4476
5143
|
if (props.length === 0)
|
|
4477
5144
|
return false;
|
|
5145
|
+
if (declaredType.kind === "dyn")
|
|
5146
|
+
return (lowerer.classImplementedProtocol(annT) &&
|
|
5147
|
+
props.some((property) => isGenericCallableMemberType(lowerer.checker.getTypeOfSymbol(property), lowerer.checker)));
|
|
5148
|
+
const shape = lowerer.shapes.get(declaredType.shapeId);
|
|
5149
|
+
if (!shape || shape.fields.length > 0 || shape.indexValue !== undefined || shape.tuple === true)
|
|
5150
|
+
return false;
|
|
4478
5151
|
return props.every((p) => isGenericCallableMemberType(lowerer.checker.getTypeOfSymbol(p), lowerer.checker));
|
|
4479
5152
|
}
|
|
4480
5153
|
/** `recv.m<T>(args)` — a GENERIC method call, dispatched STATICALLY: the
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
5154
|
+
* checker's resolved signature (type arguments substituted, inferred or
|
|
5155
|
+
* explicit) keys one instantiation of the nearest declarer's body, and
|
|
5156
|
+
* the call is a direct `call` of `%C.m%n` over the (up/down)cast
|
|
5157
|
+
* receiver. No per-instantiation vtable slots exist, so a receiver whose
|
|
5158
|
+
* runtime class could OVERRIDE the method (genericOverrideBelow) must be
|
|
5159
|
+
* statically exact (exactInstanceClassOf) — the override set then
|
|
5160
|
+
* resolves at compile time — or fences by name. */
|
|
4488
5161
|
export function lowerClassGenericMethodCall(lowerer, call, access, recvInfo, found, recvIr) {
|
|
4489
5162
|
const name = access.name.text;
|
|
4490
5163
|
let { declarer, info } = found;
|
|
4491
|
-
if (genericOverrideBelow(
|
|
5164
|
+
if (genericOverrideBelow(recvInfo, name)) {
|
|
4492
5165
|
const exact = exactInstanceClassOf(lowerer, access.expression);
|
|
4493
5166
|
const refound = exact ? findGenericMethodOn(lowerer, exact, name) : null;
|
|
4494
5167
|
if (!refound) {
|
|
@@ -4509,14 +5182,26 @@ export function lowerClassGenericMethodCall(lowerer, call, access, recvInfo, fou
|
|
|
4509
5182
|
// path; the EXACT path can land below it (a base-typed const provably
|
|
4510
5183
|
// holding the subclass) — that direction is the checker-grade downcast
|
|
4511
5184
|
// (the exactness proof is static, stronger than an instanceof guard).
|
|
4512
|
-
const thisArg = receiver.type.kind === "object" &&
|
|
4513
|
-
|
|
5185
|
+
const thisArg = receiver.type.kind === "object" &&
|
|
5186
|
+
isSubclassOf(lowerer, declarer.def.name, receiver.type.className)
|
|
5187
|
+
? {
|
|
5188
|
+
kind: "downcast",
|
|
5189
|
+
value: receiver,
|
|
5190
|
+
type: { kind: "object", className: declarer.def.name },
|
|
5191
|
+
loc,
|
|
5192
|
+
}
|
|
4514
5193
|
: upcastTo(lowerer, receiver, declarer.def.name);
|
|
4515
5194
|
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
4516
|
-
return {
|
|
5195
|
+
return {
|
|
5196
|
+
kind: "call",
|
|
5197
|
+
callee: instance.name,
|
|
5198
|
+
args: [thisArg, ...args],
|
|
5199
|
+
type: instance.returnType,
|
|
5200
|
+
loc,
|
|
5201
|
+
};
|
|
4517
5202
|
}
|
|
4518
5203
|
/** Wraps a derived-class expression in an upcast when the target base
|
|
4519
|
-
|
|
5204
|
+
* class differs (a no-op reinterpret at runtime; keeps IR types exact). */
|
|
4520
5205
|
export function upcastTo(lowerer, expr, className) {
|
|
4521
5206
|
if (expr.type.kind === "object" && expr.type.className !== className) {
|
|
4522
5207
|
return { kind: "upcast", value: expr, type: { kind: "object", className }, loc: expr.loc };
|
|
@@ -4524,12 +5209,12 @@ export function upcastTo(lowerer, expr, className) {
|
|
|
4524
5209
|
return expr;
|
|
4525
5210
|
}
|
|
4526
5211
|
/** Constructor and methods become module functions `%C.name` whose first
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
5212
|
+
* param is `this`. Field initializers run in declaration order at the top
|
|
5213
|
+
* of a base class's constructor; a derived class's run right after its
|
|
5214
|
+
* super() call returns (tsc/JS initialization order). Reachability gates
|
|
5215
|
+
* each member independently: an unreached method body never lowers and
|
|
5216
|
+
* never emits (pinned by the corpus), while every override a reachable
|
|
5217
|
+
* virtualCall can dispatch to was marked by the discovery pass. */
|
|
4533
5218
|
/** True when a MIXIN class's constructor is the pure forwarding shape:
|
|
4534
5219
|
* exactly one rest parameter, `super(...args)` as the first statement,
|
|
4535
5220
|
* and no other reference to the parameter — the one rest-constructor
|
|
@@ -4563,7 +5248,9 @@ function mixinForwardingCtor(lowerer, ctor) {
|
|
|
4563
5248
|
ts.walkPreorder(ctor.body, (n) => {
|
|
4564
5249
|
if (n === spreadIdent)
|
|
4565
5250
|
return undefined;
|
|
4566
|
-
if (ts.isIdentifier(n) &&
|
|
5251
|
+
if (ts.isIdentifier(n) &&
|
|
5252
|
+
n.text === paramName.text &&
|
|
5253
|
+
lowerer.checker.getSymbolAtLocation(n) === paramSym) {
|
|
4567
5254
|
extraRef = true;
|
|
4568
5255
|
return "stop";
|
|
4569
5256
|
}
|
|
@@ -4585,7 +5272,9 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4585
5272
|
// demand-driven like generic-fn instances, not reachability units:
|
|
4586
5273
|
// they are never registered as units, so wantBody's name-keyed gate
|
|
4587
5274
|
// cannot apply — every member of a demanded instantiation lowers.
|
|
4588
|
-
const always = info.genericInstance !== undefined ||
|
|
5275
|
+
const always = info.genericInstance !== undefined ||
|
|
5276
|
+
info.mixinInstance !== undefined ||
|
|
5277
|
+
info.localClass !== undefined;
|
|
4589
5278
|
// A FAMILY has no constructor function at all (nothing constructs it;
|
|
4590
5279
|
// construction resolves to instantiations) and declares no instance
|
|
4591
5280
|
// members — only its statics lower below.
|
|
@@ -4603,10 +5292,19 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4603
5292
|
if (!(e instanceof PoisonError))
|
|
4604
5293
|
throw e;
|
|
4605
5294
|
if (info.decl && isJsSourceFile(info.decl.getSourceFile())) {
|
|
4606
|
-
const types = [
|
|
5295
|
+
const types = [
|
|
5296
|
+
{ kind: "object", className },
|
|
5297
|
+
...info.ctorParams.map((param) => param.type),
|
|
5298
|
+
];
|
|
4607
5299
|
const fallback = lowerer.deferToRuntimeFence(diagsBefore, info.ctor ?? info.decl, {
|
|
4608
|
-
kind: "function",
|
|
4609
|
-
|
|
5300
|
+
kind: "function",
|
|
5301
|
+
name: `%${className}.constructor`,
|
|
5302
|
+
returnType: VOID,
|
|
5303
|
+
params: types.map((type, index) => ({
|
|
5304
|
+
localId: `p.${index}`,
|
|
5305
|
+
name: index === 0 ? "this" : `p${index}`,
|
|
5306
|
+
type,
|
|
5307
|
+
})),
|
|
4610
5308
|
});
|
|
4611
5309
|
if (fallback)
|
|
4612
5310
|
out.push(fallback);
|
|
@@ -4641,9 +5339,9 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4641
5339
|
return out;
|
|
4642
5340
|
}
|
|
4643
5341
|
/** The constructor function `%C.constructor`. Synthesized when absent: a
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
5342
|
+
* base class runs just its field initializers; a derived class inherits
|
|
5343
|
+
* the base's signature — forward every param to super(), then run own
|
|
5344
|
+
* field initializers. */
|
|
4647
5345
|
export function lowerClassCtor(lowerer, info) {
|
|
4648
5346
|
const cached = info.localClass?.bodies.get(`%${info.def.name}.constructor`);
|
|
4649
5347
|
if (cached)
|
|
@@ -4656,11 +5354,16 @@ function classCaptureParams(info, context) {
|
|
|
4656
5354
|
const environment = info.localClass.context;
|
|
4657
5355
|
if (!environment)
|
|
4658
5356
|
throw new InternalCompilerError("local class lowered outside its lexical environment");
|
|
4659
|
-
return {
|
|
5357
|
+
return {
|
|
5358
|
+
classCaptures: (context.captures ?? []).map((capture, index) => {
|
|
4660
5359
|
if (!capture)
|
|
4661
5360
|
throw new InternalCompilerError("missing local class capture");
|
|
4662
|
-
return {
|
|
4663
|
-
|
|
5361
|
+
return {
|
|
5362
|
+
...capture,
|
|
5363
|
+
slot: environment.captures.findIndex((entry) => entry.localId === context.captureSources[index]),
|
|
5364
|
+
};
|
|
5365
|
+
}),
|
|
5366
|
+
};
|
|
4664
5367
|
}
|
|
4665
5368
|
function lowerClassCtorInner(lowerer, info) {
|
|
4666
5369
|
const className = info.def.name;
|
|
@@ -4683,7 +5386,12 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4683
5386
|
// unchanged, and the remaining statements lower normally.
|
|
4684
5387
|
const loc = locOf(info.ctor);
|
|
4685
5388
|
const forward = info.ctorParams.map((shape, i) => {
|
|
4686
|
-
const local = {
|
|
5389
|
+
const local = {
|
|
5390
|
+
id: `arg${i}.0`,
|
|
5391
|
+
name: `arg${i}`,
|
|
5392
|
+
type: shape.type,
|
|
5393
|
+
mutable: false,
|
|
5394
|
+
};
|
|
4687
5395
|
lowerer.ctx.locals.push(local);
|
|
4688
5396
|
params.push({ localId: local.id, name: local.name, type: shape.type });
|
|
4689
5397
|
return { kind: "varRef", localId: local.id, type: shape.type, loc };
|
|
@@ -4724,7 +5432,12 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4724
5432
|
// apply in the base constructor's own prologue, never twice).
|
|
4725
5433
|
const loc = locOf(info.decl);
|
|
4726
5434
|
const superArgs = info.ctorParams.map((shape, i) => {
|
|
4727
|
-
const local = {
|
|
5435
|
+
const local = {
|
|
5436
|
+
id: `arg${i}.0`,
|
|
5437
|
+
name: `arg${i}`,
|
|
5438
|
+
type: shape.type,
|
|
5439
|
+
mutable: false,
|
|
5440
|
+
};
|
|
4728
5441
|
lowerer.ctx.locals.push(local);
|
|
4729
5442
|
params.push({ localId: local.id, name: local.name, type: shape.type });
|
|
4730
5443
|
return { kind: "varRef", localId: local.id, type: shape.type, loc };
|
|
@@ -4758,14 +5471,14 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4758
5471
|
}
|
|
4759
5472
|
}
|
|
4760
5473
|
/** The lowered method-map name of a class member: identifier text, a
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
5474
|
+
* COMPUTED name that folds to one compile-time string
|
|
5475
|
+
* (foldedStringKeyOf — the object-literal computed-key machinery
|
|
5476
|
+
* applied to method positions; tsc late-bound the member under exactly
|
|
5477
|
+
* that name), or a reserved `sym:*` slot for the well-known symbols the
|
|
5478
|
+
* compiler consumes as language protocols (iterator and explicit
|
|
5479
|
+
* resource management). These names are unspellable as user identifiers,
|
|
5480
|
+
* like the accessor `get:x` convention. Null for genuinely
|
|
5481
|
+
* runtime-keyed names — the computed-member fences stay. */
|
|
4769
5482
|
export function classMemberNameOf(lowerer, name) {
|
|
4770
5483
|
if (ts.isIdentifier(name))
|
|
4771
5484
|
return name.text;
|
|
@@ -4791,7 +5504,8 @@ export function classMemberNameOf(lowerer, name) {
|
|
|
4791
5504
|
return `sym:${member}`;
|
|
4792
5505
|
}
|
|
4793
5506
|
}
|
|
4794
|
-
return classSymbolKeyOf(lowerer, name.expression)?.fieldName ??
|
|
5507
|
+
return (classSymbolKeyOf(lowerer, name.expression)?.fieldName ??
|
|
5508
|
+
lowerer.foldedStringKeyOf(name.expression));
|
|
4795
5509
|
}
|
|
4796
5510
|
export function classIteratorOf(lowerer, t) {
|
|
4797
5511
|
if (t.kind !== "object")
|
|
@@ -4825,10 +5539,16 @@ export function classIteratorOf(lowerer, t) {
|
|
|
4825
5539
|
const done = shape.fields.find((f) => f.name === "done");
|
|
4826
5540
|
if (done && done.type.kind !== "bool")
|
|
4827
5541
|
return null;
|
|
4828
|
-
return {
|
|
5542
|
+
return {
|
|
5543
|
+
className: t.className,
|
|
5544
|
+
iterT,
|
|
5545
|
+
resultT,
|
|
5546
|
+
valueT: value.type,
|
|
5547
|
+
hasDone: done !== undefined,
|
|
5548
|
+
};
|
|
4829
5549
|
}
|
|
4830
5550
|
/** The `it.next()` step of a class iterator as an ordinary (possibly
|
|
4831
|
-
|
|
5551
|
+
* virtual) method call. */
|
|
4832
5552
|
export function classIteratorNextCall(lowerer, cit, itRef, loc) {
|
|
4833
5553
|
return accessorCall(lowerer, cit.iterT.className, "next", itRef, [], cit.resultT, loc);
|
|
4834
5554
|
}
|
|
@@ -4837,14 +5557,14 @@ export function classIteratorOpenCall(lowerer, cit, recv, loc) {
|
|
|
4837
5557
|
return accessorCall(lowerer, cit.className, "sym:iterator", recv, [], cit.iterT, loc);
|
|
4838
5558
|
}
|
|
4839
5559
|
/** `[...new C]` / `f(...new C)` over a CLASS ITERABLE: the eager drain —
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
5560
|
+
* an interned `%iter.drain.<n>(recv)` lifted function running the
|
|
5561
|
+
* whole protocol into a fresh element array (a doneless iterator loops
|
|
5562
|
+
* forever, exactly Node's spread of an infinite iterator). `elemT`
|
|
5563
|
+
* (default: the iterator's own value type) is the DESTINATION element —
|
|
5564
|
+
* a spread into a union-element literal (`[...numbers, ...symbols]` as
|
|
5565
|
+
* `(number | symbol)[]`) pushes each value wrapped into its arm. Null
|
|
5566
|
+
* when the value isn't a recognized class iterable or the element
|
|
5567
|
+
* doesn't coerce — spread fences stay. */
|
|
4848
5568
|
export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
4849
5569
|
const cit = classIteratorOf(lowerer, src.type);
|
|
4850
5570
|
if (!cit)
|
|
@@ -4867,14 +5587,33 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4867
5587
|
const itRef = { kind: "varRef", localId: "it.0", type: cit.iterT, loc };
|
|
4868
5588
|
const outRef = { kind: "varRef", localId: "out.0", type: outT, loc };
|
|
4869
5589
|
const resRef = { kind: "varRef", localId: "res.0", type: cit.resultT, loc };
|
|
4870
|
-
const valueRead = {
|
|
5590
|
+
const valueRead = {
|
|
5591
|
+
kind: "recordGet",
|
|
5592
|
+
obj: resRef,
|
|
5593
|
+
shapeId: cit.resultT.shapeId,
|
|
5594
|
+
field: "value",
|
|
5595
|
+
type: cit.valueT,
|
|
5596
|
+
loc,
|
|
5597
|
+
};
|
|
4871
5598
|
const loop = [
|
|
4872
|
-
{
|
|
5599
|
+
{
|
|
5600
|
+
kind: "varDecl",
|
|
5601
|
+
localId: "res.0",
|
|
5602
|
+
init: classIteratorNextCall(lowerer, cit, itRef, loc),
|
|
5603
|
+
loc,
|
|
5604
|
+
},
|
|
4873
5605
|
...(cit.hasDone
|
|
4874
5606
|
? [
|
|
4875
5607
|
{
|
|
4876
5608
|
kind: "if",
|
|
4877
|
-
cond: {
|
|
5609
|
+
cond: {
|
|
5610
|
+
kind: "recordGet",
|
|
5611
|
+
obj: resRef,
|
|
5612
|
+
shapeId: cit.resultT.shapeId,
|
|
5613
|
+
field: "done",
|
|
5614
|
+
type: BOOL,
|
|
5615
|
+
loc,
|
|
5616
|
+
},
|
|
4878
5617
|
then: [{ kind: "return", value: outRef, loc }],
|
|
4879
5618
|
else_: null,
|
|
4880
5619
|
loc,
|
|
@@ -4905,8 +5644,18 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4905
5644
|
{ id: "res.0", name: "res", type: cit.resultT, mutable: true },
|
|
4906
5645
|
],
|
|
4907
5646
|
body: [
|
|
4908
|
-
{
|
|
4909
|
-
|
|
5647
|
+
{
|
|
5648
|
+
kind: "varDecl",
|
|
5649
|
+
localId: "out.0",
|
|
5650
|
+
init: { kind: "arrayLit", elems: [], type: outT, loc },
|
|
5651
|
+
loc,
|
|
5652
|
+
},
|
|
5653
|
+
{
|
|
5654
|
+
kind: "varDecl",
|
|
5655
|
+
localId: "it.0",
|
|
5656
|
+
init: classIteratorOpenCall(lowerer, cit, recvRef, loc),
|
|
5657
|
+
loc,
|
|
5658
|
+
},
|
|
4910
5659
|
{
|
|
4911
5660
|
kind: "while",
|
|
4912
5661
|
cond: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
@@ -4917,7 +5666,12 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4917
5666
|
// all-paths-return rule (the retag-helper convention).
|
|
4918
5667
|
{
|
|
4919
5668
|
kind: "throw",
|
|
4920
|
-
value: {
|
|
5669
|
+
value: {
|
|
5670
|
+
kind: "strLit",
|
|
5671
|
+
value: "scriptc: internal error: iterator drain fell through",
|
|
5672
|
+
type: STRING,
|
|
5673
|
+
loc,
|
|
5674
|
+
},
|
|
4921
5675
|
loc,
|
|
4922
5676
|
},
|
|
4923
5677
|
],
|
|
@@ -4927,8 +5681,8 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4927
5681
|
return { kind: "call", callee: name, args: [src], type: outT, loc };
|
|
4928
5682
|
}
|
|
4929
5683
|
/** The tail of a class iterable's protocol from an already-open ITERATOR
|
|
4930
|
-
|
|
4931
|
-
|
|
5684
|
+
* object (`var [a, ...rest] = new C` — the rest element drains whatever
|
|
5685
|
+
* next() still yields): the drain loop keyed by the iterator class. */
|
|
4932
5686
|
export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
4933
5687
|
const outT = arrayOf(cit.valueT);
|
|
4934
5688
|
const key = `it:${cit.iterT.className}`;
|
|
@@ -4940,12 +5694,24 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4940
5694
|
const outRef = { kind: "varRef", localId: "out.0", type: outT, loc };
|
|
4941
5695
|
const resRef = { kind: "varRef", localId: "res.0", type: cit.resultT, loc };
|
|
4942
5696
|
const loop = [
|
|
4943
|
-
{
|
|
5697
|
+
{
|
|
5698
|
+
kind: "varDecl",
|
|
5699
|
+
localId: "res.0",
|
|
5700
|
+
init: classIteratorNextCall(lowerer, cit, itRef, loc),
|
|
5701
|
+
loc,
|
|
5702
|
+
},
|
|
4944
5703
|
...(cit.hasDone
|
|
4945
5704
|
? [
|
|
4946
5705
|
{
|
|
4947
5706
|
kind: "if",
|
|
4948
|
-
cond: {
|
|
5707
|
+
cond: {
|
|
5708
|
+
kind: "recordGet",
|
|
5709
|
+
obj: resRef,
|
|
5710
|
+
shapeId: cit.resultT.shapeId,
|
|
5711
|
+
field: "done",
|
|
5712
|
+
type: BOOL,
|
|
5713
|
+
loc,
|
|
5714
|
+
},
|
|
4949
5715
|
then: [{ kind: "return", value: outRef, loc }],
|
|
4950
5716
|
else_: null,
|
|
4951
5717
|
loc,
|
|
@@ -4958,7 +5724,16 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4958
5724
|
kind: "arrIntrinsic",
|
|
4959
5725
|
method: "push",
|
|
4960
5726
|
receiver: outRef,
|
|
4961
|
-
args: [
|
|
5727
|
+
args: [
|
|
5728
|
+
{
|
|
5729
|
+
kind: "recordGet",
|
|
5730
|
+
obj: resRef,
|
|
5731
|
+
shapeId: cit.resultT.shapeId,
|
|
5732
|
+
field: "value",
|
|
5733
|
+
type: cit.valueT,
|
|
5734
|
+
loc,
|
|
5735
|
+
},
|
|
5736
|
+
],
|
|
4962
5737
|
type: F64,
|
|
4963
5738
|
loc,
|
|
4964
5739
|
},
|
|
@@ -4975,11 +5750,21 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4975
5750
|
{ id: "res.0", name: "res", type: cit.resultT, mutable: true },
|
|
4976
5751
|
],
|
|
4977
5752
|
body: [
|
|
4978
|
-
{
|
|
5753
|
+
{
|
|
5754
|
+
kind: "varDecl",
|
|
5755
|
+
localId: "out.0",
|
|
5756
|
+
init: { kind: "arrayLit", elems: [], type: outT, loc },
|
|
5757
|
+
loc,
|
|
5758
|
+
},
|
|
4979
5759
|
{ kind: "while", cond: { kind: "boolLit", value: true, type: BOOL, loc }, body: loop, loc },
|
|
4980
5760
|
{
|
|
4981
5761
|
kind: "throw",
|
|
4982
|
-
value: {
|
|
5762
|
+
value: {
|
|
5763
|
+
kind: "strLit",
|
|
5764
|
+
value: "scriptc: internal error: iterator drain fell through",
|
|
5765
|
+
type: STRING,
|
|
5766
|
+
loc,
|
|
5767
|
+
},
|
|
4983
5768
|
loc,
|
|
4984
5769
|
},
|
|
4985
5770
|
],
|
|
@@ -4989,12 +5774,14 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4989
5774
|
return { kind: "call", callee: name, args: [itVal], type: outT, loc };
|
|
4990
5775
|
}
|
|
4991
5776
|
/** One method or accessor body as its module function `%C.name`
|
|
4992
|
-
|
|
4993
|
-
|
|
5777
|
+
* (accessors are methods with property syntax: "get:x"/"set:x" entries —
|
|
5778
|
+
* see collectClassShape). */
|
|
4994
5779
|
export function lowerClassMethodMember(lowerer, info, fnLike) {
|
|
4995
5780
|
if (info.localClass?.ready) {
|
|
4996
5781
|
const member = classMemberNameOf(lowerer, fnLike.name);
|
|
4997
|
-
const name = ts.isMethodDeclaration(fnLike)
|
|
5782
|
+
const name = ts.isMethodDeclaration(fnLike)
|
|
5783
|
+
? member
|
|
5784
|
+
: `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${member}`;
|
|
4998
5785
|
return info.localClass.bodies.get(`%${info.def.name}.${name}`) ?? null;
|
|
4999
5786
|
}
|
|
5000
5787
|
return withInstanceBindings(lowerer, info, () => lowerClassMethodMemberInner(lowerer, info, fnLike));
|
|
@@ -5088,12 +5875,12 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
5088
5875
|
}
|
|
5089
5876
|
}
|
|
5090
5877
|
/** One static method body as its module function `%C.static:m` — an
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5878
|
+
* ordinary function with NO `this` param. `this` and `super` inside
|
|
5879
|
+
* name the RECEIVER class in JS (dynamic — `F.who()` sees F even when
|
|
5880
|
+
* who() is declared on E), which has no static story here: both are
|
|
5881
|
+
* named fences, with arrow functions transparent (they inherit the
|
|
5882
|
+
* method's `this`) and this-binding function forms opaque — the static-
|
|
5883
|
+
* block rule verbatim. */
|
|
5097
5884
|
export function lowerStaticMethod(lowerer, info, name) {
|
|
5098
5885
|
const entry = info.staticMethods?.get(name);
|
|
5099
5886
|
if (!entry?.member.body)
|
|
@@ -5109,7 +5896,9 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
5109
5896
|
const genCh = isGenerator && entry.ret.kind === "generator" ? generatorMeta(lowerer, entry.ret) : null;
|
|
5110
5897
|
const bodyReturn = genCh !== null
|
|
5111
5898
|
? lowerer.genBodyReturnType(entry.ret)
|
|
5112
|
-
: isAsync && entry.ret.kind === "promise"
|
|
5899
|
+
: isAsync && entry.ret.kind === "promise"
|
|
5900
|
+
? entry.ret.inner
|
|
5901
|
+
: entry.ret;
|
|
5113
5902
|
const fnCtx = newFnCtx(false, null, null, bodyReturn);
|
|
5114
5903
|
fnCtx.isAsync = isAsync;
|
|
5115
5904
|
if (genCh !== null)
|
|
@@ -5153,10 +5942,10 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
5153
5942
|
}
|
|
5154
5943
|
}
|
|
5155
5944
|
/** A synthesized throwing setter: a getter-only override shadows the
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5945
|
+
* inherited pair (JS), so a base-typed write dispatches HERE and must
|
|
5946
|
+
* throw exactly like Node's TypeError — a real instance (a typed catch's
|
|
5947
|
+
* `e instanceof TypeError` matches), catchable, exit 1 uncaught (message
|
|
5948
|
+
* text is compiler-worded; stdout and exit code are the contract). */
|
|
5160
5949
|
export function throwingSetterFn(lowerer, info, prop) {
|
|
5161
5950
|
const className = info.def.name;
|
|
5162
5951
|
const thisType = { kind: "object", className };
|
|
@@ -5195,27 +5984,38 @@ export function throwingSetterFn(lowerer, info, prop) {
|
|
|
5195
5984
|
};
|
|
5196
5985
|
}
|
|
5197
5986
|
/** The base a constructor chain actually CALLS into: generic FAMILIES are
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5987
|
+
* never constructed (no `%<family>.constructor` exists), so an
|
|
5988
|
+
* instantiation's construction-relevant base is the family's own base —
|
|
5989
|
+
* null when the generic class extends nothing, exactly the source's
|
|
5990
|
+
* story (tsc forbids super() there). Ordinary classes answer their base
|
|
5991
|
+
* unchanged. */
|
|
5203
5992
|
function superBaseOf(info) {
|
|
5204
5993
|
const b = info.base;
|
|
5205
5994
|
return b?.generic ? b.base : b;
|
|
5206
5995
|
}
|
|
5207
5996
|
/** The class's OWN field initializers as fieldSet statements (declaration
|
|
5208
|
-
|
|
5209
|
-
|
|
5997
|
+
* order) — a base constructor's prologue, a derived constructor's
|
|
5998
|
+
* super()-return continuation. */
|
|
5210
5999
|
export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
5211
6000
|
const out = [];
|
|
5212
6001
|
const thisType = { kind: "object", className: info.def.name };
|
|
5213
6002
|
for (const f of info.fieldOrder) {
|
|
5214
6003
|
if (f.errorCause) {
|
|
5215
6004
|
const loc = f.initializer ? locOf(f.initializer) : f.undefinedInitializer;
|
|
5216
|
-
const value = f.initializer
|
|
5217
|
-
|
|
5218
|
-
|
|
6005
|
+
const value = f.initializer
|
|
6006
|
+
? lowerer.lowerExprExpecting(f.initializer, DYN)
|
|
6007
|
+
: dynUndefinedExpr(loc);
|
|
6008
|
+
out.push({
|
|
6009
|
+
kind: "exprStmt",
|
|
6010
|
+
expr: {
|
|
6011
|
+
kind: "libCall",
|
|
6012
|
+
fn: "error.defineCause",
|
|
6013
|
+
args: [{ kind: "varRef", localId: thisLocal.id, type: thisType, loc }, value],
|
|
6014
|
+
type: VOID,
|
|
6015
|
+
loc,
|
|
6016
|
+
},
|
|
6017
|
+
loc,
|
|
6018
|
+
});
|
|
5219
6019
|
continue;
|
|
5220
6020
|
}
|
|
5221
6021
|
if (f.undefinedInitializer) {
|
|
@@ -5251,7 +6051,9 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
5251
6051
|
lowerer.stats.statementsFailed++;
|
|
5252
6052
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
5253
6053
|
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
5254
|
-
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
6054
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
6055
|
+
kind: "statement",
|
|
6056
|
+
});
|
|
5255
6057
|
if (fence)
|
|
5256
6058
|
out.push(fence);
|
|
5257
6059
|
}
|
|
@@ -5260,14 +6062,14 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
5260
6062
|
return out;
|
|
5261
6063
|
}
|
|
5262
6064
|
/** PARAMETER-PROPERTY assignments (`this.x = x`, synthesized): run AFTER
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
6065
|
+
* the field initializers — Node's transform defines the fields at the
|
|
6066
|
+
* top of the class body (undefined until assigned) and injects the
|
|
6067
|
+
* assignments at the start of the constructor body, i.e. after super()
|
|
6068
|
+
* and after the (native) field initializers ran (probed: a field
|
|
6069
|
+
* initializer reading `this.x` sees undefined; the body sees the value).
|
|
6070
|
+
* Each assignment reads the parameter's BODY local (defaults already
|
|
6071
|
+
* applied by the declareParams prologue), whose type the collection made
|
|
6072
|
+
* the field's type — slot-exact by construction. */
|
|
5271
6073
|
function paramPropInitStmts(lowerer, info, thisLocal) {
|
|
5272
6074
|
const out = [];
|
|
5273
6075
|
const thisType = { kind: "object", className: info.def.name };
|
|
@@ -5291,8 +6093,8 @@ function paramPropInitStmts(lowerer, info, thisLocal) {
|
|
|
5291
6093
|
return out;
|
|
5292
6094
|
}
|
|
5293
6095
|
/** Super statements initialize the base and then the derived fields on
|
|
5294
|
-
|
|
5295
|
-
|
|
6096
|
+
* whichever control-flow path executes. Repeated calls are explicitly
|
|
6097
|
+
* refused until native layouts can allocate a second receiver. */
|
|
5296
6098
|
export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
5297
6099
|
let superSeen = false;
|
|
5298
6100
|
const initialized = lowerer.declareHiddenLocal("%superInitialized", BOOL);
|
|
@@ -5306,11 +6108,30 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5306
6108
|
lowerer.unsupported("SC1090", superCall, "super() in an expression position");
|
|
5307
6109
|
superSeen = true;
|
|
5308
6110
|
const loc = locOf(superCall);
|
|
5309
|
-
const statements = [
|
|
6111
|
+
const statements = [
|
|
6112
|
+
{
|
|
6113
|
+
kind: "if",
|
|
6114
|
+
cond: { kind: "varRef", localId: initialized.id, type: BOOL, loc },
|
|
6115
|
+
then: [
|
|
6116
|
+
{
|
|
6117
|
+
kind: "exprStmt",
|
|
6118
|
+
expr: nodeThrowExpr(0, "SC2020", "repeated super() calls require a fresh receiver and are not supported yet", DYN, loc),
|
|
6119
|
+
loc,
|
|
6120
|
+
},
|
|
6121
|
+
],
|
|
6122
|
+
else_: null,
|
|
6123
|
+
loc,
|
|
6124
|
+
},
|
|
6125
|
+
];
|
|
5310
6126
|
if (info.callableBase) {
|
|
5311
6127
|
if (superCall.arguments.some(ts.isSpreadElement))
|
|
5312
6128
|
lowerer.unsupported("SC1090", superCall, "spreading explicit super arguments into an ordinary constructor");
|
|
5313
|
-
const pack = {
|
|
6129
|
+
const pack = {
|
|
6130
|
+
kind: "dynArrLit",
|
|
6131
|
+
elems: superCall.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
6132
|
+
type: DYN,
|
|
6133
|
+
loc,
|
|
6134
|
+
};
|
|
5314
6135
|
statements.push(lowerer.superCallStmt(info, thisLocal, [pack], loc));
|
|
5315
6136
|
}
|
|
5316
6137
|
else {
|
|
@@ -5321,19 +6142,33 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5321
6142
|
statements.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, loc, superCall));
|
|
5322
6143
|
}
|
|
5323
6144
|
else {
|
|
5324
|
-
const surplusSpread = forward === undefined &&
|
|
5325
|
-
base.
|
|
6145
|
+
const surplusSpread = forward === undefined &&
|
|
6146
|
+
!base.builtinError &&
|
|
6147
|
+
!base.builtinEmitter &&
|
|
6148
|
+
base.ctorParams.length === 0 &&
|
|
6149
|
+
superCall.arguments.some(ts.isSpreadElement);
|
|
5326
6150
|
if (surplusSpread) {
|
|
5327
6151
|
const evaluated = lowerer.completeArgs(superCall.arguments, [{ mode: "dynRest", type: DYN }], loc, superCall);
|
|
5328
6152
|
for (const value of evaluated)
|
|
5329
6153
|
statements.push({ kind: "exprStmt", expr: value, loc });
|
|
5330
6154
|
}
|
|
5331
|
-
const surplus = forward === undefined &&
|
|
6155
|
+
const surplus = forward === undefined &&
|
|
6156
|
+
!base.builtinError &&
|
|
6157
|
+
!base.builtinEmitter &&
|
|
5332
6158
|
!base.ctorParams.some((param) => param.mode === "rest" || param.mode === "dynRest" || param.mode === "islandRest") &&
|
|
5333
|
-
!superCall.arguments.some(ts.isSpreadElement) &&
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
6159
|
+
!superCall.arguments.some(ts.isSpreadElement) &&
|
|
6160
|
+
superCall.arguments.length > base.ctorParams.length;
|
|
6161
|
+
let args = surplusSpread
|
|
6162
|
+
? []
|
|
6163
|
+
: forward !== undefined
|
|
6164
|
+
? forward
|
|
6165
|
+
: base.builtinError
|
|
6166
|
+
? lowerer.errorConstructorArgs(superCall.arguments, loc, superCall)
|
|
6167
|
+
: base.builtinEmitter
|
|
6168
|
+
? []
|
|
6169
|
+
: lowerer.completeArgs(surplus
|
|
6170
|
+
? superCall.arguments.slice(0, base.ctorParams.length)
|
|
6171
|
+
: superCall.arguments, base.ctorParams, loc, superCall);
|
|
5337
6172
|
if (surplus) {
|
|
5338
6173
|
args = args.map((arg) => {
|
|
5339
6174
|
const local = lowerer.declareHiddenLocal("%superArgument", arg.type);
|
|
@@ -5341,13 +6176,22 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5341
6176
|
return { kind: "varRef", localId: local.id, type: arg.type, loc };
|
|
5342
6177
|
});
|
|
5343
6178
|
for (const argument of superCall.arguments.slice(base.ctorParams.length)) {
|
|
5344
|
-
statements.push({
|
|
6179
|
+
statements.push({
|
|
6180
|
+
kind: "exprStmt",
|
|
6181
|
+
expr: lowerer.lowerExpr(argument),
|
|
6182
|
+
loc: locOf(argument),
|
|
6183
|
+
});
|
|
5345
6184
|
}
|
|
5346
6185
|
}
|
|
5347
6186
|
statements.push(lowerer.superCallStmt(info, thisLocal, args, loc));
|
|
5348
6187
|
}
|
|
5349
6188
|
}
|
|
5350
|
-
statements.push({
|
|
6189
|
+
statements.push({
|
|
6190
|
+
kind: "assign",
|
|
6191
|
+
localId: initialized.id,
|
|
6192
|
+
value: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
6193
|
+
loc,
|
|
6194
|
+
});
|
|
5351
6195
|
delete context.superInitialized;
|
|
5352
6196
|
try {
|
|
5353
6197
|
statements.push(...lowerer.fieldInitStmts(info, thisLocal), ...paramPropInitStmts(lowerer, info, thisLocal));
|
|
@@ -5356,16 +6200,52 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5356
6200
|
context.superInitialized = initialized;
|
|
5357
6201
|
}
|
|
5358
6202
|
const result = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
|
|
5359
|
-
return {
|
|
5360
|
-
|
|
5361
|
-
|
|
6203
|
+
return {
|
|
6204
|
+
kind: "seqExpr",
|
|
6205
|
+
stmts: statements.map((statement) => statement.kind === "runtimeFence"
|
|
6206
|
+
? {
|
|
6207
|
+
kind: "exprStmt",
|
|
6208
|
+
expr: nodeThrowExpr(0, statement.code, statement.message, DYN, statement.loc),
|
|
6209
|
+
loc: statement.loc,
|
|
6210
|
+
}
|
|
6211
|
+
: statement),
|
|
6212
|
+
result,
|
|
6213
|
+
type: result.type,
|
|
6214
|
+
loc,
|
|
6215
|
+
};
|
|
5362
6216
|
};
|
|
5363
6217
|
try {
|
|
5364
6218
|
const result = lowerer.lowerStmts(info.ctor.body.statements);
|
|
5365
|
-
result.push({
|
|
6219
|
+
result.push({
|
|
6220
|
+
kind: "if",
|
|
6221
|
+
cond: {
|
|
6222
|
+
kind: "unary",
|
|
6223
|
+
op: "!",
|
|
6224
|
+
operand: { kind: "varRef", localId: initialized.id, type: BOOL, loc: locOf(info.ctor) },
|
|
6225
|
+
type: BOOL,
|
|
6226
|
+
loc: locOf(info.ctor),
|
|
6227
|
+
},
|
|
6228
|
+
then: [
|
|
6229
|
+
{
|
|
6230
|
+
kind: "exprStmt",
|
|
6231
|
+
expr: nodeThrowExpr(5, "", "Must call super constructor in derived class before accessing 'this' or returning from derived constructor", DYN, locOf(info.ctor)),
|
|
6232
|
+
loc: locOf(info.ctor),
|
|
6233
|
+
},
|
|
6234
|
+
],
|
|
6235
|
+
else_: null,
|
|
6236
|
+
loc: locOf(info.ctor),
|
|
6237
|
+
});
|
|
5366
6238
|
if (!superSeen)
|
|
5367
6239
|
lowerer.pushDiag(unsupportedDiag("SC1090", locOf(info.ctor), "derived constructors without a lowered super() call"));
|
|
5368
|
-
return [
|
|
6240
|
+
return [
|
|
6241
|
+
{
|
|
6242
|
+
kind: "varDecl",
|
|
6243
|
+
localId: initialized.id,
|
|
6244
|
+
init: { kind: "boolLit", value: false, type: BOOL, loc: locOf(info.ctor) },
|
|
6245
|
+
loc: locOf(info.ctor),
|
|
6246
|
+
},
|
|
6247
|
+
...result,
|
|
6248
|
+
];
|
|
5369
6249
|
}
|
|
5370
6250
|
finally {
|
|
5371
6251
|
if (previous)
|
|
@@ -5379,8 +6259,8 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5379
6259
|
}
|
|
5380
6260
|
}
|
|
5381
6261
|
/** `super(args)` → direct call of the base constructor with the SAME
|
|
5382
|
-
|
|
5383
|
-
|
|
6262
|
+
* `this` (upcast; retained by the varRef read — the callee owns and
|
|
6263
|
+
* releases its param per the universal convention). */
|
|
5384
6264
|
export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
5385
6265
|
const base = superBaseOf(info);
|
|
5386
6266
|
const thisRef = {
|
|
@@ -5391,12 +6271,41 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
5391
6271
|
};
|
|
5392
6272
|
if (info.callableBase)
|
|
5393
6273
|
return {
|
|
5394
|
-
kind: "exprStmt",
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
6274
|
+
kind: "exprStmt",
|
|
6275
|
+
expr: {
|
|
6276
|
+
kind: "libCall",
|
|
6277
|
+
fn: "dyn.classSuper",
|
|
6278
|
+
args: [
|
|
6279
|
+
info.localClass
|
|
6280
|
+
? {
|
|
6281
|
+
kind: "libCall",
|
|
6282
|
+
fn: "dyn.getPrototype",
|
|
6283
|
+
args: [
|
|
6284
|
+
{
|
|
6285
|
+
kind: "dynFrom",
|
|
6286
|
+
value: {
|
|
6287
|
+
kind: "fieldGet",
|
|
6288
|
+
obj: thisRef,
|
|
6289
|
+
className: info.def.name,
|
|
6290
|
+
field: `%classEnvironment:${info.def.name}`,
|
|
6291
|
+
type: { kind: "classval", className: info.def.name },
|
|
6292
|
+
loc,
|
|
6293
|
+
},
|
|
6294
|
+
type: DYN,
|
|
6295
|
+
loc,
|
|
6296
|
+
},
|
|
6297
|
+
],
|
|
6298
|
+
type: DYN,
|
|
6299
|
+
loc,
|
|
6300
|
+
}
|
|
6301
|
+
: { kind: "varRef", localId: info.callableBase.constructorId, type: DYN, loc },
|
|
6302
|
+
lowerer.coerceToExpected(thisRef, DYN),
|
|
6303
|
+
args[0],
|
|
6304
|
+
],
|
|
6305
|
+
type: VOID,
|
|
6306
|
+
loc,
|
|
6307
|
+
},
|
|
6308
|
+
loc,
|
|
5400
6309
|
};
|
|
5401
6310
|
if (base.builtinError) {
|
|
5402
6311
|
// super(message) into the runtime-provided Error constructor: stamps
|
|
@@ -5453,8 +6362,8 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
5453
6362
|
};
|
|
5454
6363
|
}
|
|
5455
6364
|
/** `super.method(args)`: the base chain's implementation, called
|
|
5456
|
-
|
|
5457
|
-
|
|
6365
|
+
* DIRECTLY over this method's own `this` (upcast to the declarer) —
|
|
6366
|
+
* super dispatch is static in JS too, never through the dynamic class. */
|
|
5458
6367
|
export function lowerSuperMethodCall(lowerer, call, access) {
|
|
5459
6368
|
const cls = lowerer.currentClass;
|
|
5460
6369
|
if (!cls?.base) {
|
|
@@ -5516,15 +6425,33 @@ export function lowerSuperMethodCall(lowerer, call, access) {
|
|
|
5516
6425
|
if (lowerer.prototypeMethodAccesses.has(access.name.text)) {
|
|
5517
6426
|
const prototype = classPrototypeData(lowerer, cls.base, loc);
|
|
5518
6427
|
if (prototype) {
|
|
5519
|
-
const callee = {
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
6428
|
+
const callee = {
|
|
6429
|
+
kind: "dynKeyGet",
|
|
6430
|
+
value: prototype,
|
|
6431
|
+
key: { kind: "strLit", value: access.name.text, type: STRING, loc },
|
|
6432
|
+
type: DYN,
|
|
6433
|
+
loc,
|
|
6434
|
+
};
|
|
6435
|
+
const value = {
|
|
6436
|
+
kind: "dynCall",
|
|
6437
|
+
callee,
|
|
6438
|
+
receiver: lowerer.coerceToExpected(thisRef, DYN),
|
|
6439
|
+
calleeName: access.getText(),
|
|
6440
|
+
args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
6441
|
+
type: DYN,
|
|
6442
|
+
loc,
|
|
6443
|
+
};
|
|
5523
6444
|
return found.sig.ret.kind === "void" ? value : lowerer.coerceToExpected(value, found.sig.ret);
|
|
5524
6445
|
}
|
|
5525
6446
|
}
|
|
5526
6447
|
if (found.declarer.builtinError) {
|
|
5527
|
-
return {
|
|
6448
|
+
return {
|
|
6449
|
+
kind: "libCall",
|
|
6450
|
+
fn: "error.toString",
|
|
6451
|
+
args: [lowerer.upcastTo(thisRef, "%Error")],
|
|
6452
|
+
type: STRING,
|
|
6453
|
+
loc,
|
|
6454
|
+
};
|
|
5528
6455
|
}
|
|
5529
6456
|
lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
|
|
5530
6457
|
const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
|
|
@@ -5537,7 +6464,7 @@ export function lowerSuperMethodCall(lowerer, call, access) {
|
|
|
5537
6464
|
};
|
|
5538
6465
|
}
|
|
5539
6466
|
/** The `this` reference for super accessor reads/writes, with the shared
|
|
5540
|
-
|
|
6467
|
+
* validity checks (derived-class body, resolvable this). */
|
|
5541
6468
|
export function superThisRef(lowerer, access) {
|
|
5542
6469
|
const cls = lowerer.currentClass;
|
|
5543
6470
|
if (!cls?.base) {
|
|
@@ -5553,8 +6480,8 @@ export function superThisRef(lowerer, access) {
|
|
|
5553
6480
|
};
|
|
5554
6481
|
}
|
|
5555
6482
|
/** `super.x` read: a DIRECT call of the base chain's getter over this
|
|
5556
|
-
|
|
5557
|
-
|
|
6483
|
+
* method's own `this` (upcast to the declarer) — like super.method(),
|
|
6484
|
+
* never through the vtable. */
|
|
5558
6485
|
export function lowerSuperAccessorRead(lowerer, access) {
|
|
5559
6486
|
const { thisRef, base } = lowerer.superThisRef(access);
|
|
5560
6487
|
const name = access.name.text;
|
|
@@ -5578,7 +6505,7 @@ export function lowerSuperAccessorRead(lowerer, access) {
|
|
|
5578
6505
|
};
|
|
5579
6506
|
}
|
|
5580
6507
|
/** `super.x = v`: a DIRECT call of the base chain's setter (same
|
|
5581
|
-
|
|
6508
|
+
* static-dispatch rule as every super member access). */
|
|
5582
6509
|
export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
|
|
5583
6510
|
const { thisRef, base } = lowerer.superThisRef(access);
|
|
5584
6511
|
const name = access.name.text;
|
|
@@ -5605,9 +6532,9 @@ export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
|
|
|
5605
6532
|
};
|
|
5606
6533
|
}
|
|
5607
6534
|
/** True when `info`'s EFFECTIVE constructor — its own, or the one
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
6535
|
+
* inherited through ctor-less bases — is a builtin error class's. Such
|
|
6536
|
+
* classes construct with the error argument rule, and their synthesized
|
|
6537
|
+
* constructors forward both checked-dynamic values to error.ctorOptions. */
|
|
5611
6538
|
export function inheritsBuiltinErrorCtor(lowerer, info) {
|
|
5612
6539
|
for (let c = info; c; c = c.base) {
|
|
5613
6540
|
if (c.builtinError)
|
|
@@ -5618,7 +6545,7 @@ export function inheritsBuiltinErrorCtor(lowerer, info) {
|
|
|
5618
6545
|
return false;
|
|
5619
6546
|
}
|
|
5620
6547
|
/** The EventEmitter twin: a ctor-less chain into the emitter base
|
|
5621
|
-
|
|
6548
|
+
* inherits `new C()` — zero arguments (the options bag fences). */
|
|
5622
6549
|
export function inheritsBuiltinEmitterCtor(lowerer, info) {
|
|
5623
6550
|
for (let c = info; c; c = c.base) {
|
|
5624
6551
|
if (c.builtinStream)
|
|
@@ -5631,10 +6558,10 @@ export function inheritsBuiltinEmitterCtor(lowerer, info) {
|
|
|
5631
6558
|
return false;
|
|
5632
6559
|
}
|
|
5633
6560
|
/** The stream twin: a ctor-less chain into a runtime stream base
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
6561
|
+
* inherits `new C()` — zero arguments (the synthesized constructor runs
|
|
6562
|
+
* super() with default options; passing options through an inherited
|
|
6563
|
+
* constructor would need the literal at the new-site to plumb, so it
|
|
6564
|
+
* asks for a declared constructor instead). */
|
|
5638
6565
|
function inheritsBuiltinStreamCtor(lowerer, info) {
|
|
5639
6566
|
for (let c = info; c; c = c.base) {
|
|
5640
6567
|
if (c.builtinStream)
|
|
@@ -5708,8 +6635,13 @@ function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
|
|
|
5708
6635
|
: lowerer.completeArgs(expr.arguments ?? [], info.ctorParams, loc, expr);
|
|
5709
6636
|
for (let current = info; current; current = current.base) {
|
|
5710
6637
|
if (current.def.baseValueGlobal)
|
|
5711
|
-
return {
|
|
5712
|
-
|
|
6638
|
+
return {
|
|
6639
|
+
kind: "newValue",
|
|
6640
|
+
callee: classValueRef(lowerer, info, expr),
|
|
6641
|
+
args,
|
|
6642
|
+
type: { kind: "object", className: info.def.name },
|
|
6643
|
+
loc,
|
|
6644
|
+
};
|
|
5713
6645
|
}
|
|
5714
6646
|
return {
|
|
5715
6647
|
kind: "new",
|
|
@@ -5732,6 +6664,9 @@ function assignedThisFieldType(lowerer, expr) {
|
|
|
5732
6664
|
}
|
|
5733
6665
|
export function lowerNew(lowerer, expr) {
|
|
5734
6666
|
const loc = locOf(expr);
|
|
6667
|
+
const worker = lowerWorkerNew(lowerer, expr);
|
|
6668
|
+
if (worker)
|
|
6669
|
+
return worker;
|
|
5735
6670
|
let intlConstructor = expr.expression;
|
|
5736
6671
|
if (ts.isIdentifier(intlConstructor)) {
|
|
5737
6672
|
const symbol = lowerer.resolveValueSymbol(intlConstructor);
|
|
@@ -5739,7 +6674,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
5739
6674
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer)
|
|
5740
6675
|
intlConstructor = declaration.initializer;
|
|
5741
6676
|
}
|
|
5742
|
-
const intl = ts.isPropertyAccessExpression(intlConstructor)
|
|
6677
|
+
const intl = ts.isPropertyAccessExpression(intlConstructor)
|
|
6678
|
+
? lowerer.stdlibGlobalMember(intlConstructor, "Intl")
|
|
6679
|
+
: null;
|
|
5743
6680
|
if (intl && intl !== "Segmenter")
|
|
5744
6681
|
lowerer.noLowering(`new Intl.${intl}`, expr, undefined, lowerer.checker.getSymbolAtLocation(expr.expression));
|
|
5745
6682
|
const instanceConstructor = lowerInstanceConstructorNew(lowerer, expr);
|
|
@@ -5750,10 +6687,16 @@ export function lowerNew(lowerer, expr) {
|
|
|
5750
6687
|
return objectFactory;
|
|
5751
6688
|
if (ts.isIdentifier(expr.expression)) {
|
|
5752
6689
|
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
5753
|
-
const declaration = symbol &&
|
|
6690
|
+
const declaration = symbol &&
|
|
6691
|
+
lowerer.checker
|
|
6692
|
+
.declarationsOf(symbol)
|
|
6693
|
+
.find((node) => ts.isFunctionDeclaration(node) && node.body !== undefined);
|
|
5754
6694
|
if (declaration && ts.isFunctionDeclaration(declaration) && declaration.body) {
|
|
5755
6695
|
const last = declaration.body.statements.at(-1);
|
|
5756
|
-
if (last &&
|
|
6696
|
+
if (last &&
|
|
6697
|
+
ts.isReturnStatement(last) &&
|
|
6698
|
+
last.expression &&
|
|
6699
|
+
ts.isObjectLiteralExpression(last.expression)) {
|
|
5757
6700
|
lowerer.unsupported("SC1090", expr, "object-returning constructors that observe this or return mixed primitive/object values");
|
|
5758
6701
|
}
|
|
5759
6702
|
}
|
|
@@ -5767,13 +6710,24 @@ export function lowerNew(lowerer, expr) {
|
|
|
5767
6710
|
if (yes && no && !yes.classDecorators && !no.classDecorators) {
|
|
5768
6711
|
const yesType = { kind: "object", className: yes.def.name };
|
|
5769
6712
|
const noType = { kind: "object", className: no.def.name };
|
|
5770
|
-
const type = yes === no
|
|
5771
|
-
|
|
6713
|
+
const type = yes === no
|
|
6714
|
+
? yesType
|
|
6715
|
+
: {
|
|
6716
|
+
kind: "union",
|
|
6717
|
+
unionId: lowerer.unions.intern([yesType, noType].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1))),
|
|
6718
|
+
};
|
|
6719
|
+
return {
|
|
6720
|
+
kind: "ternary",
|
|
6721
|
+
cond: lowerer.lowerCondition(selected.condition),
|
|
5772
6722
|
then: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, yes, loc), type),
|
|
5773
|
-
else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type),
|
|
6723
|
+
else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type),
|
|
6724
|
+
type,
|
|
6725
|
+
loc,
|
|
6726
|
+
};
|
|
5774
6727
|
}
|
|
5775
6728
|
}
|
|
5776
|
-
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
6729
|
+
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
6730
|
+
expr.expression.name.text === "Segmenter" &&
|
|
5777
6731
|
lowerer.isStdlibGlobal(expr.expression.expression, "Intl")) {
|
|
5778
6732
|
const args = expr.arguments ?? [];
|
|
5779
6733
|
const undefinedArg = (arg) => (lowerer.typeOf(arg).flags & ts.TypeFlags.Undefined) !== 0;
|
|
@@ -5781,16 +6735,24 @@ export function lowerNew(lowerer, expr) {
|
|
|
5781
6735
|
lowerer.noLowering("Intl.Segmenter locale negotiation", expr, "omit the locale or pass undefined for default Unicode grapheme segmentation");
|
|
5782
6736
|
}
|
|
5783
6737
|
const options = args[1];
|
|
5784
|
-
if (options &&
|
|
5785
|
-
!(
|
|
5786
|
-
|
|
5787
|
-
|
|
6738
|
+
if (options &&
|
|
6739
|
+
!undefinedArg(options) &&
|
|
6740
|
+
!(ts.isObjectLiteralExpression(options) &&
|
|
6741
|
+
options.properties.every((property) => ts.isPropertyAssignment(property) &&
|
|
6742
|
+
(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) &&
|
|
6743
|
+
property.name.text === "granularity" &&
|
|
6744
|
+
ts.isStringLiteral(property.initializer) &&
|
|
6745
|
+
property.initializer.text === "grapheme"))) {
|
|
5788
6746
|
lowerer.noLowering("Intl.Segmenter options", options, 'the native segmenter supports default options and { granularity: "grapheme" }; word and sentence segmentation remain unsupported');
|
|
5789
6747
|
}
|
|
5790
6748
|
// Explicit undefined expressions can carry effects; retain argument order.
|
|
5791
6749
|
const stmts = args.map((arg) => {
|
|
5792
6750
|
const value = lowerer.lowerExpr(arg);
|
|
5793
|
-
return {
|
|
6751
|
+
return {
|
|
6752
|
+
kind: "exprStmt",
|
|
6753
|
+
expr: value.type.kind === "void" ? value : lowerer.coerceInto(arg, value, DYN),
|
|
6754
|
+
loc: locOf(arg),
|
|
6755
|
+
};
|
|
5794
6756
|
});
|
|
5795
6757
|
const result = { kind: "libCall", fn: "intl.segmenterNew", args: [], type: DYN, loc };
|
|
5796
6758
|
return stmts.length ? { kind: "seqExpr", stmts, result, type: DYN, loc } : result;
|
|
@@ -5960,8 +6922,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
5960
6922
|
if (agent)
|
|
5961
6923
|
return agent;
|
|
5962
6924
|
}
|
|
5963
|
-
if (ts.isIdentifier(expr.expression) ||
|
|
5964
|
-
|
|
6925
|
+
if (ts.isIdentifier(expr.expression) ||
|
|
6926
|
+
(ts.isPropertyAccessExpression(expr.expression) &&
|
|
6927
|
+
ts.isIdentifier(expr.expression.name) &&
|
|
6928
|
+
lowerer.isStdlibGlobal(expr.expression.expression, "globalThis"))) {
|
|
5965
6929
|
// `import C = N.C; new C()` — the alias's own source-order guards
|
|
5966
6930
|
// (a no-op for every non-import= binding).
|
|
5967
6931
|
if (ts.isIdentifier(expr.expression))
|
|
@@ -6059,8 +7023,14 @@ export function lowerNew(lowerer, expr) {
|
|
|
6059
7023
|
if (values.some((value) => value.type.kind === "dyn" || value.type.kind === "regex")) {
|
|
6060
7024
|
const checked = [0, 1].map((index) => values[index]
|
|
6061
7025
|
? lowerer.coerceInto(args[index], values[index], DYN)
|
|
6062
|
-
:
|
|
6063
|
-
return {
|
|
7026
|
+
: dynUndefinedExpr(loc));
|
|
7027
|
+
return {
|
|
7028
|
+
kind: "libCall",
|
|
7029
|
+
fn: "regex.newChecked",
|
|
7030
|
+
args: checked,
|
|
7031
|
+
type: { kind: "regex" },
|
|
7032
|
+
loc,
|
|
7033
|
+
};
|
|
6064
7034
|
}
|
|
6065
7035
|
const strArg = (a, what) => {
|
|
6066
7036
|
if (!a)
|
|
@@ -6070,9 +7040,18 @@ export function lowerNew(lowerer, expr) {
|
|
|
6070
7040
|
if (v.type.kind === "undefinedT") {
|
|
6071
7041
|
if (v.kind === "unitLit")
|
|
6072
7042
|
return empty;
|
|
6073
|
-
return {
|
|
7043
|
+
return {
|
|
7044
|
+
kind: "seqExpr",
|
|
7045
|
+
stmts: [{ kind: "exprStmt", expr: lowerer.coerceToExpected(v, DYN), loc: locOf(a) }],
|
|
7046
|
+
result: empty,
|
|
7047
|
+
type: STRING,
|
|
7048
|
+
loc,
|
|
7049
|
+
};
|
|
6074
7050
|
}
|
|
6075
|
-
if (v.type.kind === "union" &&
|
|
7051
|
+
if (v.type.kind === "union" &&
|
|
7052
|
+
lowerer.unions
|
|
7053
|
+
.get(v.type.unionId)
|
|
7054
|
+
?.arms.every((arm) => arm.kind === "string" || arm.kind === "undefinedT")) {
|
|
6076
7055
|
return { kind: "nullish", left: v, right: empty, type: STRING, loc: locOf(a) };
|
|
6077
7056
|
}
|
|
6078
7057
|
if (v.type.kind !== "string") {
|
|
@@ -6082,7 +7061,13 @@ export function lowerNew(lowerer, expr) {
|
|
|
6082
7061
|
};
|
|
6083
7062
|
const pattern = strArg(args[0], "pattern");
|
|
6084
7063
|
const flags = strArg(args[1], "flags argument");
|
|
6085
|
-
return {
|
|
7064
|
+
return {
|
|
7065
|
+
kind: "libCall",
|
|
7066
|
+
fn: "regex.new",
|
|
7067
|
+
args: [pattern, flags],
|
|
7068
|
+
type: { kind: "regex" },
|
|
7069
|
+
loc,
|
|
7070
|
+
};
|
|
6086
7071
|
}
|
|
6087
7072
|
if (symbol && symbol.name === "URL" && lowerer.isStdlibSymbol(symbol)) {
|
|
6088
7073
|
return lowerUrlNew(lowerer, expr);
|
|
@@ -6102,9 +7087,20 @@ export function lowerNew(lowerer, expr) {
|
|
|
6102
7087
|
lowerer.noLowering(`new Date with ${args.length} arguments`, expr, "new Date(), new Date(milliseconds), and new Date(dateString) are supported; the local-time year/month field constructor has no lowering", symbol);
|
|
6103
7088
|
}
|
|
6104
7089
|
if (isJsSourceFile(expr.getSourceFile())) {
|
|
6105
|
-
return {
|
|
6106
|
-
|
|
6107
|
-
|
|
7090
|
+
return {
|
|
7091
|
+
kind: "libCall",
|
|
7092
|
+
fn: "date.nativeNew",
|
|
7093
|
+
args: [
|
|
7094
|
+
{
|
|
7095
|
+
kind: "dynArrLit",
|
|
7096
|
+
elems: args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
7097
|
+
type: DYN,
|
|
7098
|
+
loc,
|
|
7099
|
+
},
|
|
7100
|
+
],
|
|
7101
|
+
type: DYN,
|
|
7102
|
+
loc,
|
|
7103
|
+
};
|
|
6108
7104
|
}
|
|
6109
7105
|
if (args.length === 0) {
|
|
6110
7106
|
return { kind: "libCall", fn: "date.newNow", args: [], type: DATE_T, loc };
|
|
@@ -6146,7 +7142,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6146
7142
|
loc,
|
|
6147
7143
|
};
|
|
6148
7144
|
}
|
|
6149
|
-
if (symbol &&
|
|
7145
|
+
if (symbol &&
|
|
7146
|
+
(symbol.name === "TextDecoder" || symbol.name === "TextEncoder") &&
|
|
7147
|
+
lowerer.isStdlibSymbol(symbol)) {
|
|
6150
7148
|
return lowerTextCodecNew(lowerer, expr, symbol.name);
|
|
6151
7149
|
}
|
|
6152
7150
|
// `new Uint8Array(...)` / `new Uint32Array(...)` / `new
|
|
@@ -6191,7 +7189,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6191
7189
|
}
|
|
6192
7190
|
if (symbol?.name === "Map" && lowerer.isStdlibSymbol(symbol)) {
|
|
6193
7191
|
const seedArg = (expr.arguments?.length ?? 0) === 1 ? expr.arguments[0] : null;
|
|
6194
|
-
const isPairLit = (el) => ts.isArrayLiteralExpression(el) &&
|
|
7192
|
+
const isPairLit = (el) => ts.isArrayLiteralExpression(el) &&
|
|
7193
|
+
el.elements.length === 2 &&
|
|
6195
7194
|
!el.elements.some(ts.isSpreadElement);
|
|
6196
7195
|
const entriesLit = seedArg && ts.isArrayLiteralExpression(seedArg) && seedArg.elements.every(isPairLit)
|
|
6197
7196
|
? seedArg.elements.filter(isPairLit)
|
|
@@ -6212,7 +7211,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6212
7211
|
while (ts.isParenthesizedExpression(parent))
|
|
6213
7212
|
parent = parent.parent;
|
|
6214
7213
|
// `satisfies` checks a view but retains the expression's own type.
|
|
6215
|
-
const contextualSeed = !ts.isSatisfiesExpression(parent) &&
|
|
7214
|
+
const contextualSeed = !ts.isSatisfiesExpression(parent) &&
|
|
7215
|
+
(expr.typeArguments?.length ?? 0) === 0 &&
|
|
6216
7216
|
(entriesLit !== null || (expr.arguments?.length ?? 0) === 0);
|
|
6217
7217
|
// JavaScript's `new Map()` has no type-argument syntax: the no-arg
|
|
6218
7218
|
// constructor overload pins Map<any, any> whatever the JSDoc says
|
|
@@ -6264,7 +7264,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6264
7264
|
return { kind: "dynObjLit", type: DYN, loc };
|
|
6265
7265
|
}
|
|
6266
7266
|
const keyIr = targs[0] ? lowerer.mapTypeOf(targs[0]) : null;
|
|
6267
|
-
if (targs[0] &&
|
|
7267
|
+
if (targs[0] &&
|
|
7268
|
+
(!keyIr ||
|
|
7269
|
+
!isSupportedMapKey(keyIr, keyIr.kind === "union" ? lowerer.unions.get(keyIr.unionId)?.arms : undefined))) {
|
|
6268
7270
|
lowerer.unsupported("SC1090", expr, `Map keys of type '${lowerer.checker.typeToString(targs[0])}' ` +
|
|
6269
7271
|
`(Map keys must be numbers, strings, booleans, bigints, identity references, or supported unions)`);
|
|
6270
7272
|
}
|
|
@@ -6276,19 +7278,35 @@ export function lowerNew(lowerer, expr) {
|
|
|
6276
7278
|
lowerer.badType(expr, tsType);
|
|
6277
7279
|
}
|
|
6278
7280
|
// Weak containers share checked native key identities and lifetime hooks.
|
|
6279
|
-
if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") &&
|
|
7281
|
+
if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") &&
|
|
7282
|
+
lowerer.isStdlibSymbol(symbol)) {
|
|
6280
7283
|
const args = expr.arguments ?? [];
|
|
6281
7284
|
if (args.length > 1 || args.some(ts.isSpreadElement)) {
|
|
6282
7285
|
lowerer.unsupported("SC1090", expr, `${symbol.name} construction with surplus or spread arguments`);
|
|
6283
7286
|
}
|
|
6284
7287
|
if (lowerer.dynamic) {
|
|
6285
|
-
const ctor = {
|
|
6286
|
-
|
|
7288
|
+
const ctor = {
|
|
7289
|
+
kind: "jsOp",
|
|
7290
|
+
op: "globalGet",
|
|
7291
|
+
name: symbol.name,
|
|
7292
|
+
args: [],
|
|
7293
|
+
type: JSVAL,
|
|
7294
|
+
loc,
|
|
7295
|
+
};
|
|
7296
|
+
return {
|
|
7297
|
+
kind: "jsOp",
|
|
7298
|
+
op: "construct",
|
|
7299
|
+
args: [ctor, ...args.map((arg) => lowerer.jsvalIn(lowerer.lowerExpr(arg), arg))],
|
|
7300
|
+
type: JSVAL,
|
|
7301
|
+
loc,
|
|
7302
|
+
};
|
|
6287
7303
|
}
|
|
6288
7304
|
return {
|
|
6289
|
-
kind: "libCall",
|
|
7305
|
+
kind: "libCall",
|
|
7306
|
+
fn: symbol.name === "WeakMap" ? "weakMap.new" : "weakSet.new",
|
|
6290
7307
|
args: [args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc)],
|
|
6291
|
-
type: DYN,
|
|
7308
|
+
type: DYN,
|
|
7309
|
+
loc,
|
|
6292
7310
|
};
|
|
6293
7311
|
}
|
|
6294
7312
|
// `new Set<T>()`: construct + bulk add from supported values,
|
|
@@ -6304,9 +7322,21 @@ export function lowerNew(lowerer, expr) {
|
|
|
6304
7322
|
if (seeded)
|
|
6305
7323
|
return seeded;
|
|
6306
7324
|
}
|
|
6307
|
-
if (!mapped &&
|
|
6308
|
-
|
|
6309
|
-
|
|
7325
|
+
if (!mapped &&
|
|
7326
|
+
isJsSourceFile(expr.getSourceFile()) &&
|
|
7327
|
+
(expr.arguments?.length ?? 0) <= 1 &&
|
|
7328
|
+
!expr.arguments?.some(ts.isSpreadElement)) {
|
|
7329
|
+
return {
|
|
7330
|
+
kind: "libCall",
|
|
7331
|
+
fn: "dyn.nativeSetNew",
|
|
7332
|
+
args: [
|
|
7333
|
+
expr.arguments?.[0]
|
|
7334
|
+
? lowerer.lowerExprExpecting(expr.arguments[0], DYN)
|
|
7335
|
+
: dynUndefinedExpr(loc),
|
|
7336
|
+
],
|
|
7337
|
+
type: DYN,
|
|
7338
|
+
loc,
|
|
7339
|
+
};
|
|
6310
7340
|
}
|
|
6311
7341
|
// JavaScript's identity-Set idiom: `new Set([setTimeout, atob,
|
|
6312
7342
|
// ...])` — the element TYPE (a union of stdlib signatures) has no
|
|
@@ -6427,7 +7457,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6427
7457
|
lowerer.mapTypeOf(lowerer.typeOf(expr.arguments[0]))?.kind !== "string" &&
|
|
6428
7458
|
lowerer.mapTypeOf(lowerer.typeOf(expr.arguments[1]))?.kind === "string") {
|
|
6429
7459
|
const first = lowerer.lowerExpr(expr.arguments[0]);
|
|
6430
|
-
if (first.kind === "unitLit" ||
|
|
7460
|
+
if (first.kind === "unitLit" ||
|
|
7461
|
+
first.type.kind === "dyn" ||
|
|
7462
|
+
lowerer.dynConvertible(first.type)) {
|
|
6431
7463
|
const got = first.type.kind === "dyn" ? first : { kind: "dynFrom", value: first, type: DYN, loc };
|
|
6432
7464
|
// The encoding argument still evaluates in Node before the
|
|
6433
7465
|
// throw only via the ctor body's later reads — it does NOT
|
|
@@ -6435,7 +7467,13 @@ export function lowerNew(lowerer, expr) {
|
|
|
6435
7467
|
// effect-free operands; effectful ones keep the fence.
|
|
6436
7468
|
const enc = lowerer.lowerExpr(expr.arguments[1]);
|
|
6437
7469
|
if (enc.kind === "strLit" || isSafeToRepeat(enc)) {
|
|
6438
|
-
return {
|
|
7470
|
+
return {
|
|
7471
|
+
kind: "libCall",
|
|
7472
|
+
fn: "buffer.newStringFail",
|
|
7473
|
+
args: [got],
|
|
7474
|
+
type: bytesOf("u8"),
|
|
7475
|
+
loc,
|
|
7476
|
+
};
|
|
6439
7477
|
}
|
|
6440
7478
|
}
|
|
6441
7479
|
}
|
|
@@ -6490,10 +7528,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
6490
7528
|
if (t?.kind !== "record")
|
|
6491
7529
|
lowerer.badType(expr, lowerer.typeOf(expr));
|
|
6492
7530
|
const key = `x509.record:${isBytes ? "bytes" : "str"}`;
|
|
6493
|
-
let helper = lowerer.
|
|
7531
|
+
let helper = lowerer.valueHelpers.get(key);
|
|
6494
7532
|
if (!helper) {
|
|
6495
|
-
helper = `%x509.record.${lowerer.
|
|
6496
|
-
lowerer.
|
|
7533
|
+
helper = `%x509.record.${lowerer.valueHelpers.size}`;
|
|
7534
|
+
lowerer.valueHelpers.set(key, helper);
|
|
6497
7535
|
const dataT = data.type;
|
|
6498
7536
|
const dRef = { kind: "varRef", localId: "d.0", type: dataT, loc };
|
|
6499
7537
|
const field = (name, fn) => ({
|
|
@@ -6539,7 +7577,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6539
7577
|
const calleeT = storedClassValueType(lowerer, expr.expression);
|
|
6540
7578
|
if (calleeT?.kind === "classval") {
|
|
6541
7579
|
let info = lowerer.classes.get(calleeT.className);
|
|
6542
|
-
if (!info &&
|
|
7580
|
+
if (!info &&
|
|
7581
|
+
ts.isPropertyAccessExpression(expr.expression) &&
|
|
7582
|
+
ts.isIdentifier(expr.expression.name)) {
|
|
6543
7583
|
// A property-assigned class expression not collected yet (this
|
|
6544
7584
|
// body lowers ahead of the assignment statement — hoisted
|
|
6545
7585
|
// functions): collect it on demand and retry, keeping the
|
|
@@ -6590,7 +7630,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6590
7630
|
if (calleeT?.kind === "union") {
|
|
6591
7631
|
const def = lowerer.unions.get(calleeT.unionId);
|
|
6592
7632
|
if (def?.arms.some((a) => a.kind === "classval")) {
|
|
6593
|
-
if (def.arms.every((arm) => arm.kind === "classval" || isJsSourceFile(expr.getSourceFile()) && isUnitType(arm)) &&
|
|
7633
|
+
if (def.arms.every((arm) => arm.kind === "classval" || (isJsSourceFile(expr.getSourceFile()) && isUnitType(arm))) &&
|
|
7634
|
+
lowerer.dynConvertible(calleeT)) {
|
|
6594
7635
|
const callee = lowerer.lowerExprExpecting(expr.expression, DYN);
|
|
6595
7636
|
return lowerCheckedConstructor(lowerer, expr, callee);
|
|
6596
7637
|
}
|
|
@@ -6621,7 +7662,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
6621
7662
|
}
|
|
6622
7663
|
// Checked construction supports emitted classes and builtin typed arrays.
|
|
6623
7664
|
const callee = tryLowerExpression(lowerer, expr.expression);
|
|
6624
|
-
if (callee &&
|
|
7665
|
+
if (callee &&
|
|
7666
|
+
(callee.type.kind === "dyn" ||
|
|
7667
|
+
((callee.type.kind === "func" || callee.type.kind === "classval") &&
|
|
7668
|
+
lowerer.dynConvertible(callee.type)))) {
|
|
6625
7669
|
return lowerCheckedConstructor(lowerer, expr, lowerer.coerceToExpected(callee, DYN));
|
|
6626
7670
|
}
|
|
6627
7671
|
lowerer.unsupported("SC1090", expr, "constructing values other than classes declared in the program");
|
|
@@ -6636,10 +7680,10 @@ function lowerCheckedConstructor(lowerer, expr, callee) {
|
|
|
6636
7680
|
return checkedClassConstruction(lowerer, callee, args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
|
|
6637
7681
|
}
|
|
6638
7682
|
/** A getter/setter invocation over an accessor target's receiver — the
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
7683
|
+
* same whole-program devirtualization as method calls: a virtualCall
|
|
7684
|
+
* when some strict subclass of the receiver's static class overrides
|
|
7685
|
+
* this HALF of the accessor (get and set devirtualize independently),
|
|
7686
|
+
* a direct call of the nearest declaration otherwise. */
|
|
6643
7687
|
export function accessorCall(lowerer, className, member, obj, extraArgs, ret, loc) {
|
|
6644
7688
|
const info = lowerer.classes.get(className);
|
|
6645
7689
|
if (!info)
|
|
@@ -6687,7 +7731,8 @@ function genericFieldFnNodeOf(member) {
|
|
|
6687
7731
|
while (ts.isParenthesizedExpression(init))
|
|
6688
7732
|
init = init.expression;
|
|
6689
7733
|
if ((ts.isArrowFunction(init) || ts.isFunctionExpression(init)) &&
|
|
6690
|
-
init.typeParameters !== undefined &&
|
|
7734
|
+
init.typeParameters !== undefined &&
|
|
7735
|
+
init.body !== undefined) {
|
|
6691
7736
|
return init;
|
|
6692
7737
|
}
|
|
6693
7738
|
return null;
|