@scriptc/compiler 0.2.4 → 0.2.5
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 +915 -215
- 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 +2 -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.js +9 -2
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +4 -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 +6 -1
- package/dist/backend/llvm/byte-numbers.js.map +1 -1
- 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 +3 -0
- package/dist/backend/llvm/call-lifetimes.js +60 -17
- 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.js +16 -12
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.js +4 -1
- package/dist/backend/llvm/common.js.map +1 -1
- 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.js +68 -22
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +9 -3
- package/dist/backend/llvm/emitter.js +238 -105
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +233 -42
- 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 +13 -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 +20 -9
- 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 +92 -33
- 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 +19 -4
- 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 +88 -19
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +43 -1
- 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-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/lib-abi.js +13 -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 +35 -16
- 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 +107 -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 +1 -0
- package/dist/backend/llvm/local-array-reads.js +96 -30
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +368 -60
- 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/map-read-lifetimes.d.ts +6 -2
- package/dist/backend/llvm/map-read-lifetimes.js +44 -14
- 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 +3 -2
- package/dist/backend/llvm/reference-effects.js +67 -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.js +60 -17
- 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.js +4 -4
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +14 -6
- package/dist/backend/llvm/split.test.js.map +1 -1
- 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 +112 -26
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- 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.js +6 -3
- 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 +118 -22
- 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 +314 -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 +1267 -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 +163 -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.js +2 -1
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +1 -1
- package/dist/backend/native-codegen.js +24 -13
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +12 -9
- package/dist/backend/native-codegen.test.js.map +1 -1
- 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.js +27 -8
- 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-pack-core.js +96 -49
- 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 +87 -15
- 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 +40 -24
- 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 +1 -1
- package/dist/executable/executable-cache.js +78 -48
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +75 -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.js +17 -12
- package/dist/frontend/fork-target.js.map +1 -1
- 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 +15 -0
- package/dist/frontend/lowering/builtins/atomics.js +46 -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 +32 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +678 -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 +303 -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/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-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-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 +92 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +1646 -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 +419 -105
- 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 +580 -158
- 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 +589 -162
- 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 +274 -0
- package/dist/frontend/lowering/generic-functions.js +1727 -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/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 +420 -71
- 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 +2593 -5667
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +243 -242
- package/dist/frontend/lowering/lower-classes.js +1701 -724
- 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 +322 -85
- 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 +3446 -1154
- 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 +365 -273
- 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 +94 -94
- package/dist/frontend/lowering/lower-modules.js +612 -321
- 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 +2312 -984
- 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 +362 -90
- 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 +21 -351
- package/dist/frontend/lowering/lowerer.js +1024 -2704
- 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/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 +42 -42
- package/dist/frontend/lowering/surfaces.js +1094 -249
- 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-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-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 +234 -101
- 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 +484 -164
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +109 -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 +1 -1
- package/dist/frontend/ts7/ast-wire.js +55 -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.js +47 -28
- 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.js +5 -3
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +54 -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.js +7 -4
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/program-host.test.js +43 -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.js +545 -204
- 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/index.d.ts +9 -8
- package/dist/index.js +150 -81
- 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 +631 -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 +3396 -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 +6 -2150
- 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/runtime-features.d.ts +221 -0
- package/dist/ir/runtime-features.js +551 -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.js +4 -2
- 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 +782 -1889
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +610 -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 +133 -57
- 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 +232 -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 +24 -13
- 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 +167 -43
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +129 -32
- 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 +119 -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 +77 -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 +1 -1
- 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,30 @@ 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 { MAX_GENERIC_INSTANCES,
|
|
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 { MAX_GENERIC_INSTANCES, genericCallInstance, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, } from "./generic-functions.js";
|
|
11
|
+
import { appendImplicitUndefinedReturn, hasExplicitJsDocReturn } from "./function-returns.js";
|
|
12
|
+
import { bodyReadsArguments } from "../arguments-usage.js";
|
|
13
|
+
import { generatorMeta } from "./call-signatures.js";
|
|
14
|
+
import { omittedArgFor } from "./call-arguments.js";
|
|
15
|
+
import { isGenericCallableMemberType, jsOpenObjectType, typeKey, withUnitArm, } from "../type-mapper.js";
|
|
16
|
+
import { cjsClassExprWholeExportOf, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeTypesPath, locOf, } from "../program.js";
|
|
17
|
+
import { PoisonError, dynFallbackType, newFnCtx, own } from "./lowerer.js";
|
|
18
|
+
import { lowerArrayConstructor } from "./containers/array-construction.js";
|
|
19
|
+
import { lowerMapSeedNew, lowerSetSeedNew } from "./containers/collection-methods.js";
|
|
20
|
+
import { lowerObjectConstructor } from "./containers/indexed-objects.js";
|
|
14
21
|
import { bufEncoding } from "./containers/bytes.js";
|
|
15
22
|
import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
|
|
16
|
-
import { lowerSearchParamsNew
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
23
|
+
import { lowerSearchParamsNew } from "./builtins/url.js";
|
|
24
|
+
import { lowerTextCodecNew } from "./builtins/text-codecs.js";
|
|
25
|
+
import { requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
26
|
+
import { STREAM_API_MEMBERS, STREAM_PROP_MEMBERS, UNDERSCORE_METHODS, lowerStreamNew, lowerStreamSuperCall, streamCtorShape, } from "./lower-stream.js";
|
|
27
|
+
import { emitOverrideShapeReason, emitSpecSuperForward, emitterRooted, lowerEmitterSuperCall, } from "./lower-event-emitter.js";
|
|
20
28
|
import { declSymbolOf } from "./lower-modules.js";
|
|
21
|
-
import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName } from "./symbol-fields.js";
|
|
29
|
+
import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName, } from "./symbol-fields.js";
|
|
22
30
|
import { builtinFenceHintOf } from "./surfaces.js";
|
|
23
31
|
import { lowerHttpAgentNew, lowerHttpServerNew } from "./lower-server.js";
|
|
24
|
-
import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead } from "./lower-namespaces.js";
|
|
32
|
+
import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead, } from "./lower-namespaces.js";
|
|
25
33
|
import { mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
26
34
|
import { hasLexicalPrivateReference, hasStaticThis, rejectStaticThis } from "./static-this.js";
|
|
27
35
|
import { lowerUrlNew } from "./lower-url.js";
|
|
@@ -68,7 +76,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
68
76
|
visiting.add(expression);
|
|
69
77
|
if (ts.isParenthesizedExpression(expression))
|
|
70
78
|
return storedClassValueType(lowerer, expression.expression, visiting);
|
|
71
|
-
if (ts.isClassExpression(expression) &&
|
|
79
|
+
if (ts.isClassExpression(expression) &&
|
|
80
|
+
!functionLocalClass(expression) &&
|
|
81
|
+
!lowerer.collectingExprClasses.has(expression)) {
|
|
72
82
|
const info = lowerer.lowerClassExpressionInfo(expression);
|
|
73
83
|
return { kind: "classval", className: info.def.name };
|
|
74
84
|
}
|
|
@@ -87,7 +97,12 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
87
97
|
if (stored?.type.kind === "classval" && lowerer.classes.has(stored.type.className))
|
|
88
98
|
return stored.type;
|
|
89
99
|
const symbol = lowerer.resolveValueSymbol(expression);
|
|
90
|
-
const declaration = symbol &&
|
|
100
|
+
const declaration = symbol &&
|
|
101
|
+
lowerer.checker
|
|
102
|
+
.declarationsOf(symbol)
|
|
103
|
+
.find((decl) => ts.isVariableDeclaration(decl) &&
|
|
104
|
+
decl.initializer &&
|
|
105
|
+
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
91
106
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
92
107
|
const value = storedClassValueType(lowerer, declaration.initializer, visiting);
|
|
93
108
|
if (value?.kind === "classval")
|
|
@@ -100,7 +115,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
100
115
|
for (const signature of lowerer.checker.getConstructSignatures(type)) {
|
|
101
116
|
const constructor = lowerer.checker.signatureDeclaration(signature);
|
|
102
117
|
const declaration = constructor && ts.isConstructorDeclaration(constructor) ? constructor.parent : undefined;
|
|
103
|
-
if (declaration &&
|
|
118
|
+
if (declaration &&
|
|
119
|
+
ts.isClassExpression(declaration) &&
|
|
120
|
+
!functionLocalClass(declaration) &&
|
|
104
121
|
!lowerer.collectingExprClasses.has(declaration)) {
|
|
105
122
|
const info = lowerer.lowerClassExpressionInfo(declaration);
|
|
106
123
|
return { kind: "classval", className: info.def.name };
|
|
@@ -134,7 +151,12 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
134
151
|
}
|
|
135
152
|
if (ts.isIdentifier(callee)) {
|
|
136
153
|
const symbol = lowerer.resolveValueSymbol(callee);
|
|
137
|
-
const declaration = symbol &&
|
|
154
|
+
const declaration = symbol &&
|
|
155
|
+
lowerer.checker
|
|
156
|
+
.declarationsOf(symbol)
|
|
157
|
+
.find((decl) => ts.isVariableDeclaration(decl) &&
|
|
158
|
+
decl.initializer &&
|
|
159
|
+
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
138
160
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
139
161
|
callee = declaration.initializer;
|
|
140
162
|
continue;
|
|
@@ -142,13 +164,18 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
142
164
|
}
|
|
143
165
|
break;
|
|
144
166
|
}
|
|
145
|
-
if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) &&
|
|
146
|
-
|
|
167
|
+
if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) &&
|
|
168
|
+
isJsSourceFile(callee.getSourceFile()) &&
|
|
169
|
+
!callee.typeParameters?.length &&
|
|
170
|
+
!lowerer.preparingClassFactories.has(callee)) {
|
|
147
171
|
const signature = lowerer.checker.getSignatureFromDeclaration(callee);
|
|
148
172
|
let result = signature && lowerer.checker.getReturnTypeOfSignature(signature);
|
|
149
173
|
for (let i = 1; result && i < calls; i++) {
|
|
150
174
|
const signatures = lowerer.checker.getCallSignatures(result);
|
|
151
|
-
result =
|
|
175
|
+
result =
|
|
176
|
+
signatures.length === 1
|
|
177
|
+
? lowerer.checker.getReturnTypeOfSignature(signatures[0])
|
|
178
|
+
: undefined;
|
|
152
179
|
}
|
|
153
180
|
if (result && lowerer.checker.getConstructSignatures(result).length > 0) {
|
|
154
181
|
const returned = (value) => {
|
|
@@ -158,7 +185,9 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
158
185
|
return type.kind === "classval" ? type : null;
|
|
159
186
|
};
|
|
160
187
|
const home = callee.parent;
|
|
161
|
-
const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)
|
|
188
|
+
const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)
|
|
189
|
+
? lowerer.genericFnOf(home.name)
|
|
190
|
+
: null;
|
|
162
191
|
if (generic?.implicitParams && ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)) {
|
|
163
192
|
const factory = lowerer.lowerGenericFnValue(home.name, generic);
|
|
164
193
|
const type = returned(factory);
|
|
@@ -202,10 +231,15 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
202
231
|
break;
|
|
203
232
|
}
|
|
204
233
|
}
|
|
205
|
-
if (!factory ||
|
|
206
|
-
!
|
|
207
|
-
|
|
208
|
-
!ts.
|
|
234
|
+
if (!factory ||
|
|
235
|
+
!isJsSourceFile(factory.getSourceFile()) ||
|
|
236
|
+
factory.typeParameters?.length ||
|
|
237
|
+
!ts.isVariableDeclaration(factory.parent) ||
|
|
238
|
+
factory.parent.initializer !== factory ||
|
|
239
|
+
!ts.isVariableDeclarationList(factory.parent.parent) ||
|
|
240
|
+
!(factory.parent.parent.flags & ts.NodeFlags.Const) ||
|
|
241
|
+
!ts.isVariableStatement(factory.parent.parent.parent) ||
|
|
242
|
+
!ts.isSourceFile(factory.parent.parent.parent.parent) ||
|
|
209
243
|
lowerer.preparingClassFactories.has(factory))
|
|
210
244
|
continue;
|
|
211
245
|
if (!lowerer.preparedClassFactories.has(factory)) {
|
|
@@ -229,10 +263,10 @@ export function storedClassValueType(lowerer, expression, visiting = new Set())
|
|
|
229
263
|
return mapped;
|
|
230
264
|
}
|
|
231
265
|
/** The KEY symbol behind a LATE-BOUND (`__@name@id`) property: resolved
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
266
|
+
* from the argument of the element-access assignment that declared it
|
|
267
|
+
* (`this[kLimit] = v` — the declaration list holds the BinaryExpression
|
|
268
|
+
* or the ElementAccessExpression itself). Null when no declaration has
|
|
269
|
+
* that shape (well-known-symbol members like `[Symbol.iterator]`). */
|
|
236
270
|
function lateBoundKeySymOf(lowerer, p) {
|
|
237
271
|
for (const d of lowerer.checker.declarationsOf(p)) {
|
|
238
272
|
const access = ts.isBinaryExpression(d) && ts.isElementAccessExpression(d.left)
|
|
@@ -249,20 +283,20 @@ function lateBoundKeySymOf(lowerer, p) {
|
|
|
249
283
|
return null;
|
|
250
284
|
}
|
|
251
285
|
/** 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
|
-
|
|
286
|
+
* late-bound property for a JS class's `this[k] = v` declaration (the
|
|
287
|
+
* finding-5 family), so an unannotated method whose returns read a
|
|
288
|
+
* declared symbol-keyed slot infers `any` — the checked-dynamic
|
|
289
|
+
* fallback would box a value whose static type the class layout already
|
|
290
|
+
* knows (5.9.3 inferred it through the late-bound property; runtime
|
|
291
|
+
* output was identical either way, but the method ABI carried a dyn
|
|
292
|
+
* box). Recovered here from the layout itself, under a shape that
|
|
293
|
+
* cannot mis-type: an unannotated, non-async, non-generator JS method
|
|
294
|
+
* whose LAST top-level statement is a return (no fall-through
|
|
295
|
+
* `undefined` completion), where EVERY return statement (nested
|
|
296
|
+
* functions excluded — they return elsewhere) returns `this[k]` with a
|
|
297
|
+
* statically-resolved key declared in symbolFields, and all the slots
|
|
298
|
+
* agree on one IR type. Null when the shape doesn't hold — the value
|
|
299
|
+
* stays checked-dynamic exactly as before. */
|
|
266
300
|
function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
267
301
|
if (symbolFields.size === 0)
|
|
268
302
|
return null;
|
|
@@ -308,12 +342,12 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
|
308
342
|
return out;
|
|
309
343
|
}
|
|
310
344
|
/** The builtin Error hierarchy
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
345
|
+
* as eagerly-registered ClassInfos: mapType names them the moment a lib
|
|
346
|
+
* Error type appears, so the infos must exist before any lowering. They
|
|
347
|
+
* are runtime-provided — no decl, no lowerable bodies; `new`/super()/
|
|
348
|
+
* toString reach them through dedicated error.* libCall lowerings, and
|
|
349
|
+
* user classes extend them like any base (the emitted subclass struct
|
|
350
|
+
* embeds ScrError's prefix). */
|
|
317
351
|
export function registerBuiltinErrorClasses(lowerer) {
|
|
318
352
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
319
353
|
for (const [irName, rec] of RUNTIME_ERROR_CLASSES) {
|
|
@@ -363,7 +397,10 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
363
397
|
ctor: null,
|
|
364
398
|
// Inherited constructors forward both raw arguments. The runtime
|
|
365
399
|
// applies the undefined message default and InstallErrorCause.
|
|
366
|
-
ctorParams: [
|
|
400
|
+
ctorParams: [
|
|
401
|
+
{ type: DYN, mode: "omittable" },
|
|
402
|
+
{ type: DYN, mode: "omittable" },
|
|
403
|
+
],
|
|
367
404
|
base,
|
|
368
405
|
subclasses: [],
|
|
369
406
|
throwingSetters: [],
|
|
@@ -375,14 +412,14 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
375
412
|
}
|
|
376
413
|
}
|
|
377
414
|
/** The runtime-provided node:events EventEmitter as an eagerly-registered
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
415
|
+
* ClassInfo (the error-hierarchy story): mapType names `%EventEmitter`
|
|
416
|
+
* the moment an emitter type appears, so the info must exist before any
|
|
417
|
+
* lowering. No decl, no lowerable bodies — `new`/super() reach it
|
|
418
|
+
* through emitter.* libCalls, the method surface lowers through
|
|
419
|
+
* lower-event-emitter.ts, and user classes extend it like any base (the
|
|
420
|
+
* emitted subclass struct embeds ScrEmitter's registry/name prefix —
|
|
421
|
+
* carried by the BACKEND, not by IR fields, so the fields list stays
|
|
422
|
+
* empty and subclass field layout starts right after the prefix). */
|
|
386
423
|
export function registerBuiltinEmitterClass(lowerer) {
|
|
387
424
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
388
425
|
const info = {
|
|
@@ -404,13 +441,13 @@ export function registerBuiltinEmitterClass(lowerer) {
|
|
|
404
441
|
lowerer.classes.set(RUNTIME_EMITTER_CLASS, info);
|
|
405
442
|
}
|
|
406
443
|
/** The runtime-provided node:stream classes as eagerly-registered
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
444
|
+
* ClassInfos (the emitter story): mapType names `%Readable` et al the
|
|
445
|
+
* moment a stream type appears, so the infos must exist before any
|
|
446
|
+
* lowering. Each roots at the emitter through its base chain, so the
|
|
447
|
+
* EventEmitter method surface, upcasts, and instanceof intervals apply
|
|
448
|
+
* unchanged; the stream method/property surface lowers through
|
|
449
|
+
* lower-stream.ts. No decl, no lowerable bodies, empty field lists —
|
|
450
|
+
* every instance is runtime-allocated (user `extends` is fenced). */
|
|
414
451
|
export function registerBuiltinStreamClasses(lowerer) {
|
|
415
452
|
const loc = { file: "<builtin>", start: 0, end: 0 };
|
|
416
453
|
for (const [irName, rec] of RUNTIME_STREAM_CLASSES) {
|
|
@@ -437,12 +474,12 @@ export function registerBuiltinStreamClasses(lowerer) {
|
|
|
437
474
|
}
|
|
438
475
|
}
|
|
439
476
|
/** The stream ClassInfo a VALUE symbol refers to (`new Readable(...)`,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
477
|
+
* `x instanceof Writable`) — any import spelling resolves to the
|
|
478
|
+
* ambient class. Provenance: a stdlib-file CLASS declaration inside the
|
|
479
|
+
* "stream" ambient module, EXCLUDING @types/node's (whose stream.Readable
|
|
480
|
+
* also types child stdio — under @types/node the childStream mapping
|
|
481
|
+
* keeps priority and the static stream classes stand down; the shipped
|
|
482
|
+
* fallback declarations are the supported surface). */
|
|
446
483
|
export function builtinStreamInfoOf(lowerer, symbol) {
|
|
447
484
|
if (!symbol)
|
|
448
485
|
return null;
|
|
@@ -454,7 +491,8 @@ export function builtinStreamInfoOf(lowerer, symbol) {
|
|
|
454
491
|
// alias plumbing (streamClassAliasDecl — both declaration walks
|
|
455
492
|
// skip it).
|
|
456
493
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
457
|
-
if (decl &&
|
|
494
|
+
if (decl &&
|
|
495
|
+
ts.isVariableDeclaration(decl) &&
|
|
458
496
|
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 &&
|
|
459
497
|
decl.initializer !== undefined &&
|
|
460
498
|
ts.isPropertyAccessExpression(decl.initializer) &&
|
|
@@ -495,8 +533,12 @@ export function builtinStreamInfoOf(lowerer, symbol) {
|
|
|
495
533
|
function jsFieldInitializerType(lowerer, type, expression) {
|
|
496
534
|
if (ts.isIdentifier(expression)) {
|
|
497
535
|
const symbol = lowerer.checker.getSymbolAtLocation(expression);
|
|
498
|
-
if (symbol &&
|
|
499
|
-
|
|
536
|
+
if (symbol &&
|
|
537
|
+
lowerer.checker
|
|
538
|
+
.declarationsOf(symbol)
|
|
539
|
+
.some((decl) => ts.isParameter(decl) &&
|
|
540
|
+
(ts.isConstructorDeclaration(decl.parent) ||
|
|
541
|
+
(lowerer.typeOf(expression).flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0)))
|
|
500
542
|
return DYN;
|
|
501
543
|
}
|
|
502
544
|
if (type.kind === "array" || type.kind === "record")
|
|
@@ -507,17 +549,25 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
507
549
|
if (type.kind === "f64" && isJsSourceFile(expression.getSourceFile())) {
|
|
508
550
|
const assignment = expression.parent;
|
|
509
551
|
const left = ts.isBinaryExpression(assignment) ? assignment.left : null;
|
|
510
|
-
const field = left &&
|
|
552
|
+
const field = left &&
|
|
553
|
+
ts.isPropertyAccessExpression(left) &&
|
|
554
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword
|
|
555
|
+
? left.name.text
|
|
556
|
+
: null;
|
|
511
557
|
let owner = expression.parent;
|
|
512
558
|
while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
|
|
513
559
|
owner = owner.parent;
|
|
514
560
|
if (field && owner) {
|
|
515
561
|
let acceptsUnchecked = false;
|
|
516
562
|
const scan = (node) => {
|
|
517
|
-
if (acceptsUnchecked ||
|
|
563
|
+
if (acceptsUnchecked ||
|
|
564
|
+
(node !== owner && (ts.isClassDeclaration(node) || ts.isClassExpression(node))))
|
|
518
565
|
return;
|
|
519
|
-
if (ts.isBinaryExpression(node) &&
|
|
520
|
-
|
|
566
|
+
if (ts.isBinaryExpression(node) &&
|
|
567
|
+
node.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
568
|
+
ts.isPropertyAccessExpression(node.left) &&
|
|
569
|
+
node.left.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
570
|
+
node.left.name.text === field) {
|
|
521
571
|
let rhs = node.right;
|
|
522
572
|
while (ts.isParenthesizedExpression(rhs))
|
|
523
573
|
rhs = rhs.expression;
|
|
@@ -538,14 +588,17 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
538
588
|
let prototypeArgument = false;
|
|
539
589
|
for (const argument of node.arguments)
|
|
540
590
|
ts.walkPreorder(argument, (part) => {
|
|
541
|
-
if (!ts.isPropertyAccessExpression(part) ||
|
|
591
|
+
if (!ts.isPropertyAccessExpression(part) ||
|
|
592
|
+
part.expression.kind !== ts.SyntaxKind.ThisKeyword)
|
|
542
593
|
return;
|
|
543
594
|
const symbol = lowerer.checker.getSymbolAtLocation(part.name);
|
|
544
|
-
if (symbol &&
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
member
|
|
548
|
-
|
|
595
|
+
if (symbol &&
|
|
596
|
+
lowerer.checker.declarationsOf(symbol).some((decl) => {
|
|
597
|
+
const member = ts.isBinaryExpression(decl) ? decl.left : decl;
|
|
598
|
+
return (ts.isPropertyAccessExpression(member) &&
|
|
599
|
+
ts.isPropertyAccessExpression(member.expression) &&
|
|
600
|
+
member.expression.name.text === "prototype");
|
|
601
|
+
}))
|
|
549
602
|
prototypeArgument = true;
|
|
550
603
|
// JS checkers can synthesize a property declaration for prototype
|
|
551
604
|
// assignments. Keep the source ownership proof when that happens.
|
|
@@ -555,12 +608,17 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
555
608
|
if (owner && (ts.isClassDeclaration(owner) || ts.isClassExpression(owner)) && owner.name) {
|
|
556
609
|
const className = owner.name.text;
|
|
557
610
|
for (const statement of owner.getSourceFile().statements) {
|
|
558
|
-
if (!ts.isExpressionStatement(statement) ||
|
|
611
|
+
if (!ts.isExpressionStatement(statement) ||
|
|
612
|
+
!ts.isBinaryExpression(statement.expression))
|
|
559
613
|
continue;
|
|
560
614
|
const left = statement.expression.left;
|
|
561
|
-
if (statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
562
|
-
|
|
563
|
-
|
|
615
|
+
if (statement.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
616
|
+
ts.isPropertyAccessExpression(left) &&
|
|
617
|
+
left.name.text === part.name.text &&
|
|
618
|
+
ts.isPropertyAccessExpression(left.expression) &&
|
|
619
|
+
left.expression.name.text === "prototype" &&
|
|
620
|
+
ts.isIdentifier(left.expression.expression) &&
|
|
621
|
+
left.expression.expression.text === className)
|
|
564
622
|
prototypeArgument = true;
|
|
565
623
|
}
|
|
566
624
|
}
|
|
@@ -572,7 +630,7 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
572
630
|
}
|
|
573
631
|
if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
|
|
574
632
|
const ret = lowerer.declaredReturnType(node, node);
|
|
575
|
-
const arms = type.kind === "union" ? lowerer.unions.get(type.unionId)?.arms ?? [] : [type];
|
|
633
|
+
const arms = type.kind === "union" ? (lowerer.unions.get(type.unionId)?.arms ?? []) : [type];
|
|
576
634
|
// Inferred arithmetic may return a checked Number or BigInt. Preserve
|
|
577
635
|
// the callable when its native return ABI differs from the checker slot.
|
|
578
636
|
if (arms.some((arm) => arm.kind === "func" && !typeEquals(arm.ret, ret)))
|
|
@@ -581,13 +639,22 @@ function jsFieldInitializerType(lowerer, type, expression) {
|
|
|
581
639
|
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
582
640
|
return withUnitArm(type, "nullT", lowerer.unions) ?? type;
|
|
583
641
|
const inferred = lowerer.typeOf(node);
|
|
584
|
-
const scalar = (inferred.flags & ts.TypeFlags.BooleanLike) !== 0
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
642
|
+
const scalar = (inferred.flags & ts.TypeFlags.BooleanLike) !== 0
|
|
643
|
+
? "bool"
|
|
644
|
+
: (inferred.flags & ts.TypeFlags.NumberLike) !== 0
|
|
645
|
+
? "f64"
|
|
646
|
+
: (inferred.flags & ts.TypeFlags.StringLike) !== 0
|
|
647
|
+
? "string"
|
|
648
|
+
: (inferred.flags & ts.TypeFlags.BigIntLike) !== 0
|
|
649
|
+
? "bigint"
|
|
650
|
+
: (inferred.flags & ts.TypeFlags.ESSymbolLike) !== 0
|
|
651
|
+
? "symbol"
|
|
652
|
+
: null;
|
|
653
|
+
if (scalar &&
|
|
654
|
+
type.kind !== "dyn" &&
|
|
655
|
+
type.kind !== scalar &&
|
|
656
|
+
!(type.kind === "union" &&
|
|
657
|
+
lowerer.unions.get(type.unionId)?.arms.some((arm) => arm.kind === scalar)))
|
|
591
658
|
return DYN;
|
|
592
659
|
for (const arm of inferred.isUnionType() ? ts.constituentTypes(inferred) : [inferred]) {
|
|
593
660
|
if ((arm.flags & ts.TypeFlags.Undefined) !== 0)
|
|
@@ -618,7 +685,10 @@ function inheritedJsFieldType(lowerer, decl, name, type) {
|
|
|
618
685
|
return type;
|
|
619
686
|
}
|
|
620
687
|
function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
621
|
-
if (!isJsSourceFile(member.getSourceFile()) ||
|
|
688
|
+
if (!isJsSourceFile(member.getSourceFile()) ||
|
|
689
|
+
member.type ||
|
|
690
|
+
member.asteriskToken ||
|
|
691
|
+
hasExplicitJsDocReturn(member))
|
|
622
692
|
return false;
|
|
623
693
|
const widened = (expression) => {
|
|
624
694
|
if (ts.isParenthesizedExpression(expression))
|
|
@@ -627,22 +697,38 @@ function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
|
627
697
|
return widened(expression.whenTrue) || widened(expression.whenFalse);
|
|
628
698
|
if (ts.isCallExpression(expression)) {
|
|
629
699
|
const callee = expression.expression;
|
|
630
|
-
const symbol = ts.isPropertyAccessExpression(callee)
|
|
631
|
-
|
|
700
|
+
const symbol = ts.isPropertyAccessExpression(callee)
|
|
701
|
+
? lowerer.checker.getSymbolAtLocation(callee.name)
|
|
702
|
+
: ts.isElementAccessExpression(callee)
|
|
703
|
+
? lowerer.checker.getPropertyOfType(lowerer.typeOf(callee.expression), lowerer.foldedStringKeyOf(callee.argumentExpression) ?? "")
|
|
632
704
|
: undefined;
|
|
633
|
-
if (symbol &&
|
|
705
|
+
if (symbol &&
|
|
706
|
+
lowerer.checker
|
|
707
|
+
.declarationsOf(symbol)
|
|
708
|
+
.some((declaration) => ts.isMethodDeclaration(declaration) &&
|
|
709
|
+
lowerer.checkedVirtualJsMethods.has(declaration)))
|
|
634
710
|
return true;
|
|
635
711
|
}
|
|
636
|
-
const name = ts.isPropertyAccessExpression(expression)
|
|
637
|
-
|
|
712
|
+
const name = ts.isPropertyAccessExpression(expression)
|
|
713
|
+
? expression.name.text
|
|
714
|
+
: ts.isElementAccessExpression(expression)
|
|
715
|
+
? lowerer.foldedStringKeyOf(expression.argumentExpression)
|
|
716
|
+
: null;
|
|
638
717
|
if (ts.isPropertyAccessExpression(expression)) {
|
|
639
718
|
const symbol = lowerer.checker.getSymbolAtLocation(expression.name);
|
|
640
|
-
if (symbol &&
|
|
719
|
+
if (symbol &&
|
|
720
|
+
lowerer.checker
|
|
721
|
+
.declarationsOf(symbol)
|
|
722
|
+
.some((declaration) => (ts.isGetAccessorDeclaration(declaration) ||
|
|
723
|
+
ts.isSetAccessorDeclaration(declaration)) &&
|
|
724
|
+
lowerer.checkedVirtualJsAccessors.has(declaration)))
|
|
641
725
|
return true;
|
|
642
726
|
}
|
|
643
|
-
if (name !== null &&
|
|
727
|
+
if (name !== null &&
|
|
728
|
+
(ts.isPropertyAccessExpression(expression) || ts.isElementAccessExpression(expression)) &&
|
|
644
729
|
expression.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
645
|
-
return fields.get(name)?.kind === "dyn" ||
|
|
730
|
+
return (fields.get(name)?.kind === "dyn" ||
|
|
731
|
+
inheritedJsFieldType(lowerer, decl, name, ret).kind === "dyn");
|
|
646
732
|
}
|
|
647
733
|
return false;
|
|
648
734
|
};
|
|
@@ -659,10 +745,10 @@ function returnsWidenedJsField(lowerer, decl, member, fields, ret) {
|
|
|
659
745
|
return result;
|
|
660
746
|
}
|
|
661
747
|
/** The undefined-armed union of a JS class property's inferred type — the
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
748
|
+
* honest slot for a field first assigned outside the constructor's top
|
|
749
|
+
* level (undefined until the write runs, Node-exact). Null when the
|
|
750
|
+
* inference is unmappable or an arm-less kind that cannot join a union
|
|
751
|
+
* (genResultRecord's list, including scalar-backed Date values). */
|
|
666
752
|
function undefArmedFieldType(lowerer, p) {
|
|
667
753
|
const t = lowerer.checker.getTypeOfSymbol(p);
|
|
668
754
|
const site = lowerer.checker.declarationsOf(p)[0];
|
|
@@ -673,7 +759,9 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
673
759
|
return null;
|
|
674
760
|
for (const declaration of lowerer.checker.declarationsOf(p)) {
|
|
675
761
|
const assignment = ts.isBinaryExpression(declaration) ? declaration : declaration.parent;
|
|
676
|
-
if (assignment &&
|
|
762
|
+
if (assignment &&
|
|
763
|
+
ts.isBinaryExpression(assignment) &&
|
|
764
|
+
assignment.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
677
765
|
mapped = jsFieldInitializerType(lowerer, mapped, assignment.right);
|
|
678
766
|
}
|
|
679
767
|
}
|
|
@@ -683,8 +771,11 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
683
771
|
const byKey = new Map();
|
|
684
772
|
const arms = mapped.kind === "union" ? (lowerer.unions.get(mapped.unionId)?.arms ?? []) : [mapped];
|
|
685
773
|
for (const a of arms) {
|
|
686
|
-
if (a.kind === "map" ||
|
|
687
|
-
a.kind === "
|
|
774
|
+
if (a.kind === "map" ||
|
|
775
|
+
a.kind === "regex" ||
|
|
776
|
+
a.kind === "date" ||
|
|
777
|
+
a.kind === "jsval" ||
|
|
778
|
+
a.kind === "generator") {
|
|
688
779
|
return null;
|
|
689
780
|
}
|
|
690
781
|
byKey.set(typeKey(a), a);
|
|
@@ -694,10 +785,10 @@ function undefArmedFieldType(lowerer, p) {
|
|
|
694
785
|
return { kind: "union", unionId: lowerer.unions.intern(sorted) };
|
|
695
786
|
}
|
|
696
787
|
/** The emitter ClassInfo a VALUE symbol refers to (`new EventEmitter`,
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
788
|
+
* `extends EventEmitter`, `x instanceof EventEmitter`) — any import
|
|
789
|
+
* spelling (named/default/namespace member, CJS require) resolves to
|
|
790
|
+
* the ambient class. Provenance-checked like the error classes: only a
|
|
791
|
+
* stdlib-file declaration inside the "events" ambient module counts. */
|
|
701
792
|
export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
702
793
|
if (!symbol)
|
|
703
794
|
return null;
|
|
@@ -709,7 +800,8 @@ export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
|
709
800
|
// itself is alias plumbing (builtinMemberRequireDecl — both
|
|
710
801
|
// declaration walks skip it).
|
|
711
802
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
712
|
-
if (decl !== undefined &&
|
|
803
|
+
if (decl !== undefined &&
|
|
804
|
+
ts.isVariableDeclaration(decl) &&
|
|
713
805
|
(ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0 &&
|
|
714
806
|
decl.initializer !== undefined &&
|
|
715
807
|
ts.isPropertyAccessExpression(decl.initializer) &&
|
|
@@ -737,9 +829,9 @@ export function builtinEmitterInfoOf(lowerer, symbol) {
|
|
|
737
829
|
return declared ? (lowerer.classes.get(RUNTIME_EMITTER_CLASS) ?? null) : null;
|
|
738
830
|
}
|
|
739
831
|
/** The builtin error ClassInfo a VALUE symbol refers to (`new Error`,
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
832
|
+
* `extends TypeError`, `x instanceof RangeError`), or null. Provenance-
|
|
833
|
+
* checked: only the standard library's declarations count — a user's own
|
|
834
|
+
* `class Error` resolves through classBySymbol instead. */
|
|
743
835
|
export function builtinErrorInfoOf(lowerer, symbol) {
|
|
744
836
|
if (!symbol || !lowerer.isStdlibSymbol(symbol))
|
|
745
837
|
return null;
|
|
@@ -753,22 +845,34 @@ export function builtinErrorInfoOf(lowerer, symbol) {
|
|
|
753
845
|
* members with these names are fenced (collectClassShapeInner) and calls
|
|
754
846
|
* to them on emitter-rooted receivers lower through lower-event-emitter.ts. */
|
|
755
847
|
export const EMITTER_API_MEMBERS = new Set([
|
|
756
|
-
"on",
|
|
757
|
-
"
|
|
758
|
-
"
|
|
848
|
+
"on",
|
|
849
|
+
"addListener",
|
|
850
|
+
"once",
|
|
851
|
+
"prependListener",
|
|
852
|
+
"prependOnceListener",
|
|
853
|
+
"off",
|
|
854
|
+
"removeListener",
|
|
855
|
+
"removeAllListeners",
|
|
856
|
+
"emit",
|
|
857
|
+
"listenerCount",
|
|
858
|
+
"listeners",
|
|
859
|
+
"rawListeners",
|
|
860
|
+
"eventNames",
|
|
861
|
+
"setMaxListeners",
|
|
862
|
+
"getMaxListeners",
|
|
759
863
|
]);
|
|
760
864
|
/** The decorators of a class-like or member node (they live in
|
|
761
|
-
|
|
865
|
+
* `modifiers` since TS 4.8). */
|
|
762
866
|
export function decoratorNodesOf(n) {
|
|
763
867
|
return (n.modifiers ?? []).filter((m) => m.kind === ts.SyntaxKind.Decorator);
|
|
764
868
|
}
|
|
765
869
|
/** The AMBIENT name a decorator expression's evaluation throws on, or
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
870
|
+
* null. Node erases ambient declarations (`declare let dec: any`,
|
|
871
|
+
* `declare const instance: T`, `declare function dec<T>(t: T): T`), so
|
|
872
|
+
* reading the name is a ReferenceError. Factory spellings ride along —
|
|
873
|
+
* `@dec(...)` evaluates the CALLEE before any argument — and property
|
|
874
|
+
* chains throw at their ROOT (`@instance.decorate` reads `instance`
|
|
875
|
+
* first). */
|
|
772
876
|
function ambientDecoratorThrowNameOf(lowerer, dExpr) {
|
|
773
877
|
let e = dExpr;
|
|
774
878
|
while (ts.isParenthesizedExpression(e))
|
|
@@ -785,16 +889,16 @@ function ambientDecoratorThrowNameOf(lowerer, dExpr) {
|
|
|
785
889
|
return null;
|
|
786
890
|
}
|
|
787
891
|
/** The guaranteed decoration THROW of a decorated class, or null. Walks
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
892
|
+
* the class definition's evaluation-order items — class decorators
|
|
893
|
+
* (source order), the heritage expression, then per member in body
|
|
894
|
+
* order its decorators and computed key (the verified TC39/tsc-downlevel
|
|
895
|
+
* order) — and answers the first AMBIENT decorator name, provided every
|
|
896
|
+
* item BEFORE it is provably effect-free and non-throwing: bare
|
|
897
|
+
* identifier decorators over defined values (a pure read), an absent /
|
|
898
|
+
* `null` / bare-identifier heritage, literal or bare-identifier
|
|
899
|
+
* computed keys. Anything richer (factory calls over defined values,
|
|
900
|
+
* property-access reads, computed-key calls) stops the proof — the
|
|
901
|
+
* named fences answer instead. */
|
|
798
902
|
export function guaranteedDecorationThrow(lowerer, decl) {
|
|
799
903
|
const stripParens = (e) => {
|
|
800
904
|
let x = e;
|
|
@@ -819,8 +923,7 @@ export function guaranteedDecorationThrow(lowerer, decl) {
|
|
|
819
923
|
if (v !== "effectFree")
|
|
820
924
|
return v;
|
|
821
925
|
}
|
|
822
|
-
const heritage = decl.heritageClauses
|
|
823
|
-
?.find((c) => c.token === ts.SyntaxKind.ExtendsKeyword)
|
|
926
|
+
const heritage = decl.heritageClauses?.find((c) => c.token === ts.SyntaxKind.ExtendsKeyword)
|
|
824
927
|
?.types[0];
|
|
825
928
|
if (heritage) {
|
|
826
929
|
const h = stripParens(heritage.expression);
|
|
@@ -898,7 +1001,9 @@ export function collectClassShape(lowerer, decl) {
|
|
|
898
1001
|
}
|
|
899
1002
|
}
|
|
900
1003
|
function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
901
|
-
if (!ts.isNewExpression(initializer) ||
|
|
1004
|
+
if (!ts.isNewExpression(initializer) ||
|
|
1005
|
+
(initializer.arguments?.length ?? 0) !== 0 ||
|
|
1006
|
+
!ts.isIdentifier(initializer.expression))
|
|
902
1007
|
return null;
|
|
903
1008
|
const collection = initializer.expression.text;
|
|
904
1009
|
if (collection !== "Map" && collection !== "Set")
|
|
@@ -912,7 +1017,11 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
912
1017
|
const mappedArgument = (argument) => {
|
|
913
1018
|
const type = lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(argument));
|
|
914
1019
|
const mapped = lowerer.mapTypeOf(type);
|
|
915
|
-
if (!mapped ||
|
|
1020
|
+
if (!mapped ||
|
|
1021
|
+
mapped.kind === "dyn" ||
|
|
1022
|
+
mapped.kind === "jsval" ||
|
|
1023
|
+
mapped.kind === "void" ||
|
|
1024
|
+
isUnitType(mapped))
|
|
916
1025
|
return null;
|
|
917
1026
|
return mapped;
|
|
918
1027
|
};
|
|
@@ -927,19 +1036,27 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
927
1036
|
receiver.name.text !== field) {
|
|
928
1037
|
return undefined;
|
|
929
1038
|
}
|
|
930
|
-
if (collection === "Map" &&
|
|
1039
|
+
if (collection === "Map" &&
|
|
1040
|
+
node.expression.name.text === "set" &&
|
|
1041
|
+
node.arguments.length === 2) {
|
|
931
1042
|
const key = mappedArgument(node.arguments[0]);
|
|
932
1043
|
const value = mappedArgument(node.arguments[1]);
|
|
933
|
-
if (key !== null &&
|
|
1044
|
+
if (key !== null &&
|
|
1045
|
+
value !== null &&
|
|
1046
|
+
isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) &&
|
|
1047
|
+
isSupportedMapValue(value)) {
|
|
934
1048
|
mapKeys.push(key);
|
|
935
1049
|
mapValues.push(value);
|
|
936
1050
|
}
|
|
937
1051
|
}
|
|
938
1052
|
if (collection === "Set" &&
|
|
939
|
-
(node.expression.name.text === "add" ||
|
|
1053
|
+
(node.expression.name.text === "add" ||
|
|
1054
|
+
node.expression.name.text === "has" ||
|
|
1055
|
+
node.expression.name.text === "delete") &&
|
|
940
1056
|
node.arguments.length === 1) {
|
|
941
1057
|
const element = mappedArgument(node.arguments[0]);
|
|
942
|
-
if (element !== null &&
|
|
1058
|
+
if (element !== null &&
|
|
1059
|
+
isSupportedSetElem(element, element.kind === "union" ? lowerer.unions.get(element.unionId)?.arms : undefined))
|
|
943
1060
|
setElements.push(element);
|
|
944
1061
|
}
|
|
945
1062
|
return undefined;
|
|
@@ -1008,8 +1125,10 @@ mixin) {
|
|
|
1008
1125
|
// The guaranteed-throw SHELL: declarations only (expressions
|
|
1009
1126
|
// lower their throw at the expression — lowerClassExpression),
|
|
1010
1127
|
// never instantiations/mixins (they share a family declaration).
|
|
1011
|
-
if (inst === undefined &&
|
|
1012
|
-
|
|
1128
|
+
if (inst === undefined &&
|
|
1129
|
+
mixin === undefined &&
|
|
1130
|
+
ts.isClassDeclaration(decl) &&
|
|
1131
|
+
decl.typeParameters === undefined) {
|
|
1013
1132
|
const thrown = guaranteedDecorationThrow(lowerer, decl);
|
|
1014
1133
|
if (thrown) {
|
|
1015
1134
|
const className = lowerer.classNamer(decl);
|
|
@@ -1055,9 +1174,9 @@ mixin) {
|
|
|
1055
1174
|
: ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)
|
|
1056
1175
|
? "accessor decorators"
|
|
1057
1176
|
: ts.isPropertyDeclaration(member)
|
|
1058
|
-
?
|
|
1177
|
+
? member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AccessorKeyword)
|
|
1059
1178
|
? "auto-accessor decorators"
|
|
1060
|
-
: "field decorators"
|
|
1179
|
+
: "field decorators"
|
|
1061
1180
|
: "member decorators";
|
|
1062
1181
|
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
1182
|
}
|
|
@@ -1100,22 +1219,35 @@ mixin) {
|
|
|
1100
1219
|
// base is its family (whose base is the declared one) — the heritage
|
|
1101
1220
|
// clause resolved when the family collected.
|
|
1102
1221
|
const computedBase = lowerer.computedClassBases.get(lowerer.classNamer(decl));
|
|
1103
|
-
let base = inst
|
|
1222
|
+
let base = inst
|
|
1223
|
+
? inst.family
|
|
1224
|
+
: mixin
|
|
1225
|
+
? mixin.base
|
|
1226
|
+
: (computedBase?.classInfo ?? null);
|
|
1104
1227
|
let callableBase;
|
|
1105
1228
|
let factoryBaseExpression;
|
|
1106
1229
|
const adoptCallableBase = (expression) => {
|
|
1107
1230
|
if (familyMode || inst || mixin)
|
|
1108
1231
|
return false;
|
|
1109
1232
|
if (lowerer.computedCallableBases.has(decl)) {
|
|
1110
|
-
callableBase = {
|
|
1233
|
+
callableBase = {
|
|
1234
|
+
expression,
|
|
1235
|
+
constructorId: `%g.${className}.base`,
|
|
1236
|
+
prototypeId: `%g.${className}.basePrototype`,
|
|
1237
|
+
};
|
|
1111
1238
|
return true;
|
|
1112
1239
|
}
|
|
1113
1240
|
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(expression));
|
|
1114
1241
|
const source = signatures.length === 1 ? lowerer.checker.signatureDeclaration(signatures[0]) : undefined;
|
|
1115
|
-
if (!source ||
|
|
1242
|
+
if (!source ||
|
|
1243
|
+
!isJsSourceFile(source.getSourceFile()) ||
|
|
1116
1244
|
!(ts.isFunctionDeclaration(source) || ts.isFunctionExpression(source)))
|
|
1117
1245
|
return false;
|
|
1118
|
-
callableBase = {
|
|
1246
|
+
callableBase = {
|
|
1247
|
+
expression,
|
|
1248
|
+
constructorId: `%g.${className}.base`,
|
|
1249
|
+
prototypeId: `%g.${className}.basePrototype`,
|
|
1250
|
+
};
|
|
1119
1251
|
return true;
|
|
1120
1252
|
};
|
|
1121
1253
|
// A family whose `extends` clause mentions its OWN type parameters
|
|
@@ -1163,8 +1295,10 @@ mixin) {
|
|
|
1163
1295
|
const resolved = memberSym && memberSym.flags & ts.SymbolFlags.Alias
|
|
1164
1296
|
? lowerer.checker.getAliasedSymbol(memberSym)
|
|
1165
1297
|
: memberSym;
|
|
1166
|
-
const globalError = !t.expression.questionDotToken &&
|
|
1167
|
-
|
|
1298
|
+
const globalError = !t.expression.questionDotToken &&
|
|
1299
|
+
lowerer.isStdlibGlobal(t.expression.expression, "globalThis")
|
|
1300
|
+
? lowerer.builtinErrorInfoOf(resolved)
|
|
1301
|
+
: null;
|
|
1168
1302
|
if (globalError && globalError.def.name !== "%DOMException") {
|
|
1169
1303
|
if (t.typeArguments)
|
|
1170
1304
|
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
@@ -1231,8 +1365,7 @@ mixin) {
|
|
|
1231
1365
|
const rebinds = memberSym !== undefined &&
|
|
1232
1366
|
lowerer.checker
|
|
1233
1367
|
.declarationsOf(memberSym)
|
|
1234
|
-
.filter((d) => ts.isBinaryExpression(d) &&
|
|
1235
|
-
d.operatorToken.kind === ts.SyntaxKind.EqualsToken).length > 1;
|
|
1368
|
+
.filter((d) => ts.isBinaryExpression(d) && d.operatorToken.kind === ts.SyntaxKind.EqualsToken).length > 1;
|
|
1236
1369
|
if (rebinds) {
|
|
1237
1370
|
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
1371
|
}
|
|
@@ -1295,8 +1428,10 @@ mixin) {
|
|
|
1295
1428
|
if (lowerer.builtinErrorInfoOf(symbol)?.def.name === "%DOMException") {
|
|
1296
1429
|
lowerer.unsupported("SC1090", t, "extending DOMException (its runtime layout carries hidden slots a subclass would overlap — extend Error and set name/code yourself)");
|
|
1297
1430
|
}
|
|
1298
|
-
const named = (symbol && lowerer.classBySymbol.get(symbol)) ??
|
|
1299
|
-
lowerer.
|
|
1431
|
+
const named = (symbol && lowerer.classBySymbol.get(symbol)) ??
|
|
1432
|
+
lowerer.builtinErrorInfoOf(symbol) ??
|
|
1433
|
+
lowerer.builtinEmitterInfoOf(symbol) ??
|
|
1434
|
+
builtinStreamInfoOf(lowerer, symbol) ??
|
|
1300
1435
|
// A const BINDING holding exactly one class (`const B = Animal`,
|
|
1301
1436
|
// `const B = class {…}`): the base is that class — extends
|
|
1302
1437
|
// through the alias is the declaration story (a general class
|
|
@@ -1314,7 +1449,8 @@ mixin) {
|
|
|
1314
1449
|
(() => {
|
|
1315
1450
|
const stored = storedClassValueType(lowerer, t.expression);
|
|
1316
1451
|
return stored?.kind === "classval" ? lowerer.classes.get(stored.className) : null;
|
|
1317
|
-
})() ??
|
|
1452
|
+
})() ??
|
|
1453
|
+
null;
|
|
1318
1454
|
// `extends Box<number>` — a GENERIC program class as the base: the
|
|
1319
1455
|
// base is the concrete INSTANTIATION, resolved through the heritage
|
|
1320
1456
|
// type (mapType registers/reuses `Box%0`).
|
|
@@ -1397,10 +1533,16 @@ mixin) {
|
|
|
1397
1533
|
const runtimePrototypeMembers = [];
|
|
1398
1534
|
// Public JS accessors need live constructor descriptors, including
|
|
1399
1535
|
// receiver-sensitive getters and setters inherited by subclasses.
|
|
1400
|
-
const checkedStatics = isJsSourceFile(decl.getSourceFile()) &&
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1536
|
+
const checkedStatics = isJsSourceFile(decl.getSourceFile()) &&
|
|
1537
|
+
((base && hasRuntimeStatics(base)) ||
|
|
1538
|
+
decl.members.some((member) => ts.isAccessor(member) &&
|
|
1539
|
+
!ts.isPrivateIdentifier(member.name) &&
|
|
1540
|
+
member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) &&
|
|
1541
|
+
!decl.members.some((member) => member.name &&
|
|
1542
|
+
ts.isPrivateIdentifier(member.name) &&
|
|
1543
|
+
ts
|
|
1544
|
+
.getModifiers(member)
|
|
1545
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
1404
1546
|
// GENERIC methods (own type parameters), instance and static: only
|
|
1405
1547
|
// the SYNTAX is checked here — parameter/return types mention the
|
|
1406
1548
|
// type parameters and cannot map yet; bodies lower per call-site
|
|
@@ -1436,7 +1578,9 @@ mixin) {
|
|
|
1436
1578
|
typeParams.push(sym);
|
|
1437
1579
|
}
|
|
1438
1580
|
for (const param of fnNode.parameters) {
|
|
1439
|
-
if (!ts.isIdentifier(param.name) &&
|
|
1581
|
+
if (!ts.isIdentifier(param.name) &&
|
|
1582
|
+
!ts.isObjectBindingPattern(param.name) &&
|
|
1583
|
+
!ts.isArrayBindingPattern(param.name)) {
|
|
1440
1584
|
lowerer.unsupported("SC1031", param);
|
|
1441
1585
|
}
|
|
1442
1586
|
}
|
|
@@ -1449,16 +1593,23 @@ mixin) {
|
|
|
1449
1593
|
});
|
|
1450
1594
|
};
|
|
1451
1595
|
for (const member of decl.members) {
|
|
1452
|
-
if ((functionLocalClass(decl) || checkedStatics) &&
|
|
1453
|
-
(
|
|
1596
|
+
if ((functionLocalClass(decl) || checkedStatics) &&
|
|
1597
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
1598
|
+
(ts.isClassStaticBlockDeclaration(member) ||
|
|
1599
|
+
ts
|
|
1600
|
+
.getModifiers(member)
|
|
1601
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) {
|
|
1454
1602
|
runtimeStatics.push(member);
|
|
1455
1603
|
continue;
|
|
1456
1604
|
}
|
|
1457
|
-
if (functionLocalClass(decl) &&
|
|
1458
|
-
(
|
|
1605
|
+
if (functionLocalClass(decl) &&
|
|
1606
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
1607
|
+
(ts.isMethodDeclaration(member) || ts.isAccessor(member)) &&
|
|
1608
|
+
member.body &&
|
|
1459
1609
|
!ts.isPrivateIdentifier(member.name)) {
|
|
1460
1610
|
runtimePrototypeMembers.push(member);
|
|
1461
|
-
if (ts.isComputedPropertyName(member.name) &&
|
|
1611
|
+
if (ts.isComputedPropertyName(member.name) &&
|
|
1612
|
+
classMemberNameOf(lowerer, member.name) === null)
|
|
1462
1613
|
continue;
|
|
1463
1614
|
}
|
|
1464
1615
|
if (ts.isClassStaticBlockDeclaration(member)) {
|
|
@@ -1507,15 +1658,19 @@ mixin) {
|
|
|
1507
1658
|
(ts.isIdentifier(member.name) || ts.isPrivateIdentifier(member.name)) &&
|
|
1508
1659
|
member.initializer &&
|
|
1509
1660
|
member.postfixToken?.kind !== ts.SyntaxKind.QuestionToken) {
|
|
1510
|
-
const initializerSymbol = ts.isIdentifier(member.initializer)
|
|
1661
|
+
const initializerSymbol = ts.isIdentifier(member.initializer)
|
|
1662
|
+
? lowerer.resolveValueSymbol(member.initializer)
|
|
1663
|
+
: null;
|
|
1511
1664
|
// Enum namespace aliases are erased; member reads fold through the checker.
|
|
1512
1665
|
if (initializerSymbol && (initializerSymbol.flags & ts.SymbolFlags.Enum) !== 0)
|
|
1513
1666
|
continue;
|
|
1514
1667
|
const type = lowerer.irTypeOf(member.name);
|
|
1515
1668
|
if (type.kind === "void")
|
|
1516
1669
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1517
|
-
if (type.kind === "dyn" &&
|
|
1518
|
-
(member.
|
|
1670
|
+
if (type.kind === "dyn" &&
|
|
1671
|
+
!isJsSourceFile(member.getSourceFile()) &&
|
|
1672
|
+
(member.type !== undefined ||
|
|
1673
|
+
(lowerer.typeOf(member.name).flags & ts.TypeFlags.Any) === 0)) {
|
|
1519
1674
|
lowerer.unsupported("SC1090", member.name, "'unknown'-typed static fields");
|
|
1520
1675
|
}
|
|
1521
1676
|
staticFields.push({
|
|
@@ -1538,14 +1693,19 @@ mixin) {
|
|
|
1538
1693
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1539
1694
|
}
|
|
1540
1695
|
staticMethods.set(member.name.text, { params: shapes, ret: ft.ret, member });
|
|
1541
|
-
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
1542
|
-
|
|
1696
|
+
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
1697
|
+
!functionLocalClass(decl) &&
|
|
1698
|
+
inst === undefined &&
|
|
1699
|
+
decl.typeParameters === undefined) {
|
|
1543
1700
|
const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
|
|
1544
1701
|
if (implicit)
|
|
1545
1702
|
genericStatics.set(member.name.text, {
|
|
1546
|
-
decl: member,
|
|
1703
|
+
decl: member,
|
|
1704
|
+
baseName: member.name.text,
|
|
1547
1705
|
qualifiedName: `%${className}.static:${member.name.text}%implicit`,
|
|
1548
|
-
typeParams: [],
|
|
1706
|
+
typeParams: [],
|
|
1707
|
+
instances: new Map(),
|
|
1708
|
+
implicitParams: implicit,
|
|
1549
1709
|
});
|
|
1550
1710
|
}
|
|
1551
1711
|
}
|
|
@@ -1577,11 +1737,18 @@ mixin) {
|
|
|
1577
1737
|
// (every named member kind stores a PropertyName there).
|
|
1578
1738
|
const memberName = member.name;
|
|
1579
1739
|
if (errorRooted && memberName && classMemberNameOf(lowerer, memberName) === "cause") {
|
|
1580
|
-
if (ts.isPropertyDeclaration(member) &&
|
|
1740
|
+
if (ts.isPropertyDeclaration(member) &&
|
|
1741
|
+
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
|
|
1581
1742
|
if (!isJsSourceFile(member.getSourceFile()))
|
|
1582
1743
|
lowerer.unsupported("SC1090", memberName, "redeclaring Error.cause (pass the cause in the Error constructor options)");
|
|
1583
|
-
fieldOrder.push({
|
|
1584
|
-
|
|
1744
|
+
fieldOrder.push({
|
|
1745
|
+
name: "cause",
|
|
1746
|
+
type: DYN,
|
|
1747
|
+
initializer: member.initializer,
|
|
1748
|
+
...(member.initializer ? {} : { undefinedInitializer: locOf(member) }),
|
|
1749
|
+
redeclared: true,
|
|
1750
|
+
errorCause: true,
|
|
1751
|
+
});
|
|
1585
1752
|
continue;
|
|
1586
1753
|
}
|
|
1587
1754
|
lowerer.unsupported("SC1090", memberName, "Error.cause accessors");
|
|
@@ -1619,7 +1786,8 @@ mixin) {
|
|
|
1619
1786
|
// keep the fence for emit too: the runtime stream machinery emits
|
|
1620
1787
|
// 'data'/'end'/... internally, which could never route through
|
|
1621
1788
|
// the override.
|
|
1622
|
-
if (memberName &&
|
|
1789
|
+
if (memberName &&
|
|
1790
|
+
ts.isIdentifier(memberName) &&
|
|
1623
1791
|
EMITTER_API_MEMBERS.has(memberName.text) &&
|
|
1624
1792
|
(() => {
|
|
1625
1793
|
for (let c = base; c; c = c.base)
|
|
@@ -1633,7 +1801,10 @@ mixin) {
|
|
|
1633
1801
|
return true;
|
|
1634
1802
|
return false;
|
|
1635
1803
|
})();
|
|
1636
|
-
if (memberName.text === "emit" &&
|
|
1804
|
+
if (memberName.text === "emit" &&
|
|
1805
|
+
!streamRooted &&
|
|
1806
|
+
!inst &&
|
|
1807
|
+
!mixin &&
|
|
1637
1808
|
ts.isMethodDeclaration(member) &&
|
|
1638
1809
|
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
|
|
1639
1810
|
const reason = emitOverrideShapeReason(lowerer, member);
|
|
@@ -1698,20 +1869,37 @@ mixin) {
|
|
|
1698
1869
|
// get/set pair — declare the field and accessors explicitly.
|
|
1699
1870
|
lowerer.unsupported("SC1090", member, "auto-accessor fields ('accessor x')");
|
|
1700
1871
|
}
|
|
1701
|
-
if (ts.isComputedPropertyName(member.name) ||
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1872
|
+
if (ts.isComputedPropertyName(member.name) ||
|
|
1873
|
+
ts.isStringLiteralLike(member.name) ||
|
|
1874
|
+
ts.isNumericLiteral(member.name)) {
|
|
1875
|
+
const symbolKey = ts.isComputedPropertyName(member.name)
|
|
1876
|
+
? classSymbolKeyOf(lowerer, member.name.expression)
|
|
1877
|
+
: null;
|
|
1878
|
+
const stringKey = ts.isComputedPropertyName(member.name)
|
|
1879
|
+
? lowerer.foldedStringKeyOf(member.name.expression)
|
|
1880
|
+
: ts.isNumericLiteral(member.name)
|
|
1881
|
+
? String(Number(member.name.text))
|
|
1882
|
+
: member.name.text;
|
|
1705
1883
|
const fieldName = symbolKey?.fieldName ?? stringKey;
|
|
1706
|
-
if (fieldName === null ||
|
|
1884
|
+
if (fieldName === null ||
|
|
1885
|
+
(!member.initializer && !isJsSourceFile(member.getSourceFile()))) {
|
|
1707
1886
|
lowerer.unsupported("SC1090", member, "computed class fields without an initializer and a stable string, number, or module-level literal Symbol()/Symbol.for() key");
|
|
1708
1887
|
}
|
|
1709
1888
|
const declared = lowerer.typeOf(member);
|
|
1710
|
-
const inferred = member.type || !member.initializer
|
|
1711
|
-
|
|
1889
|
+
const inferred = member.type || !member.initializer
|
|
1890
|
+
? declared
|
|
1891
|
+
: lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(member.initializer));
|
|
1892
|
+
const mapped = member.initializer
|
|
1893
|
+
? (lowerer.mapTypeOf(inferred) ?? dynFallbackType(lowerer, member, inferred))
|
|
1894
|
+
: DYN;
|
|
1712
1895
|
let type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
|
|
1713
|
-
? DYN
|
|
1714
|
-
|
|
1896
|
+
? DYN
|
|
1897
|
+
: mapped
|
|
1898
|
+
? jsOpenObjectType(member, mapped, lowerer.shapes, lowerer.unions)
|
|
1899
|
+
: null;
|
|
1900
|
+
if (!type ||
|
|
1901
|
+
type.kind === "void" ||
|
|
1902
|
+
(type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())))
|
|
1715
1903
|
lowerer.badType(member, inferred);
|
|
1716
1904
|
if (isJsSourceFile(member.getSourceFile())) {
|
|
1717
1905
|
type = inheritedJsFieldType(lowerer, decl, fieldName, type);
|
|
@@ -1729,11 +1917,22 @@ mixin) {
|
|
|
1729
1917
|
if (!typeEquals(previous, type)) {
|
|
1730
1918
|
lowerer.unsupported("SC1090", member.name, "redeclaring computed fields at a different type");
|
|
1731
1919
|
}
|
|
1732
|
-
fieldOrder.push({
|
|
1920
|
+
fieldOrder.push({
|
|
1921
|
+
name: fieldName,
|
|
1922
|
+
type,
|
|
1923
|
+
initializer: member.initializer,
|
|
1924
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
1925
|
+
redeclared: true,
|
|
1926
|
+
});
|
|
1733
1927
|
}
|
|
1734
1928
|
else {
|
|
1735
1929
|
fields.set(fieldName, type);
|
|
1736
|
-
fieldOrder.push({
|
|
1930
|
+
fieldOrder.push({
|
|
1931
|
+
name: fieldName,
|
|
1932
|
+
type,
|
|
1933
|
+
initializer: member.initializer,
|
|
1934
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
1935
|
+
});
|
|
1737
1936
|
}
|
|
1738
1937
|
if (symbolKey)
|
|
1739
1938
|
symbolFields.set(symbolKey.identity, fieldName);
|
|
@@ -1788,20 +1987,28 @@ mixin) {
|
|
|
1788
1987
|
if (isJsSourceFile(member.getSourceFile()) && !member.initializer) {
|
|
1789
1988
|
const constructor = decl.members.find((part) => ts.isConstructorDeclaration(part) && !!part.body);
|
|
1790
1989
|
for (const statement of constructor?.body?.statements ?? []) {
|
|
1791
|
-
if (!ts.isExpressionStatement(statement) ||
|
|
1990
|
+
if (!ts.isExpressionStatement(statement) ||
|
|
1991
|
+
!ts.isBinaryExpression(statement.expression) ||
|
|
1792
1992
|
statement.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken)
|
|
1793
1993
|
continue;
|
|
1794
1994
|
const left = statement.expression.left;
|
|
1795
|
-
if (!ts.isPropertyAccessExpression(left) ||
|
|
1995
|
+
if (!ts.isPropertyAccessExpression(left) ||
|
|
1996
|
+
left.expression.kind !== ts.SyntaxKind.ThisKeyword ||
|
|
1997
|
+
left.name.text !== member.name.text)
|
|
1796
1998
|
continue;
|
|
1797
|
-
type =
|
|
1999
|
+
type =
|
|
2000
|
+
statement.expression.right.kind === ts.SyntaxKind.NullKeyword
|
|
2001
|
+
? DYN
|
|
2002
|
+
: jsFieldInitializerType(lowerer, type, statement.expression.right);
|
|
1798
2003
|
}
|
|
1799
2004
|
}
|
|
1800
2005
|
// Unannotated JavaScript callback slots retain the original
|
|
1801
2006
|
// callable and its receiver instead of adapting its signature.
|
|
1802
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2007
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2008
|
+
!member.type &&
|
|
1803
2009
|
!/@type\b/.test(member.getSourceFile().text.slice(member.pos, member.getStart())) &&
|
|
1804
|
-
(type.kind === "func" || type.kind === "record") &&
|
|
2010
|
+
(type.kind === "func" || type.kind === "record") &&
|
|
2011
|
+
lowerer.dynConvertible(type))
|
|
1805
2012
|
type = DYN;
|
|
1806
2013
|
// JS permits reads before a constructor's first assignment even
|
|
1807
2014
|
// when its inferred field type omits undefined.
|
|
@@ -1838,7 +2045,13 @@ mixin) {
|
|
|
1838
2045
|
// Other bare or type-changing redeclarations keep the fence.
|
|
1839
2046
|
const baseType = fields.get(member.name.text);
|
|
1840
2047
|
if ((member.initializer || type.kind === "dyn") && typeEquals(type, baseType)) {
|
|
1841
|
-
fieldOrder.push({
|
|
2048
|
+
fieldOrder.push({
|
|
2049
|
+
name: member.name.text,
|
|
2050
|
+
type,
|
|
2051
|
+
initializer: member.initializer,
|
|
2052
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
2053
|
+
redeclared: true,
|
|
2054
|
+
});
|
|
1842
2055
|
continue;
|
|
1843
2056
|
}
|
|
1844
2057
|
lowerer.unsupported("SC1090", member.name, member.initializer
|
|
@@ -1862,8 +2075,10 @@ mixin) {
|
|
|
1862
2075
|
// list checked against the constructor after the member loop
|
|
1863
2076
|
// (the constructor may be declared later in the class body).
|
|
1864
2077
|
const admitsUndefined = (type.kind === "union" &&
|
|
1865
|
-
(lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ??
|
|
1866
|
-
|
|
2078
|
+
(lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ??
|
|
2079
|
+
false)) ||
|
|
2080
|
+
type.kind === "jsval" ||
|
|
2081
|
+
type.kind === "dyn";
|
|
1867
2082
|
if (!member.initializer && !admitsUndefined) {
|
|
1868
2083
|
const opts = lowerer.program.getCompilerOptions();
|
|
1869
2084
|
const spi = opts.strictPropertyInitialization ?? opts.strict ?? false;
|
|
@@ -1883,7 +2098,12 @@ mixin) {
|
|
|
1883
2098
|
}
|
|
1884
2099
|
}
|
|
1885
2100
|
fields.set(member.name.text, type);
|
|
1886
|
-
fieldOrder.push({
|
|
2101
|
+
fieldOrder.push({
|
|
2102
|
+
name: member.name.text,
|
|
2103
|
+
type,
|
|
2104
|
+
initializer: member.initializer,
|
|
2105
|
+
...(undefinedInitializer ? { undefinedInitializer } : {}),
|
|
2106
|
+
});
|
|
1887
2107
|
}
|
|
1888
2108
|
else if (ts.isConstructorDeclaration(member)) {
|
|
1889
2109
|
// A body-less constructor is an OVERLOAD SIGNATURE: type-world,
|
|
@@ -2027,15 +2247,18 @@ mixin) {
|
|
|
2027
2247
|
// signature carries bindable untyped params collects like a
|
|
2028
2248
|
// GENERIC method — into genericMethods, no vtable slot, one
|
|
2029
2249
|
// instance per call-site type tuple (the untyped params ARE the
|
|
2030
|
-
// type parameters; see
|
|
2250
|
+
// type parameters; see generic-functions.ts). DECLINES
|
|
2031
2251
|
// (falls through to the normal all-dyn ABI) wherever the two
|
|
2032
2252
|
// dispatch worlds could meet: an inherited declaration of the
|
|
2033
2253
|
// name (the override stays on the vtable), a shadowed field, or
|
|
2034
2254
|
// a generic-class instantiation's member.
|
|
2035
|
-
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
2255
|
+
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
2256
|
+
!functionLocalClass(decl) &&
|
|
2036
2257
|
ts.isIdentifier(member.name) &&
|
|
2037
|
-
!lowerer.virtualJsMethods.has(member) &&
|
|
2038
|
-
|
|
2258
|
+
!lowerer.virtualJsMethods.has(member) &&
|
|
2259
|
+
!lowerer.prototypeMethodAccesses.has(member.name.text) &&
|
|
2260
|
+
inst === undefined &&
|
|
2261
|
+
decl.typeParameters === undefined &&
|
|
2039
2262
|
!fields.has(member.name.text) &&
|
|
2040
2263
|
!lowerer.findMethodOn(base, member.name.text) &&
|
|
2041
2264
|
!findGenericMethodOn(lowerer, base, member.name.text)) {
|
|
@@ -2069,9 +2292,13 @@ mixin) {
|
|
|
2069
2292
|
}
|
|
2070
2293
|
// JS inference may retain only a symbol sentinel while a method
|
|
2071
2294
|
// also returns values from an untyped mutable field or local.
|
|
2072
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2295
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2296
|
+
!member.type &&
|
|
2297
|
+
!hasExplicitJsDocReturn(member) &&
|
|
2298
|
+
ft.ret.kind === "symbol")
|
|
2073
2299
|
ft.ret = DYN;
|
|
2074
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2300
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
2301
|
+
lowerer.prototypeMethodAccesses.has(mName) &&
|
|
2075
2302
|
!lowerer.findMethodOn(base, mName)?.declarer.def.runtime &&
|
|
2076
2303
|
shapes.every((p) => p.mode === "required" || p.mode === "omittable")) {
|
|
2077
2304
|
for (const shape of shapes) {
|
|
@@ -2087,7 +2314,8 @@ mixin) {
|
|
|
2087
2314
|
// argument slots in the base before constructing its vtable; shorter
|
|
2088
2315
|
// bodies ignore them and omitted call arguments become undefined.
|
|
2089
2316
|
const virtualArity = lowerer.virtualJsMethodArity.get(member) ?? shapes.length;
|
|
2090
|
-
if (virtualArity > shapes.length &&
|
|
2317
|
+
if (virtualArity > shapes.length &&
|
|
2318
|
+
!bodyReadsArguments(member) &&
|
|
2091
2319
|
shapes.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
2092
2320
|
while (shapes.length < virtualArity)
|
|
2093
2321
|
shapes.push({ type: DYN, mode: "omittable" });
|
|
@@ -2121,13 +2349,18 @@ mixin) {
|
|
|
2121
2349
|
// An unannotated JS override can return a checked value into
|
|
2122
2350
|
// the inherited native ABI, just as its untyped parameters do.
|
|
2123
2351
|
// Body lowering inserts the conversion at each return.
|
|
2124
|
-
if (!member.type &&
|
|
2125
|
-
|
|
2352
|
+
if (!member.type &&
|
|
2353
|
+
ft.ret.kind === "dyn" &&
|
|
2354
|
+
overridden.sig.ret.kind !== "dyn" &&
|
|
2355
|
+
!overridden.sig.async &&
|
|
2356
|
+
!overridden.sig.gen)
|
|
2126
2357
|
ft.ret = overridden.sig.ret;
|
|
2127
2358
|
// Fluent overrides return the same native receiver. Keep the
|
|
2128
2359
|
// inherited return ABI and upcast `this` when lowering returns.
|
|
2129
|
-
if (overridden.sig.ret.kind === "object" &&
|
|
2130
|
-
|
|
2360
|
+
if (overridden.sig.ret.kind === "object" &&
|
|
2361
|
+
base &&
|
|
2362
|
+
(base.def.name === overridden.sig.ret.className ||
|
|
2363
|
+
lowerer.isSubclassOf(base.def.name, overridden.sig.ret.className)) &&
|
|
2131
2364
|
returnsOnlyThis(member))
|
|
2132
2365
|
ft.ret = overridden.sig.ret;
|
|
2133
2366
|
// An unannotated JS parameter can use the base's typed ABI.
|
|
@@ -2136,8 +2369,13 @@ mixin) {
|
|
|
2136
2369
|
for (let i = 0; i < shapes.length; i++) {
|
|
2137
2370
|
const parameter = member.parameters[i];
|
|
2138
2371
|
const inherited = overridden.sig.params[i];
|
|
2139
|
-
if (parameter &&
|
|
2140
|
-
|
|
2372
|
+
if (parameter &&
|
|
2373
|
+
inherited &&
|
|
2374
|
+
!parameter.type &&
|
|
2375
|
+
!parameter.initializer &&
|
|
2376
|
+
!parameter.dotDotDotToken &&
|
|
2377
|
+
shapes[i].type.kind === "dyn" &&
|
|
2378
|
+
inherited.type.kind !== "dyn" &&
|
|
2141
2379
|
(inherited.mode === "required" || inherited.mode === "omittable")) {
|
|
2142
2380
|
shapes[i] = { ...inherited };
|
|
2143
2381
|
}
|
|
@@ -2147,12 +2385,18 @@ mixin) {
|
|
|
2147
2385
|
// checked-value ABI slots as unused parameters, and let shorter
|
|
2148
2386
|
// calls fill them with undefined. Typed tails and rest/arguments
|
|
2149
2387
|
// readers keep the exact-signature fence.
|
|
2150
|
-
if (overridden &&
|
|
2388
|
+
if (overridden &&
|
|
2389
|
+
isJsSourceFile(member.getSourceFile()) &&
|
|
2151
2390
|
shapes.length < overridden.sig.params.length &&
|
|
2152
2391
|
!bodyReadsArguments(member) &&
|
|
2153
|
-
shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") &&
|
|
2154
|
-
|
|
2155
|
-
|
|
2392
|
+
shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") &&
|
|
2393
|
+
typeEquals(p.type, overridden.sig.params[i].type)) &&
|
|
2394
|
+
overridden.sig.params
|
|
2395
|
+
.slice(shapes.length)
|
|
2396
|
+
.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
2397
|
+
shapes.push(...overridden.sig.params
|
|
2398
|
+
.slice(shapes.length)
|
|
2399
|
+
.map((p) => ({ type: p.type, mode: "omittable" })));
|
|
2156
2400
|
}
|
|
2157
2401
|
if (overridden &&
|
|
2158
2402
|
member.asteriskToken === undefined &&
|
|
@@ -2160,7 +2404,8 @@ mixin) {
|
|
|
2160
2404
|
!overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) ||
|
|
2161
2405
|
!typeEquals(overridden.sig.ret, ft.ret))) {
|
|
2162
2406
|
const fencedJsOverride = isJsSourceFile(member.getSourceFile()) &&
|
|
2163
|
-
overridden.declarer.decl !== null &&
|
|
2407
|
+
overridden.declarer.decl !== null &&
|
|
2408
|
+
isJsSourceFile(overridden.declarer.decl.getSourceFile()) &&
|
|
2164
2409
|
overridden.sig.gen === undefined;
|
|
2165
2410
|
if (fencedJsOverride) {
|
|
2166
2411
|
// A dormant JS method must not poison the whole class. Keep
|
|
@@ -2171,8 +2416,11 @@ mixin) {
|
|
|
2171
2416
|
!member.parameters.some((parameter, index) => {
|
|
2172
2417
|
if (!parameter.initializer)
|
|
2173
2418
|
return false;
|
|
2174
|
-
const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) &&
|
|
2175
|
-
|
|
2419
|
+
const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) &&
|
|
2420
|
+
classMemberNameOf(lowerer, candidate.name) === mName);
|
|
2421
|
+
const inherited = baseMember && ts.isMethodDeclaration(baseMember)
|
|
2422
|
+
? baseMember.parameters[index]?.initializer
|
|
2423
|
+
: undefined;
|
|
2176
2424
|
if (!inherited)
|
|
2177
2425
|
return false;
|
|
2178
2426
|
const ownType = lowerer.mapTypeOf(lowerer.typeOf(parameter.initializer));
|
|
@@ -2201,7 +2449,8 @@ mixin) {
|
|
|
2201
2449
|
else
|
|
2202
2450
|
lowerer.unsupported("SC1090", member.name, message);
|
|
2203
2451
|
}
|
|
2204
|
-
if (overridden &&
|
|
2452
|
+
if (overridden &&
|
|
2453
|
+
(member.asteriskToken !== undefined || overridden.sig.gen !== undefined)) {
|
|
2205
2454
|
const message = `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`;
|
|
2206
2455
|
if (isJsSourceFile(member.getSourceFile()))
|
|
2207
2456
|
methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), message));
|
|
@@ -2223,7 +2472,9 @@ mixin) {
|
|
|
2223
2472
|
});
|
|
2224
2473
|
}
|
|
2225
2474
|
else {
|
|
2226
|
-
methods.set(mName, asyncMember
|
|
2475
|
+
methods.set(mName, asyncMember
|
|
2476
|
+
? { params: shapes, ret: ft.ret, async: true }
|
|
2477
|
+
: { params: shapes, ret: ft.ret });
|
|
2227
2478
|
}
|
|
2228
2479
|
// Overrides keep the inherited ABI exactly, so only non-override
|
|
2229
2480
|
// methods may still refine once the ctor scan runs.
|
|
@@ -2262,14 +2513,19 @@ mixin) {
|
|
|
2262
2513
|
if (!member.body && !abstractAccessor)
|
|
2263
2514
|
lowerer.unsupported("SC1090", member, "bodyless accessors");
|
|
2264
2515
|
const mName = `${isGet ? "get" : "set"}:${prop}`;
|
|
2265
|
-
if (fields.has(prop) &&
|
|
2516
|
+
if (fields.has(prop) &&
|
|
2517
|
+
isJsSourceFile(decl.getSourceFile()) &&
|
|
2518
|
+
base?.fields.has(prop) &&
|
|
2266
2519
|
!fieldOrder.some((field) => field.name === prop)) {
|
|
2267
2520
|
// JS may override an inherited data field with a prototype
|
|
2268
2521
|
// accessor. Retain the base storage prefix for its constructor;
|
|
2269
2522
|
// property dispatch on this subclass selects the accessor.
|
|
2270
2523
|
fields.delete(prop);
|
|
2271
2524
|
}
|
|
2272
|
-
if (fields.has(prop) &&
|
|
2525
|
+
if (fields.has(prop) &&
|
|
2526
|
+
!((prop === "message" || prop === "name") &&
|
|
2527
|
+
base &&
|
|
2528
|
+
(base.def.name === "%Error" || lowerer.isSubclassOf(base.def.name, "%Error")))) {
|
|
2273
2529
|
// tsc rejects field/accessor mixing (TS2610/2611); defensive.
|
|
2274
2530
|
lowerer.unsupported("SC1090", member.name, "accessors sharing a name with a field");
|
|
2275
2531
|
}
|
|
@@ -2333,7 +2589,11 @@ mixin) {
|
|
|
2333
2589
|
if (paramProps.length > 0) {
|
|
2334
2590
|
for (const pp of paramProps)
|
|
2335
2591
|
fields.set(pp.name, pp.type);
|
|
2336
|
-
fieldOrder.unshift(...paramProps.map((pp) => ({
|
|
2592
|
+
fieldOrder.unshift(...paramProps.map((pp) => ({
|
|
2593
|
+
name: pp.name,
|
|
2594
|
+
type: pp.type,
|
|
2595
|
+
initializer: undefined,
|
|
2596
|
+
})));
|
|
2337
2597
|
}
|
|
2338
2598
|
// The deferred definite-assignment check: a field on the unguarded
|
|
2339
2599
|
// list passes only with an unconditional `this.x = ...` at the
|
|
@@ -2367,9 +2627,14 @@ mixin) {
|
|
|
2367
2627
|
// extraction targets one arm); union-typed `!` fields keep the
|
|
2368
2628
|
// fence.
|
|
2369
2629
|
const declared = fields.get(f.name);
|
|
2370
|
-
const armable = declared !== undefined &&
|
|
2371
|
-
declared
|
|
2372
|
-
declared.kind !== "
|
|
2630
|
+
const armable = declared !== undefined &&
|
|
2631
|
+
!isUnitType(declared) &&
|
|
2632
|
+
declared.kind !== "union" &&
|
|
2633
|
+
declared.kind !== "jsval" &&
|
|
2634
|
+
declared.kind !== "dyn" &&
|
|
2635
|
+
declared.kind !== "map" &&
|
|
2636
|
+
declared.kind !== "date" &&
|
|
2637
|
+
declared.kind !== "generator" &&
|
|
2373
2638
|
declared.kind !== "void" &&
|
|
2374
2639
|
declared.kind !== "caught";
|
|
2375
2640
|
const armed = armable ? lowerer.withUndefinedArm(declared) : null;
|
|
@@ -2436,13 +2701,18 @@ mixin) {
|
|
|
2436
2701
|
// forbids via strictPropertyInitialization — so they keep a named
|
|
2437
2702
|
// fence instead of a silent undefined.
|
|
2438
2703
|
if (isJsSourceFile(decl.getSourceFile())) {
|
|
2439
|
-
const hasAccessor = (name) => methods.has(`get:${name}`) ||
|
|
2704
|
+
const hasAccessor = (name) => methods.has(`get:${name}`) ||
|
|
2705
|
+
methods.has(`set:${name}`) ||
|
|
2440
2706
|
lowerer.findMethodOn(base, `get:${name}`) !== null ||
|
|
2441
2707
|
lowerer.findMethodOn(base, `set:${name}`) !== null;
|
|
2442
2708
|
// Named classes (declarations and self-binding expressions) resolve
|
|
2443
2709
|
// by name; the nameless default-export declaration by its module's
|
|
2444
2710
|
// default-export symbol.
|
|
2445
|
-
const classSym = decl.name
|
|
2711
|
+
const classSym = decl.name
|
|
2712
|
+
? lowerer.checker.getSymbolAtLocation(decl.name)
|
|
2713
|
+
: ts.isClassDeclaration(decl)
|
|
2714
|
+
? declSymbolOf(lowerer, decl)
|
|
2715
|
+
: undefined;
|
|
2446
2716
|
const instType = classSym ? lowerer.checker.getDeclaredTypeOfSymbol(classSym) : undefined;
|
|
2447
2717
|
// LATE-BOUND properties (the checker's `__@name@id` spelling —
|
|
2448
2718
|
// `this[kLimit] = v` where kLimit is a unique symbol const) by
|
|
@@ -2466,7 +2736,8 @@ mixin) {
|
|
|
2466
2736
|
stmt.expression.operatorToken.kind === ts.SyntaxKind.EqualsToken
|
|
2467
2737
|
? stmt.expression.left
|
|
2468
2738
|
: null;
|
|
2469
|
-
if (lhs &&
|
|
2739
|
+
if (lhs &&
|
|
2740
|
+
ts.isPropertyAccessExpression(lhs) &&
|
|
2470
2741
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
2471
2742
|
const assign = lhs;
|
|
2472
2743
|
const name = assign.name.text;
|
|
@@ -2493,7 +2764,9 @@ mixin) {
|
|
|
2493
2764
|
// TS-annotated `unknown` fields keep their fence (KEEP NARROW
|
|
2494
2765
|
// applies where an annotation could say better).
|
|
2495
2766
|
let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, assign, t)) : null;
|
|
2496
|
-
if (t &&
|
|
2767
|
+
if (t &&
|
|
2768
|
+
(t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0 &&
|
|
2769
|
+
isJsSourceFile(decl.getSourceFile()))
|
|
2497
2770
|
type = DYN;
|
|
2498
2771
|
if (type)
|
|
2499
2772
|
type = jsOpenObjectType(assign, type, lowerer.shapes, lowerer.unions);
|
|
@@ -2540,7 +2813,8 @@ mixin) {
|
|
|
2540
2813
|
// property type, through the same JS checked-dynamic fallback
|
|
2541
2814
|
// as named fields. Keys that DON'T resolve fall through to the
|
|
2542
2815
|
// late-bound fence below.
|
|
2543
|
-
if (lhs &&
|
|
2816
|
+
if (lhs &&
|
|
2817
|
+
ts.isElementAccessExpression(lhs) &&
|
|
2544
2818
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
2545
2819
|
const key = classSymbolKeyOf(lowerer, lhs.argumentExpression);
|
|
2546
2820
|
const stringKey = lowerer.foldedStringKeyOf(lhs.argumentExpression);
|
|
@@ -2566,7 +2840,11 @@ mixin) {
|
|
|
2566
2840
|
// one layout would need one printable name for two slots.
|
|
2567
2841
|
lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
|
|
2568
2842
|
}
|
|
2569
|
-
const propSym = key
|
|
2843
|
+
const propSym = key
|
|
2844
|
+
? lateBoundByKey.get(key.sym)
|
|
2845
|
+
: instType
|
|
2846
|
+
? lowerer.checker.getPropertyOfType(instType, fieldName)
|
|
2847
|
+
: undefined;
|
|
2570
2848
|
// tsgo does not synthesize the late-bound `__@name@id`
|
|
2571
2849
|
// property for a JS `this[k] = v` declaration (the finding-5
|
|
2572
2850
|
// family: no expando/late-bound synthesis in its stricter
|
|
@@ -2610,7 +2888,10 @@ mixin) {
|
|
|
2610
2888
|
continue;
|
|
2611
2889
|
if (base && (base.fields.has(p.name) || lowerer.findMethodOn(base, p.name)))
|
|
2612
2890
|
continue;
|
|
2613
|
-
const site = lowerer.checker
|
|
2891
|
+
const site = lowerer.checker
|
|
2892
|
+
.declarationsOf(p)
|
|
2893
|
+
.find((d) => ts.isPropertyAccessExpression(d) ||
|
|
2894
|
+
ts.isBinaryExpression(d) ||
|
|
2614
2895
|
ts.isElementAccessExpression(d));
|
|
2615
2896
|
if (!site)
|
|
2616
2897
|
continue;
|
|
@@ -2684,8 +2965,11 @@ mixin) {
|
|
|
2684
2965
|
const ctorParams = ctor && !mixinForwarding
|
|
2685
2966
|
? lowerer.paramShapes(ctor.parameters)
|
|
2686
2967
|
: (base?.ctorParams ?? (callableBase ? [{ type: DYN, mode: "dynRest" }] : []));
|
|
2687
|
-
if (ctor &&
|
|
2688
|
-
!
|
|
2968
|
+
if (ctor &&
|
|
2969
|
+
!mixinForwarding &&
|
|
2970
|
+
isJsSourceFile(ctor.getSourceFile()) &&
|
|
2971
|
+
!ctorParams.some((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest") &&
|
|
2972
|
+
bodyReadsArguments(ctor)) {
|
|
2689
2973
|
ctorParams.push({ type: DYN, mode: "arguments" });
|
|
2690
2974
|
}
|
|
2691
2975
|
const info = {
|
|
@@ -2708,7 +2992,9 @@ mixin) {
|
|
|
2708
2992
|
// initializers assign the prefix slot).
|
|
2709
2993
|
fields: [
|
|
2710
2994
|
...(base?.def.fields ?? []),
|
|
2711
|
-
...fieldOrder
|
|
2995
|
+
...fieldOrder
|
|
2996
|
+
.filter((f) => f.redeclared !== true)
|
|
2997
|
+
.map((f) => ({ name: f.name, type: f.type })),
|
|
2712
2998
|
],
|
|
2713
2999
|
...(methods.size > 0 ? { methods: [...methods.keys()] } : {}),
|
|
2714
3000
|
...(abstractClass ? { abstract: true } : {}),
|
|
@@ -2738,7 +3024,9 @@ mixin) {
|
|
|
2738
3024
|
...(staticBlocks.length > 0 ? { staticBlocks } : {}),
|
|
2739
3025
|
...(symbolFields.size > 0 ? { symbolFields } : {}),
|
|
2740
3026
|
...(symbolMethods.size > 0 ? { symbolMethods } : {}),
|
|
2741
|
-
...(classDecoratorNodes.length > 0
|
|
3027
|
+
...(classDecoratorNodes.length > 0
|
|
3028
|
+
? { classDecorators: { nodes: classDecoratorNodes } }
|
|
3029
|
+
: {}),
|
|
2742
3030
|
...(deferredInitFields.size > 0 ? { deferredInitFields } : {}),
|
|
2743
3031
|
};
|
|
2744
3032
|
// GENERIC members get their declaring-class backlink now that the
|
|
@@ -2793,14 +3081,29 @@ mixin) {
|
|
|
2793
3081
|
lowerer.classes.set(className, info);
|
|
2794
3082
|
if (computedBase && !functionLocalClass(decl)) {
|
|
2795
3083
|
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2796
|
-
lowerer.globalsList.push({
|
|
3084
|
+
lowerer.globalsList.push({
|
|
3085
|
+
id: info.def.baseValueGlobal,
|
|
3086
|
+
name: `${className} base`,
|
|
3087
|
+
type: computedBase.value.type,
|
|
3088
|
+
mutable: false,
|
|
3089
|
+
});
|
|
2797
3090
|
}
|
|
2798
3091
|
if (factoryBaseExpression && !functionLocalClass(decl)) {
|
|
2799
3092
|
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2800
|
-
lowerer.globalsList.push({
|
|
3093
|
+
lowerer.globalsList.push({
|
|
3094
|
+
id: info.def.baseValueGlobal,
|
|
3095
|
+
name: `${className} base`,
|
|
3096
|
+
type: { kind: "classval", className: base.def.name },
|
|
3097
|
+
mutable: false,
|
|
3098
|
+
});
|
|
2801
3099
|
}
|
|
2802
3100
|
if (callableBase && !functionLocalClass(decl)) {
|
|
2803
|
-
lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, {
|
|
3101
|
+
lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, {
|
|
3102
|
+
id: callableBase.prototypeId,
|
|
3103
|
+
name: `${className} base prototype`,
|
|
3104
|
+
type: DYN,
|
|
3105
|
+
mutable: false,
|
|
3106
|
+
});
|
|
2804
3107
|
}
|
|
2805
3108
|
// A NAMED class binds its name (declarations in their scope, class
|
|
2806
3109
|
// expressions inside their own bodies — tsc resolves both to this
|
|
@@ -2812,27 +3115,36 @@ mixin) {
|
|
|
2812
3115
|
// classes fence at their use sites).
|
|
2813
3116
|
const classSymbol = inst || mixin
|
|
2814
3117
|
? undefined
|
|
2815
|
-
: decl.name
|
|
3118
|
+
: decl.name
|
|
3119
|
+
? lowerer.checker.getSymbolAtLocation(decl.name)
|
|
3120
|
+
: ts.isClassDeclaration(decl)
|
|
3121
|
+
? declSymbolOf(lowerer, decl)
|
|
3122
|
+
: undefined;
|
|
2816
3123
|
if (classSymbol)
|
|
2817
3124
|
lowerer.classBySymbol.set(classSymbol, info);
|
|
2818
3125
|
// Static-field storage registers with the module's globals only
|
|
2819
3126
|
// once the whole shape collected (a poisoned class never leaves a
|
|
2820
3127
|
// half-registered global behind).
|
|
2821
3128
|
for (const f of staticFields) {
|
|
2822
|
-
lowerer.globalsList.push({
|
|
3129
|
+
lowerer.globalsList.push({
|
|
3130
|
+
id: f.globalId,
|
|
3131
|
+
name: `${info.def.jsName ?? className}.${f.name}`,
|
|
3132
|
+
type: f.type,
|
|
3133
|
+
mutable: !f.readonly,
|
|
3134
|
+
});
|
|
2823
3135
|
}
|
|
2824
3136
|
}
|
|
2825
3137
|
}
|
|
2826
3138
|
/** mapType's generic-class hook: the INSTANTIATION a concrete type
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
3139
|
+
* reference (`Box<number>`) names — registered on first demand. The
|
|
3140
|
+
* instance's NAME reserves its key before the shape collects, so
|
|
3141
|
+
* self-referential layouts (`next: Box<T> | null`) re-enter here and
|
|
3142
|
+
* take the name without recursing; a poisoned collection (a field type
|
|
3143
|
+
* with no lowering under these bindings — the diagnostic carries the
|
|
3144
|
+
* instantiation context) leaves the entry poisoned and the type
|
|
3145
|
+
* unmapped, the fenced-JS-class story. Null answers (unmappable type
|
|
3146
|
+
* arguments, the instance cap, an uncollected family) make the whole
|
|
3147
|
+
* reference unmappable — per-site diagnostics own the fence. */
|
|
2836
3148
|
export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
2837
3149
|
const gci = lowerer.genericClassByDecl.get(decl);
|
|
2838
3150
|
if (!gci) {
|
|
@@ -2856,7 +3168,9 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2856
3168
|
const familyT = { kind: "object", className: gci.family.def.name };
|
|
2857
3169
|
// The checker appends `this` (and outer type parameters) to
|
|
2858
3170
|
// getTypeArguments — only the declaration's own count participates.
|
|
2859
|
-
const args = lowerer.checker
|
|
3171
|
+
const args = lowerer.checker
|
|
3172
|
+
.getTypeArguments(ref)
|
|
3173
|
+
.slice(0, gci.typeParams.length);
|
|
2860
3174
|
const mapped = [];
|
|
2861
3175
|
if (args.length === gci.typeParams.length) {
|
|
2862
3176
|
for (const a of args) {
|
|
@@ -2908,7 +3222,13 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2908
3222
|
lowerer.typeParamBindings = bindings;
|
|
2909
3223
|
lowerer.instantiationContext = `instantiating class '${gci.baseName}' with ${typeArgsText}`;
|
|
2910
3224
|
try {
|
|
2911
|
-
lowerer.collectClassShapeInner(decl, undefined, {
|
|
3225
|
+
lowerer.collectClassShapeInner(decl, undefined, {
|
|
3226
|
+
family: gci.family,
|
|
3227
|
+
name,
|
|
3228
|
+
bindings,
|
|
3229
|
+
typeArgsText,
|
|
3230
|
+
ordinal,
|
|
3231
|
+
});
|
|
2912
3232
|
}
|
|
2913
3233
|
catch (e) {
|
|
2914
3234
|
// Collection fenced under THESE bindings: the diagnostic (with the
|
|
@@ -2934,11 +3254,11 @@ export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
|
2934
3254
|
return { kind: "object", className: name };
|
|
2935
3255
|
}
|
|
2936
3256
|
/** Runs a member-lowering thunk under an INSTANTIATION's type-parameter
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
3257
|
+
* bindings (the generic-fn typeParamResolver mechanism) — the checker
|
|
3258
|
+
* keeps reporting the unsubstituted `T`s inside the shared body AST.
|
|
3259
|
+
* Coverage counts a generic class's statements once: only the FIRST
|
|
3260
|
+
* instantiation contributes (the lowerGenericInstance rule). A no-op
|
|
3261
|
+
* for ordinary classes. */
|
|
2942
3262
|
function withInstanceBindings(lowerer, info, fn) {
|
|
2943
3263
|
const gi = info.genericInstance;
|
|
2944
3264
|
if (!gi) {
|
|
@@ -2983,11 +3303,11 @@ function withInstanceBindings(lowerer, info, fn) {
|
|
|
2983
3303
|
}
|
|
2984
3304
|
}
|
|
2985
3305
|
/** The `%init` statements for one class's static readonly fields AND
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
3306
|
+
* static blocks, interleaved in member order — emitted at the class
|
|
3307
|
+
* statement's source position (see lowerFileInit's merge), exactly when
|
|
3308
|
+
* JS evaluates static initializers and blocks. Field failures poison per
|
|
3309
|
+
* field, like fieldInitStmts; a block lowers as the block statement it
|
|
3310
|
+
* is, so its statements poison individually inside lowerStmts. */
|
|
2991
3311
|
export function lowerStaticFieldInits(lowerer, info) {
|
|
2992
3312
|
if (info.localClass)
|
|
2993
3313
|
return [];
|
|
@@ -3018,41 +3338,102 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3018
3338
|
// initializers and static blocks (verified against Node — the
|
|
3019
3339
|
// decorated result is what `this`/the class name mean inside them).
|
|
3020
3340
|
const out = [...lowerClassDecoration(lowerer, info)];
|
|
3021
|
-
const computedBase = info.decl
|
|
3341
|
+
const computedBase = info.decl
|
|
3342
|
+
? lowerer.computedClassBases.get(lowerer.classNamer(info.decl))
|
|
3343
|
+
: undefined;
|
|
3022
3344
|
if (info.factoryBaseExpression && info.def.baseValueGlobal) {
|
|
3023
3345
|
const loc = locOf(info.factoryBaseExpression);
|
|
3024
3346
|
const type = { kind: "classval", className: info.base.def.name };
|
|
3025
|
-
out.push({
|
|
3026
|
-
|
|
3347
|
+
out.push({
|
|
3348
|
+
kind: "assign",
|
|
3349
|
+
localId: info.def.baseValueGlobal,
|
|
3350
|
+
value: lowerer.lowerExprExpecting(info.factoryBaseExpression, type),
|
|
3351
|
+
loc,
|
|
3352
|
+
});
|
|
3353
|
+
out.push({
|
|
3354
|
+
kind: "exprStmt",
|
|
3355
|
+
expr: {
|
|
3356
|
+
kind: "libCall",
|
|
3357
|
+
fn: "dyn.classInherit",
|
|
3358
|
+
args: [
|
|
3027
3359
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3028
3360
|
lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type, loc }, DYN),
|
|
3029
|
-
],
|
|
3361
|
+
],
|
|
3362
|
+
type: DYN,
|
|
3363
|
+
loc,
|
|
3364
|
+
},
|
|
3365
|
+
loc,
|
|
3366
|
+
});
|
|
3030
3367
|
}
|
|
3031
3368
|
if (computedBase && info.def.baseValueGlobal) {
|
|
3032
3369
|
const loc = computedBase.value.loc;
|
|
3033
3370
|
out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: computedBase.value, loc });
|
|
3034
|
-
out.push({
|
|
3371
|
+
out.push({
|
|
3372
|
+
kind: "exprStmt",
|
|
3373
|
+
expr: {
|
|
3374
|
+
kind: "libCall",
|
|
3375
|
+
fn: "dyn.classInherit",
|
|
3376
|
+
args: [
|
|
3035
3377
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3036
|
-
lowerer.coerceToExpected({
|
|
3037
|
-
|
|
3378
|
+
lowerer.coerceToExpected({
|
|
3379
|
+
kind: "varRef",
|
|
3380
|
+
localId: info.def.baseValueGlobal,
|
|
3381
|
+
type: computedBase.value.type,
|
|
3382
|
+
loc,
|
|
3383
|
+
}, DYN),
|
|
3384
|
+
],
|
|
3385
|
+
type: DYN,
|
|
3386
|
+
loc,
|
|
3387
|
+
},
|
|
3388
|
+
loc,
|
|
3389
|
+
});
|
|
3038
3390
|
}
|
|
3039
3391
|
if (info.callableBase) {
|
|
3040
3392
|
const { expression, constructorId, prototypeId } = info.callableBase;
|
|
3041
3393
|
const loc = locOf(expression);
|
|
3042
|
-
out.push({
|
|
3394
|
+
out.push({
|
|
3395
|
+
kind: "assign",
|
|
3396
|
+
localId: constructorId,
|
|
3397
|
+
value: info.decl && lowerer.computedCallableBases.has(info.decl)
|
|
3043
3398
|
? lowerer.coerceToExpected(lowerer.computedCallableBases.get(info.decl), DYN)
|
|
3044
|
-
: lowerer.lowerExprExpecting(expression, DYN),
|
|
3045
|
-
|
|
3399
|
+
: lowerer.lowerExprExpecting(expression, DYN),
|
|
3400
|
+
loc,
|
|
3401
|
+
}, {
|
|
3402
|
+
kind: "assign",
|
|
3403
|
+
localId: prototypeId,
|
|
3404
|
+
value: {
|
|
3405
|
+
kind: "libCall",
|
|
3406
|
+
fn: "dyn.classBasePrototype",
|
|
3407
|
+
args: [{ kind: "varRef", localId: constructorId, type: DYN, loc }],
|
|
3408
|
+
type: DYN,
|
|
3409
|
+
loc,
|
|
3410
|
+
},
|
|
3411
|
+
loc,
|
|
3412
|
+
});
|
|
3046
3413
|
const prototype = classPrototypeData(lowerer, info, loc);
|
|
3047
3414
|
if (prototype)
|
|
3048
3415
|
out.push({ kind: "exprStmt", expr: prototype, loc });
|
|
3049
|
-
out.push({
|
|
3416
|
+
out.push({
|
|
3417
|
+
kind: "exprStmt",
|
|
3418
|
+
expr: {
|
|
3419
|
+
kind: "libCall",
|
|
3420
|
+
fn: "dyn.classInherit",
|
|
3421
|
+
args: [
|
|
3050
3422
|
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
3051
3423
|
{ kind: "varRef", localId: constructorId, type: DYN, loc },
|
|
3052
|
-
],
|
|
3424
|
+
],
|
|
3425
|
+
type: DYN,
|
|
3426
|
+
loc,
|
|
3427
|
+
},
|
|
3428
|
+
loc,
|
|
3429
|
+
});
|
|
3053
3430
|
}
|
|
3054
3431
|
if (info.runtimeStatics && !info.localClass && info.decl) {
|
|
3055
|
-
out.push({
|
|
3432
|
+
out.push({
|
|
3433
|
+
kind: "exprStmt",
|
|
3434
|
+
expr: initializeRuntimeStatics(lowerer, info, classValueRef(lowerer, info, info.decl)),
|
|
3435
|
+
loc: locOf(info.decl),
|
|
3436
|
+
});
|
|
3056
3437
|
}
|
|
3057
3438
|
const items = [
|
|
3058
3439
|
...info.staticFields.map((f) => ({ pos: f.initializer.getStart(), kind: "field", f })),
|
|
@@ -3072,11 +3453,24 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3072
3453
|
try {
|
|
3073
3454
|
const previousThis = lowerer.ctx.thisLocal;
|
|
3074
3455
|
const receiver = f.initializer.kind === ts.SyntaxKind.ThisKeyword || hasStaticThis(f.initializer)
|
|
3075
|
-
? lowerer.declareHiddenLocal("%staticThis", {
|
|
3456
|
+
? lowerer.declareHiddenLocal("%staticThis", {
|
|
3457
|
+
kind: "classval",
|
|
3458
|
+
className: info.def.name,
|
|
3459
|
+
})
|
|
3460
|
+
: null;
|
|
3076
3461
|
if (receiver) {
|
|
3077
3462
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
3078
|
-
out.push({
|
|
3079
|
-
|
|
3463
|
+
out.push({
|
|
3464
|
+
kind: "varDecl",
|
|
3465
|
+
localId: receiver.id,
|
|
3466
|
+
init: {
|
|
3467
|
+
kind: "classRef",
|
|
3468
|
+
className: info.def.name,
|
|
3469
|
+
type: receiver.type,
|
|
3470
|
+
loc: locOf(f.initializer),
|
|
3471
|
+
},
|
|
3472
|
+
loc: locOf(f.initializer),
|
|
3473
|
+
});
|
|
3080
3474
|
}
|
|
3081
3475
|
let value;
|
|
3082
3476
|
try {
|
|
@@ -3095,7 +3489,9 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3095
3489
|
lowerer.stats.statementsFailed++;
|
|
3096
3490
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
3097
3491
|
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
3098
|
-
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
3492
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
3493
|
+
kind: "statement",
|
|
3494
|
+
});
|
|
3099
3495
|
if (fence)
|
|
3100
3496
|
out.push(fence);
|
|
3101
3497
|
}
|
|
@@ -3104,22 +3500,22 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
3104
3500
|
return out;
|
|
3105
3501
|
}
|
|
3106
3502
|
/** 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
|
-
|
|
3503
|
+
* a decorator's return type may name a subclass declared BELOW the
|
|
3504
|
+
* class). Classifies every class-level decorator by its checker type:
|
|
3505
|
+
* exactly one parameter, itself a classval the decorated class legally
|
|
3506
|
+
* flows into (the class, or a base sharing its completed constructor
|
|
3507
|
+
* ABI — the classval widening rule), returning void/undefined (an
|
|
3508
|
+
* effect-only decorator) or the class/a same-ABI subclass (a REPLACING
|
|
3509
|
+
* decorator, whose result rebinds the name). Everything else is a named
|
|
3510
|
+
* fence: the standard context parameter, structural sibling
|
|
3511
|
+
* replacements tsc admits but the nominal classval world cannot carry,
|
|
3512
|
+
* unions mixing the class with undefined. A replacing decorator
|
|
3513
|
+
* registers the mutable classval global the name rebinds through, and
|
|
3514
|
+
* fences the two shapes the value rebinding cannot keep exact —
|
|
3515
|
+
* subclasses of the decorated class (the compiled hierarchy is fixed at
|
|
3516
|
+
* build time; the runtime base would be the decoration result) and
|
|
3517
|
+
* namespace-nested declarations (qualified references resolve the class
|
|
3518
|
+
* directly, not through the rebound value). */
|
|
3123
3519
|
export function analyzeClassDecoration(lowerer, info) {
|
|
3124
3520
|
const cd = info.classDecorators;
|
|
3125
3521
|
if (!cd || cd.shapes !== undefined || cd.poisoned)
|
|
@@ -3237,14 +3633,14 @@ export function analyzeClassDecoration(lowerer, info) {
|
|
|
3237
3633
|
}
|
|
3238
3634
|
}
|
|
3239
3635
|
/** The decoration statements of a decorated class — the %init code that
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3636
|
+
* runs at the class statement's position, BEFORE its static field
|
|
3637
|
+
* initializers and blocks (lowerStaticFieldInits composes them; the
|
|
3638
|
+
* lower-modules interleave places the whole bundle). Verified Node
|
|
3639
|
+
* order: decorator expressions evaluate in SOURCE order (factories run
|
|
3640
|
+
* here), then applications run in REVERSE member order over the class
|
|
3641
|
+
* object, each replacing decorator's non-undefined result feeding the
|
|
3642
|
+
* next application; the final value binds the class name (the mutable
|
|
3643
|
+
* classval global) when any decorator can replace. */
|
|
3248
3644
|
function lowerClassDecoration(lowerer, info) {
|
|
3249
3645
|
const cd = info.classDecorators;
|
|
3250
3646
|
if (!cd || cd.poisoned || cd.shapes === undefined || info.decl === null)
|
|
@@ -3264,7 +3660,11 @@ function lowerClassDecoration(lowerer, info) {
|
|
|
3264
3660
|
const d = cd.nodes[i];
|
|
3265
3661
|
const shape = cd.shapes[i];
|
|
3266
3662
|
if (shape.kind === "ambientThrow") {
|
|
3267
|
-
stmts.push({
|
|
3663
|
+
stmts.push({
|
|
3664
|
+
kind: "exprStmt",
|
|
3665
|
+
expr: nsUndefRead(lowerer, shape.name, d, F64),
|
|
3666
|
+
loc: locOf(d),
|
|
3667
|
+
});
|
|
3268
3668
|
return stmts;
|
|
3269
3669
|
}
|
|
3270
3670
|
const value = lowerer.lowerExprExpecting(d.expression, shape.funcType);
|
|
@@ -3313,9 +3713,9 @@ function lowerClassDecoration(lowerer, info) {
|
|
|
3313
3713
|
}
|
|
3314
3714
|
}
|
|
3315
3715
|
/** The nearest declaration of static member `name` at or above `info` —
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3716
|
+
* the compile-time prototype-chain walk (`D.x` reads C's global when C
|
|
3717
|
+
* declared x and nothing between redeclares it; a redeclaration shadows
|
|
3718
|
+
* with its OWN storage, exactly JS). */
|
|
3319
3719
|
export function findStaticOn(lowerer, info, name) {
|
|
3320
3720
|
for (let c = info; c; c = c.base) {
|
|
3321
3721
|
const field = c.staticFields.find((s) => s.name === name);
|
|
@@ -3328,17 +3728,17 @@ export function findStaticOn(lowerer, info, name) {
|
|
|
3328
3728
|
return null;
|
|
3329
3729
|
}
|
|
3330
3730
|
/** True when some STRICT descendant of `info` redeclares static `name` —
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
export function staticShadowBelow(
|
|
3731
|
+
* the through-a-VALUE devirtualization test: a classval(info) slot can
|
|
3732
|
+
* hold any descendant, and a shadowing redeclaration means the runtime
|
|
3733
|
+
* class decides which storage answers. */
|
|
3734
|
+
export function staticShadowBelow(info, name) {
|
|
3335
3735
|
return info.subclasses.some((s) => s.staticFields.some((f) => f.name === name) ||
|
|
3336
3736
|
s.staticMethods?.has(name) === true ||
|
|
3337
3737
|
s.genericStatics?.has(name) === true ||
|
|
3338
|
-
staticShadowBelow(
|
|
3738
|
+
staticShadowBelow(s, name));
|
|
3339
3739
|
}
|
|
3340
3740
|
/** The nearest GENERIC static declaration of `name` at/above `info` —
|
|
3341
|
-
|
|
3741
|
+
* findStaticOn's twin over the genericStatics tables. */
|
|
3342
3742
|
export function findGenericStaticOn(lowerer, info, name) {
|
|
3343
3743
|
for (let c = info; c; c = c.base) {
|
|
3344
3744
|
const gs = c.genericStatics?.get(name);
|
|
@@ -3348,8 +3748,8 @@ export function findGenericStaticOn(lowerer, info, name) {
|
|
|
3348
3748
|
return null;
|
|
3349
3749
|
}
|
|
3350
3750
|
/** A static METHOD taken as a value: the zero-capture closure over its
|
|
3351
|
-
|
|
3352
|
-
|
|
3751
|
+
* module function — the declared-function-as-value rule verbatim
|
|
3752
|
+
* (interned by the backend, so `C.m === C.m` holds). */
|
|
3353
3753
|
function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
|
|
3354
3754
|
const reflected = reflectedClassStaticMethodValue(lowerer, declarer, name);
|
|
3355
3755
|
if (reflected)
|
|
@@ -3366,13 +3766,13 @@ function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
|
|
|
3366
3766
|
return { kind: "closure", fnName, captures: [], type: funcType, loc };
|
|
3367
3767
|
}
|
|
3368
3768
|
/** The class itself taken as a VALUE (`const X = C`, an argument, an
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3769
|
+
* array element, a class expression's result): the classRef over the
|
|
3770
|
+
* per-class immortal class object. The construct thunk needs a thunk-
|
|
3771
|
+
* shaped constructor, so classes whose construction is libCall-shaped —
|
|
3772
|
+
* the runtime-provided builtins and anything inheriting a builtin
|
|
3773
|
+
* constructor (Error/EventEmitter/stream chains complete their `new`
|
|
3774
|
+
* by special rules) — are named fences here. The constructor edge is
|
|
3775
|
+
* noted at every classRef: a value can always be constructed through. */
|
|
3376
3776
|
export function classValueRef(lowerer, info, blame) {
|
|
3377
3777
|
const display = info.def.name.replace(/^%|^%m\d+\./, "");
|
|
3378
3778
|
fenceDecorationThrows(lowerer, info, blame);
|
|
@@ -3395,9 +3795,12 @@ export function classValueRef(lowerer, info, blame) {
|
|
|
3395
3795
|
}
|
|
3396
3796
|
if (lowerer.inheritsBuiltinEmitterCtor(info) ||
|
|
3397
3797
|
inheritsBuiltinStreamCtor(lowerer, info) ||
|
|
3398
|
-
(() => {
|
|
3399
|
-
|
|
3400
|
-
|
|
3798
|
+
(() => {
|
|
3799
|
+
for (let c = info.base; c; c = c.base)
|
|
3800
|
+
if (c.builtinEmitter || c.builtinStream !== undefined)
|
|
3801
|
+
return true;
|
|
3802
|
+
return false;
|
|
3803
|
+
})()) {
|
|
3401
3804
|
lowerer.unsupported("SC1090", blame, `classes extending builtin bases as values ('${display}' inherits a runtime-provided constructor)`);
|
|
3402
3805
|
}
|
|
3403
3806
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
@@ -3409,20 +3812,22 @@ export function classValueRef(lowerer, info, blame) {
|
|
|
3409
3812
|
};
|
|
3410
3813
|
}
|
|
3411
3814
|
/** Constructor-ABI equality — the classval widening rule: a classval(D)
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3815
|
+
* value may flow into a classval(C) slot only when D's completed
|
|
3816
|
+
* constructor signature equals C's (same count, modes, and ABI types),
|
|
3817
|
+
* which is what keeps newValue completion against C's one signature
|
|
3818
|
+
* sound for every value legally in the slot. */
|
|
3416
3819
|
export function ctorAbiEquals(lowerer, sub, sup) {
|
|
3417
3820
|
const a = sub.ctorParams;
|
|
3418
3821
|
const b = sup.ctorParams;
|
|
3419
|
-
return a.length === b.length &&
|
|
3822
|
+
return (a.length === b.length &&
|
|
3823
|
+
a.every((p, i) => p.mode === b[i].mode && typeEquals(p.type, b[i].type)));
|
|
3420
3824
|
}
|
|
3421
3825
|
/** Writable storage for an own static field named through its exact class.
|
|
3422
3826
|
* Inherited writes create a new subclass property in JS, so they must not
|
|
3423
3827
|
* update the declaring class's global. */
|
|
3424
3828
|
export function staticFieldWriteTarget(lowerer, access) {
|
|
3425
|
-
if (access.questionDotToken ||
|
|
3829
|
+
if (access.questionDotToken ||
|
|
3830
|
+
(!ts.isIdentifier(access.expression) && access.expression.kind !== ts.SyntaxKind.ThisKeyword))
|
|
3426
3831
|
return null;
|
|
3427
3832
|
const info = lowerer.exactClassOfReceiver(access.expression);
|
|
3428
3833
|
if (!info)
|
|
@@ -3439,20 +3844,23 @@ export function staticFieldWriteTarget(lowerer, access) {
|
|
|
3439
3844
|
return { id: found.field.globalId, type: found.field.type };
|
|
3440
3845
|
}
|
|
3441
3846
|
/** `C.x` where C is a class declared in the program and x a static
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3847
|
+
* member of its chain: field reads are the module global, static
|
|
3848
|
+
* methods become interned closures, and `.name` folds to the class's
|
|
3849
|
+
* compile-time name. Null for everything else — unresolved members
|
|
3850
|
+
* fall through to the ordinary chain so the static fence or the
|
|
3851
|
+
* generic member rejection names the site. */
|
|
3447
3852
|
export function lowerStaticFieldRead(lowerer, expr) {
|
|
3448
3853
|
if (expr.name.text === "prototype")
|
|
3449
3854
|
return null;
|
|
3450
3855
|
if (expr.questionDotToken)
|
|
3451
3856
|
return null;
|
|
3452
|
-
if (!ts.isIdentifier(expr.expression) &&
|
|
3857
|
+
if (!ts.isIdentifier(expr.expression) &&
|
|
3858
|
+
expr.expression.kind !== ts.SyntaxKind.ThisKeyword &&
|
|
3453
3859
|
exactClassOfReceiver(lowerer, expr.expression) === null)
|
|
3454
3860
|
return null;
|
|
3455
|
-
const symbol = ts.isIdentifier(expr.expression)
|
|
3861
|
+
const symbol = ts.isIdentifier(expr.expression)
|
|
3862
|
+
? lowerer.resolveValueSymbol(expr.expression)
|
|
3863
|
+
: null;
|
|
3456
3864
|
const info = (symbol ? lowerer.classBySymbol.get(symbol) : undefined) ??
|
|
3457
3865
|
// A require binding over `module.exports = class {…}` (the alias
|
|
3458
3866
|
// lands on the expression's own symbol): resolve/collect on demand,
|
|
@@ -3473,8 +3881,13 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
3473
3881
|
const loc = locOf(expr);
|
|
3474
3882
|
const found = findStaticOn(lowerer, info, expr.name.text);
|
|
3475
3883
|
if (hasRuntimeStatics(info) && !found?.field)
|
|
3476
|
-
return {
|
|
3477
|
-
|
|
3884
|
+
return {
|
|
3885
|
+
kind: "dynKeyGet",
|
|
3886
|
+
value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3887
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3888
|
+
type: DYN,
|
|
3889
|
+
loc,
|
|
3890
|
+
};
|
|
3478
3891
|
// A #private static resolves only through the DECLARING class's own
|
|
3479
3892
|
// name: in JS the brand lives on that one constructor object, so
|
|
3480
3893
|
// `D.#s` (a subclass receiver) throws Node's TypeError instead of
|
|
@@ -3503,25 +3916,38 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
3503
3916
|
return { kind: "strLit", value: info.def.jsName, type: STRING, loc };
|
|
3504
3917
|
}
|
|
3505
3918
|
if (info.callableBase)
|
|
3506
|
-
return {
|
|
3507
|
-
|
|
3919
|
+
return {
|
|
3920
|
+
kind: "dynKeyGet",
|
|
3921
|
+
value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3922
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3923
|
+
type: DYN,
|
|
3924
|
+
loc,
|
|
3925
|
+
};
|
|
3508
3926
|
const data = classStaticDataFor(lowerer, info, expr.name.text, loc);
|
|
3509
3927
|
if (data) {
|
|
3510
|
-
const value = {
|
|
3928
|
+
const value = {
|
|
3929
|
+
kind: "dynKeyGet",
|
|
3930
|
+
value: data,
|
|
3931
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc },
|
|
3932
|
+
type: DYN,
|
|
3933
|
+
loc,
|
|
3934
|
+
};
|
|
3511
3935
|
// JavaScript often assigns public statics after the class declaration.
|
|
3512
3936
|
// Their storage stays mutable and checked, while reads retain the
|
|
3513
3937
|
// checker's concrete type instead of losing the method receiver.
|
|
3514
|
-
const type = isJsSourceFile(expr.getSourceFile())
|
|
3938
|
+
const type = isJsSourceFile(expr.getSourceFile())
|
|
3939
|
+
? null
|
|
3940
|
+
: lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
3515
3941
|
return type ? lowerer.coerceToExpected(value, type) : value;
|
|
3516
3942
|
}
|
|
3517
3943
|
return null;
|
|
3518
3944
|
}
|
|
3519
3945
|
/** NamedEvaluation's answer for a class expression's `.name`: its own
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3946
|
+
* declared name, else the binding name when the expression is the
|
|
3947
|
+
* direct initializer of a variable declaration / the RHS of a simple
|
|
3948
|
+
* assignment / an object-literal property value / a default parameter —
|
|
3949
|
+
* "" everywhere else (array elements, call arguments). Verified against
|
|
3950
|
+
* Node for each shape. */
|
|
3525
3951
|
function namedEvaluationName(expr) {
|
|
3526
3952
|
if (expr.name)
|
|
3527
3953
|
return expr.name.text;
|
|
@@ -3530,7 +3956,9 @@ function namedEvaluationName(expr) {
|
|
|
3530
3956
|
p = p.parent;
|
|
3531
3957
|
if (ts.isVariableDeclaration(p) && ts.isIdentifier(p.name) && p.initializer !== undefined)
|
|
3532
3958
|
return p.name.text;
|
|
3533
|
-
if (ts.isBinaryExpression(p) &&
|
|
3959
|
+
if (ts.isBinaryExpression(p) &&
|
|
3960
|
+
p.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
3961
|
+
ts.isIdentifier(p.left))
|
|
3534
3962
|
return p.left.text;
|
|
3535
3963
|
if (ts.isPropertyAssignment(p) && ts.isIdentifier(p.name))
|
|
3536
3964
|
return p.name.text;
|
|
@@ -3567,19 +3995,28 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3567
3995
|
if (local && expr.members.some((member) => member.name && ts.isPrivateIdentifier(member.name))) {
|
|
3568
3996
|
lowerer.unsupported("SC1090", expr, "function-local classes with private brands");
|
|
3569
3997
|
}
|
|
3570
|
-
if (local &&
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3998
|
+
if (local &&
|
|
3999
|
+
(expr.typeParameters?.length ||
|
|
4000
|
+
decoratorNodesOf(expr).length ||
|
|
4001
|
+
expr.members.some((member) => decoratorNodesOf(member).length ||
|
|
4002
|
+
(!isJsSourceFile(expr.getSourceFile()) &&
|
|
4003
|
+
(ts.isClassStaticBlockDeclaration(member) ||
|
|
4004
|
+
ts
|
|
4005
|
+
.getModifiers(member)
|
|
4006
|
+
?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) ||
|
|
4007
|
+
(ts.isMethodDeclaration(member) && member.typeParameters?.length)))) {
|
|
3575
4008
|
lowerer.unsupported("SC1090", expr, "function-local classes with statics, decorators, or generic members");
|
|
3576
4009
|
}
|
|
3577
4010
|
lowerer.collectingExprClasses.add(expr);
|
|
3578
4011
|
try {
|
|
3579
|
-
if (local &&
|
|
4012
|
+
if (local &&
|
|
4013
|
+
lowerer.fnStack.length > 0 &&
|
|
4014
|
+
!lowerer.computedClassBases.has(lowerer.classNamer(expr))) {
|
|
3580
4015
|
const heritage = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
3581
|
-
if (heritage &&
|
|
3582
|
-
ts.
|
|
4016
|
+
if (heritage &&
|
|
4017
|
+
(ts.isCallExpression(heritage) ||
|
|
4018
|
+
(ts.isIdentifier(heritage) &&
|
|
4019
|
+
(lowerer.peekLocal(heritage) ?? lowerer.globalOf(heritage)) != null))) {
|
|
3583
4020
|
let value = lowerer.lowerExpr(heritage);
|
|
3584
4021
|
const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, heritage) : null;
|
|
3585
4022
|
if (known?.kind === "classval")
|
|
@@ -3601,7 +4038,10 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3601
4038
|
throw new PoisonError(); // collection poisoned and reported
|
|
3602
4039
|
if (local) {
|
|
3603
4040
|
info.def.localCaptures = [];
|
|
3604
|
-
info.def.fields.push({
|
|
4041
|
+
info.def.fields.push({
|
|
4042
|
+
name: `%classEnvironment:${info.def.name}`,
|
|
4043
|
+
type: { kind: "classval", className: info.def.name },
|
|
4044
|
+
});
|
|
3605
4045
|
info.localClass = { context: null, bodies: new Map(), captureSources: [], ready: false };
|
|
3606
4046
|
if (info.base?.localClass) {
|
|
3607
4047
|
const baseExpression = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
@@ -3619,10 +4059,17 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3619
4059
|
// drains it), which is JS's order for whole-initializer positions.
|
|
3620
4060
|
// Anything subtler (multi-declarator statements, arguments evaluated
|
|
3621
4061
|
// after other side effects) is a named fence, never a reordering.
|
|
3622
|
-
if (!local &&
|
|
4062
|
+
if (!local &&
|
|
4063
|
+
(info.callableBase ||
|
|
4064
|
+
info.def.baseValueGlobal ||
|
|
4065
|
+
info.runtimeStatics ||
|
|
4066
|
+
info.staticFields.length > 0 ||
|
|
4067
|
+
(info.staticBlocks?.length ?? 0) > 0)) {
|
|
3623
4068
|
let holder = expr.parent;
|
|
3624
|
-
while (ts.isParenthesizedExpression(holder) ||
|
|
3625
|
-
ts.
|
|
4069
|
+
while (ts.isParenthesizedExpression(holder) ||
|
|
4070
|
+
ts.isClassExpression(holder) ||
|
|
4071
|
+
ts.isHeritageClause(holder) ||
|
|
4072
|
+
ts.isExpressionWithTypeArguments(holder)) {
|
|
3626
4073
|
holder = holder.parent;
|
|
3627
4074
|
}
|
|
3628
4075
|
const wholeInit = (ts.isVariableDeclaration(holder) &&
|
|
@@ -3643,13 +4090,13 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
3643
4090
|
return info;
|
|
3644
4091
|
}
|
|
3645
4092
|
/** `class {…}` in expression position: a class definition bound to no
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
4093
|
+
* statement — once the static side is a value, the expression IS the
|
|
4094
|
+
* definition plus a classRef over it. A DECORATED class expression
|
|
4095
|
+
* whose decoration provably throws (the ambient-decorator shape) never
|
|
4096
|
+
* mints a class at all: evaluating the expression IS the
|
|
4097
|
+
* ReferenceError, so it lowers to exactly that read — every evaluation
|
|
4098
|
+
* throws identically, which is why the once-evaluated restriction and
|
|
4099
|
+
* the member fences don't apply. */
|
|
3653
4100
|
export function lowerClassExpression(lowerer, expr) {
|
|
3654
4101
|
if (decoratorNodesOf(expr).length > 0 ||
|
|
3655
4102
|
expr.members.some((m) => decoratorNodesOf(m).length > 0)) {
|
|
@@ -3664,8 +4111,13 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3664
4111
|
}
|
|
3665
4112
|
}
|
|
3666
4113
|
const info = lowerClassExpressionInfo(lowerer, expr);
|
|
3667
|
-
if (!info.localClass &&
|
|
3668
|
-
|
|
4114
|
+
if (!info.localClass &&
|
|
4115
|
+
!info.expressionInitializationEmitted &&
|
|
4116
|
+
(info.callableBase ||
|
|
4117
|
+
info.def.baseValueGlobal ||
|
|
4118
|
+
info.runtimeStatics ||
|
|
4119
|
+
info.staticFields.length > 0 ||
|
|
4120
|
+
(info.staticBlocks?.length ?? 0) > 0)) {
|
|
3669
4121
|
info.expressionInitializationEmitted = true;
|
|
3670
4122
|
lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
|
|
3671
4123
|
}
|
|
@@ -3681,7 +4133,11 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3681
4133
|
info.localClass.captureSources = context.captureSources;
|
|
3682
4134
|
if (info.localClass.baseExpression && info.base) {
|
|
3683
4135
|
info.def.localBaseCapture = info.def.localCaptures.length;
|
|
3684
|
-
info.def.localCaptures.push({
|
|
4136
|
+
info.def.localCaptures.push({
|
|
4137
|
+
localId: "%base",
|
|
4138
|
+
name: "base",
|
|
4139
|
+
type: { kind: "classval", className: info.base.def.name },
|
|
4140
|
+
});
|
|
3685
4141
|
}
|
|
3686
4142
|
info.localClass.ready = true;
|
|
3687
4143
|
lowerer.onExprClassCollected?.(info);
|
|
@@ -3701,18 +4157,47 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3701
4157
|
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3702
4158
|
const boxed = { kind: "dynFrom", value: clsRef, type: DYN, loc };
|
|
3703
4159
|
info.localPrototypeData = true;
|
|
3704
|
-
return initializeRuntimeStatics(lowerer, info, {
|
|
4160
|
+
return initializeRuntimeStatics(lowerer, info, {
|
|
4161
|
+
kind: "seqExpr",
|
|
4162
|
+
stmts: [
|
|
3705
4163
|
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3706
|
-
{
|
|
3707
|
-
|
|
3708
|
-
|
|
4164
|
+
{
|
|
4165
|
+
kind: "varDecl",
|
|
4166
|
+
localId: clsLocal.id,
|
|
4167
|
+
init: { ...value, captures: info.localClass.captureSources },
|
|
4168
|
+
loc,
|
|
4169
|
+
},
|
|
4170
|
+
{
|
|
4171
|
+
kind: "exprStmt",
|
|
4172
|
+
expr: { kind: "libCall", fn: "dyn.classInherit", args: [boxed, baseRef], type: DYN, loc },
|
|
4173
|
+
loc,
|
|
4174
|
+
},
|
|
4175
|
+
{
|
|
4176
|
+
kind: "exprStmt",
|
|
4177
|
+
expr: {
|
|
4178
|
+
kind: "libCall",
|
|
4179
|
+
fn: "dyn.classPrototype",
|
|
4180
|
+
args: [
|
|
4181
|
+
boxed,
|
|
3709
4182
|
{ kind: "libCall", fn: "dyn.classBasePrototype", args: [baseRef], type: DYN, loc },
|
|
3710
|
-
],
|
|
3711
|
-
|
|
4183
|
+
],
|
|
4184
|
+
type: DYN,
|
|
4185
|
+
loc,
|
|
4186
|
+
},
|
|
4187
|
+
loc,
|
|
4188
|
+
},
|
|
4189
|
+
],
|
|
4190
|
+
result: clsRef,
|
|
4191
|
+
type: value.type,
|
|
4192
|
+
loc,
|
|
4193
|
+
});
|
|
3712
4194
|
}
|
|
3713
4195
|
if (info.localClass?.baseExpression && info.base && value.kind === "classRef") {
|
|
3714
4196
|
const loc = locOf(expr);
|
|
3715
|
-
const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, {
|
|
4197
|
+
const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, {
|
|
4198
|
+
kind: "classval",
|
|
4199
|
+
className: info.base.def.name,
|
|
4200
|
+
});
|
|
3716
4201
|
const baseLocal = lowerer.declareHiddenLocal("%classBase", base.type);
|
|
3717
4202
|
baseLocal.boxed = true;
|
|
3718
4203
|
const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
|
|
@@ -3720,26 +4205,57 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
3720
4205
|
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3721
4206
|
const basePrototype = classPrototypeData(lowerer, info.base, loc, baseRef);
|
|
3722
4207
|
info.localPrototypeData = true;
|
|
3723
|
-
return initializeRuntimeStatics(lowerer, info, {
|
|
4208
|
+
return initializeRuntimeStatics(lowerer, info, {
|
|
4209
|
+
kind: "seqExpr",
|
|
4210
|
+
stmts: [
|
|
3724
4211
|
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3725
|
-
{
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
4212
|
+
{
|
|
4213
|
+
kind: "varDecl",
|
|
4214
|
+
localId: clsLocal.id,
|
|
4215
|
+
init: { ...value, captures: [...info.localClass.captureSources, baseLocal.id] },
|
|
4216
|
+
loc,
|
|
4217
|
+
},
|
|
4218
|
+
{
|
|
4219
|
+
kind: "exprStmt",
|
|
4220
|
+
expr: {
|
|
4221
|
+
kind: "libCall",
|
|
4222
|
+
fn: "dyn.classInherit",
|
|
4223
|
+
args: [
|
|
4224
|
+
{ kind: "dynFrom", value: clsRef, type: DYN, loc },
|
|
4225
|
+
{ kind: "dynFrom", value: baseRef, type: DYN, loc },
|
|
4226
|
+
],
|
|
4227
|
+
type: DYN,
|
|
4228
|
+
loc,
|
|
4229
|
+
},
|
|
4230
|
+
loc,
|
|
4231
|
+
},
|
|
4232
|
+
{
|
|
4233
|
+
kind: "exprStmt",
|
|
4234
|
+
expr: {
|
|
4235
|
+
kind: "libCall",
|
|
4236
|
+
fn: "dyn.classPrototype",
|
|
4237
|
+
args: [{ kind: "dynFrom", value: clsRef, type: DYN, loc }, basePrototype],
|
|
4238
|
+
type: DYN,
|
|
4239
|
+
loc,
|
|
4240
|
+
},
|
|
4241
|
+
loc,
|
|
4242
|
+
},
|
|
4243
|
+
],
|
|
4244
|
+
result: clsRef,
|
|
4245
|
+
type: value.type,
|
|
4246
|
+
loc,
|
|
4247
|
+
});
|
|
4248
|
+
}
|
|
4249
|
+
return info.localClass
|
|
4250
|
+
? initializeRuntimeStatics(lowerer, info, value.kind === "classRef" ? { ...value, captures: info.localClass.captureSources } : value)
|
|
4251
|
+
: value;
|
|
3736
4252
|
}
|
|
3737
4253
|
/** The EXACT class a receiver expression is statically known to BE (not
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
4254
|
+
* merely be typed by): the class name itself, or a `const` binding
|
|
4255
|
+
* whose initializer is a class expression / class name. Such receivers
|
|
4256
|
+
* can never hold a subclass at runtime, so static WRITES through them
|
|
4257
|
+
* hit the declaring class's storage exactly (the shadowing hazards of
|
|
4258
|
+
* general class values don't arise). Null for everything else. */
|
|
3743
4259
|
export function exactClassOfReceiver(lowerer, expr) {
|
|
3744
4260
|
if (ts.isPropertyAccessExpression(expr) && !expr.questionDotToken) {
|
|
3745
4261
|
const member = nsMemberIdentOf(lowerer, expr);
|
|
@@ -3750,7 +4266,9 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3750
4266
|
// receiver specialization; ordinary instance this remains an object.
|
|
3751
4267
|
if (expr.kind === ts.SyntaxKind.ThisKeyword) {
|
|
3752
4268
|
const receiver = lowerer.resolveThis();
|
|
3753
|
-
return receiver?.type.kind === "classval"
|
|
4269
|
+
return receiver?.type.kind === "classval"
|
|
4270
|
+
? (lowerer.classes.get(receiver.type.className) ?? null)
|
|
4271
|
+
: null;
|
|
3754
4272
|
}
|
|
3755
4273
|
if (!ts.isIdentifier(expr))
|
|
3756
4274
|
return null;
|
|
@@ -3765,7 +4283,9 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3765
4283
|
if (direct)
|
|
3766
4284
|
return direct.classDecorators?.valueGlobalId !== undefined ? null : direct;
|
|
3767
4285
|
const decl = lowerer.checker.valueDeclarationOf(symbol);
|
|
3768
|
-
if (!decl ||
|
|
4286
|
+
if (!decl ||
|
|
4287
|
+
!ts.isVariableDeclaration(decl) ||
|
|
4288
|
+
decl.initializer === undefined ||
|
|
3769
4289
|
!ts.isVariableDeclarationList(decl.parent) ||
|
|
3770
4290
|
(decl.parent.flags & ts.NodeFlags.Const) === 0) {
|
|
3771
4291
|
return null;
|
|
@@ -3785,20 +4305,20 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
3785
4305
|
return null;
|
|
3786
4306
|
}
|
|
3787
4307
|
/** The class a PROPERTY-ASSIGNMENT binding pins — the salsa/CJS
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
4308
|
+
* declaration forms of a class expression: `Common.I = class {…}`
|
|
4309
|
+
* (expando members of a plain object), `exports.I = class {…}` /
|
|
4310
|
+
* `module.exports.I = class {…}` (CJS member exports), and
|
|
4311
|
+
* `module.exports = class {…}` (the whole-export replacement, whose
|
|
4312
|
+
* export symbol requirer bindings alias to). The symbol arrives in two
|
|
4313
|
+
* shapes — an ALIAS resolving to the class expression's own symbol
|
|
4314
|
+
* (valueDeclaration IS the ts.ClassExpression), or the expando property
|
|
4315
|
+
* symbol whose declarations are the assignment BinaryExpressions — and
|
|
4316
|
+
* both pin the class exactly when ONE top-level assignment declares it:
|
|
4317
|
+
* a reassigned property is a dynamic binding (the runtime class is
|
|
4318
|
+
* whichever assignment ran last), so it answers null and the caller's
|
|
4319
|
+
* fence names it. Collection is on demand and idempotent
|
|
4320
|
+
* (lowerClassExpressionInfo), so resolution order between files and
|
|
4321
|
+
* passes never matters. */
|
|
3802
4322
|
export function propertyAssignedClassInfoOf(lowerer, symbol) {
|
|
3803
4323
|
if (!symbol)
|
|
3804
4324
|
return null;
|
|
@@ -3840,22 +4360,25 @@ export function propertyAssignedClassInfoOf(lowerer, symbol) {
|
|
|
3840
4360
|
return info;
|
|
3841
4361
|
}
|
|
3842
4362
|
/** The top-level `… = <this class expression>` assignment a class
|
|
3843
|
-
|
|
4363
|
+
* expression is the (paren-unwrapped) RHS of, or null. */
|
|
3844
4364
|
function enclosingTopLevelClassAssignment(expr) {
|
|
3845
4365
|
let value = expr;
|
|
3846
4366
|
while (ts.isParenthesizedExpression(value.parent))
|
|
3847
4367
|
value = value.parent;
|
|
3848
4368
|
const p = value.parent;
|
|
3849
|
-
if (!ts.isBinaryExpression(p) ||
|
|
3850
|
-
p.
|
|
4369
|
+
if (!ts.isBinaryExpression(p) ||
|
|
4370
|
+
p.operatorToken.kind !== ts.SyntaxKind.EqualsToken ||
|
|
4371
|
+
p.right !== value ||
|
|
4372
|
+
!ts.isExpressionStatement(p.parent) ||
|
|
4373
|
+
!ts.isSourceFile(p.parent.parent)) {
|
|
3851
4374
|
return null;
|
|
3852
4375
|
}
|
|
3853
4376
|
return p;
|
|
3854
4377
|
}
|
|
3855
4378
|
/** How many top-level statements of the file assign the same target as
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
4379
|
+
* `assign` (textual LHS match — `module.exports`, `exports.I`,
|
|
4380
|
+
* `Common.I`): a second assignment makes the binding dynamic, so
|
|
4381
|
+
* callers refuse to pin the first one's class. */
|
|
3859
4382
|
function countAssignmentsTo(assign) {
|
|
3860
4383
|
const sf = assign.getSourceFile();
|
|
3861
4384
|
// `exports.I` and `module.exports.I` are the SAME binding in Node
|
|
@@ -3871,7 +4394,8 @@ function countAssignmentsTo(assign) {
|
|
|
3871
4394
|
if (!ts.isExpressionStatement(stmt))
|
|
3872
4395
|
continue;
|
|
3873
4396
|
const e = stmt.expression;
|
|
3874
|
-
if (ts.isBinaryExpression(e) &&
|
|
4397
|
+
if (ts.isBinaryExpression(e) &&
|
|
4398
|
+
e.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
3875
4399
|
canon(e.left) === target) {
|
|
3876
4400
|
n++;
|
|
3877
4401
|
}
|
|
@@ -3879,14 +4403,14 @@ function countAssignmentsTo(assign) {
|
|
|
3879
4403
|
return n;
|
|
3880
4404
|
}
|
|
3881
4405
|
/** `C.m(args)` / `X.m(args)` — static method calls, on the class name
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
4406
|
+
* directly or through a class VALUE. Resolution walks the chain
|
|
4407
|
+
* (nearest declarer, the compile-time prototype chain); through a
|
|
4408
|
+
* VALUE the call devirtualizes exactly when no strict descendant
|
|
4409
|
+
* redeclares the member (values never leave the static class's
|
|
4410
|
+
* subtree). A func-typed static FIELD in call position reads the
|
|
4411
|
+
* global and calls through the value. Null when the receiver isn't a
|
|
4412
|
+
* class name/value or the member doesn't resolve (the fences name the
|
|
4413
|
+
* site downstream). */
|
|
3890
4414
|
export function lowerStaticMethodCall(lowerer, call, access) {
|
|
3891
4415
|
if (access.questionDotToken)
|
|
3892
4416
|
return null;
|
|
@@ -3900,7 +4424,8 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3900
4424
|
// class expression: the receiver is exactly that class (the kept
|
|
3901
4425
|
// export assignment pins it) — the direct-name rules apply.
|
|
3902
4426
|
if (!ts.isIdentifier(access.expression)) {
|
|
3903
|
-
if (!isModuleExportsAccess(access.expression) ||
|
|
4427
|
+
if (!isModuleExportsAccess(access.expression) ||
|
|
4428
|
+
!isCjsJsFile(access.getSourceFile(), lowerer.program)) {
|
|
3904
4429
|
let receiverType = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
3905
4430
|
if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile())) {
|
|
3906
4431
|
const receiver = tryLowerExpression(lowerer, access.expression);
|
|
@@ -3919,8 +4444,13 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3919
4444
|
// A typed checker projection cannot turn a replaced field into a call
|
|
3920
4445
|
// to the class that originally occupied it.
|
|
3921
4446
|
const receiver = lowerer.lowerExprExpecting(access.expression, receiverType);
|
|
3922
|
-
return {
|
|
3923
|
-
|
|
4447
|
+
return {
|
|
4448
|
+
kind: "seqExpr",
|
|
4449
|
+
stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(access.expression) }],
|
|
4450
|
+
result,
|
|
4451
|
+
type: result.type,
|
|
4452
|
+
loc: locOf(call),
|
|
4453
|
+
};
|
|
3924
4454
|
}
|
|
3925
4455
|
const whole = cjsClassExprWholeExportOf(access.getSourceFile());
|
|
3926
4456
|
if (!whole)
|
|
@@ -3949,31 +4479,42 @@ export function lowerStaticMethodCall(lowerer, call, access) {
|
|
|
3949
4479
|
return staticCallOn(lowerer, call, access, info, throughValue);
|
|
3950
4480
|
}
|
|
3951
4481
|
/** True when a class-VALUE receiver can only hold `info`'s own class
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
4482
|
+
* object at runtime: the receiver provably IS the class
|
|
4483
|
+
* (exactClassOfReceiver — the name, or a const bound to the class
|
|
4484
|
+
* expression / class name), or `info` is a LEAF class, so no strict
|
|
4485
|
+
* descendant exists to flow into the slot (the static-write path's
|
|
4486
|
+
* rule — a rebindable decorated name rides this arm, since replacement
|
|
4487
|
+
* decorators fence any class with subclasses before minting the
|
|
4488
|
+
* rebindable global). Exactly then a #private static access through
|
|
4489
|
+
* the value always carries the declaring class's brand — Node's
|
|
4490
|
+
* TypeError cannot arise. */
|
|
3961
4491
|
function classValueIsExactlyOwn(lowerer, recv, info) {
|
|
3962
4492
|
return exactClassOfReceiver(lowerer, recv) === info || info.subclasses.length === 0;
|
|
3963
4493
|
}
|
|
3964
4494
|
function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
3965
4495
|
const loc = locOf(call);
|
|
3966
|
-
if (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field ||
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
4496
|
+
if ((hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field) ||
|
|
4497
|
+
(info.callableBase &&
|
|
4498
|
+
!findStaticOn(lowerer, info, access.name.text) &&
|
|
4499
|
+
!findGenericStaticOn(lowerer, info, access.name.text)))
|
|
4500
|
+
return {
|
|
4501
|
+
kind: "dynInvoke",
|
|
4502
|
+
recv: lowerer.lowerExprExpecting(access.expression, DYN),
|
|
4503
|
+
method: access.name.text,
|
|
4504
|
+
calleeName: access.name.text,
|
|
4505
|
+
args: call.arguments.map((argument) => lowerer.lowerExprExpecting(argument, DYN)),
|
|
4506
|
+
type: DYN,
|
|
4507
|
+
loc,
|
|
4508
|
+
};
|
|
3970
4509
|
// #private statics: through-a-VALUE receiver the call devirtualizes
|
|
3971
4510
|
// exactly when the value can only BE the declaring class
|
|
3972
4511
|
// (classValueIsExactlyOwn — a slot that could hold a descendant at
|
|
3973
4512
|
// runtime fences, since only the declaring class object carries the
|
|
3974
4513
|
// brand in JS), and the direct spelling resolves only on the
|
|
3975
4514
|
// declaring class itself — `D.#s` is Node's TypeError.
|
|
3976
|
-
if (access.name.text.startsWith("#") &&
|
|
4515
|
+
if (access.name.text.startsWith("#") &&
|
|
4516
|
+
throughValue &&
|
|
4517
|
+
!classValueIsExactlyOwn(lowerer, access.expression, info)) {
|
|
3977
4518
|
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
4519
|
}
|
|
3979
4520
|
const found = findStaticOn(lowerer, info, access.name.text);
|
|
@@ -3987,14 +4528,14 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
3987
4528
|
const gfound = findGenericStaticOn(lowerer, info, access.name.text);
|
|
3988
4529
|
if (!gfound)
|
|
3989
4530
|
return null;
|
|
3990
|
-
if (throughValue && staticShadowBelow(
|
|
4531
|
+
if (throughValue && staticShadowBelow(info, access.name.text)) {
|
|
3991
4532
|
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
4533
|
}
|
|
3993
4534
|
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, gfound.info, info, throughValue));
|
|
3994
4535
|
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
3995
4536
|
return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
|
|
3996
4537
|
}
|
|
3997
|
-
if (throughValue && staticShadowBelow(
|
|
4538
|
+
if (throughValue && staticShadowBelow(info, access.name.text)) {
|
|
3998
4539
|
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
4540
|
}
|
|
4000
4541
|
const specialized = findGenericStaticOn(lowerer, info, access.name.text);
|
|
@@ -4008,7 +4549,12 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
4008
4549
|
// call through the value (the ctor-assigned-callback pattern).
|
|
4009
4550
|
if (found.field.type.kind !== "func")
|
|
4010
4551
|
return null;
|
|
4011
|
-
const callee = {
|
|
4552
|
+
const callee = {
|
|
4553
|
+
kind: "varRef",
|
|
4554
|
+
localId: found.field.globalId,
|
|
4555
|
+
type: found.field.type,
|
|
4556
|
+
loc,
|
|
4557
|
+
};
|
|
4012
4558
|
const params = found.field.type.params;
|
|
4013
4559
|
const args = call.arguments.map((a, i) => lowerer.lowerExprExpecting(a, params[i]));
|
|
4014
4560
|
for (let i = args.length; i < params.length; i++) {
|
|
@@ -4018,17 +4564,32 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
4018
4564
|
}
|
|
4019
4565
|
args.push(absent);
|
|
4020
4566
|
}
|
|
4021
|
-
return {
|
|
4567
|
+
return {
|
|
4568
|
+
kind: "callValue",
|
|
4569
|
+
callee,
|
|
4570
|
+
receiver: lowerer.lowerExprExpecting(access.expression, DYN),
|
|
4571
|
+
args,
|
|
4572
|
+
type: found.field.type.ret,
|
|
4573
|
+
loc,
|
|
4574
|
+
};
|
|
4022
4575
|
}
|
|
4023
4576
|
if (found.method.member.body && hasStaticThis(found.method.member)) {
|
|
4024
|
-
const generic = found.method.receiverInfo ??= {
|
|
4025
|
-
decl: found.method.member,
|
|
4577
|
+
const generic = (found.method.receiverInfo ??= {
|
|
4578
|
+
decl: found.method.member,
|
|
4579
|
+
baseName: access.name.text,
|
|
4026
4580
|
qualifiedName: `%${found.declarer.def.name}.static:${access.name.text}`,
|
|
4027
|
-
typeParams: [],
|
|
4028
|
-
|
|
4581
|
+
typeParams: [],
|
|
4582
|
+
instances: new Map(),
|
|
4583
|
+
member: { cls: found.declarer, kind: "static" },
|
|
4584
|
+
});
|
|
4029
4585
|
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, generic, info, throughValue));
|
|
4030
|
-
return {
|
|
4031
|
-
|
|
4586
|
+
return {
|
|
4587
|
+
kind: "call",
|
|
4588
|
+
callee: instance.name,
|
|
4589
|
+
args: lowerer.completeArgs(call.arguments, instance.params, loc, call),
|
|
4590
|
+
type: instance.returnType,
|
|
4591
|
+
loc,
|
|
4592
|
+
};
|
|
4032
4593
|
}
|
|
4033
4594
|
const fnName = `%${found.declarer.def.name}.static:${access.name.text}`;
|
|
4034
4595
|
lowerer.noteEdge(fnName);
|
|
@@ -4047,22 +4608,27 @@ function staticMethodForReceiver(lowerer, access, method, receiver, throughValue
|
|
|
4047
4608
|
if (throughValue && !classValueIsExactlyOwn(lowerer, access.expression, receiver)) {
|
|
4048
4609
|
lowerer.unsupported("SC1090", access, "receiver-dependent static methods through a polymorphic class value");
|
|
4049
4610
|
}
|
|
4050
|
-
const instances = method.receiverSpecializations ??= new Map();
|
|
4611
|
+
const instances = (method.receiverSpecializations ??= new Map());
|
|
4051
4612
|
let specialized = instances.get(receiver.def.name);
|
|
4052
4613
|
if (!specialized) {
|
|
4053
|
-
specialized = {
|
|
4054
|
-
|
|
4614
|
+
specialized = {
|
|
4615
|
+
...method,
|
|
4616
|
+
qualifiedName: `${method.qualifiedName}%on.${receiver.def.name}`,
|
|
4617
|
+
instances: new Map(),
|
|
4618
|
+
staticReceiver: receiver,
|
|
4619
|
+
receiverSpecializations: new Map(),
|
|
4620
|
+
};
|
|
4055
4621
|
instances.set(receiver.def.name, specialized);
|
|
4056
4622
|
}
|
|
4057
4623
|
return specialized;
|
|
4058
4624
|
}
|
|
4059
4625
|
/** Static member access through a class VALUE (`X.m` where X is
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4626
|
+
* classval-typed): devirtualized — the member resolves against the
|
|
4627
|
+
* static class's chain, exact when no strict descendant redeclares it
|
|
4628
|
+
* (values in the slot never leave the subtree). `X.name` is the one
|
|
4629
|
+
* genuinely dynamic member: the class.name libCall reads the runtime
|
|
4630
|
+
* class object's stored name. Null when the receiver isn't a class
|
|
4631
|
+
* value or the member doesn't resolve. */
|
|
4066
4632
|
export function lowerClassValueProperty(lowerer, expr) {
|
|
4067
4633
|
if (expr.questionDotToken)
|
|
4068
4634
|
return null;
|
|
@@ -4072,9 +4638,16 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4072
4638
|
const loc = locOf(expr);
|
|
4073
4639
|
const member = expr.name.text;
|
|
4074
4640
|
const info = lowerer.classes.get(recvT.className);
|
|
4075
|
-
if (info &&
|
|
4076
|
-
|
|
4077
|
-
|
|
4641
|
+
if (info &&
|
|
4642
|
+
((hasRuntimeStatics(info) && !findStaticOn(lowerer, info, member)?.field) ||
|
|
4643
|
+
(info.callableBase && !findStaticOn(lowerer, info, member))))
|
|
4644
|
+
return {
|
|
4645
|
+
kind: "dynKeyGet",
|
|
4646
|
+
value: lowerer.lowerExprExpecting(expr.expression, DYN),
|
|
4647
|
+
key: { kind: "strLit", value: member, type: STRING, loc },
|
|
4648
|
+
type: DYN,
|
|
4649
|
+
loc,
|
|
4650
|
+
};
|
|
4078
4651
|
// `X.name` reads the RUNTIME class object's stored name — the one
|
|
4079
4652
|
// genuinely dynamic member. It CONSUMES the receiver (no evaluation
|
|
4080
4653
|
// is discarded), so any receiver expression is fine here.
|
|
@@ -4119,7 +4692,7 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4119
4692
|
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
4693
|
}
|
|
4121
4694
|
}
|
|
4122
|
-
if (staticShadowBelow(
|
|
4695
|
+
if (staticShadowBelow(info, member)) {
|
|
4123
4696
|
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
4697
|
}
|
|
4125
4698
|
if (found.field !== undefined) {
|
|
@@ -4128,18 +4701,21 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
4128
4701
|
return staticMethodValue(lowerer, found.declarer, member, found.method, expr, loc);
|
|
4129
4702
|
}
|
|
4130
4703
|
/** An abstract method's signature — lambdaSignature minus the body check
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4704
|
+
* (an abstract declaration IS exactly a signature; tsc rejects the
|
|
4705
|
+
* async/generator/generic-with-body combinations before this runs, and
|
|
4706
|
+
* the generic case fences at the caller). */
|
|
4134
4707
|
function abstractMemberSignature(lowerer, member) {
|
|
4135
4708
|
for (const param of member.parameters) {
|
|
4136
4709
|
if (!ts.isIdentifier(param.name))
|
|
4137
4710
|
lowerer.unsupported("SC1031", param);
|
|
4138
4711
|
}
|
|
4139
|
-
return {
|
|
4712
|
+
return {
|
|
4713
|
+
shapes: lowerer.paramShapes(member.parameters),
|
|
4714
|
+
ret: lowerer.declaredReturnType(member, member.name),
|
|
4715
|
+
};
|
|
4140
4716
|
}
|
|
4141
4717
|
/** The nearest declaration of `name` at or above `info` — the method a
|
|
4142
|
-
|
|
4718
|
+
* receiver of that static class runs when nothing below overrides it. */
|
|
4143
4719
|
export function findMethodOn(lowerer, info, name) {
|
|
4144
4720
|
for (let c = info; c; c = c.base) {
|
|
4145
4721
|
const sig = c.methods.get(name);
|
|
@@ -4157,8 +4733,8 @@ export function isSubclassOf(lowerer, sub, sup) {
|
|
|
4157
4733
|
return false;
|
|
4158
4734
|
}
|
|
4159
4735
|
/** In an extends-hierarchy (as base or derived): the class carries a
|
|
4160
|
-
|
|
4161
|
-
|
|
4736
|
+
* vtable and participates in dynamic instanceof; standalone classes keep
|
|
4737
|
+
* their exact pre-inheritance layout and behavior. */
|
|
4162
4738
|
export function inHierarchy(lowerer, info) {
|
|
4163
4739
|
// The runtime emitter class is ALWAYS a hierarchy member: ScrEmitter
|
|
4164
4740
|
// carries its vtable word whether or not the program subclasses it
|
|
@@ -4166,10 +4742,10 @@ export function inHierarchy(lowerer, info) {
|
|
|
4166
4742
|
return info.base !== null || info.subclasses.length > 0 || info.builtinEmitter === true;
|
|
4167
4743
|
}
|
|
4168
4744
|
/** True when some STRICT descendant of `info` declares `name` with a BODY
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4745
|
+
* — the whole-program devirtualization test: a call through this static
|
|
4746
|
+
* class can reach a distinct implementation, so it must dispatch
|
|
4747
|
+
* dynamically. Abstract re-declarations don't count (they carry no
|
|
4748
|
+
* implementation; the concrete ones below them do, via the recursion). */
|
|
4173
4749
|
export function overrideBelow(lowerer, info, name) {
|
|
4174
4750
|
return info.subclasses.some((s) => {
|
|
4175
4751
|
const m = s.methods.get(name);
|
|
@@ -4177,7 +4753,7 @@ export function overrideBelow(lowerer, info, name) {
|
|
|
4177
4753
|
});
|
|
4178
4754
|
}
|
|
4179
4755
|
/** The nearest GENERIC-method declaration of `name` at/above `info` —
|
|
4180
|
-
|
|
4756
|
+
* findMethodOn's twin over the genericMethods tables. */
|
|
4181
4757
|
export function findGenericMethodOn(lowerer, info, name) {
|
|
4182
4758
|
for (let c = info; c; c = c.base) {
|
|
4183
4759
|
const gm = c.genericMethods?.get(name);
|
|
@@ -4187,11 +4763,11 @@ export function findGenericMethodOn(lowerer, info, name) {
|
|
|
4187
4763
|
return null;
|
|
4188
4764
|
}
|
|
4189
4765
|
/** 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(
|
|
4766
|
+
* method `name` — overrideBelow's twin: generic methods have no vtable
|
|
4767
|
+
* slot, so a call that could reach an override compiles only when the
|
|
4768
|
+
* receiver's runtime class is statically exact. */
|
|
4769
|
+
export function genericOverrideBelow(info, name) {
|
|
4770
|
+
return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(s, name));
|
|
4195
4771
|
}
|
|
4196
4772
|
/** Discover inherited data writes before any base storage ABI is chosen.
|
|
4197
4773
|
* The checker does not widen a base field for assignments in JS subclasses. */
|
|
@@ -4200,7 +4776,8 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4200
4776
|
if (!isJsSourceFile(file))
|
|
4201
4777
|
continue;
|
|
4202
4778
|
ts.walkPreorder(file, (node) => {
|
|
4203
|
-
if ((!ts.isClassDeclaration(node) && !ts.isClassExpression(node)) ||
|
|
4779
|
+
if ((!ts.isClassDeclaration(node) && !ts.isClassExpression(node)) ||
|
|
4780
|
+
!node.heritageClauses?.length)
|
|
4204
4781
|
return;
|
|
4205
4782
|
const writes = new Map();
|
|
4206
4783
|
const addWrite = (name, expression) => {
|
|
@@ -4211,14 +4788,17 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4211
4788
|
writes.set(name, [expression]);
|
|
4212
4789
|
};
|
|
4213
4790
|
const scan = (part) => {
|
|
4214
|
-
if (ts.isClassDeclaration(part) ||
|
|
4215
|
-
ts.
|
|
4791
|
+
if (ts.isClassDeclaration(part) ||
|
|
4792
|
+
ts.isClassExpression(part) ||
|
|
4793
|
+
(ts.isFunctionLike(part) && !ts.isArrowFunction(part)))
|
|
4216
4794
|
return;
|
|
4217
4795
|
if (ts.isBinaryExpression(part) && part.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
4218
4796
|
const left = part.left;
|
|
4219
|
-
if (ts.isPropertyAccessExpression(left) &&
|
|
4797
|
+
if (ts.isPropertyAccessExpression(left) &&
|
|
4798
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword)
|
|
4220
4799
|
addWrite(left.name.text, part.right);
|
|
4221
|
-
else if (ts.isElementAccessExpression(left) &&
|
|
4800
|
+
else if (ts.isElementAccessExpression(left) &&
|
|
4801
|
+
left.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
4222
4802
|
const name = lowerer.foldedStringKeyOf(left.argumentExpression);
|
|
4223
4803
|
if (name !== null)
|
|
4224
4804
|
addWrite(name, part.right);
|
|
@@ -4230,12 +4810,16 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4230
4810
|
if (member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))
|
|
4231
4811
|
continue;
|
|
4232
4812
|
if (ts.isPropertyDeclaration(member) && member.initializer) {
|
|
4233
|
-
const name = ts.isPrivateIdentifier(member.name)
|
|
4813
|
+
const name = ts.isPrivateIdentifier(member.name)
|
|
4814
|
+
? null
|
|
4815
|
+
: classMemberNameOf(lowerer, member.name);
|
|
4234
4816
|
if (name !== null)
|
|
4235
4817
|
addWrite(name, member.initializer);
|
|
4236
4818
|
scan(member.initializer);
|
|
4237
4819
|
}
|
|
4238
|
-
if (ts.isConstructorDeclaration(member) ||
|
|
4820
|
+
if (ts.isConstructorDeclaration(member) ||
|
|
4821
|
+
ts.isMethodDeclaration(member) ||
|
|
4822
|
+
ts.isAccessor(member)) {
|
|
4239
4823
|
if (member.body)
|
|
4240
4824
|
scan(member.body);
|
|
4241
4825
|
}
|
|
@@ -4259,11 +4843,13 @@ export function collectInheritedJsFieldWrites(lowerer, files) {
|
|
|
4259
4843
|
let owner = declaration.parent;
|
|
4260
4844
|
while (owner && !ts.isClassDeclaration(owner) && !ts.isClassExpression(owner))
|
|
4261
4845
|
owner = owner.parent;
|
|
4262
|
-
if (!owner ||
|
|
4846
|
+
if (!owner ||
|
|
4847
|
+
(!ts.isClassDeclaration(owner) && !ts.isClassExpression(owner)) ||
|
|
4848
|
+
!isJsSourceFile(owner.getSourceFile()))
|
|
4263
4849
|
continue;
|
|
4264
4850
|
let fields = lowerer.inheritedJsFieldWrites.get(owner);
|
|
4265
4851
|
if (!fields)
|
|
4266
|
-
lowerer.inheritedJsFieldWrites.set(owner, fields = new Map());
|
|
4852
|
+
lowerer.inheritedJsFieldWrites.set(owner, (fields = new Map()));
|
|
4267
4853
|
const existing = fields.get(name);
|
|
4268
4854
|
if (existing)
|
|
4269
4855
|
existing.push(...expressions);
|
|
@@ -4292,24 +4878,35 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4292
4878
|
ts.walkPreorder(file, (node) => {
|
|
4293
4879
|
if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
|
|
4294
4880
|
return;
|
|
4295
|
-
const name = ts.isPropertyAccessExpression(node)
|
|
4296
|
-
|
|
4881
|
+
const name = ts.isPropertyAccessExpression(node)
|
|
4882
|
+
? node.name.text
|
|
4883
|
+
: ts.isStringLiteralLike(node.argumentExpression)
|
|
4884
|
+
? node.argumentExpression.text
|
|
4885
|
+
: null;
|
|
4297
4886
|
if (name === null)
|
|
4298
4887
|
return;
|
|
4299
4888
|
const prototype = ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "prototype";
|
|
4300
|
-
const assigned = ts.isBinaryExpression(node.parent) &&
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4889
|
+
const assigned = ts.isBinaryExpression(node.parent) &&
|
|
4890
|
+
node.parent.left === node &&
|
|
4891
|
+
node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
|
|
4892
|
+
const symbol = !assigned
|
|
4893
|
+
? undefined
|
|
4894
|
+
: ts.isPropertyAccessExpression(node)
|
|
4895
|
+
? lowerer.checker.getSymbolAtLocation(node.name)
|
|
4896
|
+
: lowerer.checker.getPropertyOfType(lowerer.typeOf(node.expression), name);
|
|
4897
|
+
if (prototype ||
|
|
4898
|
+
(symbol && lowerer.checker.declarationsOf(symbol).some(ts.isMethodDeclaration))) {
|
|
4305
4899
|
lowerer.prototypeMethodAccesses.set(name, node);
|
|
4306
4900
|
}
|
|
4307
4901
|
});
|
|
4308
4902
|
const visit = (node) => {
|
|
4309
4903
|
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
|
4310
|
-
const accessors = node.members.filter((member) => (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) &&
|
|
4904
|
+
const accessors = node.members.filter((member) => (ts.isGetAccessorDeclaration(member) || ts.isSetAccessorDeclaration(member)) &&
|
|
4905
|
+
ts.isIdentifier(member.name) &&
|
|
4311
4906
|
!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
4312
|
-
if (node.heritageClauses?.length &&
|
|
4907
|
+
if (node.heritageClauses?.length &&
|
|
4908
|
+
accessors.length &&
|
|
4909
|
+
isJsSourceFile(node.getSourceFile())) {
|
|
4313
4910
|
const symbol = lowerer.typeOf(node).getSymbol();
|
|
4314
4911
|
const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
|
|
4315
4912
|
const seen = new Set();
|
|
@@ -4324,12 +4921,15 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4324
4921
|
continue;
|
|
4325
4922
|
const property = lowerer.checker.getPropertyOfType(base, member.name.text);
|
|
4326
4923
|
for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
|
|
4327
|
-
if ((ts.isGetAccessorDeclaration(declaration) ||
|
|
4924
|
+
if ((ts.isGetAccessorDeclaration(declaration) ||
|
|
4925
|
+
ts.isSetAccessorDeclaration(declaration)) &&
|
|
4926
|
+
isJsSourceFile(declaration.getSourceFile())) {
|
|
4328
4927
|
lowerer.checkedVirtualJsAccessors.add(declaration);
|
|
4329
4928
|
lowerer.checkedVirtualJsAccessors.add(member);
|
|
4330
4929
|
for (const twin of node.members)
|
|
4331
4930
|
if ((ts.isGetAccessorDeclaration(twin) || ts.isSetAccessorDeclaration(twin)) &&
|
|
4332
|
-
ts.isIdentifier(twin.name) &&
|
|
4931
|
+
ts.isIdentifier(twin.name) &&
|
|
4932
|
+
twin.name.text === member.name.text)
|
|
4333
4933
|
lowerer.checkedVirtualJsAccessors.add(twin);
|
|
4334
4934
|
}
|
|
4335
4935
|
}
|
|
@@ -4340,7 +4940,8 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4340
4940
|
if (instance)
|
|
4341
4941
|
markAccessors(instance);
|
|
4342
4942
|
}
|
|
4343
|
-
const members = node.members.filter((member) => ts.isMethodDeclaration(member) &&
|
|
4943
|
+
const members = node.members.filter((member) => ts.isMethodDeclaration(member) &&
|
|
4944
|
+
ts.isIdentifier(member.name) &&
|
|
4344
4945
|
!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
4345
4946
|
if (node.heritageClauses?.length && members.length > 0) {
|
|
4346
4947
|
const symbol = lowerer.typeOf(node).getSymbol();
|
|
@@ -4357,14 +4958,18 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4357
4958
|
continue;
|
|
4358
4959
|
const property = lowerer.checker.getPropertyOfType(base, member.name.text);
|
|
4359
4960
|
for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
|
|
4360
|
-
if (ts.isMethodDeclaration(declaration) &&
|
|
4961
|
+
if (ts.isMethodDeclaration(declaration) &&
|
|
4962
|
+
isJsSourceFile(declaration.getSourceFile())) {
|
|
4361
4963
|
lowerer.virtualJsMethods.add(declaration);
|
|
4362
|
-
if (isJsSourceFile(member.getSourceFile()) &&
|
|
4363
|
-
!member.
|
|
4964
|
+
if (isJsSourceFile(member.getSourceFile()) &&
|
|
4965
|
+
!member.typeParameters &&
|
|
4966
|
+
!member.asteriskToken &&
|
|
4967
|
+
!member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
4364
4968
|
!bodyReadsArguments(member) &&
|
|
4365
4969
|
member.parameters.every((p) => !p.dotDotDotToken)) {
|
|
4366
4970
|
lowerer.virtualJsMethodArity.set(declaration, Math.max(lowerer.virtualJsMethodArity.get(declaration) ?? 0, member.parameters.length));
|
|
4367
|
-
const checked = !declaration.typeParameters &&
|
|
4971
|
+
const checked = !declaration.typeParameters &&
|
|
4972
|
+
!declaration.asteriskToken &&
|
|
4368
4973
|
!declaration.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
4369
4974
|
!bodyReadsArguments(declaration) &&
|
|
4370
4975
|
[...member.parameters, ...declaration.parameters].every((p) => !p.dotDotDotToken);
|
|
@@ -4401,7 +5006,8 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4401
5006
|
while (changed) {
|
|
4402
5007
|
changed = false;
|
|
4403
5008
|
for (const [base, derived] of families) {
|
|
4404
|
-
if (!lowerer.checkedVirtualJsValueReturns.has(base) &&
|
|
5009
|
+
if (!lowerer.checkedVirtualJsValueReturns.has(base) &&
|
|
5010
|
+
!lowerer.checkedVirtualJsValueReturns.has(derived))
|
|
4405
5011
|
continue;
|
|
4406
5012
|
for (const member of [base, derived])
|
|
4407
5013
|
if (!lowerer.checkedVirtualJsValueReturns.has(member)) {
|
|
@@ -4412,11 +5018,11 @@ export function collectVirtualJsMethods(lowerer, files) {
|
|
|
4412
5018
|
}
|
|
4413
5019
|
}
|
|
4414
5020
|
/** The receiver's EXACT runtime class, when the expression proves it: a
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
5021
|
+
* `new C(...)` expression directly, or a const binding initialized with
|
|
5022
|
+
* one (the binding can never be reassigned to a subclass instance).
|
|
5023
|
+
* The class is read off the mapped INITIALIZER type — a `const b: Base =
|
|
5024
|
+
* new D()` receiver is exactly D, not its annotation. Distinct from
|
|
5025
|
+
* exactClassOfReceiver, which answers for CLASS-VALUE receivers. */
|
|
4420
5026
|
export function exactInstanceClassOf(lowerer, expr) {
|
|
4421
5027
|
let e = expr;
|
|
4422
5028
|
while (ts.isParenthesizedExpression(e))
|
|
@@ -4434,7 +5040,9 @@ export function exactInstanceClassOf(lowerer, expr) {
|
|
|
4434
5040
|
return null;
|
|
4435
5041
|
const symbol = lowerer.resolveValueSymbol(e);
|
|
4436
5042
|
const decl = symbol ? lowerer.checker.valueDeclarationOf(symbol) : undefined;
|
|
4437
|
-
if (!decl ||
|
|
5043
|
+
if (!decl ||
|
|
5044
|
+
!ts.isVariableDeclaration(decl) ||
|
|
5045
|
+
decl.initializer === undefined ||
|
|
4438
5046
|
!ts.isVariableDeclarationList(decl.parent) ||
|
|
4439
5047
|
(decl.parent.flags & ts.NodeFlags.Const) === 0) {
|
|
4440
5048
|
return null;
|
|
@@ -4445,17 +5053,17 @@ export function exactInstanceClassOf(lowerer, expr) {
|
|
|
4445
5053
|
return classOfNew(init);
|
|
4446
5054
|
}
|
|
4447
5055
|
/** `const r: Repo = new MemRepo()` where EVERY member of the annotation's
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
5056
|
+
* checker type is a generic-callable method (`interface Repo { get<T>(id:
|
|
5057
|
+
* string): T }`): the record shape maps EMPTY — generic members are
|
|
5058
|
+
* excluded (no closure slot can hold a generic function) — so the
|
|
5059
|
+
* copy-reshape width coercion would DROP the exact class the method
|
|
5060
|
+
* calls monomorphize against, and in JS the binding IS the instance (no
|
|
5061
|
+
* copy exists). The binding keeps the initializer's class
|
|
5062
|
+
* representation instead: generic-method calls resolve like class-typed
|
|
5063
|
+
* receivers (exactInstanceClassOf reads the same const+new discipline),
|
|
5064
|
+
* and uses that want the empty record width-coerce at the use site.
|
|
5065
|
+
* Const + direct `new` only — a reassignable binding or a produced
|
|
5066
|
+
* value keeps today's record story and its fences. */
|
|
4459
5067
|
export function genericIfaceBindingKeepsClass(lowerer, decl, declaredType) {
|
|
4460
5068
|
if (declaredType.kind !== "record")
|
|
4461
5069
|
return false;
|
|
@@ -4478,17 +5086,17 @@ export function genericIfaceBindingKeepsClass(lowerer, decl, declaredType) {
|
|
|
4478
5086
|
return props.every((p) => isGenericCallableMemberType(lowerer.checker.getTypeOfSymbol(p), lowerer.checker));
|
|
4479
5087
|
}
|
|
4480
5088
|
/** `recv.m<T>(args)` — a GENERIC method call, dispatched STATICALLY: the
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
5089
|
+
* checker's resolved signature (type arguments substituted, inferred or
|
|
5090
|
+
* explicit) keys one instantiation of the nearest declarer's body, and
|
|
5091
|
+
* the call is a direct `call` of `%C.m%n` over the (up/down)cast
|
|
5092
|
+
* receiver. No per-instantiation vtable slots exist, so a receiver whose
|
|
5093
|
+
* runtime class could OVERRIDE the method (genericOverrideBelow) must be
|
|
5094
|
+
* statically exact (exactInstanceClassOf) — the override set then
|
|
5095
|
+
* resolves at compile time — or fences by name. */
|
|
4488
5096
|
export function lowerClassGenericMethodCall(lowerer, call, access, recvInfo, found, recvIr) {
|
|
4489
5097
|
const name = access.name.text;
|
|
4490
5098
|
let { declarer, info } = found;
|
|
4491
|
-
if (genericOverrideBelow(
|
|
5099
|
+
if (genericOverrideBelow(recvInfo, name)) {
|
|
4492
5100
|
const exact = exactInstanceClassOf(lowerer, access.expression);
|
|
4493
5101
|
const refound = exact ? findGenericMethodOn(lowerer, exact, name) : null;
|
|
4494
5102
|
if (!refound) {
|
|
@@ -4509,14 +5117,26 @@ export function lowerClassGenericMethodCall(lowerer, call, access, recvInfo, fou
|
|
|
4509
5117
|
// path; the EXACT path can land below it (a base-typed const provably
|
|
4510
5118
|
// holding the subclass) — that direction is the checker-grade downcast
|
|
4511
5119
|
// (the exactness proof is static, stronger than an instanceof guard).
|
|
4512
|
-
const thisArg = receiver.type.kind === "object" &&
|
|
4513
|
-
|
|
5120
|
+
const thisArg = receiver.type.kind === "object" &&
|
|
5121
|
+
isSubclassOf(lowerer, declarer.def.name, receiver.type.className)
|
|
5122
|
+
? {
|
|
5123
|
+
kind: "downcast",
|
|
5124
|
+
value: receiver,
|
|
5125
|
+
type: { kind: "object", className: declarer.def.name },
|
|
5126
|
+
loc,
|
|
5127
|
+
}
|
|
4514
5128
|
: upcastTo(lowerer, receiver, declarer.def.name);
|
|
4515
5129
|
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
4516
|
-
return {
|
|
5130
|
+
return {
|
|
5131
|
+
kind: "call",
|
|
5132
|
+
callee: instance.name,
|
|
5133
|
+
args: [thisArg, ...args],
|
|
5134
|
+
type: instance.returnType,
|
|
5135
|
+
loc,
|
|
5136
|
+
};
|
|
4517
5137
|
}
|
|
4518
5138
|
/** Wraps a derived-class expression in an upcast when the target base
|
|
4519
|
-
|
|
5139
|
+
* class differs (a no-op reinterpret at runtime; keeps IR types exact). */
|
|
4520
5140
|
export function upcastTo(lowerer, expr, className) {
|
|
4521
5141
|
if (expr.type.kind === "object" && expr.type.className !== className) {
|
|
4522
5142
|
return { kind: "upcast", value: expr, type: { kind: "object", className }, loc: expr.loc };
|
|
@@ -4524,12 +5144,12 @@ export function upcastTo(lowerer, expr, className) {
|
|
|
4524
5144
|
return expr;
|
|
4525
5145
|
}
|
|
4526
5146
|
/** Constructor and methods become module functions `%C.name` whose first
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
5147
|
+
* param is `this`. Field initializers run in declaration order at the top
|
|
5148
|
+
* of a base class's constructor; a derived class's run right after its
|
|
5149
|
+
* super() call returns (tsc/JS initialization order). Reachability gates
|
|
5150
|
+
* each member independently: an unreached method body never lowers and
|
|
5151
|
+
* never emits (pinned by the corpus), while every override a reachable
|
|
5152
|
+
* virtualCall can dispatch to was marked by the discovery pass. */
|
|
4533
5153
|
/** True when a MIXIN class's constructor is the pure forwarding shape:
|
|
4534
5154
|
* exactly one rest parameter, `super(...args)` as the first statement,
|
|
4535
5155
|
* and no other reference to the parameter — the one rest-constructor
|
|
@@ -4563,7 +5183,9 @@ function mixinForwardingCtor(lowerer, ctor) {
|
|
|
4563
5183
|
ts.walkPreorder(ctor.body, (n) => {
|
|
4564
5184
|
if (n === spreadIdent)
|
|
4565
5185
|
return undefined;
|
|
4566
|
-
if (ts.isIdentifier(n) &&
|
|
5186
|
+
if (ts.isIdentifier(n) &&
|
|
5187
|
+
n.text === paramName.text &&
|
|
5188
|
+
lowerer.checker.getSymbolAtLocation(n) === paramSym) {
|
|
4567
5189
|
extraRef = true;
|
|
4568
5190
|
return "stop";
|
|
4569
5191
|
}
|
|
@@ -4585,7 +5207,9 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4585
5207
|
// demand-driven like generic-fn instances, not reachability units:
|
|
4586
5208
|
// they are never registered as units, so wantBody's name-keyed gate
|
|
4587
5209
|
// cannot apply — every member of a demanded instantiation lowers.
|
|
4588
|
-
const always = info.genericInstance !== undefined ||
|
|
5210
|
+
const always = info.genericInstance !== undefined ||
|
|
5211
|
+
info.mixinInstance !== undefined ||
|
|
5212
|
+
info.localClass !== undefined;
|
|
4589
5213
|
// A FAMILY has no constructor function at all (nothing constructs it;
|
|
4590
5214
|
// construction resolves to instantiations) and declares no instance
|
|
4591
5215
|
// members — only its statics lower below.
|
|
@@ -4603,10 +5227,19 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4603
5227
|
if (!(e instanceof PoisonError))
|
|
4604
5228
|
throw e;
|
|
4605
5229
|
if (info.decl && isJsSourceFile(info.decl.getSourceFile())) {
|
|
4606
|
-
const types = [
|
|
5230
|
+
const types = [
|
|
5231
|
+
{ kind: "object", className },
|
|
5232
|
+
...info.ctorParams.map((param) => param.type),
|
|
5233
|
+
];
|
|
4607
5234
|
const fallback = lowerer.deferToRuntimeFence(diagsBefore, info.ctor ?? info.decl, {
|
|
4608
|
-
kind: "function",
|
|
4609
|
-
|
|
5235
|
+
kind: "function",
|
|
5236
|
+
name: `%${className}.constructor`,
|
|
5237
|
+
returnType: VOID,
|
|
5238
|
+
params: types.map((type, index) => ({
|
|
5239
|
+
localId: `p.${index}`,
|
|
5240
|
+
name: index === 0 ? "this" : `p${index}`,
|
|
5241
|
+
type,
|
|
5242
|
+
})),
|
|
4610
5243
|
});
|
|
4611
5244
|
if (fallback)
|
|
4612
5245
|
out.push(fallback);
|
|
@@ -4641,9 +5274,9 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
4641
5274
|
return out;
|
|
4642
5275
|
}
|
|
4643
5276
|
/** The constructor function `%C.constructor`. Synthesized when absent: a
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
5277
|
+
* base class runs just its field initializers; a derived class inherits
|
|
5278
|
+
* the base's signature — forward every param to super(), then run own
|
|
5279
|
+
* field initializers. */
|
|
4647
5280
|
export function lowerClassCtor(lowerer, info) {
|
|
4648
5281
|
const cached = info.localClass?.bodies.get(`%${info.def.name}.constructor`);
|
|
4649
5282
|
if (cached)
|
|
@@ -4656,11 +5289,16 @@ function classCaptureParams(info, context) {
|
|
|
4656
5289
|
const environment = info.localClass.context;
|
|
4657
5290
|
if (!environment)
|
|
4658
5291
|
throw new InternalCompilerError("local class lowered outside its lexical environment");
|
|
4659
|
-
return {
|
|
5292
|
+
return {
|
|
5293
|
+
classCaptures: (context.captures ?? []).map((capture, index) => {
|
|
4660
5294
|
if (!capture)
|
|
4661
5295
|
throw new InternalCompilerError("missing local class capture");
|
|
4662
|
-
return {
|
|
4663
|
-
|
|
5296
|
+
return {
|
|
5297
|
+
...capture,
|
|
5298
|
+
slot: environment.captures.findIndex((entry) => entry.localId === context.captureSources[index]),
|
|
5299
|
+
};
|
|
5300
|
+
}),
|
|
5301
|
+
};
|
|
4664
5302
|
}
|
|
4665
5303
|
function lowerClassCtorInner(lowerer, info) {
|
|
4666
5304
|
const className = info.def.name;
|
|
@@ -4683,7 +5321,12 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4683
5321
|
// unchanged, and the remaining statements lower normally.
|
|
4684
5322
|
const loc = locOf(info.ctor);
|
|
4685
5323
|
const forward = info.ctorParams.map((shape, i) => {
|
|
4686
|
-
const local = {
|
|
5324
|
+
const local = {
|
|
5325
|
+
id: `arg${i}.0`,
|
|
5326
|
+
name: `arg${i}`,
|
|
5327
|
+
type: shape.type,
|
|
5328
|
+
mutable: false,
|
|
5329
|
+
};
|
|
4687
5330
|
lowerer.ctx.locals.push(local);
|
|
4688
5331
|
params.push({ localId: local.id, name: local.name, type: shape.type });
|
|
4689
5332
|
return { kind: "varRef", localId: local.id, type: shape.type, loc };
|
|
@@ -4724,7 +5367,12 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4724
5367
|
// apply in the base constructor's own prologue, never twice).
|
|
4725
5368
|
const loc = locOf(info.decl);
|
|
4726
5369
|
const superArgs = info.ctorParams.map((shape, i) => {
|
|
4727
|
-
const local = {
|
|
5370
|
+
const local = {
|
|
5371
|
+
id: `arg${i}.0`,
|
|
5372
|
+
name: `arg${i}`,
|
|
5373
|
+
type: shape.type,
|
|
5374
|
+
mutable: false,
|
|
5375
|
+
};
|
|
4728
5376
|
lowerer.ctx.locals.push(local);
|
|
4729
5377
|
params.push({ localId: local.id, name: local.name, type: shape.type });
|
|
4730
5378
|
return { kind: "varRef", localId: local.id, type: shape.type, loc };
|
|
@@ -4758,14 +5406,14 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
4758
5406
|
}
|
|
4759
5407
|
}
|
|
4760
5408
|
/** The lowered method-map name of a class member: identifier text, a
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
5409
|
+
* COMPUTED name that folds to one compile-time string
|
|
5410
|
+
* (foldedStringKeyOf — the object-literal computed-key machinery
|
|
5411
|
+
* applied to method positions; tsc late-bound the member under exactly
|
|
5412
|
+
* that name), or a reserved `sym:*` slot for the well-known symbols the
|
|
5413
|
+
* compiler consumes as language protocols (iterator and explicit
|
|
5414
|
+
* resource management). These names are unspellable as user identifiers,
|
|
5415
|
+
* like the accessor `get:x` convention. Null for genuinely
|
|
5416
|
+
* runtime-keyed names — the computed-member fences stay. */
|
|
4769
5417
|
export function classMemberNameOf(lowerer, name) {
|
|
4770
5418
|
if (ts.isIdentifier(name))
|
|
4771
5419
|
return name.text;
|
|
@@ -4791,7 +5439,8 @@ export function classMemberNameOf(lowerer, name) {
|
|
|
4791
5439
|
return `sym:${member}`;
|
|
4792
5440
|
}
|
|
4793
5441
|
}
|
|
4794
|
-
return classSymbolKeyOf(lowerer, name.expression)?.fieldName ??
|
|
5442
|
+
return (classSymbolKeyOf(lowerer, name.expression)?.fieldName ??
|
|
5443
|
+
lowerer.foldedStringKeyOf(name.expression));
|
|
4795
5444
|
}
|
|
4796
5445
|
export function classIteratorOf(lowerer, t) {
|
|
4797
5446
|
if (t.kind !== "object")
|
|
@@ -4825,10 +5474,16 @@ export function classIteratorOf(lowerer, t) {
|
|
|
4825
5474
|
const done = shape.fields.find((f) => f.name === "done");
|
|
4826
5475
|
if (done && done.type.kind !== "bool")
|
|
4827
5476
|
return null;
|
|
4828
|
-
return {
|
|
5477
|
+
return {
|
|
5478
|
+
className: t.className,
|
|
5479
|
+
iterT,
|
|
5480
|
+
resultT,
|
|
5481
|
+
valueT: value.type,
|
|
5482
|
+
hasDone: done !== undefined,
|
|
5483
|
+
};
|
|
4829
5484
|
}
|
|
4830
5485
|
/** The `it.next()` step of a class iterator as an ordinary (possibly
|
|
4831
|
-
|
|
5486
|
+
* virtual) method call. */
|
|
4832
5487
|
export function classIteratorNextCall(lowerer, cit, itRef, loc) {
|
|
4833
5488
|
return accessorCall(lowerer, cit.iterT.className, "next", itRef, [], cit.resultT, loc);
|
|
4834
5489
|
}
|
|
@@ -4837,14 +5492,14 @@ export function classIteratorOpenCall(lowerer, cit, recv, loc) {
|
|
|
4837
5492
|
return accessorCall(lowerer, cit.className, "sym:iterator", recv, [], cit.iterT, loc);
|
|
4838
5493
|
}
|
|
4839
5494
|
/** `[...new C]` / `f(...new C)` over a CLASS ITERABLE: the eager drain —
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
5495
|
+
* an interned `%iter.drain.<n>(recv)` lifted function running the
|
|
5496
|
+
* whole protocol into a fresh element array (a doneless iterator loops
|
|
5497
|
+
* forever, exactly Node's spread of an infinite iterator). `elemT`
|
|
5498
|
+
* (default: the iterator's own value type) is the DESTINATION element —
|
|
5499
|
+
* a spread into a union-element literal (`[...numbers, ...symbols]` as
|
|
5500
|
+
* `(number | symbol)[]`) pushes each value wrapped into its arm. Null
|
|
5501
|
+
* when the value isn't a recognized class iterable or the element
|
|
5502
|
+
* doesn't coerce — spread fences stay. */
|
|
4848
5503
|
export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
4849
5504
|
const cit = classIteratorOf(lowerer, src.type);
|
|
4850
5505
|
if (!cit)
|
|
@@ -4867,14 +5522,33 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4867
5522
|
const itRef = { kind: "varRef", localId: "it.0", type: cit.iterT, loc };
|
|
4868
5523
|
const outRef = { kind: "varRef", localId: "out.0", type: outT, loc };
|
|
4869
5524
|
const resRef = { kind: "varRef", localId: "res.0", type: cit.resultT, loc };
|
|
4870
|
-
const valueRead = {
|
|
5525
|
+
const valueRead = {
|
|
5526
|
+
kind: "recordGet",
|
|
5527
|
+
obj: resRef,
|
|
5528
|
+
shapeId: cit.resultT.shapeId,
|
|
5529
|
+
field: "value",
|
|
5530
|
+
type: cit.valueT,
|
|
5531
|
+
loc,
|
|
5532
|
+
};
|
|
4871
5533
|
const loop = [
|
|
4872
|
-
{
|
|
5534
|
+
{
|
|
5535
|
+
kind: "varDecl",
|
|
5536
|
+
localId: "res.0",
|
|
5537
|
+
init: classIteratorNextCall(lowerer, cit, itRef, loc),
|
|
5538
|
+
loc,
|
|
5539
|
+
},
|
|
4873
5540
|
...(cit.hasDone
|
|
4874
5541
|
? [
|
|
4875
5542
|
{
|
|
4876
5543
|
kind: "if",
|
|
4877
|
-
cond: {
|
|
5544
|
+
cond: {
|
|
5545
|
+
kind: "recordGet",
|
|
5546
|
+
obj: resRef,
|
|
5547
|
+
shapeId: cit.resultT.shapeId,
|
|
5548
|
+
field: "done",
|
|
5549
|
+
type: BOOL,
|
|
5550
|
+
loc,
|
|
5551
|
+
},
|
|
4878
5552
|
then: [{ kind: "return", value: outRef, loc }],
|
|
4879
5553
|
else_: null,
|
|
4880
5554
|
loc,
|
|
@@ -4905,8 +5579,18 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4905
5579
|
{ id: "res.0", name: "res", type: cit.resultT, mutable: true },
|
|
4906
5580
|
],
|
|
4907
5581
|
body: [
|
|
4908
|
-
{
|
|
4909
|
-
|
|
5582
|
+
{
|
|
5583
|
+
kind: "varDecl",
|
|
5584
|
+
localId: "out.0",
|
|
5585
|
+
init: { kind: "arrayLit", elems: [], type: outT, loc },
|
|
5586
|
+
loc,
|
|
5587
|
+
},
|
|
5588
|
+
{
|
|
5589
|
+
kind: "varDecl",
|
|
5590
|
+
localId: "it.0",
|
|
5591
|
+
init: classIteratorOpenCall(lowerer, cit, recvRef, loc),
|
|
5592
|
+
loc,
|
|
5593
|
+
},
|
|
4910
5594
|
{
|
|
4911
5595
|
kind: "while",
|
|
4912
5596
|
cond: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
@@ -4917,7 +5601,12 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4917
5601
|
// all-paths-return rule (the retag-helper convention).
|
|
4918
5602
|
{
|
|
4919
5603
|
kind: "throw",
|
|
4920
|
-
value: {
|
|
5604
|
+
value: {
|
|
5605
|
+
kind: "strLit",
|
|
5606
|
+
value: "scriptc: internal error: iterator drain fell through",
|
|
5607
|
+
type: STRING,
|
|
5608
|
+
loc,
|
|
5609
|
+
},
|
|
4921
5610
|
loc,
|
|
4922
5611
|
},
|
|
4923
5612
|
],
|
|
@@ -4927,8 +5616,8 @@ export function classIteratorDrainCall(lowerer, src, loc, elemT) {
|
|
|
4927
5616
|
return { kind: "call", callee: name, args: [src], type: outT, loc };
|
|
4928
5617
|
}
|
|
4929
5618
|
/** The tail of a class iterable's protocol from an already-open ITERATOR
|
|
4930
|
-
|
|
4931
|
-
|
|
5619
|
+
* object (`var [a, ...rest] = new C` — the rest element drains whatever
|
|
5620
|
+
* next() still yields): the drain loop keyed by the iterator class. */
|
|
4932
5621
|
export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
4933
5622
|
const outT = arrayOf(cit.valueT);
|
|
4934
5623
|
const key = `it:${cit.iterT.className}`;
|
|
@@ -4940,12 +5629,24 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4940
5629
|
const outRef = { kind: "varRef", localId: "out.0", type: outT, loc };
|
|
4941
5630
|
const resRef = { kind: "varRef", localId: "res.0", type: cit.resultT, loc };
|
|
4942
5631
|
const loop = [
|
|
4943
|
-
{
|
|
5632
|
+
{
|
|
5633
|
+
kind: "varDecl",
|
|
5634
|
+
localId: "res.0",
|
|
5635
|
+
init: classIteratorNextCall(lowerer, cit, itRef, loc),
|
|
5636
|
+
loc,
|
|
5637
|
+
},
|
|
4944
5638
|
...(cit.hasDone
|
|
4945
5639
|
? [
|
|
4946
5640
|
{
|
|
4947
5641
|
kind: "if",
|
|
4948
|
-
cond: {
|
|
5642
|
+
cond: {
|
|
5643
|
+
kind: "recordGet",
|
|
5644
|
+
obj: resRef,
|
|
5645
|
+
shapeId: cit.resultT.shapeId,
|
|
5646
|
+
field: "done",
|
|
5647
|
+
type: BOOL,
|
|
5648
|
+
loc,
|
|
5649
|
+
},
|
|
4949
5650
|
then: [{ kind: "return", value: outRef, loc }],
|
|
4950
5651
|
else_: null,
|
|
4951
5652
|
loc,
|
|
@@ -4958,7 +5659,16 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4958
5659
|
kind: "arrIntrinsic",
|
|
4959
5660
|
method: "push",
|
|
4960
5661
|
receiver: outRef,
|
|
4961
|
-
args: [
|
|
5662
|
+
args: [
|
|
5663
|
+
{
|
|
5664
|
+
kind: "recordGet",
|
|
5665
|
+
obj: resRef,
|
|
5666
|
+
shapeId: cit.resultT.shapeId,
|
|
5667
|
+
field: "value",
|
|
5668
|
+
type: cit.valueT,
|
|
5669
|
+
loc,
|
|
5670
|
+
},
|
|
5671
|
+
],
|
|
4962
5672
|
type: F64,
|
|
4963
5673
|
loc,
|
|
4964
5674
|
},
|
|
@@ -4975,11 +5685,21 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4975
5685
|
{ id: "res.0", name: "res", type: cit.resultT, mutable: true },
|
|
4976
5686
|
],
|
|
4977
5687
|
body: [
|
|
4978
|
-
{
|
|
5688
|
+
{
|
|
5689
|
+
kind: "varDecl",
|
|
5690
|
+
localId: "out.0",
|
|
5691
|
+
init: { kind: "arrayLit", elems: [], type: outT, loc },
|
|
5692
|
+
loc,
|
|
5693
|
+
},
|
|
4979
5694
|
{ kind: "while", cond: { kind: "boolLit", value: true, type: BOOL, loc }, body: loop, loc },
|
|
4980
5695
|
{
|
|
4981
5696
|
kind: "throw",
|
|
4982
|
-
value: {
|
|
5697
|
+
value: {
|
|
5698
|
+
kind: "strLit",
|
|
5699
|
+
value: "scriptc: internal error: iterator drain fell through",
|
|
5700
|
+
type: STRING,
|
|
5701
|
+
loc,
|
|
5702
|
+
},
|
|
4983
5703
|
loc,
|
|
4984
5704
|
},
|
|
4985
5705
|
],
|
|
@@ -4989,12 +5709,14 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
4989
5709
|
return { kind: "call", callee: name, args: [itVal], type: outT, loc };
|
|
4990
5710
|
}
|
|
4991
5711
|
/** One method or accessor body as its module function `%C.name`
|
|
4992
|
-
|
|
4993
|
-
|
|
5712
|
+
* (accessors are methods with property syntax: "get:x"/"set:x" entries —
|
|
5713
|
+
* see collectClassShape). */
|
|
4994
5714
|
export function lowerClassMethodMember(lowerer, info, fnLike) {
|
|
4995
5715
|
if (info.localClass?.ready) {
|
|
4996
5716
|
const member = classMemberNameOf(lowerer, fnLike.name);
|
|
4997
|
-
const name = ts.isMethodDeclaration(fnLike)
|
|
5717
|
+
const name = ts.isMethodDeclaration(fnLike)
|
|
5718
|
+
? member
|
|
5719
|
+
: `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${member}`;
|
|
4998
5720
|
return info.localClass.bodies.get(`%${info.def.name}.${name}`) ?? null;
|
|
4999
5721
|
}
|
|
5000
5722
|
return withInstanceBindings(lowerer, info, () => lowerClassMethodMemberInner(lowerer, info, fnLike));
|
|
@@ -5088,12 +5810,12 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
5088
5810
|
}
|
|
5089
5811
|
}
|
|
5090
5812
|
/** One static method body as its module function `%C.static:m` — an
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5813
|
+
* ordinary function with NO `this` param. `this` and `super` inside
|
|
5814
|
+
* name the RECEIVER class in JS (dynamic — `F.who()` sees F even when
|
|
5815
|
+
* who() is declared on E), which has no static story here: both are
|
|
5816
|
+
* named fences, with arrow functions transparent (they inherit the
|
|
5817
|
+
* method's `this`) and this-binding function forms opaque — the static-
|
|
5818
|
+
* block rule verbatim. */
|
|
5097
5819
|
export function lowerStaticMethod(lowerer, info, name) {
|
|
5098
5820
|
const entry = info.staticMethods?.get(name);
|
|
5099
5821
|
if (!entry?.member.body)
|
|
@@ -5109,7 +5831,9 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
5109
5831
|
const genCh = isGenerator && entry.ret.kind === "generator" ? generatorMeta(lowerer, entry.ret) : null;
|
|
5110
5832
|
const bodyReturn = genCh !== null
|
|
5111
5833
|
? lowerer.genBodyReturnType(entry.ret)
|
|
5112
|
-
: isAsync && entry.ret.kind === "promise"
|
|
5834
|
+
: isAsync && entry.ret.kind === "promise"
|
|
5835
|
+
? entry.ret.inner
|
|
5836
|
+
: entry.ret;
|
|
5113
5837
|
const fnCtx = newFnCtx(false, null, null, bodyReturn);
|
|
5114
5838
|
fnCtx.isAsync = isAsync;
|
|
5115
5839
|
if (genCh !== null)
|
|
@@ -5153,10 +5877,10 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
5153
5877
|
}
|
|
5154
5878
|
}
|
|
5155
5879
|
/** A synthesized throwing setter: a getter-only override shadows the
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5880
|
+
* inherited pair (JS), so a base-typed write dispatches HERE and must
|
|
5881
|
+
* throw exactly like Node's TypeError — a real instance (a typed catch's
|
|
5882
|
+
* `e instanceof TypeError` matches), catchable, exit 1 uncaught (message
|
|
5883
|
+
* text is compiler-worded; stdout and exit code are the contract). */
|
|
5160
5884
|
export function throwingSetterFn(lowerer, info, prop) {
|
|
5161
5885
|
const className = info.def.name;
|
|
5162
5886
|
const thisType = { kind: "object", className };
|
|
@@ -5195,27 +5919,38 @@ export function throwingSetterFn(lowerer, info, prop) {
|
|
|
5195
5919
|
};
|
|
5196
5920
|
}
|
|
5197
5921
|
/** The base a constructor chain actually CALLS into: generic FAMILIES are
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5922
|
+
* never constructed (no `%<family>.constructor` exists), so an
|
|
5923
|
+
* instantiation's construction-relevant base is the family's own base —
|
|
5924
|
+
* null when the generic class extends nothing, exactly the source's
|
|
5925
|
+
* story (tsc forbids super() there). Ordinary classes answer their base
|
|
5926
|
+
* unchanged. */
|
|
5203
5927
|
function superBaseOf(info) {
|
|
5204
5928
|
const b = info.base;
|
|
5205
5929
|
return b?.generic ? b.base : b;
|
|
5206
5930
|
}
|
|
5207
5931
|
/** The class's OWN field initializers as fieldSet statements (declaration
|
|
5208
|
-
|
|
5209
|
-
|
|
5932
|
+
* order) — a base constructor's prologue, a derived constructor's
|
|
5933
|
+
* super()-return continuation. */
|
|
5210
5934
|
export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
5211
5935
|
const out = [];
|
|
5212
5936
|
const thisType = { kind: "object", className: info.def.name };
|
|
5213
5937
|
for (const f of info.fieldOrder) {
|
|
5214
5938
|
if (f.errorCause) {
|
|
5215
5939
|
const loc = f.initializer ? locOf(f.initializer) : f.undefinedInitializer;
|
|
5216
|
-
const value = f.initializer
|
|
5217
|
-
|
|
5218
|
-
|
|
5940
|
+
const value = f.initializer
|
|
5941
|
+
? lowerer.lowerExprExpecting(f.initializer, DYN)
|
|
5942
|
+
: dynUndefinedExpr(loc);
|
|
5943
|
+
out.push({
|
|
5944
|
+
kind: "exprStmt",
|
|
5945
|
+
expr: {
|
|
5946
|
+
kind: "libCall",
|
|
5947
|
+
fn: "error.defineCause",
|
|
5948
|
+
args: [{ kind: "varRef", localId: thisLocal.id, type: thisType, loc }, value],
|
|
5949
|
+
type: VOID,
|
|
5950
|
+
loc,
|
|
5951
|
+
},
|
|
5952
|
+
loc,
|
|
5953
|
+
});
|
|
5219
5954
|
continue;
|
|
5220
5955
|
}
|
|
5221
5956
|
if (f.undefinedInitializer) {
|
|
@@ -5251,7 +5986,9 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
5251
5986
|
lowerer.stats.statementsFailed++;
|
|
5252
5987
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
5253
5988
|
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
5254
|
-
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
5989
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, {
|
|
5990
|
+
kind: "statement",
|
|
5991
|
+
});
|
|
5255
5992
|
if (fence)
|
|
5256
5993
|
out.push(fence);
|
|
5257
5994
|
}
|
|
@@ -5260,14 +5997,14 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
5260
5997
|
return out;
|
|
5261
5998
|
}
|
|
5262
5999
|
/** PARAMETER-PROPERTY assignments (`this.x = x`, synthesized): run AFTER
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
6000
|
+
* the field initializers — Node's transform defines the fields at the
|
|
6001
|
+
* top of the class body (undefined until assigned) and injects the
|
|
6002
|
+
* assignments at the start of the constructor body, i.e. after super()
|
|
6003
|
+
* and after the (native) field initializers ran (probed: a field
|
|
6004
|
+
* initializer reading `this.x` sees undefined; the body sees the value).
|
|
6005
|
+
* Each assignment reads the parameter's BODY local (defaults already
|
|
6006
|
+
* applied by the declareParams prologue), whose type the collection made
|
|
6007
|
+
* the field's type — slot-exact by construction. */
|
|
5271
6008
|
function paramPropInitStmts(lowerer, info, thisLocal) {
|
|
5272
6009
|
const out = [];
|
|
5273
6010
|
const thisType = { kind: "object", className: info.def.name };
|
|
@@ -5291,8 +6028,8 @@ function paramPropInitStmts(lowerer, info, thisLocal) {
|
|
|
5291
6028
|
return out;
|
|
5292
6029
|
}
|
|
5293
6030
|
/** Super statements initialize the base and then the derived fields on
|
|
5294
|
-
|
|
5295
|
-
|
|
6031
|
+
* whichever control-flow path executes. Repeated calls are explicitly
|
|
6032
|
+
* refused until native layouts can allocate a second receiver. */
|
|
5296
6033
|
export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
5297
6034
|
let superSeen = false;
|
|
5298
6035
|
const initialized = lowerer.declareHiddenLocal("%superInitialized", BOOL);
|
|
@@ -5306,11 +6043,30 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5306
6043
|
lowerer.unsupported("SC1090", superCall, "super() in an expression position");
|
|
5307
6044
|
superSeen = true;
|
|
5308
6045
|
const loc = locOf(superCall);
|
|
5309
|
-
const statements = [
|
|
6046
|
+
const statements = [
|
|
6047
|
+
{
|
|
6048
|
+
kind: "if",
|
|
6049
|
+
cond: { kind: "varRef", localId: initialized.id, type: BOOL, loc },
|
|
6050
|
+
then: [
|
|
6051
|
+
{
|
|
6052
|
+
kind: "exprStmt",
|
|
6053
|
+
expr: nodeThrowExpr(0, "SC2020", "repeated super() calls require a fresh receiver and are not supported yet", DYN, loc),
|
|
6054
|
+
loc,
|
|
6055
|
+
},
|
|
6056
|
+
],
|
|
6057
|
+
else_: null,
|
|
6058
|
+
loc,
|
|
6059
|
+
},
|
|
6060
|
+
];
|
|
5310
6061
|
if (info.callableBase) {
|
|
5311
6062
|
if (superCall.arguments.some(ts.isSpreadElement))
|
|
5312
6063
|
lowerer.unsupported("SC1090", superCall, "spreading explicit super arguments into an ordinary constructor");
|
|
5313
|
-
const pack = {
|
|
6064
|
+
const pack = {
|
|
6065
|
+
kind: "dynArrLit",
|
|
6066
|
+
elems: superCall.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
6067
|
+
type: DYN,
|
|
6068
|
+
loc,
|
|
6069
|
+
};
|
|
5314
6070
|
statements.push(lowerer.superCallStmt(info, thisLocal, [pack], loc));
|
|
5315
6071
|
}
|
|
5316
6072
|
else {
|
|
@@ -5321,19 +6077,33 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5321
6077
|
statements.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, loc, superCall));
|
|
5322
6078
|
}
|
|
5323
6079
|
else {
|
|
5324
|
-
const surplusSpread = forward === undefined &&
|
|
5325
|
-
base.
|
|
6080
|
+
const surplusSpread = forward === undefined &&
|
|
6081
|
+
!base.builtinError &&
|
|
6082
|
+
!base.builtinEmitter &&
|
|
6083
|
+
base.ctorParams.length === 0 &&
|
|
6084
|
+
superCall.arguments.some(ts.isSpreadElement);
|
|
5326
6085
|
if (surplusSpread) {
|
|
5327
6086
|
const evaluated = lowerer.completeArgs(superCall.arguments, [{ mode: "dynRest", type: DYN }], loc, superCall);
|
|
5328
6087
|
for (const value of evaluated)
|
|
5329
6088
|
statements.push({ kind: "exprStmt", expr: value, loc });
|
|
5330
6089
|
}
|
|
5331
|
-
const surplus = forward === undefined &&
|
|
6090
|
+
const surplus = forward === undefined &&
|
|
6091
|
+
!base.builtinError &&
|
|
6092
|
+
!base.builtinEmitter &&
|
|
5332
6093
|
!base.ctorParams.some((param) => param.mode === "rest" || param.mode === "dynRest" || param.mode === "islandRest") &&
|
|
5333
|
-
!superCall.arguments.some(ts.isSpreadElement) &&
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
6094
|
+
!superCall.arguments.some(ts.isSpreadElement) &&
|
|
6095
|
+
superCall.arguments.length > base.ctorParams.length;
|
|
6096
|
+
let args = surplusSpread
|
|
6097
|
+
? []
|
|
6098
|
+
: forward !== undefined
|
|
6099
|
+
? forward
|
|
6100
|
+
: base.builtinError
|
|
6101
|
+
? lowerer.errorConstructorArgs(superCall.arguments, loc, superCall)
|
|
6102
|
+
: base.builtinEmitter
|
|
6103
|
+
? []
|
|
6104
|
+
: lowerer.completeArgs(surplus
|
|
6105
|
+
? superCall.arguments.slice(0, base.ctorParams.length)
|
|
6106
|
+
: superCall.arguments, base.ctorParams, loc, superCall);
|
|
5337
6107
|
if (surplus) {
|
|
5338
6108
|
args = args.map((arg) => {
|
|
5339
6109
|
const local = lowerer.declareHiddenLocal("%superArgument", arg.type);
|
|
@@ -5341,13 +6111,22 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5341
6111
|
return { kind: "varRef", localId: local.id, type: arg.type, loc };
|
|
5342
6112
|
});
|
|
5343
6113
|
for (const argument of superCall.arguments.slice(base.ctorParams.length)) {
|
|
5344
|
-
statements.push({
|
|
6114
|
+
statements.push({
|
|
6115
|
+
kind: "exprStmt",
|
|
6116
|
+
expr: lowerer.lowerExpr(argument),
|
|
6117
|
+
loc: locOf(argument),
|
|
6118
|
+
});
|
|
5345
6119
|
}
|
|
5346
6120
|
}
|
|
5347
6121
|
statements.push(lowerer.superCallStmt(info, thisLocal, args, loc));
|
|
5348
6122
|
}
|
|
5349
6123
|
}
|
|
5350
|
-
statements.push({
|
|
6124
|
+
statements.push({
|
|
6125
|
+
kind: "assign",
|
|
6126
|
+
localId: initialized.id,
|
|
6127
|
+
value: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
6128
|
+
loc,
|
|
6129
|
+
});
|
|
5351
6130
|
delete context.superInitialized;
|
|
5352
6131
|
try {
|
|
5353
6132
|
statements.push(...lowerer.fieldInitStmts(info, thisLocal), ...paramPropInitStmts(lowerer, info, thisLocal));
|
|
@@ -5356,16 +6135,52 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5356
6135
|
context.superInitialized = initialized;
|
|
5357
6136
|
}
|
|
5358
6137
|
const result = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
|
|
5359
|
-
return {
|
|
5360
|
-
|
|
5361
|
-
|
|
6138
|
+
return {
|
|
6139
|
+
kind: "seqExpr",
|
|
6140
|
+
stmts: statements.map((statement) => statement.kind === "runtimeFence"
|
|
6141
|
+
? {
|
|
6142
|
+
kind: "exprStmt",
|
|
6143
|
+
expr: nodeThrowExpr(0, statement.code, statement.message, DYN, statement.loc),
|
|
6144
|
+
loc: statement.loc,
|
|
6145
|
+
}
|
|
6146
|
+
: statement),
|
|
6147
|
+
result,
|
|
6148
|
+
type: result.type,
|
|
6149
|
+
loc,
|
|
6150
|
+
};
|
|
5362
6151
|
};
|
|
5363
6152
|
try {
|
|
5364
6153
|
const result = lowerer.lowerStmts(info.ctor.body.statements);
|
|
5365
|
-
result.push({
|
|
6154
|
+
result.push({
|
|
6155
|
+
kind: "if",
|
|
6156
|
+
cond: {
|
|
6157
|
+
kind: "unary",
|
|
6158
|
+
op: "!",
|
|
6159
|
+
operand: { kind: "varRef", localId: initialized.id, type: BOOL, loc: locOf(info.ctor) },
|
|
6160
|
+
type: BOOL,
|
|
6161
|
+
loc: locOf(info.ctor),
|
|
6162
|
+
},
|
|
6163
|
+
then: [
|
|
6164
|
+
{
|
|
6165
|
+
kind: "exprStmt",
|
|
6166
|
+
expr: nodeThrowExpr(5, "", "Must call super constructor in derived class before accessing 'this' or returning from derived constructor", DYN, locOf(info.ctor)),
|
|
6167
|
+
loc: locOf(info.ctor),
|
|
6168
|
+
},
|
|
6169
|
+
],
|
|
6170
|
+
else_: null,
|
|
6171
|
+
loc: locOf(info.ctor),
|
|
6172
|
+
});
|
|
5366
6173
|
if (!superSeen)
|
|
5367
6174
|
lowerer.pushDiag(unsupportedDiag("SC1090", locOf(info.ctor), "derived constructors without a lowered super() call"));
|
|
5368
|
-
return [
|
|
6175
|
+
return [
|
|
6176
|
+
{
|
|
6177
|
+
kind: "varDecl",
|
|
6178
|
+
localId: initialized.id,
|
|
6179
|
+
init: { kind: "boolLit", value: false, type: BOOL, loc: locOf(info.ctor) },
|
|
6180
|
+
loc: locOf(info.ctor),
|
|
6181
|
+
},
|
|
6182
|
+
...result,
|
|
6183
|
+
];
|
|
5369
6184
|
}
|
|
5370
6185
|
finally {
|
|
5371
6186
|
if (previous)
|
|
@@ -5379,8 +6194,8 @@ export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
|
5379
6194
|
}
|
|
5380
6195
|
}
|
|
5381
6196
|
/** `super(args)` → direct call of the base constructor with the SAME
|
|
5382
|
-
|
|
5383
|
-
|
|
6197
|
+
* `this` (upcast; retained by the varRef read — the callee owns and
|
|
6198
|
+
* releases its param per the universal convention). */
|
|
5384
6199
|
export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
5385
6200
|
const base = superBaseOf(info);
|
|
5386
6201
|
const thisRef = {
|
|
@@ -5391,12 +6206,41 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
5391
6206
|
};
|
|
5392
6207
|
if (info.callableBase)
|
|
5393
6208
|
return {
|
|
5394
|
-
kind: "exprStmt",
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
6209
|
+
kind: "exprStmt",
|
|
6210
|
+
expr: {
|
|
6211
|
+
kind: "libCall",
|
|
6212
|
+
fn: "dyn.classSuper",
|
|
6213
|
+
args: [
|
|
6214
|
+
info.localClass
|
|
6215
|
+
? {
|
|
6216
|
+
kind: "libCall",
|
|
6217
|
+
fn: "dyn.getPrototype",
|
|
6218
|
+
args: [
|
|
6219
|
+
{
|
|
6220
|
+
kind: "dynFrom",
|
|
6221
|
+
value: {
|
|
6222
|
+
kind: "fieldGet",
|
|
6223
|
+
obj: thisRef,
|
|
6224
|
+
className: info.def.name,
|
|
6225
|
+
field: `%classEnvironment:${info.def.name}`,
|
|
6226
|
+
type: { kind: "classval", className: info.def.name },
|
|
6227
|
+
loc,
|
|
6228
|
+
},
|
|
6229
|
+
type: DYN,
|
|
6230
|
+
loc,
|
|
6231
|
+
},
|
|
6232
|
+
],
|
|
6233
|
+
type: DYN,
|
|
6234
|
+
loc,
|
|
6235
|
+
}
|
|
6236
|
+
: { kind: "varRef", localId: info.callableBase.constructorId, type: DYN, loc },
|
|
6237
|
+
lowerer.coerceToExpected(thisRef, DYN),
|
|
6238
|
+
args[0],
|
|
6239
|
+
],
|
|
6240
|
+
type: VOID,
|
|
6241
|
+
loc,
|
|
6242
|
+
},
|
|
6243
|
+
loc,
|
|
5400
6244
|
};
|
|
5401
6245
|
if (base.builtinError) {
|
|
5402
6246
|
// super(message) into the runtime-provided Error constructor: stamps
|
|
@@ -5453,8 +6297,8 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
5453
6297
|
};
|
|
5454
6298
|
}
|
|
5455
6299
|
/** `super.method(args)`: the base chain's implementation, called
|
|
5456
|
-
|
|
5457
|
-
|
|
6300
|
+
* DIRECTLY over this method's own `this` (upcast to the declarer) —
|
|
6301
|
+
* super dispatch is static in JS too, never through the dynamic class. */
|
|
5458
6302
|
export function lowerSuperMethodCall(lowerer, call, access) {
|
|
5459
6303
|
const cls = lowerer.currentClass;
|
|
5460
6304
|
if (!cls?.base) {
|
|
@@ -5516,15 +6360,33 @@ export function lowerSuperMethodCall(lowerer, call, access) {
|
|
|
5516
6360
|
if (lowerer.prototypeMethodAccesses.has(access.name.text)) {
|
|
5517
6361
|
const prototype = classPrototypeData(lowerer, cls.base, loc);
|
|
5518
6362
|
if (prototype) {
|
|
5519
|
-
const callee = {
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
6363
|
+
const callee = {
|
|
6364
|
+
kind: "dynKeyGet",
|
|
6365
|
+
value: prototype,
|
|
6366
|
+
key: { kind: "strLit", value: access.name.text, type: STRING, loc },
|
|
6367
|
+
type: DYN,
|
|
6368
|
+
loc,
|
|
6369
|
+
};
|
|
6370
|
+
const value = {
|
|
6371
|
+
kind: "dynCall",
|
|
6372
|
+
callee,
|
|
6373
|
+
receiver: lowerer.coerceToExpected(thisRef, DYN),
|
|
6374
|
+
calleeName: access.getText(),
|
|
6375
|
+
args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
6376
|
+
type: DYN,
|
|
6377
|
+
loc,
|
|
6378
|
+
};
|
|
5523
6379
|
return found.sig.ret.kind === "void" ? value : lowerer.coerceToExpected(value, found.sig.ret);
|
|
5524
6380
|
}
|
|
5525
6381
|
}
|
|
5526
6382
|
if (found.declarer.builtinError) {
|
|
5527
|
-
return {
|
|
6383
|
+
return {
|
|
6384
|
+
kind: "libCall",
|
|
6385
|
+
fn: "error.toString",
|
|
6386
|
+
args: [lowerer.upcastTo(thisRef, "%Error")],
|
|
6387
|
+
type: STRING,
|
|
6388
|
+
loc,
|
|
6389
|
+
};
|
|
5528
6390
|
}
|
|
5529
6391
|
lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
|
|
5530
6392
|
const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
|
|
@@ -5537,7 +6399,7 @@ export function lowerSuperMethodCall(lowerer, call, access) {
|
|
|
5537
6399
|
};
|
|
5538
6400
|
}
|
|
5539
6401
|
/** The `this` reference for super accessor reads/writes, with the shared
|
|
5540
|
-
|
|
6402
|
+
* validity checks (derived-class body, resolvable this). */
|
|
5541
6403
|
export function superThisRef(lowerer, access) {
|
|
5542
6404
|
const cls = lowerer.currentClass;
|
|
5543
6405
|
if (!cls?.base) {
|
|
@@ -5553,8 +6415,8 @@ export function superThisRef(lowerer, access) {
|
|
|
5553
6415
|
};
|
|
5554
6416
|
}
|
|
5555
6417
|
/** `super.x` read: a DIRECT call of the base chain's getter over this
|
|
5556
|
-
|
|
5557
|
-
|
|
6418
|
+
* method's own `this` (upcast to the declarer) — like super.method(),
|
|
6419
|
+
* never through the vtable. */
|
|
5558
6420
|
export function lowerSuperAccessorRead(lowerer, access) {
|
|
5559
6421
|
const { thisRef, base } = lowerer.superThisRef(access);
|
|
5560
6422
|
const name = access.name.text;
|
|
@@ -5578,7 +6440,7 @@ export function lowerSuperAccessorRead(lowerer, access) {
|
|
|
5578
6440
|
};
|
|
5579
6441
|
}
|
|
5580
6442
|
/** `super.x = v`: a DIRECT call of the base chain's setter (same
|
|
5581
|
-
|
|
6443
|
+
* static-dispatch rule as every super member access). */
|
|
5582
6444
|
export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
|
|
5583
6445
|
const { thisRef, base } = lowerer.superThisRef(access);
|
|
5584
6446
|
const name = access.name.text;
|
|
@@ -5605,9 +6467,9 @@ export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
|
|
|
5605
6467
|
};
|
|
5606
6468
|
}
|
|
5607
6469
|
/** True when `info`'s EFFECTIVE constructor — its own, or the one
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
6470
|
+
* inherited through ctor-less bases — is a builtin error class's. Such
|
|
6471
|
+
* classes construct with the error argument rule, and their synthesized
|
|
6472
|
+
* constructors forward both checked-dynamic values to error.ctorOptions. */
|
|
5611
6473
|
export function inheritsBuiltinErrorCtor(lowerer, info) {
|
|
5612
6474
|
for (let c = info; c; c = c.base) {
|
|
5613
6475
|
if (c.builtinError)
|
|
@@ -5618,7 +6480,7 @@ export function inheritsBuiltinErrorCtor(lowerer, info) {
|
|
|
5618
6480
|
return false;
|
|
5619
6481
|
}
|
|
5620
6482
|
/** The EventEmitter twin: a ctor-less chain into the emitter base
|
|
5621
|
-
|
|
6483
|
+
* inherits `new C()` — zero arguments (the options bag fences). */
|
|
5622
6484
|
export function inheritsBuiltinEmitterCtor(lowerer, info) {
|
|
5623
6485
|
for (let c = info; c; c = c.base) {
|
|
5624
6486
|
if (c.builtinStream)
|
|
@@ -5631,10 +6493,10 @@ export function inheritsBuiltinEmitterCtor(lowerer, info) {
|
|
|
5631
6493
|
return false;
|
|
5632
6494
|
}
|
|
5633
6495
|
/** The stream twin: a ctor-less chain into a runtime stream base
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
6496
|
+
* inherits `new C()` — zero arguments (the synthesized constructor runs
|
|
6497
|
+
* super() with default options; passing options through an inherited
|
|
6498
|
+
* constructor would need the literal at the new-site to plumb, so it
|
|
6499
|
+
* asks for a declared constructor instead). */
|
|
5638
6500
|
function inheritsBuiltinStreamCtor(lowerer, info) {
|
|
5639
6501
|
for (let c = info; c; c = c.base) {
|
|
5640
6502
|
if (c.builtinStream)
|
|
@@ -5708,8 +6570,13 @@ function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
|
|
|
5708
6570
|
: lowerer.completeArgs(expr.arguments ?? [], info.ctorParams, loc, expr);
|
|
5709
6571
|
for (let current = info; current; current = current.base) {
|
|
5710
6572
|
if (current.def.baseValueGlobal)
|
|
5711
|
-
return {
|
|
5712
|
-
|
|
6573
|
+
return {
|
|
6574
|
+
kind: "newValue",
|
|
6575
|
+
callee: classValueRef(lowerer, info, expr),
|
|
6576
|
+
args,
|
|
6577
|
+
type: { kind: "object", className: info.def.name },
|
|
6578
|
+
loc,
|
|
6579
|
+
};
|
|
5713
6580
|
}
|
|
5714
6581
|
return {
|
|
5715
6582
|
kind: "new",
|
|
@@ -5739,7 +6606,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
5739
6606
|
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer)
|
|
5740
6607
|
intlConstructor = declaration.initializer;
|
|
5741
6608
|
}
|
|
5742
|
-
const intl = ts.isPropertyAccessExpression(intlConstructor)
|
|
6609
|
+
const intl = ts.isPropertyAccessExpression(intlConstructor)
|
|
6610
|
+
? lowerer.stdlibGlobalMember(intlConstructor, "Intl")
|
|
6611
|
+
: null;
|
|
5743
6612
|
if (intl && intl !== "Segmenter")
|
|
5744
6613
|
lowerer.noLowering(`new Intl.${intl}`, expr, undefined, lowerer.checker.getSymbolAtLocation(expr.expression));
|
|
5745
6614
|
const instanceConstructor = lowerInstanceConstructorNew(lowerer, expr);
|
|
@@ -5750,10 +6619,16 @@ export function lowerNew(lowerer, expr) {
|
|
|
5750
6619
|
return objectFactory;
|
|
5751
6620
|
if (ts.isIdentifier(expr.expression)) {
|
|
5752
6621
|
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
5753
|
-
const declaration = symbol &&
|
|
6622
|
+
const declaration = symbol &&
|
|
6623
|
+
lowerer.checker
|
|
6624
|
+
.declarationsOf(symbol)
|
|
6625
|
+
.find((node) => ts.isFunctionDeclaration(node) && node.body !== undefined);
|
|
5754
6626
|
if (declaration && ts.isFunctionDeclaration(declaration) && declaration.body) {
|
|
5755
6627
|
const last = declaration.body.statements.at(-1);
|
|
5756
|
-
if (last &&
|
|
6628
|
+
if (last &&
|
|
6629
|
+
ts.isReturnStatement(last) &&
|
|
6630
|
+
last.expression &&
|
|
6631
|
+
ts.isObjectLiteralExpression(last.expression)) {
|
|
5757
6632
|
lowerer.unsupported("SC1090", expr, "object-returning constructors that observe this or return mixed primitive/object values");
|
|
5758
6633
|
}
|
|
5759
6634
|
}
|
|
@@ -5767,13 +6642,24 @@ export function lowerNew(lowerer, expr) {
|
|
|
5767
6642
|
if (yes && no && !yes.classDecorators && !no.classDecorators) {
|
|
5768
6643
|
const yesType = { kind: "object", className: yes.def.name };
|
|
5769
6644
|
const noType = { kind: "object", className: no.def.name };
|
|
5770
|
-
const type = yes === no
|
|
5771
|
-
|
|
6645
|
+
const type = yes === no
|
|
6646
|
+
? yesType
|
|
6647
|
+
: {
|
|
6648
|
+
kind: "union",
|
|
6649
|
+
unionId: lowerer.unions.intern([yesType, noType].sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1))),
|
|
6650
|
+
};
|
|
6651
|
+
return {
|
|
6652
|
+
kind: "ternary",
|
|
6653
|
+
cond: lowerer.lowerCondition(selected.condition),
|
|
5772
6654
|
then: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, yes, loc), type),
|
|
5773
|
-
else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type),
|
|
6655
|
+
else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type),
|
|
6656
|
+
type,
|
|
6657
|
+
loc,
|
|
6658
|
+
};
|
|
5774
6659
|
}
|
|
5775
6660
|
}
|
|
5776
|
-
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
6661
|
+
if (ts.isPropertyAccessExpression(expr.expression) &&
|
|
6662
|
+
expr.expression.name.text === "Segmenter" &&
|
|
5777
6663
|
lowerer.isStdlibGlobal(expr.expression.expression, "Intl")) {
|
|
5778
6664
|
const args = expr.arguments ?? [];
|
|
5779
6665
|
const undefinedArg = (arg) => (lowerer.typeOf(arg).flags & ts.TypeFlags.Undefined) !== 0;
|
|
@@ -5781,16 +6667,24 @@ export function lowerNew(lowerer, expr) {
|
|
|
5781
6667
|
lowerer.noLowering("Intl.Segmenter locale negotiation", expr, "omit the locale or pass undefined for default Unicode grapheme segmentation");
|
|
5782
6668
|
}
|
|
5783
6669
|
const options = args[1];
|
|
5784
|
-
if (options &&
|
|
5785
|
-
!(
|
|
5786
|
-
|
|
5787
|
-
|
|
6670
|
+
if (options &&
|
|
6671
|
+
!undefinedArg(options) &&
|
|
6672
|
+
!(ts.isObjectLiteralExpression(options) &&
|
|
6673
|
+
options.properties.every((property) => ts.isPropertyAssignment(property) &&
|
|
6674
|
+
(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) &&
|
|
6675
|
+
property.name.text === "granularity" &&
|
|
6676
|
+
ts.isStringLiteral(property.initializer) &&
|
|
6677
|
+
property.initializer.text === "grapheme"))) {
|
|
5788
6678
|
lowerer.noLowering("Intl.Segmenter options", options, 'the native segmenter supports default options and { granularity: "grapheme" }; word and sentence segmentation remain unsupported');
|
|
5789
6679
|
}
|
|
5790
6680
|
// Explicit undefined expressions can carry effects; retain argument order.
|
|
5791
6681
|
const stmts = args.map((arg) => {
|
|
5792
6682
|
const value = lowerer.lowerExpr(arg);
|
|
5793
|
-
return {
|
|
6683
|
+
return {
|
|
6684
|
+
kind: "exprStmt",
|
|
6685
|
+
expr: value.type.kind === "void" ? value : lowerer.coerceInto(arg, value, DYN),
|
|
6686
|
+
loc: locOf(arg),
|
|
6687
|
+
};
|
|
5794
6688
|
});
|
|
5795
6689
|
const result = { kind: "libCall", fn: "intl.segmenterNew", args: [], type: DYN, loc };
|
|
5796
6690
|
return stmts.length ? { kind: "seqExpr", stmts, result, type: DYN, loc } : result;
|
|
@@ -5960,8 +6854,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
5960
6854
|
if (agent)
|
|
5961
6855
|
return agent;
|
|
5962
6856
|
}
|
|
5963
|
-
if (ts.isIdentifier(expr.expression) ||
|
|
5964
|
-
|
|
6857
|
+
if (ts.isIdentifier(expr.expression) ||
|
|
6858
|
+
(ts.isPropertyAccessExpression(expr.expression) &&
|
|
6859
|
+
ts.isIdentifier(expr.expression.name) &&
|
|
6860
|
+
lowerer.isStdlibGlobal(expr.expression.expression, "globalThis"))) {
|
|
5965
6861
|
// `import C = N.C; new C()` — the alias's own source-order guards
|
|
5966
6862
|
// (a no-op for every non-import= binding).
|
|
5967
6863
|
if (ts.isIdentifier(expr.expression))
|
|
@@ -6059,8 +6955,14 @@ export function lowerNew(lowerer, expr) {
|
|
|
6059
6955
|
if (values.some((value) => value.type.kind === "dyn" || value.type.kind === "regex")) {
|
|
6060
6956
|
const checked = [0, 1].map((index) => values[index]
|
|
6061
6957
|
? lowerer.coerceInto(args[index], values[index], DYN)
|
|
6062
|
-
:
|
|
6063
|
-
return {
|
|
6958
|
+
: dynUndefinedExpr(loc));
|
|
6959
|
+
return {
|
|
6960
|
+
kind: "libCall",
|
|
6961
|
+
fn: "regex.newChecked",
|
|
6962
|
+
args: checked,
|
|
6963
|
+
type: { kind: "regex" },
|
|
6964
|
+
loc,
|
|
6965
|
+
};
|
|
6064
6966
|
}
|
|
6065
6967
|
const strArg = (a, what) => {
|
|
6066
6968
|
if (!a)
|
|
@@ -6070,9 +6972,18 @@ export function lowerNew(lowerer, expr) {
|
|
|
6070
6972
|
if (v.type.kind === "undefinedT") {
|
|
6071
6973
|
if (v.kind === "unitLit")
|
|
6072
6974
|
return empty;
|
|
6073
|
-
return {
|
|
6975
|
+
return {
|
|
6976
|
+
kind: "seqExpr",
|
|
6977
|
+
stmts: [{ kind: "exprStmt", expr: lowerer.coerceToExpected(v, DYN), loc: locOf(a) }],
|
|
6978
|
+
result: empty,
|
|
6979
|
+
type: STRING,
|
|
6980
|
+
loc,
|
|
6981
|
+
};
|
|
6074
6982
|
}
|
|
6075
|
-
if (v.type.kind === "union" &&
|
|
6983
|
+
if (v.type.kind === "union" &&
|
|
6984
|
+
lowerer.unions
|
|
6985
|
+
.get(v.type.unionId)
|
|
6986
|
+
?.arms.every((arm) => arm.kind === "string" || arm.kind === "undefinedT")) {
|
|
6076
6987
|
return { kind: "nullish", left: v, right: empty, type: STRING, loc: locOf(a) };
|
|
6077
6988
|
}
|
|
6078
6989
|
if (v.type.kind !== "string") {
|
|
@@ -6082,7 +6993,13 @@ export function lowerNew(lowerer, expr) {
|
|
|
6082
6993
|
};
|
|
6083
6994
|
const pattern = strArg(args[0], "pattern");
|
|
6084
6995
|
const flags = strArg(args[1], "flags argument");
|
|
6085
|
-
return {
|
|
6996
|
+
return {
|
|
6997
|
+
kind: "libCall",
|
|
6998
|
+
fn: "regex.new",
|
|
6999
|
+
args: [pattern, flags],
|
|
7000
|
+
type: { kind: "regex" },
|
|
7001
|
+
loc,
|
|
7002
|
+
};
|
|
6086
7003
|
}
|
|
6087
7004
|
if (symbol && symbol.name === "URL" && lowerer.isStdlibSymbol(symbol)) {
|
|
6088
7005
|
return lowerUrlNew(lowerer, expr);
|
|
@@ -6102,9 +7019,20 @@ export function lowerNew(lowerer, expr) {
|
|
|
6102
7019
|
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
7020
|
}
|
|
6104
7021
|
if (isJsSourceFile(expr.getSourceFile())) {
|
|
6105
|
-
return {
|
|
6106
|
-
|
|
6107
|
-
|
|
7022
|
+
return {
|
|
7023
|
+
kind: "libCall",
|
|
7024
|
+
fn: "date.nativeNew",
|
|
7025
|
+
args: [
|
|
7026
|
+
{
|
|
7027
|
+
kind: "dynArrLit",
|
|
7028
|
+
elems: args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)),
|
|
7029
|
+
type: DYN,
|
|
7030
|
+
loc,
|
|
7031
|
+
},
|
|
7032
|
+
],
|
|
7033
|
+
type: DYN,
|
|
7034
|
+
loc,
|
|
7035
|
+
};
|
|
6108
7036
|
}
|
|
6109
7037
|
if (args.length === 0) {
|
|
6110
7038
|
return { kind: "libCall", fn: "date.newNow", args: [], type: DATE_T, loc };
|
|
@@ -6146,7 +7074,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6146
7074
|
loc,
|
|
6147
7075
|
};
|
|
6148
7076
|
}
|
|
6149
|
-
if (symbol &&
|
|
7077
|
+
if (symbol &&
|
|
7078
|
+
(symbol.name === "TextDecoder" || symbol.name === "TextEncoder") &&
|
|
7079
|
+
lowerer.isStdlibSymbol(symbol)) {
|
|
6150
7080
|
return lowerTextCodecNew(lowerer, expr, symbol.name);
|
|
6151
7081
|
}
|
|
6152
7082
|
// `new Uint8Array(...)` / `new Uint32Array(...)` / `new
|
|
@@ -6191,7 +7121,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6191
7121
|
}
|
|
6192
7122
|
if (symbol?.name === "Map" && lowerer.isStdlibSymbol(symbol)) {
|
|
6193
7123
|
const seedArg = (expr.arguments?.length ?? 0) === 1 ? expr.arguments[0] : null;
|
|
6194
|
-
const isPairLit = (el) => ts.isArrayLiteralExpression(el) &&
|
|
7124
|
+
const isPairLit = (el) => ts.isArrayLiteralExpression(el) &&
|
|
7125
|
+
el.elements.length === 2 &&
|
|
6195
7126
|
!el.elements.some(ts.isSpreadElement);
|
|
6196
7127
|
const entriesLit = seedArg && ts.isArrayLiteralExpression(seedArg) && seedArg.elements.every(isPairLit)
|
|
6197
7128
|
? seedArg.elements.filter(isPairLit)
|
|
@@ -6212,7 +7143,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6212
7143
|
while (ts.isParenthesizedExpression(parent))
|
|
6213
7144
|
parent = parent.parent;
|
|
6214
7145
|
// `satisfies` checks a view but retains the expression's own type.
|
|
6215
|
-
const contextualSeed = !ts.isSatisfiesExpression(parent) &&
|
|
7146
|
+
const contextualSeed = !ts.isSatisfiesExpression(parent) &&
|
|
7147
|
+
(expr.typeArguments?.length ?? 0) === 0 &&
|
|
6216
7148
|
(entriesLit !== null || (expr.arguments?.length ?? 0) === 0);
|
|
6217
7149
|
// JavaScript's `new Map()` has no type-argument syntax: the no-arg
|
|
6218
7150
|
// constructor overload pins Map<any, any> whatever the JSDoc says
|
|
@@ -6264,7 +7196,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6264
7196
|
return { kind: "dynObjLit", type: DYN, loc };
|
|
6265
7197
|
}
|
|
6266
7198
|
const keyIr = targs[0] ? lowerer.mapTypeOf(targs[0]) : null;
|
|
6267
|
-
if (targs[0] &&
|
|
7199
|
+
if (targs[0] &&
|
|
7200
|
+
(!keyIr ||
|
|
7201
|
+
!isSupportedMapKey(keyIr, keyIr.kind === "union" ? lowerer.unions.get(keyIr.unionId)?.arms : undefined))) {
|
|
6268
7202
|
lowerer.unsupported("SC1090", expr, `Map keys of type '${lowerer.checker.typeToString(targs[0])}' ` +
|
|
6269
7203
|
`(Map keys must be numbers, strings, booleans, bigints, identity references, or supported unions)`);
|
|
6270
7204
|
}
|
|
@@ -6276,19 +7210,35 @@ export function lowerNew(lowerer, expr) {
|
|
|
6276
7210
|
lowerer.badType(expr, tsType);
|
|
6277
7211
|
}
|
|
6278
7212
|
// Weak containers share checked native key identities and lifetime hooks.
|
|
6279
|
-
if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") &&
|
|
7213
|
+
if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") &&
|
|
7214
|
+
lowerer.isStdlibSymbol(symbol)) {
|
|
6280
7215
|
const args = expr.arguments ?? [];
|
|
6281
7216
|
if (args.length > 1 || args.some(ts.isSpreadElement)) {
|
|
6282
7217
|
lowerer.unsupported("SC1090", expr, `${symbol.name} construction with surplus or spread arguments`);
|
|
6283
7218
|
}
|
|
6284
7219
|
if (lowerer.dynamic) {
|
|
6285
|
-
const ctor = {
|
|
6286
|
-
|
|
7220
|
+
const ctor = {
|
|
7221
|
+
kind: "jsOp",
|
|
7222
|
+
op: "globalGet",
|
|
7223
|
+
name: symbol.name,
|
|
7224
|
+
args: [],
|
|
7225
|
+
type: JSVAL,
|
|
7226
|
+
loc,
|
|
7227
|
+
};
|
|
7228
|
+
return {
|
|
7229
|
+
kind: "jsOp",
|
|
7230
|
+
op: "construct",
|
|
7231
|
+
args: [ctor, ...args.map((arg) => lowerer.jsvalIn(lowerer.lowerExpr(arg), arg))],
|
|
7232
|
+
type: JSVAL,
|
|
7233
|
+
loc,
|
|
7234
|
+
};
|
|
6287
7235
|
}
|
|
6288
7236
|
return {
|
|
6289
|
-
kind: "libCall",
|
|
7237
|
+
kind: "libCall",
|
|
7238
|
+
fn: symbol.name === "WeakMap" ? "weakMap.new" : "weakSet.new",
|
|
6290
7239
|
args: [args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc)],
|
|
6291
|
-
type: DYN,
|
|
7240
|
+
type: DYN,
|
|
7241
|
+
loc,
|
|
6292
7242
|
};
|
|
6293
7243
|
}
|
|
6294
7244
|
// `new Set<T>()`: construct + bulk add from supported values,
|
|
@@ -6304,9 +7254,21 @@ export function lowerNew(lowerer, expr) {
|
|
|
6304
7254
|
if (seeded)
|
|
6305
7255
|
return seeded;
|
|
6306
7256
|
}
|
|
6307
|
-
if (!mapped &&
|
|
6308
|
-
|
|
6309
|
-
|
|
7257
|
+
if (!mapped &&
|
|
7258
|
+
isJsSourceFile(expr.getSourceFile()) &&
|
|
7259
|
+
(expr.arguments?.length ?? 0) <= 1 &&
|
|
7260
|
+
!expr.arguments?.some(ts.isSpreadElement)) {
|
|
7261
|
+
return {
|
|
7262
|
+
kind: "libCall",
|
|
7263
|
+
fn: "dyn.nativeSetNew",
|
|
7264
|
+
args: [
|
|
7265
|
+
expr.arguments?.[0]
|
|
7266
|
+
? lowerer.lowerExprExpecting(expr.arguments[0], DYN)
|
|
7267
|
+
: dynUndefinedExpr(loc),
|
|
7268
|
+
],
|
|
7269
|
+
type: DYN,
|
|
7270
|
+
loc,
|
|
7271
|
+
};
|
|
6310
7272
|
}
|
|
6311
7273
|
// JavaScript's identity-Set idiom: `new Set([setTimeout, atob,
|
|
6312
7274
|
// ...])` — the element TYPE (a union of stdlib signatures) has no
|
|
@@ -6427,7 +7389,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6427
7389
|
lowerer.mapTypeOf(lowerer.typeOf(expr.arguments[0]))?.kind !== "string" &&
|
|
6428
7390
|
lowerer.mapTypeOf(lowerer.typeOf(expr.arguments[1]))?.kind === "string") {
|
|
6429
7391
|
const first = lowerer.lowerExpr(expr.arguments[0]);
|
|
6430
|
-
if (first.kind === "unitLit" ||
|
|
7392
|
+
if (first.kind === "unitLit" ||
|
|
7393
|
+
first.type.kind === "dyn" ||
|
|
7394
|
+
lowerer.dynConvertible(first.type)) {
|
|
6431
7395
|
const got = first.type.kind === "dyn" ? first : { kind: "dynFrom", value: first, type: DYN, loc };
|
|
6432
7396
|
// The encoding argument still evaluates in Node before the
|
|
6433
7397
|
// throw only via the ctor body's later reads — it does NOT
|
|
@@ -6435,7 +7399,13 @@ export function lowerNew(lowerer, expr) {
|
|
|
6435
7399
|
// effect-free operands; effectful ones keep the fence.
|
|
6436
7400
|
const enc = lowerer.lowerExpr(expr.arguments[1]);
|
|
6437
7401
|
if (enc.kind === "strLit" || isSafeToRepeat(enc)) {
|
|
6438
|
-
return {
|
|
7402
|
+
return {
|
|
7403
|
+
kind: "libCall",
|
|
7404
|
+
fn: "buffer.newStringFail",
|
|
7405
|
+
args: [got],
|
|
7406
|
+
type: bytesOf("u8"),
|
|
7407
|
+
loc,
|
|
7408
|
+
};
|
|
6439
7409
|
}
|
|
6440
7410
|
}
|
|
6441
7411
|
}
|
|
@@ -6490,10 +7460,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
6490
7460
|
if (t?.kind !== "record")
|
|
6491
7461
|
lowerer.badType(expr, lowerer.typeOf(expr));
|
|
6492
7462
|
const key = `x509.record:${isBytes ? "bytes" : "str"}`;
|
|
6493
|
-
let helper = lowerer.
|
|
7463
|
+
let helper = lowerer.valueHelpers.get(key);
|
|
6494
7464
|
if (!helper) {
|
|
6495
|
-
helper = `%x509.record.${lowerer.
|
|
6496
|
-
lowerer.
|
|
7465
|
+
helper = `%x509.record.${lowerer.valueHelpers.size}`;
|
|
7466
|
+
lowerer.valueHelpers.set(key, helper);
|
|
6497
7467
|
const dataT = data.type;
|
|
6498
7468
|
const dRef = { kind: "varRef", localId: "d.0", type: dataT, loc };
|
|
6499
7469
|
const field = (name, fn) => ({
|
|
@@ -6539,7 +7509,9 @@ export function lowerNew(lowerer, expr) {
|
|
|
6539
7509
|
const calleeT = storedClassValueType(lowerer, expr.expression);
|
|
6540
7510
|
if (calleeT?.kind === "classval") {
|
|
6541
7511
|
let info = lowerer.classes.get(calleeT.className);
|
|
6542
|
-
if (!info &&
|
|
7512
|
+
if (!info &&
|
|
7513
|
+
ts.isPropertyAccessExpression(expr.expression) &&
|
|
7514
|
+
ts.isIdentifier(expr.expression.name)) {
|
|
6543
7515
|
// A property-assigned class expression not collected yet (this
|
|
6544
7516
|
// body lowers ahead of the assignment statement — hoisted
|
|
6545
7517
|
// functions): collect it on demand and retry, keeping the
|
|
@@ -6590,7 +7562,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
6590
7562
|
if (calleeT?.kind === "union") {
|
|
6591
7563
|
const def = lowerer.unions.get(calleeT.unionId);
|
|
6592
7564
|
if (def?.arms.some((a) => a.kind === "classval")) {
|
|
6593
|
-
if (def.arms.every((arm) => arm.kind === "classval" || isJsSourceFile(expr.getSourceFile()) && isUnitType(arm)) &&
|
|
7565
|
+
if (def.arms.every((arm) => arm.kind === "classval" || (isJsSourceFile(expr.getSourceFile()) && isUnitType(arm))) &&
|
|
7566
|
+
lowerer.dynConvertible(calleeT)) {
|
|
6594
7567
|
const callee = lowerer.lowerExprExpecting(expr.expression, DYN);
|
|
6595
7568
|
return lowerCheckedConstructor(lowerer, expr, callee);
|
|
6596
7569
|
}
|
|
@@ -6621,7 +7594,10 @@ export function lowerNew(lowerer, expr) {
|
|
|
6621
7594
|
}
|
|
6622
7595
|
// Checked construction supports emitted classes and builtin typed arrays.
|
|
6623
7596
|
const callee = tryLowerExpression(lowerer, expr.expression);
|
|
6624
|
-
if (callee &&
|
|
7597
|
+
if (callee &&
|
|
7598
|
+
(callee.type.kind === "dyn" ||
|
|
7599
|
+
((callee.type.kind === "func" || callee.type.kind === "classval") &&
|
|
7600
|
+
lowerer.dynConvertible(callee.type)))) {
|
|
6625
7601
|
return lowerCheckedConstructor(lowerer, expr, lowerer.coerceToExpected(callee, DYN));
|
|
6626
7602
|
}
|
|
6627
7603
|
lowerer.unsupported("SC1090", expr, "constructing values other than classes declared in the program");
|
|
@@ -6636,10 +7612,10 @@ function lowerCheckedConstructor(lowerer, expr, callee) {
|
|
|
6636
7612
|
return checkedClassConstruction(lowerer, callee, args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
|
|
6637
7613
|
}
|
|
6638
7614
|
/** A getter/setter invocation over an accessor target's receiver — the
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
7615
|
+
* same whole-program devirtualization as method calls: a virtualCall
|
|
7616
|
+
* when some strict subclass of the receiver's static class overrides
|
|
7617
|
+
* this HALF of the accessor (get and set devirtualize independently),
|
|
7618
|
+
* a direct call of the nearest declaration otherwise. */
|
|
6643
7619
|
export function accessorCall(lowerer, className, member, obj, extraArgs, ret, loc) {
|
|
6644
7620
|
const info = lowerer.classes.get(className);
|
|
6645
7621
|
if (!info)
|
|
@@ -6687,7 +7663,8 @@ function genericFieldFnNodeOf(member) {
|
|
|
6687
7663
|
while (ts.isParenthesizedExpression(init))
|
|
6688
7664
|
init = init.expression;
|
|
6689
7665
|
if ((ts.isArrowFunction(init) || ts.isFunctionExpression(init)) &&
|
|
6690
|
-
init.typeParameters !== undefined &&
|
|
7666
|
+
init.typeParameters !== undefined &&
|
|
7667
|
+
init.body !== undefined) {
|
|
6691
7668
|
return init;
|
|
6692
7669
|
}
|
|
6693
7670
|
return null;
|