@scriptc/compiler 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +98 -39
- package/ambient/scriptc-overrides.d.ts +10 -6
- package/ambient/scriptc.d.ts +15 -0
- package/dist/backend/build-cache.d.ts +1 -3
- package/dist/backend/build-cache.js +3 -22
- package/dist/backend/build-cache.js.map +1 -1
- package/dist/backend/cache-root.d.ts +3 -0
- package/dist/backend/cache-root.js +23 -0
- package/dist/backend/cache-root.js.map +1 -0
- package/dist/backend/cycle-analysis.d.ts +15 -0
- package/dist/backend/cycle-analysis.js +108 -0
- package/dist/backend/cycle-analysis.js.map +1 -0
- package/dist/backend/cycle-analysis.test.js +124 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -0
- package/dist/backend/executable-features.d.ts +4 -0
- package/dist/backend/executable-features.js +42 -0
- package/dist/backend/executable-features.js.map +1 -0
- package/dist/backend/external-c.d.ts +5 -27
- package/dist/backend/external-c.js +5 -40
- package/dist/backend/external-c.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +2 -3
- package/dist/backend/ffi-callbacks.js +2 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/library-identity-markers.d.ts +4 -9
- package/dist/backend/library-identity-markers.js +11 -49
- package/dist/backend/library-identity-markers.js.map +1 -1
- package/dist/backend/library-pack.d.ts +5 -0
- package/dist/backend/library-pack.js +123 -0
- package/dist/backend/library-pack.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +20 -0
- package/dist/backend/link-plan-core.js +18 -0
- package/dist/backend/link-plan-core.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -1
- package/dist/backend/link-plan.js +16 -17
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/link-trace.d.ts +2 -0
- package/dist/backend/link-trace.js +24 -0
- package/dist/backend/link-trace.js.map +1 -0
- package/dist/backend/linker.js +1 -1
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/literals.d.ts +9 -0
- package/dist/backend/literals.js +35 -0
- package/dist/backend/literals.js.map +1 -0
- package/dist/backend/literals.test.d.ts +1 -0
- package/dist/backend/literals.test.js +53 -0
- package/dist/backend/literals.test.js.map +1 -0
- package/dist/backend/llvm/blocks.d.ts +2 -0
- package/dist/backend/llvm/blocks.js +9 -4
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.d.ts +1 -0
- package/dist/backend/llvm/blocks.test.js +91 -0
- package/dist/backend/llvm/blocks.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +14 -8
- package/dist/backend/llvm/classes.js +88 -30
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +5 -1
- package/dist/backend/llvm/common.js +45 -4
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -7
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/debug-info.test.d.ts +1 -0
- package/dist/backend/llvm/debug-info.test.js +110 -0
- package/dist/backend/llvm/debug-info.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +21 -2
- package/dist/backend/llvm/dyn.js +647 -251
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +596 -1
- package/dist/backend/llvm/emitter.js +769 -425
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.d.ts +1 -0
- package/dist/backend/llvm/emitter.test.js +179 -0
- package/dist/backend/llvm/emitter.test.js.map +1 -0
- package/dist/backend/llvm/expr-async.js +23 -14
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -2
- package/dist/backend/llvm/expr-bytes.js +60 -31
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-callbacks.js +25 -22
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.js +136 -35
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +1 -1
- package/dist/backend/llvm/expr-containers.js +43 -14
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +5 -260
- package/dist/backend/llvm/expr-control.js +10 -6
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.d.ts +1 -1
- package/dist/backend/llvm/expr-dispatch.js +2 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +78 -81
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.d.ts +1 -1
- package/dist/backend/llvm/expr-island.js +11 -7
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +62 -31
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +1 -1
- package/dist/backend/llvm/expr-records.d.ts +5 -1
- package/dist/backend/llvm/expr-records.js +54 -7
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +4 -4
- package/dist/backend/llvm/expr-stream-bridges.js +220 -131
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.d.ts +1 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js +55 -0
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -0
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +12 -12
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +19 -0
- package/dist/backend/llvm/layouts.js +12 -0
- package/dist/backend/llvm/layouts.js.map +1 -0
- package/dist/backend/llvm/lib-abi.d.ts +19 -0
- package/dist/backend/llvm/lib-abi.js +82 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -0
- package/dist/backend/llvm/lib-connect.d.ts +2 -0
- package/dist/backend/llvm/lib-connect.js +51 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.d.ts +2 -0
- package/dist/backend/llvm/lib-datagram.js +135 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -0
- package/dist/backend/llvm/lib-dispatch.js +50 -6
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +30 -18
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +2 -0
- package/dist/backend/llvm/lib-http2.js +215 -0
- package/dist/backend/llvm/lib-http2.js.map +1 -0
- package/dist/backend/llvm/lib-lookup.d.ts +2 -0
- package/dist/backend/llvm/lib-lookup.js +39 -0
- package/dist/backend/llvm/lib-lookup.js.map +1 -0
- package/dist/backend/llvm/lib-network.js +25 -2
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +44 -19
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +162 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +3 -2
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.d.ts +2 -0
- package/dist/backend/llvm/lib-test.js +34 -0
- package/dist/backend/llvm/lib-test.js.map +1 -0
- package/dist/backend/llvm/lib-tls.d.ts +2 -0
- package/dist/backend/llvm/lib-tls.js +82 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +10 -9
- package/dist/backend/llvm/shapes.js +42 -131
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/unsupported.d.ts +1 -0
- package/dist/backend/llvm/unsupported.js +1 -2
- package/dist/backend/llvm/unsupported.js.map +1 -1
- package/dist/backend/llvm/walkers.js +1 -7
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/mangle.d.ts +2 -2
- package/dist/backend/mangle.js +16 -5
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/{c/may-throw.d.ts → may-throw.d.ts} +1 -1
- package/dist/backend/{c/may-throw.js → may-throw.js} +51 -46
- package/dist/backend/may-throw.js.map +1 -0
- package/dist/backend/may-throw.test.d.ts +1 -0
- package/dist/backend/may-throw.test.js +58 -0
- package/dist/backend/may-throw.test.js.map +1 -0
- package/dist/backend/native-codegen-core.d.ts +22 -0
- package/dist/backend/native-codegen-core.js +44 -0
- package/dist/backend/native-codegen-core.js.map +1 -0
- package/dist/backend/native-codegen.d.ts +3 -19
- package/dist/backend/native-codegen.js +5 -44
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +2 -2
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +94 -0
- package/dist/backend/native-link-info-core.js +62 -0
- package/dist/backend/native-link-info-core.js.map +1 -0
- package/dist/backend/native-link-info.d.ts +3 -88
- package/dist/backend/native-link-info.js +12 -243
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +41 -146
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-toolchain.d.ts +12 -30
- package/dist/backend/native-toolchain.js +83 -233
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +77 -5
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +24 -0
- package/dist/backend/native-tools.js +33 -0
- package/dist/backend/native-tools.js.map +1 -0
- package/dist/backend/object-localize.js +19 -8
- package/dist/backend/object-localize.js.map +1 -1
- package/dist/backend/object-localize.test.js +22 -0
- package/dist/backend/object-localize.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +101 -0
- package/dist/backend/runtime-pack-core.js +172 -0
- package/dist/backend/runtime-pack-core.js.map +1 -0
- package/dist/backend/runtime-pack-native.d.ts +21 -0
- package/dist/backend/runtime-pack-native.js +73 -0
- package/dist/backend/runtime-pack-native.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +3 -83
- package/dist/backend/runtime-pack.js +8 -151
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +24 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.d.ts +22 -0
- package/dist/backend/target-diagnostics.js +108 -0
- package/dist/backend/target-diagnostics.js.map +1 -0
- package/dist/backend/target-platform.d.ts +15 -0
- package/dist/backend/target-platform.js +72 -0
- package/dist/backend/target-platform.js.map +1 -0
- package/dist/backend/targets.d.ts +13 -4
- package/dist/backend/targets.js +103 -34
- package/dist/backend/targets.js.map +1 -1
- package/dist/backend/targets.test.js +72 -4
- package/dist/backend/targets.test.js.map +1 -1
- package/dist/backend/toolchain-environment.d.ts +6 -0
- package/dist/backend/toolchain-environment.js +99 -0
- package/dist/backend/toolchain-environment.js.map +1 -0
- package/dist/backend/vendor-archives.d.ts +1 -9
- package/dist/backend/vendor-archives.js +2 -9
- package/dist/backend/vendor-archives.js.map +1 -1
- package/dist/backend/vendor-inputs.d.ts +9 -0
- package/dist/backend/vendor-inputs.js +10 -0
- package/dist/backend/vendor-inputs.js.map +1 -0
- package/dist/backend/warm-cache.d.ts +3 -0
- package/dist/backend/warm-cache.js +41 -0
- package/dist/backend/warm-cache.js.map +1 -0
- package/dist/cli/command.d.ts +3 -0
- package/dist/cli/command.js +328 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/cli/host.d.ts +24 -0
- package/dist/cli/host.js +2 -0
- package/dist/cli/host.js.map +1 -0
- package/dist/cli/output-options.d.ts +26 -0
- package/dist/cli/output-options.js +60 -0
- package/dist/cli/output-options.js.map +1 -0
- package/dist/cli/paths.d.ts +12 -0
- package/dist/cli/paths.js +42 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/usage.d.ts +74 -0
- package/dist/cli/usage.js +86 -0
- package/dist/cli/usage.js.map +1 -0
- package/dist/cli/wasi-paths.d.ts +8 -0
- package/dist/cli/wasi-paths.js +41 -0
- package/dist/cli/wasi-paths.js.map +1 -0
- package/dist/cli/wasi-runner.d.ts +2 -0
- package/dist/cli/wasi-runner.js +28 -0
- package/dist/cli/wasi-runner.js.map +1 -0
- package/dist/compat/fetch-profile.js +37 -7
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +162 -0
- package/dist/compile-types.js +2 -0
- package/dist/compile-types.js.map +1 -0
- package/dist/coverage/report.js +11 -5
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +5 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +5 -10
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +3 -4
- package/dist/executable/executable-cache.js +5 -6
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +16 -17
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.d.ts +14 -0
- package/dist/executable/prepare.js +66 -0
- package/dist/executable/prepare.js.map +1 -0
- package/dist/ffi/ffi-manifest.d.ts +11 -4
- package/dist/ffi/ffi-manifest.js +170 -58
- package/dist/ffi/ffi-manifest.js.map +1 -1
- package/dist/ffi/ffi-manifest.test.d.ts +1 -0
- package/dist/ffi/ffi-manifest.test.js +111 -0
- package/dist/ffi/ffi-manifest.test.js.map +1 -0
- package/dist/format-integer.d.ts +3 -0
- package/dist/format-integer.js +14 -0
- package/dist/format-integer.js.map +1 -0
- package/dist/frontend/analysis.d.ts +5 -0
- package/dist/frontend/analysis.js +88 -0
- package/dist/frontend/analysis.js.map +1 -0
- package/dist/frontend/arguments-usage.d.ts +1 -3
- package/dist/frontend/arguments-usage.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -1
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-lexer.d.ts +4 -25
- package/dist/frontend/cjs-lexer.js +6 -806
- package/dist/frontend/cjs-lexer.js.map +1 -1
- package/dist/frontend/cjs-resolve.d.ts +5 -0
- package/dist/frontend/cjs-resolve.js +429 -0
- package/dist/frontend/cjs-resolve.js.map +1 -0
- package/dist/frontend/cjs-syntax.d.ts +26 -0
- package/dist/frontend/cjs-syntax.js +806 -0
- package/dist/frontend/cjs-syntax.js.map +1 -0
- package/dist/frontend/comptime-node.d.ts +4 -0
- package/dist/frontend/comptime-node.js +16 -0
- package/dist/frontend/comptime-node.js.map +1 -0
- package/dist/frontend/comptime-node.test.d.ts +1 -0
- package/dist/frontend/comptime-node.test.js +37 -0
- package/dist/frontend/comptime-node.test.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +3 -4
- package/dist/frontend/dts-paths.js +15 -8
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/fork-target.js +2 -2
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/helper-tokens.d.ts +1 -0
- package/dist/frontend/helper-tokens.js +147 -0
- package/dist/frontend/helper-tokens.js.map +1 -0
- package/dist/frontend/helper-tokens.test.d.ts +1 -0
- package/dist/frontend/helper-tokens.test.js +35 -0
- package/dist/frontend/helper-tokens.test.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.d.ts +5 -0
- package/dist/frontend/inferred-js-diagnostics.js +69 -0
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.d.ts +1 -0
- package/dist/frontend/inferred-js-diagnostics.test.js +58 -0
- package/dist/frontend/inferred-js-diagnostics.test.js.map +1 -0
- package/dist/frontend/input-tracker.d.ts +5 -2
- package/dist/frontend/input-tracker.js +24 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +23 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/lib-contract.js +32 -24
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/literal-values.d.ts +4 -0
- package/dist/frontend/literal-values.js +21 -0
- package/dist/frontend/literal-values.js.map +1 -0
- package/dist/frontend/literal-values.test.d.ts +1 -0
- package/dist/frontend/literal-values.test.js +91 -0
- package/dist/frontend/literal-values.test.js.map +1 -0
- package/dist/frontend/lowering/abstract-equality.d.ts +1 -1
- package/dist/frontend/lowering/abstract-equality.js +3 -0
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +11 -6
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +4 -1
- package/dist/frontend/lowering/array-values.js +43 -1
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/callback-arg.js +1 -0
- package/dist/frontend/lowering/callback-arg.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +12 -0
- package/dist/frontend/lowering/class-callbacks.js +74 -0
- package/dist/frontend/lowering/class-callbacks.js.map +1 -0
- package/dist/frontend/lowering/class-construction.d.ts +12 -0
- package/dist/frontend/lowering/class-construction.js +156 -0
- package/dist/frontend/lowering/class-construction.js.map +1 -0
- package/dist/frontend/lowering/class-descriptors.d.ts +10 -0
- package/dist/frontend/lowering/class-descriptors.js +114 -0
- package/dist/frontend/lowering/class-descriptors.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +51 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1158 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +93 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -0
- package/dist/frontend/lowering/class-instance-constructor.d.ts +7 -0
- package/dist/frontend/lowering/class-instance-constructor.js +67 -0
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.d.ts +13 -0
- package/dist/frontend/lowering/class-method-values.js +235 -0
- package/dist/frontend/lowering/class-method-values.js.map +1 -0
- package/dist/frontend/lowering/class-prototypes.d.ts +19 -0
- package/dist/frontend/lowering/class-prototypes.js +242 -0
- package/dist/frontend/lowering/class-prototypes.js.map +1 -0
- package/dist/frontend/lowering/class-runtime-statics.d.ts +8 -0
- package/dist/frontend/lowering/class-runtime-statics.js +66 -0
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -0
- package/dist/frontend/lowering/class-static-data.d.ts +6 -0
- package/dist/frontend/lowering/class-static-data.js +56 -0
- package/dist/frontend/lowering/class-static-data.js.map +1 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.d.ts +4 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js +26 -0
- package/dist/frontend/lowering/containers/buffer-numeric-methods.js.map +1 -0
- package/dist/frontend/lowering/containers/bytes.d.ts +11 -7
- package/dist/frontend/lowering/containers/bytes.js +208 -163
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +2 -2
- package/dist/frontend/lowering/containers/string-and-regexp.js +58 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-replacement.js +217 -0
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -0
- package/dist/frontend/lowering/error-methods.d.ts +14 -0
- package/dist/frontend/lowering/error-methods.js +177 -0
- package/dist/frontend/lowering/error-methods.js.map +1 -0
- package/dist/frontend/lowering/expressions/global-symbols.d.ts +6 -0
- package/dist/frontend/lowering/expressions/global-symbols.js +11 -0
- package/dist/frontend/lowering/expressions/global-symbols.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.d.ts +7 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +51 -0
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.d.ts +6 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js +132 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.d.ts +8 -8
- package/dist/frontend/lowering/expressions/object-literals.js +509 -183
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +3 -4
- package/dist/frontend/lowering/expressions/optional-chains.js +88 -24
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/try-lower-expression.js +1 -0
- package/dist/frontend/lowering/expressions/try-lower-expression.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +8 -0
- package/dist/frontend/lowering/expressions/union-field-write.js +71 -0
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +101 -0
- package/dist/frontend/lowering/function-context.js +109 -0
- package/dist/frontend/lowering/function-context.js.map +1 -0
- package/dist/frontend/lowering/generator-delegation.d.ts +7 -0
- package/dist/frontend/lowering/generator-delegation.js +85 -0
- package/dist/frontend/lowering/generator-delegation.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +143 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -0
- package/dist/frontend/lowering/lib-boundary.d.ts +4 -1
- package/dist/frontend/lowering/lib-boundary.js +112 -20
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.test.d.ts +1 -0
- package/dist/frontend/lowering/lib-boundary.test.js +45 -0
- package/dist/frontend/lowering/lib-boundary.test.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.d.ts +1 -1
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +18 -0
- package/dist/frontend/lowering/lower-builtin-values.js +249 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +33 -46
- package/dist/frontend/lowering/lower-builtins.js +676 -365
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +28 -22
- package/dist/frontend/lowering/lower-calls.js +1660 -412
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +95 -57
- package/dist/frontend/lowering/lower-classes.js +1491 -404
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +23 -32
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +36 -32
- package/dist/frontend/lowering/lower-containers.js +925 -181
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -2
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.d.ts +1 -1
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +30 -1
- package/dist/frontend/lowering/lower-event-emitter.js +58 -26
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.d.ts +7 -1
- package/dist/frontend/lowering/lower-expando.js +14 -6
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +37 -13
- package/dist/frontend/lowering/lower-exprs.js +2163 -863
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +2 -5
- package/dist/frontend/lowering/lower-generators.js +88 -46
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.d.ts +7 -0
- package/dist/frontend/lowering/lower-global-value.js +17 -0
- package/dist/frontend/lowering/lower-global-value.js.map +1 -0
- package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +17 -8
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +7 -8
- package/dist/frontend/lowering/lower-island.js +66 -33
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.d.ts +2 -2
- package/dist/frontend/lowering/lower-mixins.js +5 -3
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +445 -39
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-modules.test.js +39 -0
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -0
- package/dist/frontend/lowering/lower-namespaces.d.ts +1 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +1 -1
- package/dist/frontend/lowering/lower-node-module.js +13 -10
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +1 -1
- package/dist/frontend/lowering/lower-server.js +6 -10
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +17 -17
- package/dist/frontend/lowering/lower-stmts.js +855 -514
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -1
- package/dist/frontend/lowering/lower-stream.js +20 -11
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +1 -1
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-url.d.ts +6 -0
- package/dist/frontend/lowering/lower-url.js +77 -0
- package/dist/frontend/lowering/lower-url.js.map +1 -0
- package/dist/frontend/lowering/lowerer.d.ts +140 -190
- package/dist/frontend/lowering/lowerer.js +1193 -712
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.d.ts +1 -0
- package/dist/frontend/lowering/lowerer.test.js +172 -0
- package/dist/frontend/lowering/lowerer.test.js.map +1 -0
- package/dist/frontend/lowering/native-ffi.d.ts +5 -0
- package/dist/frontend/lowering/native-ffi.js +40 -0
- package/dist/frontend/lowering/native-ffi.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.d.ts +7 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +33 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.d.ts +8 -0
- package/dist/frontend/lowering/object-factory-new.js +68 -0
- package/dist/frontend/lowering/object-factory-new.js.map +1 -0
- package/dist/frontend/lowering/optional-arguments.js +6 -1
- package/dist/frontend/lowering/optional-arguments.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-locals.d.ts +14 -0
- package/dist/frontend/lowering/runtime-optional-locals.js +41 -0
- package/dist/frontend/lowering/runtime-optional-locals.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js +85 -0
- package/dist/frontend/lowering/runtime-optional-locals.test.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.d.ts +8 -0
- package/dist/frontend/lowering/sanitize-class-types.js +79 -0
- package/dist/frontend/lowering/sanitize-class-types.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +60 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/static-this.d.ts +5 -1
- package/dist/frontend/lowering/static-this.js +28 -2
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +7 -0
- package/dist/frontend/lowering/string-index.js +39 -0
- package/dist/frontend/lowering/string-index.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +10 -3
- package/dist/frontend/lowering/surfaces.js +86 -37
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +22 -0
- package/dist/frontend/lowering/symbol-fields.js +183 -0
- package/dist/frontend/lowering/symbol-fields.js.map +1 -0
- package/dist/frontend/lowering/symbol-methods.d.ts +7 -0
- package/dist/frontend/lowering/symbol-methods.js +30 -0
- package/dist/frontend/lowering/symbol-methods.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.d.ts +12 -0
- package/dist/frontend/lowering/text-decoder-encoding.js +82 -0
- package/dist/frontend/lowering/text-decoder-encoding.js.map +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.d.ts +1 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js +38 -0
- package/dist/frontend/lowering/text-decoder-encoding.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +9 -0
- package/dist/frontend/lowering/union-narrow.js +59 -0
- package/dist/frontend/lowering/union-narrow.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.test.d.ts +1 -0
- package/dist/frontend/lowering/union-narrow.test.js +72 -0
- package/dist/frontend/lowering/union-narrow.test.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +43 -0
- package/dist/frontend/lowering/union-retag.js +259 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -0
- package/dist/frontend/lowering/union-retag.test.d.ts +1 -0
- package/dist/frontend/lowering/union-retag.test.js +405 -0
- package/dist/frontend/lowering/union-retag.test.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.d.ts +14 -0
- package/dist/frontend/lowering/unregistered-class-types.js +94 -0
- package/dist/frontend/lowering/unregistered-class-types.js.map +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.d.ts +1 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js +65 -0
- package/dist/frontend/lowering/unregistered-class-types.test.js.map +1 -0
- package/dist/frontend/lowering/width-lift.d.ts +40 -0
- package/dist/frontend/lowering/width-lift.js +2 -0
- package/dist/frontend/lowering/width-lift.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +58 -0
- package/dist/frontend/module-syntax.js +123 -0
- package/dist/frontend/module-syntax.js.map +1 -0
- package/dist/frontend/module-syntax.test.d.ts +1 -0
- package/dist/frontend/module-syntax.test.js +78 -0
- package/dist/frontend/module-syntax.test.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.d.ts +17 -0
- package/dist/frontend/npm-fetch-analysis.js +100 -0
- package/dist/frontend/npm-fetch-analysis.js.map +1 -0
- package/dist/frontend/npm-fetch-analysis.test.d.ts +1 -0
- package/dist/frontend/npm-fetch-analysis.test.js +107 -0
- package/dist/frontend/npm-fetch-analysis.test.js.map +1 -0
- package/dist/frontend/npm-fetch-node.d.ts +2 -0
- package/dist/frontend/npm-fetch-node.js +12 -0
- package/dist/frontend/npm-fetch-node.js.map +1 -0
- package/dist/frontend/npm-fetch-syntax.d.ts +6 -0
- package/dist/frontend/npm-fetch-syntax.js +207 -0
- package/dist/frontend/npm-fetch-syntax.js.map +1 -0
- package/dist/frontend/npm-node.d.ts +10 -0
- package/dist/frontend/npm-node.js +14 -0
- package/dist/frontend/npm-node.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.d.ts +8 -0
- package/dist/frontend/npm-static-bundled-cjs.js +236 -0
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js +69 -0
- package/dist/frontend/npm-static-bundled-cjs.test.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.d.ts +57 -0
- package/dist/frontend/npm-static-declaration-syntax.js +944 -0
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -0
- package/dist/frontend/npm-static-declarations.d.ts +11 -39
- package/dist/frontend/npm-static-declarations.js +22 -561
- package/dist/frontend/npm-static-declarations.js.map +1 -1
- package/dist/frontend/npm-static-declarations.test.js +245 -6
- package/dist/frontend/npm-static-declarations.test.js.map +1 -1
- package/dist/frontend/npm-static-prune.d.ts +1 -1
- package/dist/frontend/npm-static-prune.js +121 -38
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-prune.test.js +9 -1
- package/dist/frontend/npm-static-prune.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -0
- package/dist/frontend/npm-static-rewrite-host.js +179 -0
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -0
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +16 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +905 -0
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -0
- package/dist/frontend/npm-static-rewrite.d.ts +0 -5
- package/dist/frontend/npm-static-rewrite.js +2 -1079
- package/dist/frontend/npm-static-rewrite.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.d.ts +5 -0
- package/dist/frontend/npm-static-subtyping.js +55 -0
- package/dist/frontend/npm-static-subtyping.js.map +1 -0
- package/dist/frontend/npm-static-subtyping.test.d.ts +1 -0
- package/dist/frontend/npm-static-subtyping.test.js +58 -0
- package/dist/frontend/npm-static-subtyping.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +7 -15
- package/dist/frontend/npm-static.js +19 -28
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm.d.ts +8 -69
- package/dist/frontend/npm.js +21 -361
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/npm.test.js +2 -2
- package/dist/frontend/npm.test.js.map +1 -1
- package/dist/frontend/pipeline-native.d.ts +6 -0
- package/dist/frontend/pipeline-native.js +32 -0
- package/dist/frontend/pipeline-native.js.map +1 -0
- package/dist/frontend/pipeline.d.ts +54 -0
- package/dist/frontend/pipeline.js +382 -0
- package/dist/frontend/pipeline.js.map +1 -0
- package/dist/frontend/pipeline.test.d.ts +1 -0
- package/dist/frontend/pipeline.test.js +77 -0
- package/dist/frontend/pipeline.test.js.map +1 -0
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +14 -0
- package/dist/frontend/program-analysis.js.map +1 -0
- package/dist/frontend/program-node.d.ts +9 -0
- package/dist/frontend/program-node.js +48 -0
- package/dist/frontend/program-node.js.map +1 -0
- package/dist/frontend/program.d.ts +39 -20
- package/dist/frontend/program.js +393 -189
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +105 -2
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/provenance-core.d.ts +9 -0
- package/dist/frontend/provenance-core.js +435 -0
- package/dist/frontend/provenance-core.js.map +1 -0
- package/dist/frontend/provenance.d.ts +0 -4
- package/dist/frontend/provenance.js +4 -459
- package/dist/frontend/provenance.js.map +1 -1
- package/dist/frontend/resolve.d.ts +3 -1
- package/dist/frontend/resolve.js +6 -3
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.d.ts +4 -3
- package/dist/frontend/runtime-resolve.js +22 -18
- package/dist/frontend/runtime-resolve.js.map +1 -1
- package/dist/frontend/runtime-resolve.test.js +53 -0
- package/dist/frontend/runtime-resolve.test.js.map +1 -1
- package/dist/frontend/services-node.d.ts +5 -0
- package/dist/frontend/services-node.js +19 -0
- package/dist/frontend/services-node.js.map +1 -0
- package/dist/frontend/services-node.test.d.ts +1 -0
- package/dist/frontend/services-node.test.js +70 -0
- package/dist/frontend/services-node.test.js.map +1 -0
- package/dist/frontend/services.d.ts +44 -0
- package/dist/frontend/services.js +90 -0
- package/dist/frontend/services.js.map +1 -0
- package/dist/frontend/services.test.d.ts +1 -0
- package/dist/frontend/services.test.js +174 -0
- package/dist/frontend/services.test.js.map +1 -0
- package/dist/frontend/ts7/adapter.d.ts +3 -3
- package/dist/frontend/ts7/adapter.js +14 -31
- package/dist/frontend/ts7/adapter.js.map +1 -1
- package/dist/frontend/ts7/api.d.ts +16 -0
- package/dist/frontend/ts7/api.js +24 -0
- package/dist/frontend/ts7/api.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.d.ts +31 -0
- package/dist/frontend/ts7/ast-bytes.js +137 -0
- package/dist/frontend/ts7/ast-bytes.js.map +1 -0
- package/dist/frontend/ts7/ast-bytes.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-bytes.test.js +73 -0
- package/dist/frontend/ts7/ast-bytes.test.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.d.ts +353 -0
- package/dist/frontend/ts7/ast-guards.generated.js +1951 -0
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-guards.test.js +43 -0
- package/dist/frontend/ts7/ast-guards.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +194 -0
- package/dist/frontend/ts7/ast-node.js +448 -0
- package/dist/frontend/ts7/ast-node.js.map +1 -0
- package/dist/frontend/ts7/ast-node.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-node.test.js +266 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -0
- package/dist/frontend/ts7/ast-schema.generated.d.ts +503 -0
- package/dist/frontend/ts7/ast-schema.generated.js +1446 -0
- package/dist/frontend/ts7/ast-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-text.d.ts +6 -0
- package/dist/frontend/ts7/ast-text.js +124 -0
- package/dist/frontend/ts7/ast-text.js.map +1 -0
- package/dist/frontend/ts7/ast-text.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-text.test.js +38 -0
- package/dist/frontend/ts7/ast-text.test.js.map +1 -0
- package/dist/frontend/ts7/ast-tokens.generated.d.ts +2 -0
- package/dist/frontend/ts7/ast-tokens.generated.js +155 -0
- package/dist/frontend/ts7/ast-tokens.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.d.ts +42 -0
- package/dist/frontend/ts7/ast-types.generated.d.ts +1615 -0
- package/dist/frontend/ts7/ast-types.generated.js +5 -0
- package/dist/frontend/ts7/ast-types.generated.js.map +1 -0
- package/dist/frontend/ts7/ast-types.js +3 -0
- package/dist/frontend/ts7/ast-types.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.d.ts +58 -0
- package/dist/frontend/ts7/ast-wire.js +267 -0
- package/dist/frontend/ts7/ast-wire.js.map +1 -0
- package/dist/frontend/ts7/ast-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/ast-wire.test.js +151 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -0
- package/dist/frontend/ts7/ast.d.ts +14 -14
- package/dist/frontend/ts7/ast.js +25 -18
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/census-check.js +1 -0
- package/dist/frontend/ts7/census-check.js.map +1 -1
- package/dist/frontend/ts7/checker-cache.d.ts +48 -0
- package/dist/frontend/ts7/checker-cache.js +92 -0
- package/dist/frontend/ts7/checker-cache.js.map +1 -0
- package/dist/frontend/ts7/checker.d.ts +19 -46
- package/dist/frontend/ts7/checker.js +231 -161
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.d.ts +1 -0
- package/dist/frontend/ts7/checker.test.js +335 -0
- package/dist/frontend/ts7/checker.test.js.map +1 -0
- package/dist/frontend/ts7/enums.d.ts +4 -27
- package/dist/frontend/ts7/enums.generated.d.ts +878 -0
- package/dist/frontend/ts7/enums.generated.js +1313 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -0
- package/dist/frontend/ts7/enums.js +4 -45
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/enums.test.d.ts +1 -0
- package/dist/frontend/ts7/enums.test.js +48 -0
- package/dist/frontend/ts7/enums.test.js.map +1 -0
- package/dist/frontend/ts7/native-api.d.ts +10 -0
- package/dist/frontend/ts7/native-api.js +10 -0
- package/dist/frontend/ts7/native-api.js.map +1 -0
- package/dist/frontend/ts7/native-host.d.ts +2 -0
- package/dist/frontend/ts7/native-host.js +11 -0
- package/dist/frontend/ts7/native-host.js.map +1 -0
- package/dist/frontend/ts7/native-process.d.ts +14 -0
- package/dist/frontend/ts7/native-process.js +62 -0
- package/dist/frontend/ts7/native-process.js.map +1 -0
- package/dist/frontend/ts7/program-adapter.d.ts +10 -98
- package/dist/frontend/ts7/program-adapter.js +16 -310
- package/dist/frontend/ts7/program-adapter.js.map +1 -1
- package/dist/frontend/ts7/program-host.d.ts +115 -0
- package/dist/frontend/ts7/program-host.js +347 -0
- package/dist/frontend/ts7/program-host.js.map +1 -0
- package/dist/frontend/ts7/program-host.test.d.ts +1 -0
- package/dist/frontend/ts7/program-host.test.js +207 -0
- package/dist/frontend/ts7/program-host.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-api.d.ts +12 -0
- package/dist/frontend/ts7/rpc-api.js +23 -0
- package/dist/frontend/ts7/rpc-api.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.d.ts +27 -0
- package/dist/frontend/ts7/rpc-client.js +102 -0
- package/dist/frontend/ts7/rpc-client.js.map +1 -0
- package/dist/frontend/ts7/rpc-client.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-client.test.js +133 -0
- package/dist/frontend/ts7/rpc-client.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.d.ts +16 -0
- package/dist/frontend/ts7/rpc-filesystem.js +42 -0
- package/dist/frontend/ts7/rpc-filesystem.js.map +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js +89 -0
- package/dist/frontend/ts7/rpc-filesystem.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.d.ts +2 -0
- package/dist/frontend/ts7/rpc-process.js +148 -0
- package/dist/frontend/ts7/rpc-process.js.map +1 -0
- package/dist/frontend/ts7/rpc-process.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-process.test.js +29 -0
- package/dist/frontend/ts7/rpc-process.test.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.d.ts +46 -0
- package/dist/frontend/ts7/rpc-wire.js +195 -0
- package/dist/frontend/ts7/rpc-wire.js.map +1 -0
- package/dist/frontend/ts7/rpc-wire.test.d.ts +1 -0
- package/dist/frontend/ts7/rpc-wire.test.js +168 -0
- package/dist/frontend/ts7/rpc-wire.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.d.ts +137 -0
- package/dist/frontend/ts7/semantic-checker.js +221 -0
- package/dist/frontend/ts7/semantic-checker.js.map +1 -0
- package/dist/frontend/ts7/semantic-checker.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-checker.test.js +119 -0
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.d.ts +5 -0
- package/dist/frontend/ts7/semantic-json.js +47 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -0
- package/dist/frontend/ts7/semantic-json.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-json.test.js +42 -0
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.d.ts +222 -0
- package/dist/frontend/ts7/semantic-model.js +423 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -0
- package/dist/frontend/ts7/semantic-model.test.d.ts +1 -0
- package/dist/frontend/ts7/semantic-model.test.js +322 -0
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -0
- package/dist/frontend/ts7/semantic-schema.generated.d.ts +283 -0
- package/dist/frontend/ts7/semantic-schema.generated.js +222 -0
- package/dist/frontend/ts7/semantic-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/semantic-types.d.ts +5 -0
- package/dist/frontend/ts7/semantic-types.js +2 -0
- package/dist/frontend/ts7/semantic-types.js.map +1 -0
- package/dist/frontend/ts7/session-cache.d.ts +17 -0
- package/dist/frontend/ts7/session-cache.js +97 -0
- package/dist/frontend/ts7/session-cache.js.map +1 -0
- package/dist/frontend/ts7/session-cache.test.d.ts +1 -0
- package/dist/frontend/ts7/session-cache.test.js +87 -0
- package/dist/frontend/ts7/session-cache.test.js.map +1 -0
- package/dist/frontend/ts7/session-path.d.ts +18 -0
- package/dist/frontend/ts7/session-path.js +203 -0
- package/dist/frontend/ts7/session-path.js.map +1 -0
- package/dist/frontend/ts7/session-path.test.d.ts +1 -0
- package/dist/frontend/ts7/session-path.test.js +34 -0
- package/dist/frontend/ts7/session-path.test.js.map +1 -0
- package/dist/frontend/ts7/session-schema.generated.d.ts +167 -0
- package/dist/frontend/ts7/session-schema.generated.js +5 -0
- package/dist/frontend/ts7/session-schema.generated.js.map +1 -0
- package/dist/frontend/ts7/session-timing.d.ts +50 -0
- package/dist/frontend/ts7/session-timing.js +61 -0
- package/dist/frontend/ts7/session-timing.js.map +1 -0
- package/dist/frontend/ts7/session-timing.test.d.ts +1 -0
- package/dist/frontend/ts7/session-timing.test.js +52 -0
- package/dist/frontend/ts7/session-timing.test.js.map +1 -0
- package/dist/frontend/ts7/session.d.ts +105 -0
- package/dist/frontend/ts7/session.js +233 -0
- package/dist/frontend/ts7/session.js.map +1 -0
- package/dist/frontend/ts7/session.test.d.ts +1 -0
- package/dist/frontend/ts7/session.test.js +215 -0
- package/dist/frontend/ts7/session.test.js.map +1 -0
- package/dist/frontend/ts7/source-parser-node.d.ts +6 -0
- package/dist/frontend/ts7/source-parser-node.js +15 -0
- package/dist/frontend/ts7/source-parser-node.js.map +1 -0
- package/dist/frontend/ts7/source-parser.d.ts +25 -0
- package/dist/frontend/ts7/source-parser.js +96 -0
- package/dist/frontend/ts7/source-parser.js.map +1 -0
- package/dist/frontend/ts7/source-parser.test.d.ts +1 -0
- package/dist/frontend/ts7/source-parser.test.js +151 -0
- package/dist/frontend/ts7/source-parser.test.js.map +1 -0
- package/dist/frontend/ts7/syntax.d.ts +3 -0
- package/dist/frontend/ts7/syntax.js +4 -0
- package/dist/frontend/ts7/syntax.js.map +1 -0
- package/dist/frontend/tsc-codes.js +3 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +34 -18
- package/dist/frontend/type-mapper.js +552 -131
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +146 -2
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend/union-discriminants.d.ts +16 -0
- package/dist/frontend/union-discriminants.js +98 -0
- package/dist/frontend/union-discriminants.js.map +1 -0
- package/dist/frontend/union-discriminants.test.d.ts +1 -0
- package/dist/frontend/union-discriminants.test.js +182 -0
- package/dist/frontend/union-discriminants.test.js.map +1 -0
- package/dist/index.d.ts +7 -198
- package/dist/index.js +369 -1572
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +16 -4
- package/dist/ir/analysis.js +23 -4
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -2
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/constant-tables.js +67 -49
- package/dist/ir/constant-tables.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/control-flow.d.ts +6 -0
- package/dist/ir/control-flow.js +142 -0
- package/dist/ir/control-flow.js.map +1 -0
- package/dist/ir/control-flow.test.d.ts +1 -0
- package/dist/ir/control-flow.test.js +113 -0
- package/dist/ir/control-flow.test.js.map +1 -0
- package/dist/ir/integer-loops.js +7 -18
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-ranges.js +53 -27
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/ir.d.ts +334 -176
- package/dist/ir/ir.js +710 -903
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +162 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/scalar-records.js +165 -134
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +4 -2
- package/dist/ir/serialize.js +33 -14
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.d.ts +1 -0
- package/dist/ir/serialize.test.js +57 -0
- package/dist/ir/serialize.test.js.map +1 -0
- package/dist/ir/traverse.d.ts +41 -0
- package/dist/ir/traverse.js +660 -0
- package/dist/ir/traverse.js.map +1 -0
- package/dist/ir/traverse.test.d.ts +1 -0
- package/dist/ir/traverse.test.js +242 -0
- package/dist/ir/traverse.test.js.map +1 -0
- package/dist/ir/validate.js +2018 -1498
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +536 -2
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/cache-primitives.d.ts +2 -3
- package/dist/library/cache-primitives.js +4 -6
- package/dist/library/cache-primitives.js.map +1 -1
- package/dist/library/fence-eval.js +2 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.js +7 -6
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.d.ts +3 -2
- package/dist/library/library-cache.js +5 -17
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +54 -41
- package/dist/library/library-cache.test.js.map +1 -1
- package/dist/library/library-profile.d.ts +3 -1
- package/dist/library/library-profile.js +15 -6
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.d.ts +15 -0
- package/dist/library/prepare.js +584 -0
- package/dist/library/prepare.js.map +1 -0
- package/dist/library/semantic-source.d.ts +1 -1
- package/dist/library/semantic-source.js +8 -6
- package/dist/library/semantic-source.js.map +1 -1
- package/dist/library/sidecar-validate.js +4 -4
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +2 -0
- package/dist/library/sidecar.js +10 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/cache.d.ts +11 -0
- package/dist/native/cache.js +113 -0
- package/dist/native/cache.js.map +1 -0
- package/dist/native/cache.test.d.ts +1 -0
- package/dist/native/cache.test.js +66 -0
- package/dist/native/cache.test.js.map +1 -0
- package/dist/native/cli.d.ts +1 -0
- package/dist/native/cli.js +112 -0
- package/dist/native/cli.js.map +1 -0
- package/dist/native/compiler.d.ts +15 -0
- package/dist/native/compiler.js +336 -0
- package/dist/native/compiler.js.map +1 -0
- package/dist/native/compiler.test.d.ts +1 -0
- package/dist/native/compiler.test.js +174 -0
- package/dist/native/compiler.test.js.map +1 -0
- package/dist/native/comptime.d.ts +5 -0
- package/dist/native/comptime.js +73 -0
- package/dist/native/comptime.js.map +1 -0
- package/dist/native/comptime.test.d.ts +1 -0
- package/dist/native/comptime.test.js +65 -0
- package/dist/native/comptime.test.js.map +1 -0
- package/dist/native/executable-cache.d.ts +26 -0
- package/dist/native/executable-cache.js +228 -0
- package/dist/native/executable-cache.js.map +1 -0
- package/dist/native/executable-cache.test.d.ts +1 -0
- package/dist/native/executable-cache.test.js +151 -0
- package/dist/native/executable-cache.test.js.map +1 -0
- package/dist/native/file-identity.d.ts +4 -0
- package/dist/native/file-identity.js +14 -0
- package/dist/native/file-identity.js.map +1 -0
- package/dist/native/file-identity.test.d.ts +1 -0
- package/dist/native/file-identity.test.js +43 -0
- package/dist/native/file-identity.test.js.map +1 -0
- package/dist/native/library.d.ts +22 -0
- package/dist/native/library.js +83 -0
- package/dist/native/library.js.map +1 -0
- package/dist/native/prepare.d.ts +21 -0
- package/dist/native/prepare.js +174 -0
- package/dist/native/prepare.js.map +1 -0
- package/dist/native/prepare.test.d.ts +1 -0
- package/dist/native/prepare.test.js +70 -0
- package/dist/native/prepare.test.js.map +1 -0
- package/dist/native/sanitizer.d.ts +11 -0
- package/dist/native/sanitizer.js +137 -0
- package/dist/native/sanitizer.js.map +1 -0
- package/dist/native/sanitizer.test.d.ts +1 -0
- package/dist/native/sanitizer.test.js +58 -0
- package/dist/native/sanitizer.test.js.map +1 -0
- package/dist/native/task.d.ts +4 -0
- package/dist/native/task.js +16 -0
- package/dist/native/task.js.map +1 -0
- package/dist/native/task.test.d.ts +1 -0
- package/dist/native/task.test.js +17 -0
- package/dist/native/task.test.js.map +1 -0
- package/dist/native/toolchain.d.ts +45 -0
- package/dist/native/toolchain.js +94 -0
- package/dist/native/toolchain.js.map +1 -0
- package/dist/native/toolchain.test.d.ts +1 -0
- package/dist/native/toolchain.test.js +85 -0
- package/dist/native/toolchain.test.js.map +1 -0
- package/dist/startup-cache.d.ts +1 -1
- package/dist/startup-cache.js +2 -5
- package/dist/startup-cache.js.map +1 -1
- package/dist/timing.d.ts +4 -0
- package/dist/timing.js +19 -0
- package/dist/timing.js.map +1 -0
- package/dist/wasi-paths.js +10 -7
- package/dist/wasi-paths.js.map +1 -1
- package/package.json +28 -19
- package/surface-manifest.json +107 -98
- package/dist/backend/c/async.d.ts +0 -171
- package/dist/backend/c/async.js +0 -1317
- package/dist/backend/c/async.js.map +0 -1
- package/dist/backend/c/c-emitter.d.ts +0 -536
- package/dist/backend/c/c-emitter.js +0 -1932
- package/dist/backend/c/c-emitter.js.map +0 -1
- package/dist/backend/c/exprs.d.ts +0 -15
- package/dist/backend/c/exprs.js +0 -8847
- package/dist/backend/c/exprs.js.map +0 -1
- package/dist/backend/c/island.d.ts +0 -45
- package/dist/backend/c/island.js +0 -281
- package/dist/backend/c/island.js.map +0 -1
- package/dist/backend/c/may-throw.js.map +0 -1
- package/dist/backend/c/shapes.d.ts +0 -142
- package/dist/backend/c/shapes.js +0 -603
- package/dist/backend/c/shapes.js.map +0 -1
- package/dist/backend/c/stmts.d.ts +0 -76
- package/dist/backend/c/stmts.js +0 -1108
- package/dist/backend/c/stmts.js.map +0 -1
- package/dist/backend/c/types.d.ts +0 -71
- package/dist/backend/c/types.js +0 -459
- package/dist/backend/c/types.js.map +0 -1
- package/dist/backend/c/types.test.js +0 -32
- package/dist/backend/c/types.test.js.map +0 -1
- package/dist/backend/c/walkers.d.ts +0 -134
- package/dist/backend/c/walkers.js +0 -1772
- package/dist/backend/c/walkers.js.map +0 -1
- /package/dist/backend/{c/types.test.d.ts → cycle-analysis.test.d.ts} +0 -0
|
@@ -5,25 +5,228 @@ import { InternalCompilerError } from "../../errors.js";
|
|
|
5
5
|
* accessor access, upcasts, `new` expressions, and the builtin Error
|
|
6
6
|
* hierarchy registration. */
|
|
7
7
|
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,
|
|
9
|
-
import { MAX_GENERIC_INSTANCES, appendImplicitUndefinedReturn, generatorMeta, genericCallInstance, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, omittedArgFor } from "./lower-calls.js";
|
|
10
|
-
import { isGenericCallableMemberType, typeKey } from "../type-mapper.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, appendImplicitUndefinedReturn, bodyReadsArguments, generatorMeta, genericCallInstance, hasExplicitJsDocReturn, implicitAnyParamSymbolsOf, implicitCallInstance, implicitMonoFile, omittedArgFor } from "./lower-calls.js";
|
|
10
|
+
import { isGenericCallableMemberType, jsOpenObjectType, typeKey, withUnitArm } from "../type-mapper.js";
|
|
11
11
|
import { cjsClassExprWholeExportOf, isCjsJsFile, isJsSourceFile, isModuleExportsAccess, isNodeTypesPath, locOf } from "../program.js";
|
|
12
|
-
import { PoisonError, dynFallbackType, dynUndefinedExpr, newFnCtx, own } from "./lowerer.js";
|
|
13
|
-
import { lowerArrayConstructor,
|
|
12
|
+
import { PoisonError, dynFallbackType, dynUndefinedExpr, newFnCtx, nodeThrowExpr, own } from "./lowerer.js";
|
|
13
|
+
import { lowerArrayConstructor, lowerMapSeedNew, lowerObjectConstructor, lowerSetSeedNew } from "./lower-containers.js";
|
|
14
14
|
import { bufEncoding } from "./containers/bytes.js";
|
|
15
15
|
import { isSafeToRepeat } from "./expressions/evaluation-safety.js";
|
|
16
|
-
import { lowerSearchParamsNew } from "./lower-builtins.js";
|
|
16
|
+
import { lowerSearchParamsNew, lowerTextCodecNew } from "./lower-builtins.js";
|
|
17
17
|
import { requiresDynamicPackageDiag, unsupportedDiag } from "../../diagnostics/diagnostic.js";
|
|
18
18
|
import { STREAM_API_MEMBERS, STREAM_PROP_MEMBERS, UNDERSCORE_METHODS, lowerStreamNew, lowerStreamSuperCall, streamCtorShape } from "./lower-stream.js";
|
|
19
19
|
import { emitOverrideShapeReason, emitSpecSuperForward, emitterRooted, lowerEmitterSuperCall } from "./lower-event-emitter.js";
|
|
20
20
|
import { declSymbolOf } from "./lower-modules.js";
|
|
21
|
-
import {
|
|
21
|
+
import { classSymbolKeyOf, classSymbolKeyOfSymbol, symbolFieldDisplayName } from "./symbol-fields.js";
|
|
22
|
+
import { builtinFenceHintOf } from "./surfaces.js";
|
|
22
23
|
import { lowerHttpAgentNew, lowerHttpServerNew } from "./lower-server.js";
|
|
23
24
|
import { ambientNsRootOf, ambientUndefReadType, ambientUndefVarRootOf, ambientUndefinedFnSymbolOf, fenceEarlyAliasUse, fenceEarlyNsMemberRef, nsMemberIdentOf, nsUndefRead } from "./lower-namespaces.js";
|
|
24
25
|
import { mixinResultBindingClassOf } from "./lower-mixins.js";
|
|
25
|
-
import { rejectStaticThis } from "./static-this.js";
|
|
26
|
-
import {
|
|
26
|
+
import { hasLexicalPrivateReference, hasStaticThis, rejectStaticThis } from "./static-this.js";
|
|
27
|
+
import { lowerUrlNew } from "./lower-url.js";
|
|
28
|
+
import { isNativeProxyInitializer, lowerNativeProxy } from "./expressions/native-proxy.js";
|
|
29
|
+
import { classStaticDataFor } from "./class-static-data.js";
|
|
30
|
+
import { lowerObjectFactoryNew } from "./object-factory-new.js";
|
|
31
|
+
import { tryLowerExpression } from "./expressions/try-lower-expression.js";
|
|
32
|
+
import { lowerInstanceConstructorNew } from "./class-instance-constructor.js";
|
|
33
|
+
import { classPrototypeData } from "./class-prototypes.js";
|
|
34
|
+
import { checkedClassConstruction } from "./class-construction.js";
|
|
35
|
+
import { initializeRuntimeStatics, hasRuntimeStatics } from "./class-runtime-statics.js";
|
|
36
|
+
export function returnsOnlyThis(member) {
|
|
37
|
+
const body = member.body;
|
|
38
|
+
const last = body?.statements.at(-1);
|
|
39
|
+
if (!body || !last || !ts.isReturnStatement(last))
|
|
40
|
+
return false;
|
|
41
|
+
let valid = true;
|
|
42
|
+
const visit = (node) => {
|
|
43
|
+
if (ts.isFunctionLike(node))
|
|
44
|
+
return;
|
|
45
|
+
if (ts.isReturnStatement(node)) {
|
|
46
|
+
let value = node.expression;
|
|
47
|
+
while (value && ts.isParenthesizedExpression(value))
|
|
48
|
+
value = value.expression;
|
|
49
|
+
if (!value || value.kind !== ts.SyntaxKind.ThisKeyword)
|
|
50
|
+
valid = false;
|
|
51
|
+
}
|
|
52
|
+
node.forEachChild(visit);
|
|
53
|
+
};
|
|
54
|
+
body.forEachChild(visit);
|
|
55
|
+
return valid;
|
|
56
|
+
}
|
|
57
|
+
function functionLocalClass(decl) {
|
|
58
|
+
for (let parent = decl.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
59
|
+
if (ts.isFunctionLike(parent))
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
export function storedClassValueType(lowerer, expression, visiting = new Set()) {
|
|
65
|
+
if (visiting.has(expression))
|
|
66
|
+
return null;
|
|
67
|
+
visiting.add(expression);
|
|
68
|
+
if (ts.isParenthesizedExpression(expression))
|
|
69
|
+
return storedClassValueType(lowerer, expression.expression, visiting);
|
|
70
|
+
if (ts.isClassExpression(expression) && !functionLocalClass(expression) && !lowerer.collectingExprClasses.has(expression)) {
|
|
71
|
+
const info = lowerer.lowerClassExpressionInfo(expression);
|
|
72
|
+
return { kind: "classval", className: info.def.name };
|
|
73
|
+
}
|
|
74
|
+
if (ts.isPropertyAccessExpression(expression) && !expression.questionDotToken) {
|
|
75
|
+
const member = nsMemberIdentOf(lowerer, expression);
|
|
76
|
+
if (member)
|
|
77
|
+
return storedClassValueType(lowerer, member, visiting);
|
|
78
|
+
}
|
|
79
|
+
if (expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
80
|
+
const stored = lowerer.resolveThis();
|
|
81
|
+
if (stored?.type.kind === "classval")
|
|
82
|
+
return stored.type;
|
|
83
|
+
}
|
|
84
|
+
if (ts.isIdentifier(expression)) {
|
|
85
|
+
const stored = lowerer.peekLocal(expression) ?? lowerer.globalOf(expression);
|
|
86
|
+
if (stored?.type.kind === "classval" && lowerer.classes.has(stored.type.className))
|
|
87
|
+
return stored.type;
|
|
88
|
+
const symbol = lowerer.resolveValueSymbol(expression);
|
|
89
|
+
const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isVariableDeclaration(decl) && decl.initializer && (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
90
|
+
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
91
|
+
const value = storedClassValueType(lowerer, declaration.initializer, visiting);
|
|
92
|
+
if (value?.kind === "classval")
|
|
93
|
+
return value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const type = lowerer.typeOf(expression);
|
|
97
|
+
const mapped = lowerer.mapTypeOf(type);
|
|
98
|
+
if (mapped?.kind === "classval" && !lowerer.classes.has(mapped.className)) {
|
|
99
|
+
for (const signature of lowerer.checker.getConstructSignatures(type)) {
|
|
100
|
+
const constructor = lowerer.checker.signatureDeclaration(signature);
|
|
101
|
+
const declaration = constructor && ts.isConstructorDeclaration(constructor) ? constructor.parent : undefined;
|
|
102
|
+
if (declaration && ts.isClassExpression(declaration) && !functionLocalClass(declaration) &&
|
|
103
|
+
!lowerer.collectingExprClasses.has(declaration)) {
|
|
104
|
+
const info = lowerer.lowerClassExpressionInfo(declaration);
|
|
105
|
+
return { kind: "classval", className: info.def.name };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (mapped?.kind === "classval" || !ts.isCallExpression(expression))
|
|
110
|
+
return mapped;
|
|
111
|
+
let callee = expression.expression;
|
|
112
|
+
let calls = 1;
|
|
113
|
+
const aliases = new Set();
|
|
114
|
+
for (;;) {
|
|
115
|
+
if (aliases.has(callee))
|
|
116
|
+
break;
|
|
117
|
+
aliases.add(callee);
|
|
118
|
+
if (ts.isParenthesizedExpression(callee)) {
|
|
119
|
+
callee = callee.expression;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (ts.isCallExpression(callee)) {
|
|
123
|
+
calls++;
|
|
124
|
+
callee = callee.expression;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
128
|
+
const member = nsMemberIdentOf(lowerer, callee);
|
|
129
|
+
if (member) {
|
|
130
|
+
callee = member;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (ts.isIdentifier(callee)) {
|
|
135
|
+
const symbol = lowerer.resolveValueSymbol(callee);
|
|
136
|
+
const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((decl) => ts.isVariableDeclaration(decl) && decl.initializer && (ts.getCombinedNodeFlags(decl) & ts.NodeFlags.Const) !== 0);
|
|
137
|
+
if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
138
|
+
callee = declaration.initializer;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
if ((ts.isArrowFunction(callee) || ts.isFunctionExpression(callee)) && isJsSourceFile(callee.getSourceFile()) &&
|
|
145
|
+
!callee.typeParameters?.length && !lowerer.preparingClassFactories.has(callee)) {
|
|
146
|
+
const signature = lowerer.checker.getSignatureFromDeclaration(callee);
|
|
147
|
+
let result = signature && lowerer.checker.getReturnTypeOfSignature(signature);
|
|
148
|
+
for (let i = 1; result && i < calls; i++) {
|
|
149
|
+
const signatures = lowerer.checker.getCallSignatures(result);
|
|
150
|
+
result = signatures.length === 1 ? lowerer.checker.getReturnTypeOfSignature(signatures[0]) : undefined;
|
|
151
|
+
}
|
|
152
|
+
if (result && lowerer.checker.getConstructSignatures(result).length > 0) {
|
|
153
|
+
const returned = (value) => {
|
|
154
|
+
let type = value.type;
|
|
155
|
+
for (let i = 0; i < calls && type.kind === "func"; i++)
|
|
156
|
+
type = type.ret;
|
|
157
|
+
return type.kind === "classval" ? type : null;
|
|
158
|
+
};
|
|
159
|
+
const home = callee.parent;
|
|
160
|
+
const generic = ts.isVariableDeclaration(home) && ts.isIdentifier(home.name) ? lowerer.genericFnOf(home.name) : null;
|
|
161
|
+
if (generic?.implicitParams && ts.isVariableDeclaration(home) && ts.isIdentifier(home.name)) {
|
|
162
|
+
const factory = lowerer.lowerGenericFnValue(home.name, generic);
|
|
163
|
+
const type = returned(factory);
|
|
164
|
+
if (type)
|
|
165
|
+
return type;
|
|
166
|
+
}
|
|
167
|
+
lowerer.preparingClassFactories.add(callee);
|
|
168
|
+
const collecting = lowerer.collecting, sink = lowerer.diagSink;
|
|
169
|
+
lowerer.collecting = false;
|
|
170
|
+
lowerer.diagSink = null;
|
|
171
|
+
try {
|
|
172
|
+
const factory = lowerer.preparedClassFactories.get(callee) ?? lowerer.lowerLambda(callee);
|
|
173
|
+
lowerer.preparedClassFactories.set(callee, factory);
|
|
174
|
+
const type = returned(factory);
|
|
175
|
+
if (type)
|
|
176
|
+
return type;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
lowerer.collecting = collecting;
|
|
180
|
+
lowerer.diagSink = sink;
|
|
181
|
+
lowerer.preparingClassFactories.delete(callee);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// A checked call can erase its returned constructor's ABI while the
|
|
186
|
+
// checker still identifies the class declaration. Collect that class in
|
|
187
|
+
// its factory's lexical scope before choosing the derived native layout.
|
|
188
|
+
// Cache the module-level closure so its captures and lifted bodies are
|
|
189
|
+
// exactly the ones used when the declaration executes.
|
|
190
|
+
for (const signature of lowerer.checker.getConstructSignatures(type)) {
|
|
191
|
+
const declaration = lowerer.checker.signatureDeclaration(signature);
|
|
192
|
+
const cls = declaration && ts.isConstructorDeclaration(declaration) ? declaration.parent : null;
|
|
193
|
+
if (!cls || (!ts.isClassExpression(cls) && !ts.isClassDeclaration(cls)))
|
|
194
|
+
continue;
|
|
195
|
+
let factory;
|
|
196
|
+
for (let parent = cls.parent; parent && !ts.isSourceFile(parent); parent = parent.parent) {
|
|
197
|
+
if (ts.isArrowFunction(parent) || ts.isFunctionExpression(parent))
|
|
198
|
+
factory = parent;
|
|
199
|
+
else if (ts.isFunctionLike(parent)) {
|
|
200
|
+
factory = undefined;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (!factory || !isJsSourceFile(factory.getSourceFile()) || factory.typeParameters?.length ||
|
|
205
|
+
!ts.isVariableDeclaration(factory.parent) || factory.parent.initializer !== factory ||
|
|
206
|
+
!ts.isVariableDeclarationList(factory.parent.parent) || !(factory.parent.parent.flags & ts.NodeFlags.Const) ||
|
|
207
|
+
!ts.isVariableStatement(factory.parent.parent.parent) || !ts.isSourceFile(factory.parent.parent.parent.parent) ||
|
|
208
|
+
lowerer.preparingClassFactories.has(factory))
|
|
209
|
+
continue;
|
|
210
|
+
if (!lowerer.preparedClassFactories.has(factory)) {
|
|
211
|
+
lowerer.preparingClassFactories.add(factory);
|
|
212
|
+
const collecting = lowerer.collecting, sink = lowerer.diagSink;
|
|
213
|
+
lowerer.collecting = false;
|
|
214
|
+
lowerer.diagSink = null;
|
|
215
|
+
try {
|
|
216
|
+
lowerer.preparedClassFactories.set(factory, lowerer.lowerLambda(factory));
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
lowerer.collecting = collecting;
|
|
220
|
+
lowerer.diagSink = sink;
|
|
221
|
+
lowerer.preparingClassFactories.delete(factory);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const resolved = lowerer.mapTypeOf(type);
|
|
225
|
+
if (resolved?.kind === "classval")
|
|
226
|
+
return resolved;
|
|
227
|
+
}
|
|
228
|
+
return mapped;
|
|
229
|
+
}
|
|
27
230
|
/** The KEY symbol behind a LATE-BOUND (`__@name@id`) property: resolved
|
|
28
231
|
* from the argument of the element-access assignment that declared it
|
|
29
232
|
* (`this[kLimit] = v` — the declaration list holds the BinaryExpression
|
|
@@ -92,8 +295,8 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
|
92
295
|
return null;
|
|
93
296
|
if (e.expression.kind !== ts.SyntaxKind.ThisKeyword)
|
|
94
297
|
return null;
|
|
95
|
-
const key =
|
|
96
|
-
const fieldName = key ? symbolFields.get(key.
|
|
298
|
+
const key = classSymbolKeyOf(lowerer, e.argumentExpression);
|
|
299
|
+
const fieldName = key ? symbolFields.get(key.identity) : undefined;
|
|
97
300
|
const t = fieldName !== undefined ? fields.get(fieldName) : undefined;
|
|
98
301
|
if (t === undefined || t.kind === "dyn")
|
|
99
302
|
return null;
|
|
@@ -103,7 +306,7 @@ function symbolSlotReturnType(lowerer, fnLike, symbolFields, fields) {
|
|
|
103
306
|
}
|
|
104
307
|
return out;
|
|
105
308
|
}
|
|
106
|
-
/** The builtin Error hierarchy
|
|
309
|
+
/** The builtin Error hierarchy
|
|
107
310
|
* as eagerly-registered ClassInfos: mapType names them the moment a lib
|
|
108
311
|
* Error type appears, so the infos must exist before any lowering. They
|
|
109
312
|
* are runtime-provided — no decl, no lowerable bodies; `new`/super()/
|
|
@@ -126,11 +329,20 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
126
329
|
// subclass declaring its own `code` field lays out AFTER it,
|
|
127
330
|
// never colliding), and it is NOT in the fields map below: the
|
|
128
331
|
// READ has its own `string | undefined` lowering (error.code),
|
|
129
|
-
// never a plain-string field access.
|
|
332
|
+
// never a plain-string field access. `%cause` is the following
|
|
333
|
+
// owned dyn slot; NULL means absent, dyn undefined means present.
|
|
130
334
|
fields: [
|
|
131
335
|
{ name: "name", type: STRING },
|
|
132
336
|
{ name: "message", type: STRING },
|
|
133
337
|
{ name: "%code", type: STRING },
|
|
338
|
+
{ name: "%cause", type: DYN },
|
|
339
|
+
{ name: "%causeEnumerable", type: BOOL },
|
|
340
|
+
{ name: "%messagePresent", type: BOOL },
|
|
341
|
+
{ name: "%messageEnumerable", type: BOOL },
|
|
342
|
+
{ name: "%namePresent", type: BOOL },
|
|
343
|
+
{ name: "%nameEnumerable", type: BOOL },
|
|
344
|
+
{ name: "%stackFrames", type: STRING },
|
|
345
|
+
{ name: "%stack", type: STRING },
|
|
134
346
|
],
|
|
135
347
|
loc,
|
|
136
348
|
},
|
|
@@ -148,10 +360,9 @@ export function registerBuiltinErrorClasses(lowerer) {
|
|
|
148
360
|
decl: null,
|
|
149
361
|
builtinError: true,
|
|
150
362
|
ctor: null,
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
ctorParams: [{ type: STRING, mode: "omittable" }],
|
|
363
|
+
// Inherited constructors forward both raw arguments. The runtime
|
|
364
|
+
// applies the undefined message default and InstallErrorCause.
|
|
365
|
+
ctorParams: [{ type: DYN, mode: "omittable" }, { type: DYN, mode: "omittable" }],
|
|
155
366
|
base,
|
|
156
367
|
subclasses: [],
|
|
157
368
|
throwingSetters: [],
|
|
@@ -278,17 +489,64 @@ export function builtinStreamInfoOf(lowerer, symbol) {
|
|
|
278
489
|
});
|
|
279
490
|
return declared ? (lowerer.classes.get(irName) ?? null) : null;
|
|
280
491
|
}
|
|
492
|
+
/** A dictionary lookup may be absent even when its checker type is a
|
|
493
|
+
* required reference. Keep literal nullish fallbacks in inferred JS storage. */
|
|
494
|
+
function jsFieldInitializerType(lowerer, type, expression) {
|
|
495
|
+
let node = expression;
|
|
496
|
+
while (ts.isParenthesizedExpression(node))
|
|
497
|
+
node = node.expression;
|
|
498
|
+
if (ts.isFunctionExpression(node) || ts.isArrowFunction(node)) {
|
|
499
|
+
const ret = lowerer.declaredReturnType(node, node);
|
|
500
|
+
const arms = type.kind === "union" ? lowerer.unions.get(type.unionId)?.arms ?? [] : [type];
|
|
501
|
+
// Inferred arithmetic may return a checked Number or BigInt. Preserve
|
|
502
|
+
// the callable when its native return ABI differs from the checker slot.
|
|
503
|
+
if (arms.some((arm) => arm.kind === "func" && !typeEquals(arm.ret, ret)))
|
|
504
|
+
return DYN;
|
|
505
|
+
}
|
|
506
|
+
if (node.kind === ts.SyntaxKind.NullKeyword)
|
|
507
|
+
return withUnitArm(type, "nullT", lowerer.unions) ?? type;
|
|
508
|
+
const inferred = lowerer.typeOf(node);
|
|
509
|
+
for (const arm of inferred.isUnionType() ? ts.constituentTypes(inferred) : [inferred]) {
|
|
510
|
+
if ((arm.flags & ts.TypeFlags.Undefined) !== 0)
|
|
511
|
+
type = lowerer.withUndefinedArmOf(type) ?? type;
|
|
512
|
+
if ((arm.flags & ts.TypeFlags.Null) !== 0)
|
|
513
|
+
type = withUnitArm(type, "nullT", lowerer.unions) ?? type;
|
|
514
|
+
}
|
|
515
|
+
if (ts.isConditionalExpression(node)) {
|
|
516
|
+
return jsFieldInitializerType(lowerer, jsFieldInitializerType(lowerer, type, node.whenTrue), node.whenFalse);
|
|
517
|
+
}
|
|
518
|
+
if (ts.isBinaryExpression(node)) {
|
|
519
|
+
if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)
|
|
520
|
+
type = jsFieldInitializerType(lowerer, type, node.left);
|
|
521
|
+
if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
|
|
522
|
+
node.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
|
|
523
|
+
node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken)
|
|
524
|
+
return jsFieldInitializerType(lowerer, type, node.right);
|
|
525
|
+
}
|
|
526
|
+
return type;
|
|
527
|
+
}
|
|
281
528
|
/** The undefined-armed union of a JS class property's inferred type — the
|
|
282
529
|
* honest slot for a field first assigned outside the constructor's top
|
|
283
530
|
* level (undefined until the write runs, Node-exact). Null when the
|
|
284
|
-
* inference is unmappable
|
|
285
|
-
* fields — KEEP NARROW), or an arm-less kind that cannot join a union
|
|
531
|
+
* inference is unmappable or an arm-less kind that cannot join a union
|
|
286
532
|
* (genResultRecord's list, including scalar-backed Date values). */
|
|
287
533
|
function undefArmedFieldType(lowerer, p) {
|
|
288
534
|
const t = lowerer.checker.getTypeOfSymbol(p);
|
|
289
|
-
const
|
|
290
|
-
|
|
535
|
+
const site = lowerer.checker.declarationsOf(p)[0];
|
|
536
|
+
let mapped = lowerer.mapTypeOf(t) ?? (site ? dynFallbackType(lowerer, site, t) : null);
|
|
537
|
+
if (mapped && site)
|
|
538
|
+
mapped = jsOpenObjectType(site, mapped, lowerer.shapes, lowerer.unions);
|
|
539
|
+
if (!mapped || mapped.kind === "void")
|
|
291
540
|
return null;
|
|
541
|
+
for (const declaration of lowerer.checker.declarationsOf(p)) {
|
|
542
|
+
const assignment = ts.isBinaryExpression(declaration) ? declaration : declaration.parent;
|
|
543
|
+
if (assignment && ts.isBinaryExpression(assignment) && assignment.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
544
|
+
mapped = jsFieldInitializerType(lowerer, mapped, assignment.right);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
// An implicit JS value already carries undefined in its native box.
|
|
548
|
+
if (mapped.kind === "dyn")
|
|
549
|
+
return mapped;
|
|
292
550
|
const byKey = new Map();
|
|
293
551
|
const arms = mapped.kind === "union" ? (lowerer.unions.get(mapped.unionId)?.arms ?? []) : [mapped];
|
|
294
552
|
for (const a of arms) {
|
|
@@ -539,7 +797,7 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
539
797
|
if (collection === "Map" && node.expression.name.text === "set" && node.arguments.length === 2) {
|
|
540
798
|
const key = mappedArgument(node.arguments[0]);
|
|
541
799
|
const value = mappedArgument(node.arguments[1]);
|
|
542
|
-
if (key !== null && value !== null && isSupportedMapKey(key) && isSupportedMapValue(value)) {
|
|
800
|
+
if (key !== null && value !== null && isSupportedMapKey(key, key.kind === "union" ? lowerer.unions.get(key.unionId)?.arms : undefined) && isSupportedMapValue(value)) {
|
|
543
801
|
mapKeys.push(key);
|
|
544
802
|
mapValues.push(value);
|
|
545
803
|
}
|
|
@@ -548,7 +806,7 @@ function inferredEmptyCollectionFieldType(lowerer, decl, field, initializer) {
|
|
|
548
806
|
(node.expression.name.text === "add" || node.expression.name.text === "has" || node.expression.name.text === "delete") &&
|
|
549
807
|
node.arguments.length === 1) {
|
|
550
808
|
const element = mappedArgument(node.arguments[0]);
|
|
551
|
-
if (element !== null && isSupportedSetElem(element))
|
|
809
|
+
if (element !== null && isSupportedSetElem(element, element.kind === "union" ? lowerer.unions.get(element.unionId)?.arms : undefined))
|
|
552
810
|
setElements.push(element);
|
|
553
811
|
}
|
|
554
812
|
return undefined;
|
|
@@ -708,7 +966,25 @@ mixin) {
|
|
|
708
966
|
// so the base's ClassInfo already exists here. An INSTANTIATION's
|
|
709
967
|
// base is its family (whose base is the declared one) — the heritage
|
|
710
968
|
// clause resolved when the family collected.
|
|
711
|
-
|
|
969
|
+
const computedBase = lowerer.computedClassBases.get(lowerer.classNamer(decl));
|
|
970
|
+
let base = inst ? inst.family : mixin ? mixin.base : computedBase?.classInfo ?? null;
|
|
971
|
+
let callableBase;
|
|
972
|
+
let factoryBaseExpression;
|
|
973
|
+
const adoptCallableBase = (expression) => {
|
|
974
|
+
if (familyMode || inst || mixin)
|
|
975
|
+
return false;
|
|
976
|
+
if (lowerer.computedCallableBases.has(decl)) {
|
|
977
|
+
callableBase = { expression, constructorId: `%g.${className}.base`, prototypeId: `%g.${className}.basePrototype` };
|
|
978
|
+
return true;
|
|
979
|
+
}
|
|
980
|
+
const signatures = lowerer.checker.getCallSignatures(lowerer.typeOf(expression));
|
|
981
|
+
const source = signatures.length === 1 ? lowerer.checker.signatureDeclaration(signatures[0]) : undefined;
|
|
982
|
+
if (!source || !isJsSourceFile(source.getSourceFile()) ||
|
|
983
|
+
!(ts.isFunctionDeclaration(source) || ts.isFunctionExpression(source)))
|
|
984
|
+
return false;
|
|
985
|
+
callableBase = { expression, constructorId: `%g.${className}.base`, prototypeId: `%g.${className}.basePrototype` };
|
|
986
|
+
return true;
|
|
987
|
+
};
|
|
712
988
|
// A family whose `extends` clause mentions its OWN type parameters
|
|
713
989
|
// (`class D<T> extends Box<T>`) would need a different base per
|
|
714
990
|
// instantiation — no single family interval can sit above all of
|
|
@@ -739,7 +1015,7 @@ mixin) {
|
|
|
739
1015
|
}
|
|
740
1016
|
}
|
|
741
1017
|
}
|
|
742
|
-
for (const clause of inst || mixin ? [] : (decl.heritageClauses ?? [])) {
|
|
1018
|
+
for (const clause of inst || mixin || computedBase ? [] : (decl.heritageClauses ?? [])) {
|
|
743
1019
|
// `implements` is pure type-world: tsc checked the conformance and
|
|
744
1020
|
// the clause erases — nothing about the runtime class changes.
|
|
745
1021
|
// (Assigning an instance INTO an interface-typed slot is a separate
|
|
@@ -754,6 +1030,14 @@ mixin) {
|
|
|
754
1030
|
const resolved = memberSym && memberSym.flags & ts.SymbolFlags.Alias
|
|
755
1031
|
? lowerer.checker.getAliasedSymbol(memberSym)
|
|
756
1032
|
: memberSym;
|
|
1033
|
+
const globalError = !t.expression.questionDotToken && lowerer.isStdlibGlobal(t.expression.expression, "globalThis")
|
|
1034
|
+
? lowerer.builtinErrorInfoOf(resolved) : null;
|
|
1035
|
+
if (globalError && globalError.def.name !== "%DOMException") {
|
|
1036
|
+
if (t.typeArguments)
|
|
1037
|
+
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
1038
|
+
base = globalError;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
757
1041
|
const emitterBase = lowerer.builtinEmitterInfoOf(resolved);
|
|
758
1042
|
const streamBaseNs = builtinStreamInfoOf(lowerer, resolved);
|
|
759
1043
|
if (emitterBase || streamBaseNs) {
|
|
@@ -768,14 +1052,18 @@ mixin) {
|
|
|
768
1052
|
// (the class statement evaluates at its init position; a base
|
|
769
1053
|
// block below it would still be uninitialized in Node).
|
|
770
1054
|
if (!t.expression.questionDotToken && nsMemberIdentOf(lowerer, t.expression)) {
|
|
771
|
-
if (t.typeArguments)
|
|
772
|
-
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
773
1055
|
if (memberSym)
|
|
774
1056
|
fenceEarlyNsMemberRef(lowerer, t.expression, memberSym);
|
|
775
|
-
const
|
|
1057
|
+
const stored = storedClassValueType(lowerer, t.expression);
|
|
1058
|
+
const nsBase = (resolved ? lowerer.classBySymbol.get(resolved) : undefined) ??
|
|
1059
|
+
(stored?.kind === "classval" ? lowerer.classes.get(stored.className) : undefined);
|
|
776
1060
|
if (!nsBase) {
|
|
1061
|
+
if (adoptCallableBase(t.expression))
|
|
1062
|
+
continue;
|
|
777
1063
|
lowerer.unsupported("SC1090", t, `extending the namespace member '${t.expression.name.text}' (no class lowering)`);
|
|
778
1064
|
}
|
|
1065
|
+
if (t.typeArguments)
|
|
1066
|
+
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
779
1067
|
base = nsBase;
|
|
780
1068
|
continue;
|
|
781
1069
|
}
|
|
@@ -840,8 +1128,17 @@ mixin) {
|
|
|
840
1128
|
base = mixinBase;
|
|
841
1129
|
continue;
|
|
842
1130
|
}
|
|
1131
|
+
const stored = storedClassValueType(lowerer, t.expression);
|
|
1132
|
+
const factoryBase = stored?.kind === "classval" ? lowerer.classes.get(stored.className) : undefined;
|
|
1133
|
+
if (factoryBase) {
|
|
1134
|
+
base = factoryBase;
|
|
1135
|
+
factoryBaseExpression = t.expression;
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
843
1138
|
}
|
|
844
1139
|
if (!t || !ts.isIdentifier(t.expression)) {
|
|
1140
|
+
if (t && adoptCallableBase(t.expression))
|
|
1141
|
+
continue;
|
|
845
1142
|
lowerer.unsupported("SC1090", clause, "extending computed expressions");
|
|
846
1143
|
}
|
|
847
1144
|
const symbol = lowerer.resolveValueSymbol(t.expression);
|
|
@@ -880,7 +1177,11 @@ mixin) {
|
|
|
880
1177
|
// A const BINDING of a mixin call (`const Tagged = M(Base);
|
|
881
1178
|
// class D extends Tagged {}`): the binding pins that call's
|
|
882
1179
|
// instantiation — collected on demand (lower-mixins.ts).
|
|
883
|
-
mixinResultBindingClassOf(lowerer, symbol) ??
|
|
1180
|
+
mixinResultBindingClassOf(lowerer, symbol) ??
|
|
1181
|
+
(() => {
|
|
1182
|
+
const stored = storedClassValueType(lowerer, t.expression);
|
|
1183
|
+
return stored?.kind === "classval" ? lowerer.classes.get(stored.className) : null;
|
|
1184
|
+
})() ?? null;
|
|
884
1185
|
// `extends Box<number>` — a GENERIC program class as the base: the
|
|
885
1186
|
// base is the concrete INSTANTIATION, resolved through the heritage
|
|
886
1187
|
// type (mapType registers/reuses `Box%0`).
|
|
@@ -898,13 +1199,43 @@ mixin) {
|
|
|
898
1199
|
lowerer.unsupported("SC1090", t, "extending generic classes");
|
|
899
1200
|
base = named;
|
|
900
1201
|
if (!base) {
|
|
1202
|
+
if (adoptCallableBase(t.expression))
|
|
1203
|
+
continue;
|
|
901
1204
|
lowerer.unsupported("SC1090", t, `extending classes not declared in the program ('${t.expression.text}')`);
|
|
902
1205
|
}
|
|
903
1206
|
}
|
|
1207
|
+
if (base?.localClass && !functionLocalClass(decl) && !computedBase && !factoryBaseExpression) {
|
|
1208
|
+
const heritage = decl.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0];
|
|
1209
|
+
if (heritage)
|
|
1210
|
+
factoryBaseExpression = heritage.expression;
|
|
1211
|
+
else
|
|
1212
|
+
lowerer.unsupported("SC1090", decl, "extending a function-local class outside a function");
|
|
1213
|
+
}
|
|
1214
|
+
if (lowerer.collectingExprClasses.has(decl)) {
|
|
1215
|
+
for (let parent = base; parent; parent = parent.base) {
|
|
1216
|
+
if (parent.builtinEmitter || parent.builtinStream !== undefined) {
|
|
1217
|
+
lowerer.unsupported("SC1090", decl, "classes extending builtin bases as values (the inherited runtime constructor has no class-value adapter)");
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
904
1221
|
const fields = new Map(base ? base.fields : []);
|
|
905
|
-
const
|
|
1222
|
+
const errorRooted = (() => {
|
|
1223
|
+
for (let c = base; c; c = c.base)
|
|
1224
|
+
if (c.builtinError)
|
|
1225
|
+
return true;
|
|
1226
|
+
return false;
|
|
1227
|
+
})();
|
|
1228
|
+
const symbolFields = new Map();
|
|
1229
|
+
if (base?.symbolFields)
|
|
1230
|
+
for (const [symbol, name] of base.symbolFields)
|
|
1231
|
+
symbolFields.set(symbol, name);
|
|
1232
|
+
const symbolMethods = new Map();
|
|
1233
|
+
if (base?.symbolMethods)
|
|
1234
|
+
for (const [symbol, name] of base.symbolMethods)
|
|
1235
|
+
symbolMethods.set(symbol, name);
|
|
906
1236
|
const fieldOrder = [];
|
|
907
1237
|
const methods = new Map();
|
|
1238
|
+
const methodEntryFences = new Map();
|
|
908
1239
|
// Own accessor declarations ("get:x"/"set:x" → node), for the
|
|
909
1240
|
// partial-override analysis below (diagnostics need the node).
|
|
910
1241
|
const accessorNodes = new Map();
|
|
@@ -929,6 +1260,8 @@ mixin) {
|
|
|
929
1260
|
const staticFields = [];
|
|
930
1261
|
const staticMethods = new Map();
|
|
931
1262
|
const staticBlocks = [];
|
|
1263
|
+
const runtimeStatics = [];
|
|
1264
|
+
const runtimePrototypeMembers = [];
|
|
932
1265
|
// GENERIC methods (own type parameters), instance and static: only
|
|
933
1266
|
// the SYNTAX is checked here — parameter/return types mention the
|
|
934
1267
|
// type parameters and cannot map yet; bodies lower per call-site
|
|
@@ -977,6 +1310,18 @@ mixin) {
|
|
|
977
1310
|
});
|
|
978
1311
|
};
|
|
979
1312
|
for (const member of decl.members) {
|
|
1313
|
+
if (functionLocalClass(decl) && isJsSourceFile(decl.getSourceFile()) &&
|
|
1314
|
+
(ts.isClassStaticBlockDeclaration(member) || ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) {
|
|
1315
|
+
runtimeStatics.push(member);
|
|
1316
|
+
continue;
|
|
1317
|
+
}
|
|
1318
|
+
if (functionLocalClass(decl) && isJsSourceFile(decl.getSourceFile()) &&
|
|
1319
|
+
(ts.isMethodDeclaration(member) || ts.isAccessor(member)) && member.body &&
|
|
1320
|
+
!ts.isPrivateIdentifier(member.name)) {
|
|
1321
|
+
runtimePrototypeMembers.push(member);
|
|
1322
|
+
if (ts.isComputedPropertyName(member.name) && classMemberNameOf(lowerer, member.name) === null)
|
|
1323
|
+
continue;
|
|
1324
|
+
}
|
|
980
1325
|
if (ts.isClassStaticBlockDeclaration(member)) {
|
|
981
1326
|
// Statics live on the FAMILY (JS has one class, one static
|
|
982
1327
|
// storage, however many instantiations exist) — instantiations
|
|
@@ -1026,7 +1371,8 @@ mixin) {
|
|
|
1026
1371
|
const type = lowerer.irTypeOf(member.name);
|
|
1027
1372
|
if (type.kind === "void")
|
|
1028
1373
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1029
|
-
if (type.kind === "dyn")
|
|
1374
|
+
if (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile()) &&
|
|
1375
|
+
(member.type !== undefined || (lowerer.typeOf(member.name).flags & ts.TypeFlags.Any) === 0)) {
|
|
1030
1376
|
lowerer.unsupported("SC1090", member.name, "'unknown'-typed static fields");
|
|
1031
1377
|
}
|
|
1032
1378
|
staticFields.push({
|
|
@@ -1043,10 +1389,22 @@ mixin) {
|
|
|
1043
1389
|
if (ts.isMethodDeclaration(member) &&
|
|
1044
1390
|
(ts.isIdentifier(member.name) || ts.isPrivateIdentifier(member.name)) &&
|
|
1045
1391
|
member.body &&
|
|
1046
|
-
member.typeParameters === undefined
|
|
1047
|
-
member.asteriskToken === undefined) {
|
|
1392
|
+
member.typeParameters === undefined) {
|
|
1048
1393
|
const { shapes, funcType: ft } = lowerer.lambdaSignature(member);
|
|
1394
|
+
if (member.asteriskToken !== undefined && ft.ret.kind !== "generator") {
|
|
1395
|
+
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1396
|
+
}
|
|
1049
1397
|
staticMethods.set(member.name.text, { params: shapes, ret: ft.ret, member });
|
|
1398
|
+
if (implicitMonoFile(decl.getSourceFile()) && !functionLocalClass(decl) &&
|
|
1399
|
+
inst === undefined && decl.typeParameters === undefined) {
|
|
1400
|
+
const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
|
|
1401
|
+
if (implicit)
|
|
1402
|
+
genericStatics.set(member.name.text, {
|
|
1403
|
+
decl: member, baseName: member.name.text,
|
|
1404
|
+
qualifiedName: `%${className}.static:${member.name.text}%implicit`,
|
|
1405
|
+
typeParams: [], instances: new Map(), implicitParams: implicit,
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1050
1408
|
}
|
|
1051
1409
|
// GENERIC static methods monomorphize like top-level generic
|
|
1052
1410
|
// functions (`%C.static:m%n`), async ones included — a generic
|
|
@@ -1075,6 +1433,16 @@ mixin) {
|
|
|
1075
1433
|
// 7's ClassElement base carries no `name`; read it structurally
|
|
1076
1434
|
// (every named member kind stores a PropertyName there).
|
|
1077
1435
|
const memberName = member.name;
|
|
1436
|
+
if (errorRooted && memberName && classMemberNameOf(lowerer, memberName) === "cause") {
|
|
1437
|
+
if (ts.isPropertyDeclaration(member) && !member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) {
|
|
1438
|
+
if (!isJsSourceFile(member.getSourceFile()))
|
|
1439
|
+
lowerer.unsupported("SC1090", memberName, "redeclaring Error.cause (pass the cause in the Error constructor options)");
|
|
1440
|
+
fieldOrder.push({ name: "cause", type: DYN, initializer: member.initializer,
|
|
1441
|
+
...(member.initializer ? {} : { undefinedInitializer: locOf(member) }), redeclared: true, errorCause: true });
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
lowerer.unsupported("SC1090", memberName, "Error.cause accessors");
|
|
1445
|
+
}
|
|
1078
1446
|
// #PRIVATE members compile: their names ('#m') are unspellable by
|
|
1079
1447
|
// any public identifier, so they ride the ordinary fields/methods
|
|
1080
1448
|
// maps collision-free — with the base-chain walks doubling as
|
|
@@ -1187,6 +1555,40 @@ mixin) {
|
|
|
1187
1555
|
// get/set pair — declare the field and accessors explicitly.
|
|
1188
1556
|
lowerer.unsupported("SC1090", member, "auto-accessor fields ('accessor x')");
|
|
1189
1557
|
}
|
|
1558
|
+
if (ts.isComputedPropertyName(member.name) || ts.isStringLiteralLike(member.name) || ts.isNumericLiteral(member.name)) {
|
|
1559
|
+
const symbolKey = ts.isComputedPropertyName(member.name) ? classSymbolKeyOf(lowerer, member.name.expression) : null;
|
|
1560
|
+
const stringKey = ts.isComputedPropertyName(member.name) ? lowerer.foldedStringKeyOf(member.name.expression)
|
|
1561
|
+
: ts.isNumericLiteral(member.name) ? String(Number(member.name.text)) : member.name.text;
|
|
1562
|
+
const fieldName = symbolKey?.fieldName ?? stringKey;
|
|
1563
|
+
if (fieldName === null || (!member.initializer && !isJsSourceFile(member.getSourceFile()))) {
|
|
1564
|
+
lowerer.unsupported("SC1090", member, "computed class fields without an initializer and a stable string, number, or module-level literal Symbol()/Symbol.for() key");
|
|
1565
|
+
}
|
|
1566
|
+
const declared = lowerer.typeOf(member);
|
|
1567
|
+
const inferred = member.type || !member.initializer ? declared : lowerer.checker.getBaseTypeOfLiteralType(lowerer.typeOf(member.initializer));
|
|
1568
|
+
const mapped = member.initializer ? lowerer.mapTypeOf(inferred) ?? dynFallbackType(lowerer, member, inferred) : DYN;
|
|
1569
|
+
const type = mapped?.kind === "record" && isJsSourceFile(member.getSourceFile()) && !member.type
|
|
1570
|
+
? DYN : mapped ? jsOpenObjectType(member, mapped, lowerer.shapes, lowerer.unions) : null;
|
|
1571
|
+
if (!type || type.kind === "void" || (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())))
|
|
1572
|
+
lowerer.badType(member, inferred);
|
|
1573
|
+
const undefinedInitializer = !member.initializer ? locOf(member) : undefined;
|
|
1574
|
+
const previous = fields.get(fieldName);
|
|
1575
|
+
if (previous) {
|
|
1576
|
+
if (symbolKey && !symbolFields.has(symbolKey.identity)) {
|
|
1577
|
+
lowerer.unsupported("SC1090", member.name, `distinct keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
|
|
1578
|
+
}
|
|
1579
|
+
if (!typeEquals(previous, type)) {
|
|
1580
|
+
lowerer.unsupported("SC1090", member.name, "redeclaring computed fields at a different type");
|
|
1581
|
+
}
|
|
1582
|
+
fieldOrder.push({ name: fieldName, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}), redeclared: true });
|
|
1583
|
+
}
|
|
1584
|
+
else {
|
|
1585
|
+
fields.set(fieldName, type);
|
|
1586
|
+
fieldOrder.push({ name: fieldName, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}) });
|
|
1587
|
+
}
|
|
1588
|
+
if (symbolKey)
|
|
1589
|
+
symbolFields.set(symbolKey.identity, fieldName);
|
|
1590
|
+
continue;
|
|
1591
|
+
}
|
|
1190
1592
|
// #private fields ride the ordinary field machinery — the '#'
|
|
1191
1593
|
// name is unspellable publicly, so the slot never collides, and
|
|
1192
1594
|
// enumeration surfaces (inspect) exclude it like Node.
|
|
@@ -1232,14 +1634,27 @@ mixin) {
|
|
|
1232
1634
|
// undefined arm (undefFieldInitLineC — Node defines the property
|
|
1233
1635
|
// as undefined on construction, verified), and reads/writes ride
|
|
1234
1636
|
// the ordinary undefined-armed union machinery.
|
|
1235
|
-
|
|
1637
|
+
let type = lowerer.irTypeOf(member.name);
|
|
1638
|
+
// Unannotated JavaScript callback slots retain the original
|
|
1639
|
+
// callable and its receiver instead of adapting its signature.
|
|
1640
|
+
if (isJsSourceFile(member.getSourceFile()) && !member.type &&
|
|
1641
|
+
!/@type\b/.test(member.getSourceFile().text.slice(member.pos, member.getStart())) &&
|
|
1642
|
+
(type.kind === "func" || type.kind === "record") && lowerer.dynConvertible(type))
|
|
1643
|
+
type = DYN;
|
|
1644
|
+
// JS permits reads before a constructor's first assignment even
|
|
1645
|
+
// when its inferred field type omits undefined.
|
|
1646
|
+
if (isJsSourceFile(member.getSourceFile()) && !member.initializer && type.kind !== "dyn") {
|
|
1647
|
+
type = lowerer.withUndefinedArmOf(type) ?? DYN;
|
|
1648
|
+
}
|
|
1236
1649
|
if (type.kind === "void")
|
|
1237
1650
|
lowerer.badType(member.name, lowerer.typeOf(member.name));
|
|
1238
|
-
//
|
|
1239
|
-
//
|
|
1240
|
-
|
|
1651
|
+
// Bundled JS declares fields without annotations before assigning
|
|
1652
|
+
// them in the constructor. Use the same native checked-dynamic
|
|
1653
|
+
// storage as implicit constructor-assigned JS fields.
|
|
1654
|
+
if (type.kind === "dyn" && !isJsSourceFile(member.getSourceFile())) {
|
|
1241
1655
|
lowerer.unsupported("SC1090", member.name, "'unknown'-typed class fields");
|
|
1242
1656
|
}
|
|
1657
|
+
const undefinedInitializer = type.kind === "dyn" && !member.initializer ? locOf(member) : undefined;
|
|
1243
1658
|
if (fields.has(member.name.text)) {
|
|
1244
1659
|
// REDECLARING an inherited field: Node [[Define]]s the OWN
|
|
1245
1660
|
// property again when THIS class's field initializers run
|
|
@@ -1249,13 +1664,12 @@ mixin) {
|
|
|
1249
1664
|
// slot, no new slot, no layout change (the `class
|
|
1250
1665
|
// ConfigError extends Error { name = "ConfigError" }`; the
|
|
1251
1666
|
// builtin Error prefix included — reads, toString, and throw
|
|
1252
|
-
// reports all answer the overwritten name like Node). A
|
|
1253
|
-
//
|
|
1254
|
-
//
|
|
1255
|
-
// no single slot type — both keep the fence.
|
|
1667
|
+
// reports all answer the overwritten name like Node). A bare
|
|
1668
|
+
// JS dyn redeclaration resets the existing slot to undefined.
|
|
1669
|
+
// Other bare or type-changing redeclarations keep the fence.
|
|
1256
1670
|
const baseType = fields.get(member.name.text);
|
|
1257
|
-
if (member.initializer && typeEquals(type, baseType)) {
|
|
1258
|
-
fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, redeclared: true });
|
|
1671
|
+
if ((member.initializer || type.kind === "dyn") && typeEquals(type, baseType)) {
|
|
1672
|
+
fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}), redeclared: true });
|
|
1259
1673
|
continue;
|
|
1260
1674
|
}
|
|
1261
1675
|
lowerer.unsupported("SC1090", member.name, member.initializer
|
|
@@ -1280,7 +1694,7 @@ mixin) {
|
|
|
1280
1694
|
// (the constructor may be declared later in the class body).
|
|
1281
1695
|
const admitsUndefined = (type.kind === "union" &&
|
|
1282
1696
|
(lowerer.unions.get(type.unionId)?.arms.some((a) => a.kind === "undefinedT") ?? false)) ||
|
|
1283
|
-
type.kind === "jsval";
|
|
1697
|
+
type.kind === "jsval" || type.kind === "dyn";
|
|
1284
1698
|
if (!member.initializer && !admitsUndefined) {
|
|
1285
1699
|
const opts = lowerer.program.getCompilerOptions();
|
|
1286
1700
|
const spi = opts.strictPropertyInitialization ?? opts.strict ?? false;
|
|
@@ -1300,7 +1714,7 @@ mixin) {
|
|
|
1300
1714
|
}
|
|
1301
1715
|
}
|
|
1302
1716
|
fields.set(member.name.text, type);
|
|
1303
|
-
fieldOrder.push({ name: member.name.text, type, initializer: member.initializer });
|
|
1717
|
+
fieldOrder.push({ name: member.name.text, type, initializer: member.initializer, ...(undefinedInitializer ? { undefinedInitializer } : {}) });
|
|
1304
1718
|
}
|
|
1305
1719
|
else if (ts.isConstructorDeclaration(member)) {
|
|
1306
1720
|
// A body-less constructor is an OVERLOAD SIGNATURE: type-world,
|
|
@@ -1344,6 +1758,9 @@ mixin) {
|
|
|
1344
1758
|
lowerer.unsupported("SC1090", p, "this parameter property form");
|
|
1345
1759
|
}
|
|
1346
1760
|
const name = p.name.text;
|
|
1761
|
+
if (errorRooted && name === "cause") {
|
|
1762
|
+
lowerer.unsupported("SC1090", p.name, "redeclaring Error.cause (pass the cause in the Error constructor options)");
|
|
1763
|
+
}
|
|
1347
1764
|
const shape = lowerer.paramShape(p);
|
|
1348
1765
|
const type = shape.bodyType ?? shape.type;
|
|
1349
1766
|
if (type.kind === "void")
|
|
@@ -1368,15 +1785,18 @@ mixin) {
|
|
|
1368
1785
|
const mName = classMemberNameOf(lowerer, member.name);
|
|
1369
1786
|
if (mName === null)
|
|
1370
1787
|
lowerer.unsupported("SC1090", member, "computed method names");
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1788
|
+
if (ts.isComputedPropertyName(member.name)) {
|
|
1789
|
+
const key = classSymbolKeyOf(lowerer, member.name.expression);
|
|
1790
|
+
if (key) {
|
|
1791
|
+
if ([...symbolMethods, ...symbolFields].some(([identity, name]) => name === mName && identity !== key.identity)) {
|
|
1792
|
+
lowerer.unsupported("SC1090", member.name, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(mName)}' in one class`);
|
|
1793
|
+
}
|
|
1794
|
+
symbolMethods.set(key.identity, mName);
|
|
1795
|
+
}
|
|
1379
1796
|
}
|
|
1797
|
+
// Generator calls use their spawn wrapper. Public methods are
|
|
1798
|
+
// direct calls only when no subclass overrides the method;
|
|
1799
|
+
// override chains involving generators fence below.
|
|
1380
1800
|
// An ABSTRACT method is a signature with no body — type-world,
|
|
1381
1801
|
// except that it declares the vtable slot: calls through
|
|
1382
1802
|
// base-typed receivers are ordinary virtual dispatch, and tsc
|
|
@@ -1431,20 +1851,9 @@ mixin) {
|
|
|
1431
1851
|
collectGenericMember(member, false);
|
|
1432
1852
|
continue;
|
|
1433
1853
|
}
|
|
1434
|
-
// Async
|
|
1435
|
-
//
|
|
1436
|
-
//
|
|
1437
|
-
// surface is synchronous still compiles (commander: parse()
|
|
1438
|
-
// works, parseAsync() traps where called). TS async methods
|
|
1439
|
-
// collect below like any method: the body is an async
|
|
1440
|
-
// IrFunction (fiber spawn wrapper, `this` as param 0), calls
|
|
1441
|
-
// dispatch STATICALLY — override chains fence (the vtable slot
|
|
1442
|
-
// machinery has no fiber-spawn story), so every call site is a
|
|
1443
|
-
// direct call the emitter routes through the spawn wrapper.
|
|
1444
|
-
if (member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
1445
|
-
isJsSourceFile(decl.getSourceFile())) {
|
|
1446
|
-
continue;
|
|
1447
|
-
}
|
|
1854
|
+
// Async methods collect with the same direct-call spawn wrapper
|
|
1855
|
+
// for JavaScript and TypeScript classes. Override chains remain
|
|
1856
|
+
// fenced below because vtable slots cannot enter that wrapper.
|
|
1448
1857
|
// IMPLICIT-ANY monomorphization (npm-static JS): a method whose
|
|
1449
1858
|
// signature carries bindable untyped params collects like a
|
|
1450
1859
|
// GENERIC method — into genericMethods, no vtable slot, one
|
|
@@ -1454,13 +1863,14 @@ mixin) {
|
|
|
1454
1863
|
// dispatch worlds could meet: an inherited declaration of the
|
|
1455
1864
|
// name (the override stays on the vtable), a shadowed field, or
|
|
1456
1865
|
// a generic-class instantiation's member.
|
|
1457
|
-
if (implicitMonoFile(decl.getSourceFile()) &&
|
|
1866
|
+
if (implicitMonoFile(decl.getSourceFile()) && !functionLocalClass(decl) &&
|
|
1458
1867
|
ts.isIdentifier(member.name) &&
|
|
1868
|
+
!lowerer.virtualJsMethods.has(member) && !lowerer.prototypeMethodAccesses.has(member.name.text) &&
|
|
1459
1869
|
inst === undefined && decl.typeParameters === undefined &&
|
|
1460
1870
|
!fields.has(member.name.text) &&
|
|
1461
1871
|
!lowerer.findMethodOn(base, member.name.text) &&
|
|
1462
1872
|
!findGenericMethodOn(lowerer, base, member.name.text)) {
|
|
1463
|
-
const implicit = implicitAnyParamSymbolsOf(lowerer, member);
|
|
1873
|
+
const implicit = implicitAnyParamSymbolsOf(lowerer, member, true);
|
|
1464
1874
|
if (implicit) {
|
|
1465
1875
|
genericMethods.set(member.name.text, {
|
|
1466
1876
|
decl: member,
|
|
@@ -1474,6 +1884,31 @@ mixin) {
|
|
|
1474
1884
|
}
|
|
1475
1885
|
}
|
|
1476
1886
|
const { shapes, funcType: ft } = lowerer.lambdaSignature(member);
|
|
1887
|
+
// JS inference may retain only a symbol sentinel while a method
|
|
1888
|
+
// also returns values from an untyped mutable field or local.
|
|
1889
|
+
if (isJsSourceFile(member.getSourceFile()) && !member.type && !hasExplicitJsDocReturn(member) && ft.ret.kind === "symbol")
|
|
1890
|
+
ft.ret = DYN;
|
|
1891
|
+
if (isJsSourceFile(member.getSourceFile()) && lowerer.prototypeMethodAccesses.has(mName) &&
|
|
1892
|
+
!lowerer.findMethodOn(base, mName)?.declarer.def.runtime &&
|
|
1893
|
+
shapes.every((p) => p.mode === "required" || p.mode === "omittable")) {
|
|
1894
|
+
for (const shape of shapes) {
|
|
1895
|
+
shape.type = DYN;
|
|
1896
|
+
if (shape.bodyType)
|
|
1897
|
+
shape.bodyType = DYN;
|
|
1898
|
+
}
|
|
1899
|
+
ft.params = shapes.map((shape) => shape.type);
|
|
1900
|
+
if (ft.ret.kind !== "void")
|
|
1901
|
+
ft.ret = DYN;
|
|
1902
|
+
}
|
|
1903
|
+
// JS subclasses can add parameters to a method. Reserve checked
|
|
1904
|
+
// argument slots in the base before constructing its vtable; shorter
|
|
1905
|
+
// bodies ignore them and omitted call arguments become undefined.
|
|
1906
|
+
const virtualArity = lowerer.virtualJsMethodArity.get(member) ?? shapes.length;
|
|
1907
|
+
if (virtualArity > shapes.length && !bodyReadsArguments(member) &&
|
|
1908
|
+
shapes.every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
1909
|
+
while (shapes.length < virtualArity)
|
|
1910
|
+
shapes.push({ type: DYN, mode: "omittable" });
|
|
1911
|
+
}
|
|
1477
1912
|
if (fields.has(mName)) {
|
|
1478
1913
|
lowerer.unsupported("SC1090", member.name, "methods shadowing inherited fields");
|
|
1479
1914
|
}
|
|
@@ -1499,17 +1934,78 @@ mixin) {
|
|
|
1499
1934
|
// against the STATIC receiver's shape, so `m(x?: number)` and
|
|
1500
1935
|
// `m(x: number | undefined)` interchange soundly in overrides.
|
|
1501
1936
|
const overridden = lowerer.findMethodOn(base, mName);
|
|
1502
|
-
if (overridden
|
|
1503
|
-
//
|
|
1504
|
-
//
|
|
1505
|
-
//
|
|
1506
|
-
|
|
1937
|
+
if (overridden && isJsSourceFile(member.getSourceFile())) {
|
|
1938
|
+
// An unannotated JS override can return a checked value into
|
|
1939
|
+
// the inherited native ABI, just as its untyped parameters do.
|
|
1940
|
+
// Body lowering inserts the conversion at each return.
|
|
1941
|
+
if (!member.type && ft.ret.kind === "dyn" && overridden.sig.ret.kind !== "dyn" &&
|
|
1942
|
+
!overridden.sig.async && !overridden.sig.gen)
|
|
1943
|
+
ft.ret = overridden.sig.ret;
|
|
1944
|
+
// Fluent overrides return the same native receiver. Keep the
|
|
1945
|
+
// inherited return ABI and upcast `this` when lowering returns.
|
|
1946
|
+
if (overridden.sig.ret.kind === "object" && base &&
|
|
1947
|
+
(base.def.name === overridden.sig.ret.className || lowerer.isSubclassOf(base.def.name, overridden.sig.ret.className)) &&
|
|
1948
|
+
returnsOnlyThis(member))
|
|
1949
|
+
ft.ret = overridden.sig.ret;
|
|
1950
|
+
// An unannotated JS parameter can use the base's typed ABI.
|
|
1951
|
+
// Defaults stay local to each declaration, so only inherited
|
|
1952
|
+
// required/optional slots participate in this refinement.
|
|
1953
|
+
for (let i = 0; i < shapes.length; i++) {
|
|
1954
|
+
const parameter = member.parameters[i];
|
|
1955
|
+
const inherited = overridden.sig.params[i];
|
|
1956
|
+
if (parameter && inherited && !parameter.type && !parameter.initializer && !parameter.dotDotDotToken &&
|
|
1957
|
+
shapes[i].type.kind === "dyn" && inherited.type.kind !== "dyn" &&
|
|
1958
|
+
(inherited.mode === "required" || inherited.mode === "omittable")) {
|
|
1959
|
+
shapes[i] = { ...inherited };
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
// JS overrides may ignore trailing arguments. Retain the base's
|
|
1964
|
+
// checked-value ABI slots as unused parameters, and let shorter
|
|
1965
|
+
// calls fill them with undefined. Typed tails and rest/arguments
|
|
1966
|
+
// readers keep the exact-signature fence.
|
|
1967
|
+
if (overridden && isJsSourceFile(member.getSourceFile()) &&
|
|
1968
|
+
shapes.length < overridden.sig.params.length &&
|
|
1969
|
+
!bodyReadsArguments(member) &&
|
|
1970
|
+
shapes.every((p, i) => (p.mode === "required" || p.mode === "omittable") && typeEquals(p.type, overridden.sig.params[i].type)) &&
|
|
1971
|
+
overridden.sig.params.slice(shapes.length).every((p) => p.type.kind === "dyn" && (p.mode === "required" || p.mode === "omittable"))) {
|
|
1972
|
+
shapes.push(...overridden.sig.params.slice(shapes.length).map((p) => ({ type: p.type, mode: "omittable" })));
|
|
1507
1973
|
}
|
|
1508
1974
|
if (overridden &&
|
|
1509
1975
|
(overridden.sig.params.length !== shapes.length ||
|
|
1510
1976
|
!overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) ||
|
|
1511
1977
|
!typeEquals(overridden.sig.ret, ft.ret))) {
|
|
1512
|
-
|
|
1978
|
+
const fencedJsOverride = isJsSourceFile(member.getSourceFile()) &&
|
|
1979
|
+
overridden.declarer.decl !== null && isJsSourceFile(overridden.declarer.decl.getSourceFile()) &&
|
|
1980
|
+
member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) !== true &&
|
|
1981
|
+
overridden.sig.async !== true &&
|
|
1982
|
+
member.asteriskToken === undefined && overridden.sig.gen === undefined;
|
|
1983
|
+
if (fencedJsOverride) {
|
|
1984
|
+
// A dormant JS method must not poison the whole class. Keep
|
|
1985
|
+
// the inherited call/dispatch ABI and refuse at method entry;
|
|
1986
|
+
// lowering this body with the base signature would change JS.
|
|
1987
|
+
const returnOnly = overridden.sig.params.length === shapes.length &&
|
|
1988
|
+
overridden.sig.params.every((p, i) => typeEquals(p.type, shapes[i].type)) &&
|
|
1989
|
+
!member.parameters.some((parameter, index) => {
|
|
1990
|
+
if (!parameter.initializer)
|
|
1991
|
+
return false;
|
|
1992
|
+
const baseMember = overridden.declarer.decl?.members.find((candidate) => ts.isMethodDeclaration(candidate) && classMemberNameOf(lowerer, candidate.name) === mName);
|
|
1993
|
+
const inherited = baseMember && ts.isMethodDeclaration(baseMember) ? baseMember.parameters[index]?.initializer : undefined;
|
|
1994
|
+
if (!inherited)
|
|
1995
|
+
return false;
|
|
1996
|
+
const ownType = lowerer.mapTypeOf(lowerer.typeOf(parameter.initializer));
|
|
1997
|
+
const baseType = lowerer.mapTypeOf(lowerer.typeOf(inherited));
|
|
1998
|
+
return ownType !== null && baseType !== null && !typeEquals(ownType, baseType);
|
|
1999
|
+
});
|
|
2000
|
+
methodEntryFences.set(mName, unsupportedDiag("SC1090", locOf(member.name), returnOnly
|
|
2001
|
+
? `overriding method '${mName}' with a different return type (the native return type must match the base declaration exactly)`
|
|
2002
|
+
: `overriding method '${mName}' with a different signature (the native parameter and return types must match the base declaration exactly)`));
|
|
2003
|
+
shapes.splice(0, shapes.length, ...overridden.sig.params);
|
|
2004
|
+
ft.ret = overridden.sig.ret;
|
|
2005
|
+
}
|
|
2006
|
+
else {
|
|
2007
|
+
lowerer.unsupported("SC1090", member.name, "overriding a method with a different signature (parameter and return types must match the base declaration exactly)");
|
|
2008
|
+
}
|
|
1513
2009
|
}
|
|
1514
2010
|
const asyncMember = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
1515
2011
|
// Async methods dispatch STATICALLY (the body enters through its
|
|
@@ -1519,7 +2015,10 @@ mixin) {
|
|
|
1519
2015
|
if (overridden && (asyncMember || overridden.sig.async === true)) {
|
|
1520
2016
|
lowerer.unsupported("SC1090", member.name, `overriding ${overridden.sig.async === true ? "the async method" : "a method with an async method"} '${mName}' (async methods dispatch statically — the vtable slot machinery has no fiber-spawn story)`);
|
|
1521
2017
|
}
|
|
1522
|
-
|
|
2018
|
+
if (overridden && (member.asteriskToken !== undefined || overridden.sig.gen !== undefined)) {
|
|
2019
|
+
lowerer.unsupported("SC1090", member.name, `overriding the generator method '${mName}' (generator methods dispatch statically — a virtual slot cannot enter their spawn wrapper)`);
|
|
2020
|
+
}
|
|
2021
|
+
// A GENERATOR method carries its channels on the sig:
|
|
1523
2022
|
// the body lowers as a generator IrFunction (`this` as param 0),
|
|
1524
2023
|
// and every call — direct by construction — enters through the
|
|
1525
2024
|
// emitted gen-spawn wrapper, answering the suspended generator.
|
|
@@ -1552,9 +2051,19 @@ mixin) {
|
|
|
1552
2051
|
const isGet = ts.isGetAccessor(member);
|
|
1553
2052
|
// #private accessors collect as "get:#x"/"set:#x" — the same
|
|
1554
2053
|
// reserved spelling, one more unspellable segment.
|
|
1555
|
-
|
|
2054
|
+
const prop = classMemberNameOf(lowerer, member.name);
|
|
2055
|
+
if (prop === null) {
|
|
1556
2056
|
lowerer.unsupported("SC1090", member, "computed accessor names");
|
|
1557
2057
|
}
|
|
2058
|
+
if (ts.isComputedPropertyName(member.name)) {
|
|
2059
|
+
const key = classSymbolKeyOf(lowerer, member.name.expression);
|
|
2060
|
+
if (key) {
|
|
2061
|
+
if ([...symbolMethods, ...symbolFields].some(([identity, name]) => name === prop && identity !== key.identity)) {
|
|
2062
|
+
lowerer.unsupported("SC1090", member.name, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(prop)}' in one class`);
|
|
2063
|
+
}
|
|
2064
|
+
symbolMethods.set(key.identity, prop);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
1558
2067
|
// ABSTRACT accessors are the abstract-method story with property
|
|
1559
2068
|
// syntax: body-less by definition, they enter `methods` (marked
|
|
1560
2069
|
// abstract) as their "get:x"/"set:x" halves — slot declaration
|
|
@@ -1562,9 +2071,8 @@ mixin) {
|
|
|
1562
2071
|
const abstractAccessor = ts.getModifiers(member)?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword) === true;
|
|
1563
2072
|
if (!member.body && !abstractAccessor)
|
|
1564
2073
|
lowerer.unsupported("SC1090", member, "bodyless accessors");
|
|
1565
|
-
const prop = member.name.text;
|
|
1566
2074
|
const mName = `${isGet ? "get" : "set"}:${prop}`;
|
|
1567
|
-
if (fields.has(prop)) {
|
|
2075
|
+
if (fields.has(prop) && !((prop === "message" || prop === "name") && base && (base.def.name === "%Error" || lowerer.isSubclassOf(base.def.name, "%Error")))) {
|
|
1568
2076
|
// tsc rejects field/accessor mixing (TS2610/2611); defensive.
|
|
1569
2077
|
lowerer.unsupported("SC1090", member.name, "accessors sharing a name with a field");
|
|
1570
2078
|
}
|
|
@@ -1609,7 +2117,7 @@ mixin) {
|
|
|
1609
2117
|
lowerer.unsupported("SC1090", member, "index signatures");
|
|
1610
2118
|
}
|
|
1611
2119
|
else if (!ts.isSemicolonClassElement(member)) {
|
|
1612
|
-
lowerer.unsupported("SC1090", member, `syntax '${ts.
|
|
2120
|
+
lowerer.unsupported("SC1090", member, `syntax '${ts.syntaxKindName(member.kind)}'`);
|
|
1613
2121
|
}
|
|
1614
2122
|
}
|
|
1615
2123
|
// Parameter properties join the shape FIRST among own fields —
|
|
@@ -1724,6 +2232,9 @@ mixin) {
|
|
|
1724
2232
|
// forbids via strictPropertyInitialization — so they keep a named
|
|
1725
2233
|
// fence instead of a silent undefined.
|
|
1726
2234
|
if (isJsSourceFile(decl.getSourceFile())) {
|
|
2235
|
+
const hasAccessor = (name) => methods.has(`get:${name}`) || methods.has(`set:${name}`) ||
|
|
2236
|
+
lowerer.findMethodOn(base, `get:${name}`) !== null ||
|
|
2237
|
+
lowerer.findMethodOn(base, `set:${name}`) !== null;
|
|
1727
2238
|
// Named classes (declarations and self-binding expressions) resolve
|
|
1728
2239
|
// by name; the nameless default-export declaration by its module's
|
|
1729
2240
|
// default-export symbol.
|
|
@@ -1755,9 +2266,11 @@ mixin) {
|
|
|
1755
2266
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
1756
2267
|
const assign = lhs;
|
|
1757
2268
|
const name = assign.name.text;
|
|
2269
|
+
if (errorRooted && name === "cause")
|
|
2270
|
+
continue;
|
|
1758
2271
|
// Later assignments to an already-declared field (own or
|
|
1759
2272
|
// inherited) are writes, not declarations.
|
|
1760
|
-
if (fields.has(name))
|
|
2273
|
+
if (fields.has(name) || hasAccessor(name))
|
|
1761
2274
|
continue;
|
|
1762
2275
|
if (methods.has(name) || lowerer.findMethodOn(base, name)) {
|
|
1763
2276
|
lowerer.unsupported("SC1090", assign, "constructor-assigned fields shadowing methods");
|
|
@@ -1772,11 +2285,16 @@ mixin) {
|
|
|
1772
2285
|
// TS-annotated `unknown` fields keep their fence (KEEP NARROW
|
|
1773
2286
|
// applies where an annotation could say better).
|
|
1774
2287
|
let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, assign, t)) : null;
|
|
2288
|
+
if (t && (t.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0 && isJsSourceFile(decl.getSourceFile()))
|
|
2289
|
+
type = DYN;
|
|
2290
|
+
if (type)
|
|
2291
|
+
type = jsOpenObjectType(assign, type, lowerer.shapes, lowerer.unions);
|
|
1775
2292
|
if (type?.kind === "dyn") {
|
|
1776
2293
|
type = inferredEmptyCollectionFieldType(lowerer, decl, name, rhs) ?? type;
|
|
1777
2294
|
}
|
|
1778
2295
|
if (!type || type.kind === "void")
|
|
1779
2296
|
lowerer.badType(assign, t ?? lowerer.typeOf(assign));
|
|
2297
|
+
type = jsFieldInitializerType(lowerer, type, rhs);
|
|
1780
2298
|
// A JSDoc claim the BODY contradicts (`@type {Command}`
|
|
1781
2299
|
// assigned `undefined` — the lazy-init idiom): the
|
|
1782
2300
|
// representation follows the body — the field widens to the
|
|
@@ -1801,7 +2319,7 @@ mixin) {
|
|
|
1801
2319
|
continue;
|
|
1802
2320
|
}
|
|
1803
2321
|
// `this[kLimit] = v` at the constructor's top level with a
|
|
1804
|
-
// STATICALLY-RESOLVABLE
|
|
2322
|
+
// STATICALLY-RESOLVABLE symbol key (classSymbolKeyOf's
|
|
1805
2323
|
// contract — the countdown.js idiom): the key is a compile-time
|
|
1806
2324
|
// identity, so the member is an ordinary hidden field of the
|
|
1807
2325
|
// static layout under Node's inspect spelling; no runtime
|
|
@@ -1811,19 +2329,30 @@ mixin) {
|
|
|
1811
2329
|
// late-bound fence below.
|
|
1812
2330
|
if (lhs && ts.isElementAccessExpression(lhs) &&
|
|
1813
2331
|
lhs.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
1814
|
-
const key =
|
|
1815
|
-
|
|
2332
|
+
const key = classSymbolKeyOf(lowerer, lhs.argumentExpression);
|
|
2333
|
+
const stringKey = lowerer.foldedStringKeyOf(lhs.argumentExpression);
|
|
2334
|
+
const fieldName = key?.fieldName ?? stringKey;
|
|
2335
|
+
if (fieldName === null) {
|
|
2336
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(lhs.argumentExpression))?.kind === "symbol") {
|
|
2337
|
+
lowerer.unsupported("SC1090", lhs, "symbol-keyed class fields require a stable module-level key");
|
|
2338
|
+
}
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
if (!key && (fields.has(fieldName) || hasAccessor(fieldName)))
|
|
1816
2342
|
continue;
|
|
2343
|
+
if (!key && (methods.has(fieldName) || lowerer.findMethodOn(base, fieldName))) {
|
|
2344
|
+
lowerer.unsupported("SC1090", lhs, "constructor-assigned fields shadowing methods");
|
|
2345
|
+
}
|
|
1817
2346
|
// A key already declared (own or inherited) makes later
|
|
1818
2347
|
// assignments writes, not declarations.
|
|
1819
|
-
if (symbolFields.has(key.
|
|
2348
|
+
if (key && symbolFields.has(key.identity))
|
|
1820
2349
|
continue;
|
|
1821
|
-
if (fields.has(
|
|
2350
|
+
if (fields.has(fieldName)) {
|
|
1822
2351
|
// Two DISTINCT Symbol(...) consts with one description in
|
|
1823
2352
|
// one layout would need one printable name for two slots.
|
|
1824
|
-
lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${
|
|
2353
|
+
lowerer.unsupported("SC1090", lhs, `distinct symbol keys sharing the printable name '${symbolFieldDisplayName(fieldName)}' in one class`);
|
|
1825
2354
|
}
|
|
1826
|
-
const propSym = lateBoundByKey.get(key.sym);
|
|
2355
|
+
const propSym = key ? lateBoundByKey.get(key.sym) : instType ? lowerer.checker.getPropertyOfType(instType, fieldName) : undefined;
|
|
1827
2356
|
// tsgo does not synthesize the late-bound `__@name@id`
|
|
1828
2357
|
// property for a JS `this[k] = v` declaration (the finding-5
|
|
1829
2358
|
// family: no expando/late-bound synthesis in its stricter
|
|
@@ -1838,12 +2367,15 @@ mixin) {
|
|
|
1838
2367
|
: rhs
|
|
1839
2368
|
? lowerer.checker.getBaseTypeOfLiteralType(lowerer.checker.getTypeAtLocation(rhs))
|
|
1840
2369
|
: undefined;
|
|
1841
|
-
|
|
2370
|
+
let type = t ? (lowerer.mapTypeOf(t) ?? dynFallbackType(lowerer, lhs, t)) : null;
|
|
2371
|
+
if (type)
|
|
2372
|
+
type = jsOpenObjectType(lhs, type, lowerer.shapes, lowerer.unions);
|
|
1842
2373
|
if (!type || type.kind === "void")
|
|
1843
2374
|
lowerer.badType(lhs, t ?? lowerer.typeOf(lhs));
|
|
1844
|
-
fields.set(
|
|
1845
|
-
|
|
1846
|
-
|
|
2375
|
+
fields.set(fieldName, type);
|
|
2376
|
+
if (key)
|
|
2377
|
+
symbolFields.set(key.identity, fieldName);
|
|
2378
|
+
fieldOrder.push({ name: fieldName, type, initializer: undefined });
|
|
1847
2379
|
}
|
|
1848
2380
|
}
|
|
1849
2381
|
}
|
|
@@ -1853,9 +2385,11 @@ mixin) {
|
|
|
1853
2385
|
// static layouts cannot represent. Named fence, at the first
|
|
1854
2386
|
// assignment site.
|
|
1855
2387
|
for (const p of instType ? lowerer.checker.getPropertiesOfType(instType) : []) {
|
|
2388
|
+
if (errorRooted && p.name === "cause")
|
|
2389
|
+
continue;
|
|
1856
2390
|
if (fields.has(p.name) || methods.has(p.name))
|
|
1857
2391
|
continue;
|
|
1858
|
-
if (
|
|
2392
|
+
if (hasAccessor(p.name))
|
|
1859
2393
|
continue;
|
|
1860
2394
|
if (base && (base.fields.has(p.name) || lowerer.findMethodOn(base, p.name)))
|
|
1861
2395
|
continue;
|
|
@@ -1866,14 +2400,15 @@ mixin) {
|
|
|
1866
2400
|
// Late-bound properties: the ones the scan above collected are
|
|
1867
2401
|
// real fields under their printable names — skip. The rest keep
|
|
1868
2402
|
// a fence that names the supported form: keys that are runtime
|
|
1869
|
-
// identities (symbol parameters,
|
|
2403
|
+
// identities (symbol parameters, mutable bindings, computed
|
|
1870
2404
|
// descriptions) or assignments outside the constructor's top
|
|
1871
2405
|
// level.
|
|
1872
2406
|
if (p.name.startsWith("__@")) {
|
|
1873
2407
|
const keySym = lateBoundKeySymOf(lowerer, p);
|
|
1874
|
-
|
|
2408
|
+
const key = keySym ? classSymbolKeyOfSymbol(lowerer, keySym) : null;
|
|
2409
|
+
if (key && symbolFields.has(key.identity))
|
|
1875
2410
|
continue;
|
|
1876
|
-
lowerer.unsupported("SC1090", site, "symbol-keyed class fields outside the supported form (a module-level
|
|
2411
|
+
lowerer.unsupported("SC1090", site, "symbol-keyed class fields outside the supported form (a stable module-level literal Symbol()/Symbol.for() key, assigned unconditionally at the top of the constructor)");
|
|
1877
2412
|
}
|
|
1878
2413
|
// JS classes: a property first assigned in a method or a
|
|
1879
2414
|
// conditional constructor position holds `undefined` until the
|
|
@@ -1888,6 +2423,11 @@ mixin) {
|
|
|
1888
2423
|
if (isJsSourceFile(decl.getSourceFile())) {
|
|
1889
2424
|
const armed = undefArmedFieldType(lowerer, p);
|
|
1890
2425
|
if (armed !== null) {
|
|
2426
|
+
// Unknown JS properties use the instance bag: they do not
|
|
2427
|
+
// exist until assigned, and a subclass may declare the same
|
|
2428
|
+
// name as an ordinary layout field.
|
|
2429
|
+
if (armed.kind === "dyn")
|
|
2430
|
+
continue;
|
|
1891
2431
|
fields.set(p.name, armed);
|
|
1892
2432
|
fieldOrder.push({ name: p.name, type: armed, initializer: undefined });
|
|
1893
2433
|
continue;
|
|
@@ -1925,8 +2465,14 @@ mixin) {
|
|
|
1925
2465
|
// synthesized constructor forwards the same params to super).
|
|
1926
2466
|
const ctorParams = ctor && !mixinForwarding
|
|
1927
2467
|
? lowerer.paramShapes(ctor.parameters)
|
|
1928
|
-
: (base?.ctorParams ?? []);
|
|
2468
|
+
: (base?.ctorParams ?? (callableBase ? [{ type: DYN, mode: "dynRest" }] : []));
|
|
2469
|
+
if (ctor && !mixinForwarding && isJsSourceFile(ctor.getSourceFile()) &&
|
|
2470
|
+
!ctorParams.some((shape) => shape.mode === "rest" || shape.mode === "dynRest" || shape.mode === "islandRest") && bodyReadsArguments(ctor)) {
|
|
2471
|
+
ctorParams.push({ type: DYN, mode: "arguments" });
|
|
2472
|
+
}
|
|
1929
2473
|
const info = {
|
|
2474
|
+
...(runtimeStatics.length ? { runtimeStatics } : {}),
|
|
2475
|
+
...(runtimePrototypeMembers.length ? { runtimePrototypeMembers } : {}),
|
|
1930
2476
|
def: {
|
|
1931
2477
|
name: className,
|
|
1932
2478
|
// The JS-observable .name (the class object's name string and
|
|
@@ -1935,6 +2481,9 @@ mixin) {
|
|
|
1935
2481
|
// INSTANTIATION prints its family's name — JS has one `Box`.
|
|
1936
2482
|
jsName: jsNameOverride ?? decl.name?.text ?? "",
|
|
1937
2483
|
...(base ? { base: base.def.name } : {}),
|
|
2484
|
+
jsLength: ctor?.parameters.findIndex((parameter) => parameter.initializer || parameter.dotDotDotToken) === -1
|
|
2485
|
+
? ctor.parameters.length
|
|
2486
|
+
: Math.max(0, ctor?.parameters.findIndex((parameter) => parameter.initializer || parameter.dotDotDotToken) ?? 0),
|
|
1938
2487
|
// Layout order: the base chain's fields as an IDENTICAL prefix,
|
|
1939
2488
|
// then this class's own — what makes an upcast a reinterpret.
|
|
1940
2489
|
// Redeclared INHERITED fields contribute no slot (their
|
|
@@ -1955,18 +2504,22 @@ mixin) {
|
|
|
1955
2504
|
fields,
|
|
1956
2505
|
fieldOrder,
|
|
1957
2506
|
methods,
|
|
2507
|
+
...(methodEntryFences.size > 0 ? { methodEntryFences } : {}),
|
|
1958
2508
|
decl,
|
|
1959
2509
|
...(emitOverride !== undefined ? { emitOverride } : {}),
|
|
1960
2510
|
ctor,
|
|
1961
2511
|
ctorParams,
|
|
1962
2512
|
...(paramProps.length > 0 ? { paramProps } : {}),
|
|
1963
2513
|
base,
|
|
2514
|
+
...(callableBase ? { callableBase } : {}),
|
|
2515
|
+
...(factoryBaseExpression ? { factoryBaseExpression } : {}),
|
|
1964
2516
|
subclasses: [],
|
|
1965
2517
|
throwingSetters,
|
|
1966
2518
|
staticFields,
|
|
1967
2519
|
...(staticMethods.size > 0 ? { staticMethods } : {}),
|
|
1968
2520
|
...(staticBlocks.length > 0 ? { staticBlocks } : {}),
|
|
1969
2521
|
...(symbolFields.size > 0 ? { symbolFields } : {}),
|
|
2522
|
+
...(symbolMethods.size > 0 ? { symbolMethods } : {}),
|
|
1970
2523
|
...(classDecoratorNodes.length > 0 ? { classDecorators: { nodes: classDecoratorNodes } } : {}),
|
|
1971
2524
|
...(deferredInitFields.size > 0 ? { deferredInitFields } : {}),
|
|
1972
2525
|
};
|
|
@@ -2020,6 +2573,17 @@ mixin) {
|
|
|
2020
2573
|
if (base)
|
|
2021
2574
|
base.subclasses.push(info);
|
|
2022
2575
|
lowerer.classes.set(className, info);
|
|
2576
|
+
if (computedBase && !functionLocalClass(decl)) {
|
|
2577
|
+
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2578
|
+
lowerer.globalsList.push({ id: info.def.baseValueGlobal, name: `${className} base`, type: computedBase.value.type, mutable: false });
|
|
2579
|
+
}
|
|
2580
|
+
if (factoryBaseExpression && !functionLocalClass(decl)) {
|
|
2581
|
+
info.def.baseValueGlobal = `%g.${className}.computedBase`;
|
|
2582
|
+
lowerer.globalsList.push({ id: info.def.baseValueGlobal, name: `${className} base`, type: { kind: "classval", className: base.def.name }, mutable: false });
|
|
2583
|
+
}
|
|
2584
|
+
if (callableBase && !functionLocalClass(decl)) {
|
|
2585
|
+
lowerer.globalsList.push({ id: callableBase.constructorId, name: `${className} base`, type: DYN, mutable: false }, { id: callableBase.prototypeId, name: `${className} base prototype`, type: DYN, mutable: false });
|
|
2586
|
+
}
|
|
2023
2587
|
// A NAMED class binds its name (declarations in their scope, class
|
|
2024
2588
|
// expressions inside their own bodies — tsc resolves both to this
|
|
2025
2589
|
// symbol); a nameless default-export declaration binds its module's
|
|
@@ -2051,7 +2615,7 @@ mixin) {
|
|
|
2051
2615
|
* unmapped, the fenced-JS-class story. Null answers (unmappable type
|
|
2052
2616
|
* arguments, the instance cap, an uncollected family) make the whole
|
|
2053
2617
|
* reference unmappable — per-site diagnostics own the fence. */
|
|
2054
|
-
export function genericClassInstanceType(lowerer, decl, ref) {
|
|
2618
|
+
export function genericClassInstanceType(lowerer, decl, ref, mapArgument) {
|
|
2055
2619
|
const gci = lowerer.genericClassByDecl.get(decl);
|
|
2056
2620
|
if (!gci) {
|
|
2057
2621
|
// The family never collected (a deferred/poisoned declaration): the
|
|
@@ -2078,7 +2642,7 @@ export function genericClassInstanceType(lowerer, decl, ref) {
|
|
|
2078
2642
|
const mapped = [];
|
|
2079
2643
|
if (args.length === gci.typeParams.length) {
|
|
2080
2644
|
for (const a of args) {
|
|
2081
|
-
const m = lowerer.mapTypeOf(a);
|
|
2645
|
+
const m = lowerer.mapTypeOf(a, mapArgument);
|
|
2082
2646
|
if (!m || m.kind === "void") {
|
|
2083
2647
|
// An UNBOUND type parameter argument (`Box<T>` outside any
|
|
2084
2648
|
// instantiation) stays honestly unmapped — nothing concrete is
|
|
@@ -2207,10 +2771,28 @@ function withInstanceBindings(lowerer, info, fn) {
|
|
|
2207
2771
|
* field, like fieldInitStmts; a block lowers as the block statement it
|
|
2208
2772
|
* is, so its statements poison individually inside lowerStmts. */
|
|
2209
2773
|
export function lowerStaticFieldInits(lowerer, info) {
|
|
2774
|
+
if (info.localClass)
|
|
2775
|
+
return [];
|
|
2210
2776
|
// Mixin instantiations lower their initializers under the
|
|
2211
2777
|
// instantiation's bindings/context (a no-op for everything else —
|
|
2212
2778
|
// generic FAMILIES own their statics and carry no genericInstance).
|
|
2213
|
-
|
|
2779
|
+
const diagsBefore = lowerer.diags.length;
|
|
2780
|
+
try {
|
|
2781
|
+
return withInstanceBindings(lowerer, info, () => lowerStaticFieldInitsInner(lowerer, info));
|
|
2782
|
+
}
|
|
2783
|
+
catch (error) {
|
|
2784
|
+
// Heritage and decorators run before the per-field recovery below.
|
|
2785
|
+
// Keep their refusal attached to the class declaration instead of
|
|
2786
|
+
// letting a poisoned initializer escape the module lowering pass.
|
|
2787
|
+
if (!(error instanceof PoisonError))
|
|
2788
|
+
throw error;
|
|
2789
|
+
if (info.decl && isJsSourceFile(info.decl.getSourceFile()) && lowerer.diagSink === null) {
|
|
2790
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, info.decl, { kind: "statement" });
|
|
2791
|
+
if (fence)
|
|
2792
|
+
return [fence];
|
|
2793
|
+
}
|
|
2794
|
+
return [];
|
|
2795
|
+
}
|
|
2214
2796
|
}
|
|
2215
2797
|
function lowerStaticFieldInitsInner(lowerer, info) {
|
|
2216
2798
|
// Decoration first: TC39 evaluates decorator expressions, creates the
|
|
@@ -2218,6 +2800,39 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
2218
2800
|
// initializers and static blocks (verified against Node — the
|
|
2219
2801
|
// decorated result is what `this`/the class name mean inside them).
|
|
2220
2802
|
const out = [...lowerClassDecoration(lowerer, info)];
|
|
2803
|
+
const computedBase = info.decl ? lowerer.computedClassBases.get(lowerer.classNamer(info.decl)) : undefined;
|
|
2804
|
+
if (info.factoryBaseExpression && info.def.baseValueGlobal) {
|
|
2805
|
+
const loc = locOf(info.factoryBaseExpression);
|
|
2806
|
+
const type = { kind: "classval", className: info.base.def.name };
|
|
2807
|
+
out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: lowerer.lowerExprExpecting(info.factoryBaseExpression, type), loc });
|
|
2808
|
+
out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
|
|
2809
|
+
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
2810
|
+
lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type, loc }, DYN),
|
|
2811
|
+
], type: DYN, loc }, loc });
|
|
2812
|
+
}
|
|
2813
|
+
if (computedBase && info.def.baseValueGlobal) {
|
|
2814
|
+
const loc = computedBase.value.loc;
|
|
2815
|
+
out.push({ kind: "assign", localId: info.def.baseValueGlobal, value: computedBase.value, loc });
|
|
2816
|
+
out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
|
|
2817
|
+
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
2818
|
+
lowerer.coerceToExpected({ kind: "varRef", localId: info.def.baseValueGlobal, type: computedBase.value.type, loc }, DYN),
|
|
2819
|
+
], type: DYN, loc }, loc });
|
|
2820
|
+
}
|
|
2821
|
+
if (info.callableBase) {
|
|
2822
|
+
const { expression, constructorId, prototypeId } = info.callableBase;
|
|
2823
|
+
const loc = locOf(expression);
|
|
2824
|
+
out.push({ kind: "assign", localId: constructorId, value: info.decl && lowerer.computedCallableBases.has(info.decl)
|
|
2825
|
+
? lowerer.coerceToExpected(lowerer.computedCallableBases.get(info.decl), DYN)
|
|
2826
|
+
: lowerer.lowerExprExpecting(expression, DYN), loc }, { kind: "assign", localId: prototypeId, value: { kind: "libCall", fn: "dyn.classBasePrototype",
|
|
2827
|
+
args: [{ kind: "varRef", localId: constructorId, type: DYN, loc }], type: DYN, loc }, loc });
|
|
2828
|
+
const prototype = classPrototypeData(lowerer, info, loc);
|
|
2829
|
+
if (prototype)
|
|
2830
|
+
out.push({ kind: "exprStmt", expr: prototype, loc });
|
|
2831
|
+
out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
|
|
2832
|
+
lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN),
|
|
2833
|
+
{ kind: "varRef", localId: constructorId, type: DYN, loc },
|
|
2834
|
+
], type: DYN, loc }, loc });
|
|
2835
|
+
}
|
|
2221
2836
|
const items = [
|
|
2222
2837
|
...info.staticFields.map((f) => ({ pos: f.initializer.getStart(), kind: "field", f })),
|
|
2223
2838
|
...(info.staticBlocks ?? []).map((b) => ({ pos: b.getStart(), kind: "block", b })),
|
|
@@ -2232,13 +2847,25 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
2232
2847
|
const f = item.f;
|
|
2233
2848
|
lowerer.stats.statementsTotal++;
|
|
2234
2849
|
lowerer.bumpFileStat(locOf(f.initializer).file, "total");
|
|
2850
|
+
const diagsBefore = lowerer.diags.length;
|
|
2235
2851
|
try {
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2852
|
+
const previousThis = lowerer.ctx.thisLocal;
|
|
2853
|
+
const receiver = f.initializer.kind === ts.SyntaxKind.ThisKeyword || hasStaticThis(f.initializer)
|
|
2854
|
+
? lowerer.declareHiddenLocal("%staticThis", { kind: "classval", className: info.def.name }) : null;
|
|
2855
|
+
if (receiver) {
|
|
2856
|
+
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
2857
|
+
out.push({ kind: "varDecl", localId: receiver.id, init: { kind: "classRef", className: info.def.name,
|
|
2858
|
+
type: receiver.type, loc: locOf(f.initializer) }, loc: locOf(f.initializer) });
|
|
2859
|
+
}
|
|
2860
|
+
let value;
|
|
2861
|
+
try {
|
|
2862
|
+
if (receiver)
|
|
2863
|
+
lowerer.ctx.thisLocal = receiver;
|
|
2864
|
+
value = lowerer.lowerExprExpecting(f.initializer, f.type);
|
|
2865
|
+
}
|
|
2866
|
+
finally {
|
|
2867
|
+
lowerer.ctx.thisLocal = previousThis;
|
|
2868
|
+
}
|
|
2242
2869
|
out.push({ kind: "assign", localId: f.globalId, value, loc: locOf(f.initializer) });
|
|
2243
2870
|
}
|
|
2244
2871
|
catch (e) {
|
|
@@ -2246,6 +2873,11 @@ function lowerStaticFieldInitsInner(lowerer, info) {
|
|
|
2246
2873
|
throw e;
|
|
2247
2874
|
lowerer.stats.statementsFailed++;
|
|
2248
2875
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
2876
|
+
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
2877
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, { kind: "statement" });
|
|
2878
|
+
if (fence)
|
|
2879
|
+
out.push(fence);
|
|
2880
|
+
}
|
|
2249
2881
|
}
|
|
2250
2882
|
}
|
|
2251
2883
|
return out;
|
|
@@ -2520,6 +3152,14 @@ function staticMethodValue(lowerer, declarer, name, sig, blame, loc) {
|
|
|
2520
3152
|
export function classValueRef(lowerer, info, blame) {
|
|
2521
3153
|
const display = info.def.name.replace(/^%|^%m\d+\./, "");
|
|
2522
3154
|
fenceDecorationThrows(lowerer, info, blame);
|
|
3155
|
+
if (info.localClass && ts.isIdentifier(blame)) {
|
|
3156
|
+
const stored = lowerer.resolveLocal(blame);
|
|
3157
|
+
if (stored)
|
|
3158
|
+
return lowerer.coerceToExpected({ kind: "varRef", localId: stored.id, type: stored.type, loc: locOf(blame) }, { kind: "classval", className: info.def.name });
|
|
3159
|
+
}
|
|
3160
|
+
if (info.localClass && !ts.isClassExpression(blame) && !ts.isClassDeclaration(blame)) {
|
|
3161
|
+
lowerer.unsupported("SC1090", blame, "named self references inside function-local classes");
|
|
3162
|
+
}
|
|
2523
3163
|
if (info.generic) {
|
|
2524
3164
|
// `typeof Box` — the uninstantiated FAMILY as a value: no thunk, no
|
|
2525
3165
|
// single constructor ABI. INSTANTIATIONS have class objects
|
|
@@ -2529,10 +3169,10 @@ export function classValueRef(lowerer, info, blame) {
|
|
|
2529
3169
|
if (info.builtinError || info.builtinEmitter || info.builtinStream !== undefined) {
|
|
2530
3170
|
lowerer.unsupported("SC1090", blame, `builtin classes as values ('${display}' is runtime-provided — reference program-declared classes instead)`);
|
|
2531
3171
|
}
|
|
2532
|
-
if (lowerer.
|
|
3172
|
+
if (lowerer.inheritsBuiltinEmitterCtor(info) ||
|
|
2533
3173
|
inheritsBuiltinStreamCtor(lowerer, info) ||
|
|
2534
3174
|
(() => { for (let c = info.base; c; c = c.base)
|
|
2535
|
-
if (c.
|
|
3175
|
+
if (c.builtinEmitter || c.builtinStream !== undefined)
|
|
2536
3176
|
return true; return false; })()) {
|
|
2537
3177
|
lowerer.unsupported("SC1090", blame, `classes extending builtin bases as values ('${display}' inherits a runtime-provided constructor)`);
|
|
2538
3178
|
}
|
|
@@ -2554,6 +3194,26 @@ export function ctorAbiEquals(lowerer, sub, sup) {
|
|
|
2554
3194
|
const b = sup.ctorParams;
|
|
2555
3195
|
return a.length === b.length && a.every((p, i) => p.mode === b[i].mode && typeEquals(p.type, b[i].type));
|
|
2556
3196
|
}
|
|
3197
|
+
/** Writable storage for an own static field named through its exact class.
|
|
3198
|
+
* Inherited writes create a new subclass property in JS, so they must not
|
|
3199
|
+
* update the declaring class's global. */
|
|
3200
|
+
export function staticFieldWriteTarget(lowerer, access) {
|
|
3201
|
+
if (access.questionDotToken || (!ts.isIdentifier(access.expression) && access.expression.kind !== ts.SyntaxKind.ThisKeyword))
|
|
3202
|
+
return null;
|
|
3203
|
+
const info = lowerer.exactClassOfReceiver(access.expression);
|
|
3204
|
+
if (!info)
|
|
3205
|
+
return null;
|
|
3206
|
+
const found = lowerer.findStaticOn(info, access.name.text);
|
|
3207
|
+
if (!found?.field)
|
|
3208
|
+
return null;
|
|
3209
|
+
if (found.declarer !== info) {
|
|
3210
|
+
lowerer.unsupported("SC1090", access, `assigning the inherited static '${access.name.text}' through a subclass name (JS creates an OWN property on the subclass — assign through '${found.declarer.def.jsName ?? found.declarer.def.name}' instead)`);
|
|
3211
|
+
}
|
|
3212
|
+
if (found.field.readonly) {
|
|
3213
|
+
lowerer.unsupported("SC1090", access, `assigning the readonly static '${access.name.text}'`);
|
|
3214
|
+
}
|
|
3215
|
+
return { id: found.field.globalId, type: found.field.type };
|
|
3216
|
+
}
|
|
2557
3217
|
/** `C.x` where C is a class declared in the program and x a static
|
|
2558
3218
|
* member of its chain: field reads are the module global, static
|
|
2559
3219
|
* methods become interned closures, and `.name` folds to the class's
|
|
@@ -2561,17 +3221,20 @@ export function ctorAbiEquals(lowerer, sub, sup) {
|
|
|
2561
3221
|
* fall through to the ordinary chain so the static fence or the
|
|
2562
3222
|
* generic member rejection names the site. */
|
|
2563
3223
|
export function lowerStaticFieldRead(lowerer, expr) {
|
|
3224
|
+
if (expr.name.text === "prototype")
|
|
3225
|
+
return null;
|
|
2564
3226
|
if (expr.questionDotToken)
|
|
2565
3227
|
return null;
|
|
2566
|
-
if (!ts.isIdentifier(expr.expression))
|
|
3228
|
+
if (!ts.isIdentifier(expr.expression) && expr.expression.kind !== ts.SyntaxKind.ThisKeyword)
|
|
2567
3229
|
return null;
|
|
2568
|
-
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
3230
|
+
const symbol = ts.isIdentifier(expr.expression) ? lowerer.resolveValueSymbol(expr.expression) : null;
|
|
2569
3231
|
const info = (symbol ? lowerer.classBySymbol.get(symbol) : undefined) ??
|
|
2570
3232
|
// A require binding over `module.exports = class {…}` (the alias
|
|
2571
3233
|
// lands on the expression's own symbol): resolve/collect on demand,
|
|
2572
3234
|
// or `C.name` below would fall through to paths that answer for
|
|
2573
3235
|
// stdlib globals instead of this class.
|
|
2574
3236
|
propertyAssignedClassInfoOf(lowerer, symbol) ??
|
|
3237
|
+
exactClassOfReceiver(lowerer, expr.expression) ??
|
|
2575
3238
|
undefined;
|
|
2576
3239
|
if (!info)
|
|
2577
3240
|
return null;
|
|
@@ -2584,6 +3247,9 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
2584
3247
|
return null;
|
|
2585
3248
|
const loc = locOf(expr);
|
|
2586
3249
|
const found = findStaticOn(lowerer, info, expr.name.text);
|
|
3250
|
+
if (hasRuntimeStatics(info) && !found?.field)
|
|
3251
|
+
return { kind: "dynKeyGet", value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3252
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
|
|
2587
3253
|
// A #private static resolves only through the DECLARING class's own
|
|
2588
3254
|
// name: in JS the brand lives on that one constructor object, so
|
|
2589
3255
|
// `D.#s` (a subclass receiver) throws Node's TypeError instead of
|
|
@@ -2611,6 +3277,12 @@ export function lowerStaticFieldRead(lowerer, expr) {
|
|
|
2611
3277
|
if (expr.name.text === "name" && info.def.jsName !== undefined) {
|
|
2612
3278
|
return { kind: "strLit", value: info.def.jsName, type: STRING, loc };
|
|
2613
3279
|
}
|
|
3280
|
+
if (info.callableBase)
|
|
3281
|
+
return { kind: "dynKeyGet", value: lowerer.coerceToExpected(classValueRef(lowerer, info, expr.expression), DYN),
|
|
3282
|
+
key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
|
|
3283
|
+
const data = classStaticDataFor(lowerer, info, expr.name.text, loc);
|
|
3284
|
+
if (data)
|
|
3285
|
+
return { kind: "dynKeyGet", value: data, key: { kind: "strLit", value: expr.name.text, type: STRING, loc }, type: DYN, loc };
|
|
2614
3286
|
return null;
|
|
2615
3287
|
}
|
|
2616
3288
|
/** NamedEvaluation's answer for a class expression's `.name`: its own
|
|
@@ -2635,19 +3307,12 @@ function namedEvaluationName(expr) {
|
|
|
2635
3307
|
return p.name.text;
|
|
2636
3308
|
return "";
|
|
2637
3309
|
}
|
|
2638
|
-
/**
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
* first collection. The honest v1 boundary is TOP-LEVEL evaluation
|
|
2643
|
-
* positions only: each evaluation of a class expression in JS mints a
|
|
2644
|
-
* DISTINCT class (fresh identity, fresh statics), and one immortal
|
|
2645
|
-
* class object is exact only for expressions that evaluate exactly
|
|
2646
|
-
* once. Statics-bearing expressions additionally restrict to positions
|
|
2647
|
-
* where "immediately before the enclosing statement" IS the evaluation
|
|
2648
|
-
* point (lowerFileInit drains pendingClassExprInits there). */
|
|
3310
|
+
/** Collect a class expression once per enclosing specialization. Function-local
|
|
3311
|
+
* evaluations allocate fresh constructor objects; top-level expressions use
|
|
3312
|
+
* immortal templates. Static initialization remains limited to whole top-level
|
|
3313
|
+
* initializers, where pendingClassExprInits preserves its evaluation point. */
|
|
2649
3314
|
export function lowerClassExpressionInfo(lowerer, expr) {
|
|
2650
|
-
const cached = lowerer.
|
|
3315
|
+
const cached = lowerer.exprClassInfoByName.get(lowerer.classNamer(expr));
|
|
2651
3316
|
if (cached)
|
|
2652
3317
|
return cached;
|
|
2653
3318
|
// Reentrancy guard: heritage resolution can DEMAND another class
|
|
@@ -2660,16 +3325,41 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
2660
3325
|
if (lowerer.collectingExprClasses.has(expr)) {
|
|
2661
3326
|
lowerer.unsupported("SC1090", expr, "class expressions whose extends chain re-enters their own collection (a cyclic base through property assignments)");
|
|
2662
3327
|
}
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
if (ts.isFunctionLike(p) || ts.isClassStaticBlockDeclaration(p)) {
|
|
2668
|
-
lowerer.unsupported("SC1090", expr, "class expressions inside functions (each evaluation creates a DISTINCT class in JS — fresh identity, fresh statics; declare the class at top level)");
|
|
3328
|
+
let local = false;
|
|
3329
|
+
for (let p = expr.parent; p !== undefined && !ts.isSourceFile(p); p = p.parent) {
|
|
3330
|
+
if (ts.isClassStaticBlockDeclaration(p)) {
|
|
3331
|
+
lowerer.unsupported("SC1090", expr, "class expressions inside static blocks");
|
|
2669
3332
|
}
|
|
3333
|
+
if (ts.isFunctionLike(p))
|
|
3334
|
+
local = true;
|
|
3335
|
+
}
|
|
3336
|
+
if (local && expr.members.some((member) => member.name && ts.isPrivateIdentifier(member.name))) {
|
|
3337
|
+
lowerer.unsupported("SC1090", expr, "function-local classes with private brands");
|
|
3338
|
+
}
|
|
3339
|
+
if (local && (expr.typeParameters?.length ||
|
|
3340
|
+
decoratorNodesOf(expr).length || expr.members.some((member) => decoratorNodesOf(member).length ||
|
|
3341
|
+
(!isJsSourceFile(expr.getSourceFile()) && (ts.isClassStaticBlockDeclaration(member) ||
|
|
3342
|
+
ts.getModifiers(member)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword))) ||
|
|
3343
|
+
(ts.isMethodDeclaration(member) && member.typeParameters?.length)))) {
|
|
3344
|
+
lowerer.unsupported("SC1090", expr, "function-local classes with statics, decorators, or generic members");
|
|
2670
3345
|
}
|
|
2671
3346
|
lowerer.collectingExprClasses.add(expr);
|
|
2672
3347
|
try {
|
|
3348
|
+
if (local && lowerer.fnStack.length > 0 && !lowerer.computedClassBases.has(lowerer.classNamer(expr))) {
|
|
3349
|
+
const heritage = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
3350
|
+
if (heritage && (ts.isCallExpression(heritage) ||
|
|
3351
|
+
ts.isIdentifier(heritage) && (lowerer.peekLocal(heritage) ?? lowerer.globalOf(heritage)) != null)) {
|
|
3352
|
+
let value = lowerer.lowerExpr(heritage);
|
|
3353
|
+
const known = value.type.kind === "dyn" ? storedClassValueType(lowerer, heritage) : null;
|
|
3354
|
+
if (known?.kind === "classval")
|
|
3355
|
+
value = lowerer.coerceToExpected(value, known);
|
|
3356
|
+
const base = value.type.kind === "classval" ? lowerer.classes.get(value.type.className) : undefined;
|
|
3357
|
+
if (base)
|
|
3358
|
+
lowerer.computedClassBases.set(lowerer.classNamer(expr), { value, classInfo: base });
|
|
3359
|
+
else if (value.type.kind === "dyn" || value.type.kind === "func")
|
|
3360
|
+
lowerer.computedCallableBases.set(expr, value);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
2673
3363
|
lowerer.collectClassShapeInner(expr, namedEvaluationName(expr));
|
|
2674
3364
|
}
|
|
2675
3365
|
finally {
|
|
@@ -2678,7 +3368,17 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
2678
3368
|
const info = lowerer.classes.get(lowerer.classNamer(expr));
|
|
2679
3369
|
if (!info)
|
|
2680
3370
|
throw new PoisonError(); // collection poisoned and reported
|
|
2681
|
-
|
|
3371
|
+
if (local) {
|
|
3372
|
+
info.def.localCaptures = [];
|
|
3373
|
+
info.def.fields.push({ name: `%classEnvironment:${info.def.name}`, type: { kind: "classval", className: info.def.name } });
|
|
3374
|
+
info.localClass = { context: null, bodies: new Map(), captureSources: [], ready: false };
|
|
3375
|
+
if (info.base?.localClass) {
|
|
3376
|
+
const baseExpression = expr.heritageClauses?.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]?.expression;
|
|
3377
|
+
if (baseExpression)
|
|
3378
|
+
info.localClass.baseExpression = baseExpression;
|
|
3379
|
+
}
|
|
3380
|
+
}
|
|
3381
|
+
lowerer.exprClassInfoByName.set(info.def.name, info);
|
|
2682
3382
|
lowerer.exprClasses.push(info);
|
|
2683
3383
|
lowerer.onExprClassCollected?.(info);
|
|
2684
3384
|
// Static field initializers and static blocks run when the class
|
|
@@ -2688,7 +3388,7 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
2688
3388
|
// drains it), which is JS's order for whole-initializer positions.
|
|
2689
3389
|
// Anything subtler (multi-declarator statements, arguments evaluated
|
|
2690
3390
|
// after other side effects) is a named fence, never a reordering.
|
|
2691
|
-
if (info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0) {
|
|
3391
|
+
if (!local && (info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
|
|
2692
3392
|
let holder = expr.parent;
|
|
2693
3393
|
while (ts.isParenthesizedExpression(holder) || ts.isClassExpression(holder) ||
|
|
2694
3394
|
ts.isHeritageClause(holder) || ts.isExpressionWithTypeArguments(holder)) {
|
|
@@ -2708,7 +3408,6 @@ export function lowerClassExpressionInfo(lowerer, expr) {
|
|
|
2708
3408
|
if (!wholeInit) {
|
|
2709
3409
|
lowerer.unsupported("SC1090", expr, "class expressions with static initializers or static blocks outside a whole-initializer position (their declaration-time code must run exactly where the expression evaluates — bind the class in its own top-level `const C = class …` statement)");
|
|
2710
3410
|
}
|
|
2711
|
-
lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
|
|
2712
3411
|
}
|
|
2713
3412
|
return info;
|
|
2714
3413
|
}
|
|
@@ -2733,7 +3432,77 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
2733
3432
|
}
|
|
2734
3433
|
}
|
|
2735
3434
|
}
|
|
2736
|
-
|
|
3435
|
+
const info = lowerClassExpressionInfo(lowerer, expr);
|
|
3436
|
+
if (!info.localClass && !info.expressionInitializationEmitted &&
|
|
3437
|
+
(info.callableBase || info.def.baseValueGlobal || info.staticFields.length > 0 || (info.staticBlocks?.length ?? 0) > 0)) {
|
|
3438
|
+
info.expressionInitializationEmitted = true;
|
|
3439
|
+
lowerer.pendingClassExprInits.push(...lowerer.lowerStaticFieldInits(info));
|
|
3440
|
+
}
|
|
3441
|
+
if (info.localClass && !info.localClass.ready) {
|
|
3442
|
+
const context = newFnCtx(true, null, null, VOID);
|
|
3443
|
+
info.localClass.context = context;
|
|
3444
|
+
lowerer.fnStack.push(context);
|
|
3445
|
+
try {
|
|
3446
|
+
const bodies = lowerClassMembers(lowerer, info);
|
|
3447
|
+
for (const body of bodies)
|
|
3448
|
+
info.localClass.bodies.set(body.name, body);
|
|
3449
|
+
info.def.localCaptures = context.captures;
|
|
3450
|
+
info.localClass.captureSources = context.captureSources;
|
|
3451
|
+
if (info.localClass.baseExpression && info.base) {
|
|
3452
|
+
info.def.localBaseCapture = info.def.localCaptures.length;
|
|
3453
|
+
info.def.localCaptures.push({ localId: "%base", name: "base", type: { kind: "classval", className: info.base.def.name } });
|
|
3454
|
+
}
|
|
3455
|
+
info.localClass.ready = true;
|
|
3456
|
+
lowerer.onExprClassCollected?.(info);
|
|
3457
|
+
}
|
|
3458
|
+
finally {
|
|
3459
|
+
lowerer.fnStack.pop();
|
|
3460
|
+
info.localClass.context = null;
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
const value = classValueRef(lowerer, info, expr);
|
|
3464
|
+
if (info.localClass && info.callableBase && value.kind === "classRef") {
|
|
3465
|
+
const loc = locOf(expr);
|
|
3466
|
+
const base = lowerer.lowerExprExpecting(info.callableBase.expression, DYN);
|
|
3467
|
+
const baseLocal = lowerer.declareHiddenLocal("%classBase", DYN);
|
|
3468
|
+
const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
|
|
3469
|
+
const baseRef = { kind: "varRef", localId: baseLocal.id, type: DYN, loc };
|
|
3470
|
+
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3471
|
+
const boxed = { kind: "dynFrom", value: clsRef, type: DYN, loc };
|
|
3472
|
+
info.localPrototypeData = true;
|
|
3473
|
+
return initializeRuntimeStatics(lowerer, info, { kind: "seqExpr", stmts: [
|
|
3474
|
+
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3475
|
+
{ kind: "varDecl", localId: clsLocal.id, init: { ...value, captures: info.localClass.captureSources }, loc },
|
|
3476
|
+
{ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [boxed, baseRef], type: DYN, loc }, loc },
|
|
3477
|
+
{ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classPrototype", args: [boxed,
|
|
3478
|
+
{ kind: "libCall", fn: "dyn.classBasePrototype", args: [baseRef], type: DYN, loc },
|
|
3479
|
+
], type: DYN, loc }, loc },
|
|
3480
|
+
], result: clsRef, type: value.type, loc });
|
|
3481
|
+
}
|
|
3482
|
+
if (info.localClass?.baseExpression && info.base && value.kind === "classRef") {
|
|
3483
|
+
const loc = locOf(expr);
|
|
3484
|
+
const base = lowerer.lowerExprExpecting(info.localClass.baseExpression, { kind: "classval", className: info.base.def.name });
|
|
3485
|
+
const baseLocal = lowerer.declareHiddenLocal("%classBase", base.type);
|
|
3486
|
+
baseLocal.boxed = true;
|
|
3487
|
+
const clsLocal = lowerer.declareHiddenLocal("%classValue", value.type);
|
|
3488
|
+
const baseRef = { kind: "varRef", localId: baseLocal.id, type: base.type, loc };
|
|
3489
|
+
const clsRef = { kind: "varRef", localId: clsLocal.id, type: value.type, loc };
|
|
3490
|
+
const basePrototype = classPrototypeData(lowerer, info.base, loc, baseRef);
|
|
3491
|
+
info.localPrototypeData = true;
|
|
3492
|
+
return initializeRuntimeStatics(lowerer, info, { kind: "seqExpr", stmts: [
|
|
3493
|
+
{ kind: "varDecl", localId: baseLocal.id, init: base, loc },
|
|
3494
|
+
{ kind: "varDecl", localId: clsLocal.id, init: { ...value, captures: [...info.localClass.captureSources, baseLocal.id] }, loc },
|
|
3495
|
+
{ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classInherit", args: [
|
|
3496
|
+
{ kind: "dynFrom", value: clsRef, type: DYN, loc }, { kind: "dynFrom", value: baseRef, type: DYN, loc },
|
|
3497
|
+
], type: DYN, loc }, loc },
|
|
3498
|
+
{ kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classPrototype", args: [
|
|
3499
|
+
{ kind: "dynFrom", value: clsRef, type: DYN, loc }, basePrototype,
|
|
3500
|
+
], type: DYN, loc }, loc },
|
|
3501
|
+
], result: clsRef, type: value.type, loc });
|
|
3502
|
+
}
|
|
3503
|
+
return initializeRuntimeStatics(lowerer, info, info.localClass && value.kind === "classRef"
|
|
3504
|
+
? { ...value, captures: info.localClass.captureSources }
|
|
3505
|
+
: value);
|
|
2737
3506
|
}
|
|
2738
3507
|
/** The EXACT class a receiver expression is statically known to BE (not
|
|
2739
3508
|
* merely be typed by): the class name itself, or a `const` binding
|
|
@@ -2742,6 +3511,12 @@ export function lowerClassExpression(lowerer, expr) {
|
|
|
2742
3511
|
* hit the declaring class's storage exactly (the shadowing hazards of
|
|
2743
3512
|
* general class values don't arise). Null for everything else. */
|
|
2744
3513
|
export function exactClassOfReceiver(lowerer, expr) {
|
|
3514
|
+
// A class-valued lexical this is introduced only for an exact static
|
|
3515
|
+
// receiver specialization; ordinary instance this remains an object.
|
|
3516
|
+
if (expr.kind === ts.SyntaxKind.ThisKeyword) {
|
|
3517
|
+
const receiver = lowerer.resolveThis();
|
|
3518
|
+
return receiver?.type.kind === "classval" ? lowerer.classes.get(receiver.type.className) ?? null : null;
|
|
3519
|
+
}
|
|
2745
3520
|
if (!ts.isIdentifier(expr))
|
|
2746
3521
|
return null;
|
|
2747
3522
|
const symbol = lowerer.resolveValueSymbol(expr);
|
|
@@ -2764,7 +3539,7 @@ export function exactClassOfReceiver(lowerer, expr) {
|
|
|
2764
3539
|
while (ts.isParenthesizedExpression(init))
|
|
2765
3540
|
init = init.expression;
|
|
2766
3541
|
if (ts.isClassExpression(init))
|
|
2767
|
-
return lowerer.
|
|
3542
|
+
return lowerer.exprClassInfoByName.get(lowerer.classNamer(init)) ?? null;
|
|
2768
3543
|
if (ts.isIdentifier(init)) {
|
|
2769
3544
|
const initSym = lowerer.resolveValueSymbol(init);
|
|
2770
3545
|
const aliased = initSym ? (lowerer.classBySymbol.get(initSym) ?? null) : null;
|
|
@@ -2880,12 +3655,37 @@ function countAssignmentsTo(assign) {
|
|
|
2880
3655
|
export function lowerStaticMethodCall(lowerer, call, access) {
|
|
2881
3656
|
if (access.questionDotToken)
|
|
2882
3657
|
return null;
|
|
3658
|
+
if (access.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
3659
|
+
const receiver = lowerer.resolveThis();
|
|
3660
|
+
const info = receiver?.type.kind === "classval" ? lowerer.classes.get(receiver.type.className) : undefined;
|
|
3661
|
+
if (info)
|
|
3662
|
+
return staticCallOn(lowerer, call, access, info, false);
|
|
3663
|
+
}
|
|
2883
3664
|
// `module.exports.describe()` in a module whose whole export IS a
|
|
2884
3665
|
// class expression: the receiver is exactly that class (the kept
|
|
2885
3666
|
// export assignment pins it) — the direct-name rules apply.
|
|
2886
3667
|
if (!ts.isIdentifier(access.expression)) {
|
|
2887
|
-
if (!isModuleExportsAccess(access.expression) || !isCjsJsFile(access.getSourceFile())) {
|
|
2888
|
-
|
|
3668
|
+
if (!isModuleExportsAccess(access.expression) || !isCjsJsFile(access.getSourceFile(), lowerer.program)) {
|
|
3669
|
+
let receiverType = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
3670
|
+
if (receiverType?.kind !== "classval" && isJsSourceFile(call.getSourceFile()) && ts.isCallExpression(access.expression)) {
|
|
3671
|
+
const receiver = tryLowerExpression(lowerer, access.expression);
|
|
3672
|
+
if (receiver?.type.kind === "classval")
|
|
3673
|
+
receiverType = receiver.type;
|
|
3674
|
+
}
|
|
3675
|
+
if (receiverType?.kind !== "classval")
|
|
3676
|
+
return null;
|
|
3677
|
+
const info = lowerer.classes.get(receiverType.className);
|
|
3678
|
+
if (!info)
|
|
3679
|
+
return null;
|
|
3680
|
+
const result = staticCallOn(lowerer, call, access, info, true);
|
|
3681
|
+
if (!result)
|
|
3682
|
+
return null;
|
|
3683
|
+
// Evaluate and validate the receiver before evaluating arguments.
|
|
3684
|
+
// A typed checker projection cannot turn a replaced field into a call
|
|
3685
|
+
// to the class that originally occupied it.
|
|
3686
|
+
const receiver = lowerer.lowerExprExpecting(access.expression, receiverType);
|
|
3687
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: receiver, loc: locOf(access.expression) }],
|
|
3688
|
+
result, type: result.type, loc: locOf(call) };
|
|
2889
3689
|
}
|
|
2890
3690
|
const whole = cjsClassExprWholeExportOf(access.getSourceFile());
|
|
2891
3691
|
if (!whole)
|
|
@@ -2928,6 +3728,10 @@ function classValueIsExactlyOwn(lowerer, recv, info) {
|
|
|
2928
3728
|
}
|
|
2929
3729
|
function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
2930
3730
|
const loc = locOf(call);
|
|
3731
|
+
if (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, access.name.text)?.field || info.callableBase && !findStaticOn(lowerer, info, access.name.text) && !findGenericStaticOn(lowerer, info, access.name.text))
|
|
3732
|
+
return { kind: "dynInvoke", recv: lowerer.lowerExprExpecting(access.expression, DYN),
|
|
3733
|
+
method: access.name.text, calleeName: access.name.text,
|
|
3734
|
+
args: call.arguments.map((argument) => lowerer.lowerExprExpecting(argument, DYN)), type: DYN, loc };
|
|
2931
3735
|
// #private statics: through-a-VALUE receiver the call devirtualizes
|
|
2932
3736
|
// exactly when the value can only BE the declaring class
|
|
2933
3737
|
// (classValueIsExactlyOwn — a slot that could hold a descendant at
|
|
@@ -2951,13 +3755,19 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
2951
3755
|
if (throughValue && staticShadowBelow(lowerer, info, access.name.text)) {
|
|
2952
3756
|
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)`);
|
|
2953
3757
|
}
|
|
2954
|
-
const instance = genericCallInstance(lowerer, call, gfound.info);
|
|
3758
|
+
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, gfound.info, info, throughValue));
|
|
2955
3759
|
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
2956
3760
|
return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
|
|
2957
3761
|
}
|
|
2958
3762
|
if (throughValue && staticShadowBelow(lowerer, info, access.name.text)) {
|
|
2959
3763
|
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)`);
|
|
2960
3764
|
}
|
|
3765
|
+
const specialized = findGenericStaticOn(lowerer, info, access.name.text);
|
|
3766
|
+
if (specialized?.declarer === found.declarer && specialized.info.implicitParams) {
|
|
3767
|
+
const instance = implicitCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, specialized.info, info, throughValue));
|
|
3768
|
+
const args = lowerer.completeArgs(call.arguments, instance.params, loc, call);
|
|
3769
|
+
return { kind: "call", callee: instance.name, args, type: instance.returnType, loc };
|
|
3770
|
+
}
|
|
2961
3771
|
if (found.field !== undefined) {
|
|
2962
3772
|
// A func-typed static field in call position: read the global,
|
|
2963
3773
|
// call through the value (the ctor-assigned-callback pattern).
|
|
@@ -2973,13 +3783,44 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
2973
3783
|
}
|
|
2974
3784
|
args.push(absent);
|
|
2975
3785
|
}
|
|
2976
|
-
return { kind: "callValue", callee, args, type: found.field.type.ret, loc };
|
|
3786
|
+
return { kind: "callValue", callee, receiver: lowerer.lowerExprExpecting(access.expression, DYN), args, type: found.field.type.ret, loc };
|
|
3787
|
+
}
|
|
3788
|
+
if (found.method.member.body && hasStaticThis(found.method.member)) {
|
|
3789
|
+
const generic = found.method.receiverInfo ??= {
|
|
3790
|
+
decl: found.method.member, baseName: access.name.text,
|
|
3791
|
+
qualifiedName: `%${found.declarer.def.name}.static:${access.name.text}`,
|
|
3792
|
+
typeParams: [], instances: new Map(), member: { cls: found.declarer, kind: "static" },
|
|
3793
|
+
};
|
|
3794
|
+
const instance = genericCallInstance(lowerer, call, staticMethodForReceiver(lowerer, access, generic, info, throughValue));
|
|
3795
|
+
return { kind: "call", callee: instance.name,
|
|
3796
|
+
args: lowerer.completeArgs(call.arguments, instance.params, loc, call), type: instance.returnType, loc };
|
|
2977
3797
|
}
|
|
2978
3798
|
const fnName = `%${found.declarer.def.name}.static:${access.name.text}`;
|
|
2979
3799
|
lowerer.noteEdge(fnName);
|
|
2980
3800
|
const args = lowerer.completeArgs(call.arguments, found.method.params, loc, call);
|
|
2981
3801
|
return { kind: "call", callee: fnName, args, type: found.method.ret, loc };
|
|
2982
3802
|
}
|
|
3803
|
+
function staticMethodForReceiver(lowerer, access, method, receiver, throughValue) {
|
|
3804
|
+
if (!hasStaticThis(method.decl))
|
|
3805
|
+
return method;
|
|
3806
|
+
// A private name in the inherited body belongs to the declaring class,
|
|
3807
|
+
// even when the receiver declares a different private with that spelling.
|
|
3808
|
+
// Do not resolve it by receiver name until the static ABI tracks the brand.
|
|
3809
|
+
if (method.member && method.member.cls !== receiver && hasLexicalPrivateReference(method.decl)) {
|
|
3810
|
+
lowerer.unsupported("SC1090", access, "private member references in an inherited receiver-dependent static method");
|
|
3811
|
+
}
|
|
3812
|
+
if (throughValue && !classValueIsExactlyOwn(lowerer, access.expression, receiver)) {
|
|
3813
|
+
lowerer.unsupported("SC1090", access, "receiver-dependent static methods through a polymorphic class value");
|
|
3814
|
+
}
|
|
3815
|
+
const instances = method.receiverSpecializations ??= new Map();
|
|
3816
|
+
let specialized = instances.get(receiver.def.name);
|
|
3817
|
+
if (!specialized) {
|
|
3818
|
+
specialized = { ...method, qualifiedName: `${method.qualifiedName}%on.${receiver.def.name}`,
|
|
3819
|
+
instances: new Map(), staticReceiver: receiver, receiverSpecializations: new Map() };
|
|
3820
|
+
instances.set(receiver.def.name, specialized);
|
|
3821
|
+
}
|
|
3822
|
+
return specialized;
|
|
3823
|
+
}
|
|
2983
3824
|
/** Static member access through a class VALUE (`X.m` where X is
|
|
2984
3825
|
* classval-typed): devirtualized — the member resolves against the
|
|
2985
3826
|
* static class's chain, exact when no strict descendant redeclares it
|
|
@@ -2990,11 +3831,15 @@ function staticCallOn(lowerer, call, access, info, throughValue) {
|
|
|
2990
3831
|
export function lowerClassValueProperty(lowerer, expr) {
|
|
2991
3832
|
if (expr.questionDotToken)
|
|
2992
3833
|
return null;
|
|
2993
|
-
const recvT =
|
|
3834
|
+
const recvT = storedClassValueType(lowerer, expr.expression);
|
|
2994
3835
|
if (recvT?.kind !== "classval")
|
|
2995
3836
|
return null;
|
|
2996
3837
|
const loc = locOf(expr);
|
|
2997
3838
|
const member = expr.name.text;
|
|
3839
|
+
const info = lowerer.classes.get(recvT.className);
|
|
3840
|
+
if (info && (hasRuntimeStatics(info) && !findStaticOn(lowerer, info, member)?.field || info.callableBase && !findStaticOn(lowerer, info, member)))
|
|
3841
|
+
return { kind: "dynKeyGet", value: lowerer.lowerExprExpecting(expr.expression, DYN),
|
|
3842
|
+
key: { kind: "strLit", value: member, type: STRING, loc }, type: DYN, loc };
|
|
2998
3843
|
// `X.name` reads the RUNTIME class object's stored name — the one
|
|
2999
3844
|
// genuinely dynamic member. It CONSUMES the receiver (no evaluation
|
|
3000
3845
|
// is discarded), so any receiver expression is fine here.
|
|
@@ -3004,11 +3849,14 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
3004
3849
|
return null;
|
|
3005
3850
|
return { kind: "libCall", fn: "class.name", args: [recv], type: STRING, loc };
|
|
3006
3851
|
}
|
|
3852
|
+
if (!info)
|
|
3853
|
+
return null;
|
|
3007
3854
|
if (!ts.isIdentifier(expr.expression) &&
|
|
3855
|
+
expr.expression.kind !== ts.SyntaxKind.ThisKeyword &&
|
|
3008
3856
|
// `module.exports.label` in a class-replaced CJS module: the
|
|
3009
3857
|
// receiver is the exact exported class, and the read is
|
|
3010
3858
|
// side-effect-free — as bindable as an identifier.
|
|
3011
|
-
!(isModuleExportsAccess(expr.expression) && isCjsJsFile(expr.getSourceFile()))) {
|
|
3859
|
+
!(isModuleExportsAccess(expr.expression) && isCjsJsFile(expr.getSourceFile(), lowerer.program))) {
|
|
3012
3860
|
// Devirtualized reads DISCARD the receiver value, so only
|
|
3013
3861
|
// side-effect-free receivers are claimed (the instanceOf fold
|
|
3014
3862
|
// rule); computed ones meet the pointed fence with a bindable fix.
|
|
@@ -3016,9 +3864,6 @@ export function lowerClassValueProperty(lowerer, expr) {
|
|
|
3016
3864
|
}
|
|
3017
3865
|
// The direct class-name spelling resolved in lowerStaticFieldRead;
|
|
3018
3866
|
// reaching here means the receiver is a classval-typed BINDING.
|
|
3019
|
-
const info = lowerer.classes.get(recvT.className);
|
|
3020
|
-
if (!info)
|
|
3021
|
-
return null;
|
|
3022
3867
|
const found = findStaticOn(lowerer, info, member);
|
|
3023
3868
|
if (!found) {
|
|
3024
3869
|
lowerer.unsupported("SC1090", expr, `the static member '${member}' of class '${info.def.name.replace(/^%|^%m\d+\./, "")}' (static accessors and initializer-less static fields have no lowering, and Function members like .call/.bind/.prototype have no value form)`);
|
|
@@ -3110,9 +3955,75 @@ export function findGenericMethodOn(lowerer, info, name) {
|
|
|
3110
3955
|
* method `name` — overrideBelow's twin: generic methods have no vtable
|
|
3111
3956
|
* slot, so a call that could reach an override compiles only when the
|
|
3112
3957
|
* receiver's runtime class is statically exact. */
|
|
3113
|
-
function genericOverrideBelow(lowerer, info, name) {
|
|
3958
|
+
export function genericOverrideBelow(lowerer, info, name) {
|
|
3114
3959
|
return info.subclasses.some((s) => s.genericMethods?.has(name) === true || genericOverrideBelow(lowerer, s, name));
|
|
3115
3960
|
}
|
|
3961
|
+
/** Discover overrides before choosing inferred method ABIs. Class collection
|
|
3962
|
+
* visits bases first, including imported bases and class expressions, so the
|
|
3963
|
+
* collected subclass graph cannot answer this question yet. The checker
|
|
3964
|
+
* hierarchy identifies the original declarations through aliases as well. */
|
|
3965
|
+
export function collectVirtualJsMethods(lowerer, files) {
|
|
3966
|
+
// Record named prototype accesses before collecting method signatures.
|
|
3967
|
+
// Those slots need a callable ABI even when JavaScript would otherwise
|
|
3968
|
+
// specialize each call independently.
|
|
3969
|
+
for (const file of files)
|
|
3970
|
+
ts.walkPreorder(file, (node) => {
|
|
3971
|
+
if (!ts.isPropertyAccessExpression(node) && !ts.isElementAccessExpression(node))
|
|
3972
|
+
return;
|
|
3973
|
+
const name = ts.isPropertyAccessExpression(node) ? node.name.text
|
|
3974
|
+
: ts.isStringLiteralLike(node.argumentExpression) ? node.argumentExpression.text : null;
|
|
3975
|
+
if (name === null)
|
|
3976
|
+
return;
|
|
3977
|
+
const prototype = ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "prototype";
|
|
3978
|
+
const assigned = ts.isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken;
|
|
3979
|
+
const symbol = !assigned ? undefined : ts.isPropertyAccessExpression(node)
|
|
3980
|
+
? lowerer.checker.getSymbolAtLocation(node.name)
|
|
3981
|
+
: lowerer.checker.getPropertyOfType(lowerer.typeOf(node.expression), name);
|
|
3982
|
+
if (prototype || symbol && lowerer.checker.declarationsOf(symbol).some(ts.isMethodDeclaration)) {
|
|
3983
|
+
lowerer.prototypeMethodAccesses.set(name, node);
|
|
3984
|
+
}
|
|
3985
|
+
});
|
|
3986
|
+
const visit = (node) => {
|
|
3987
|
+
if (ts.isClassDeclaration(node) || ts.isClassExpression(node)) {
|
|
3988
|
+
const members = node.members.filter((member) => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
|
|
3989
|
+
!member.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword));
|
|
3990
|
+
if (node.heritageClauses?.length && members.length > 0) {
|
|
3991
|
+
const symbol = lowerer.typeOf(node).getSymbol();
|
|
3992
|
+
const instance = symbol ? lowerer.checker.getDeclaredTypeOfSymbol(symbol) : null;
|
|
3993
|
+
const seen = new Set();
|
|
3994
|
+
const markBases = (type) => {
|
|
3995
|
+
const target = type.isTypeReference() ? type.getTarget() : type;
|
|
3996
|
+
if (target === undefined || !target.isClassOrInterface() || seen.has(target))
|
|
3997
|
+
return;
|
|
3998
|
+
seen.add(target);
|
|
3999
|
+
for (const base of lowerer.checker.getBaseTypes(target)) {
|
|
4000
|
+
for (const member of members) {
|
|
4001
|
+
if (!ts.isIdentifier(member.name))
|
|
4002
|
+
continue;
|
|
4003
|
+
const property = lowerer.checker.getPropertyOfType(base, member.name.text);
|
|
4004
|
+
for (const declaration of property ? lowerer.checker.declarationsOf(property) : []) {
|
|
4005
|
+
if (ts.isMethodDeclaration(declaration) && isJsSourceFile(declaration.getSourceFile())) {
|
|
4006
|
+
lowerer.virtualJsMethods.add(declaration);
|
|
4007
|
+
if (isJsSourceFile(member.getSourceFile()) && !member.typeParameters &&
|
|
4008
|
+
!member.asteriskToken && !member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) &&
|
|
4009
|
+
!bodyReadsArguments(member) &&
|
|
4010
|
+
member.parameters.every((p) => !p.initializer && !p.dotDotDotToken)) {
|
|
4011
|
+
lowerer.virtualJsMethodArity.set(declaration, Math.max(lowerer.virtualJsMethodArity.get(declaration) ?? 0, member.parameters.length));
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
markBases(base);
|
|
4017
|
+
}
|
|
4018
|
+
};
|
|
4019
|
+
if (instance)
|
|
4020
|
+
markBases(instance);
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
};
|
|
4024
|
+
for (const file of files)
|
|
4025
|
+
ts.walkPreorder(file, visit);
|
|
4026
|
+
}
|
|
3116
4027
|
/** The receiver's EXACT runtime class, when the expression proves it: a
|
|
3117
4028
|
* `new C(...)` expression directly, or a const binding initialized with
|
|
3118
4029
|
* one (the binding can never be reassigned to a subclass instance).
|
|
@@ -3274,13 +4185,20 @@ function mixinForwardingCtor(lowerer, ctor) {
|
|
|
3274
4185
|
return !extraRef;
|
|
3275
4186
|
}
|
|
3276
4187
|
export function lowerClassMembers(lowerer, info) {
|
|
4188
|
+
// Local class bodies are lowered when their expression captures its
|
|
4189
|
+
// lexical environment. Type collection alone can discover a class in
|
|
4190
|
+
// an owner skipped by the coverage remainder; it must not relower the
|
|
4191
|
+
// constructor without that environment.
|
|
4192
|
+
if (info.localClass && info.localClass.context === null) {
|
|
4193
|
+
return [...info.localClass.bodies.values()];
|
|
4194
|
+
}
|
|
3277
4195
|
const out = [];
|
|
3278
4196
|
const className = info.def.name;
|
|
3279
4197
|
// Generic-class INSTANTIATIONS (and mixin instantiations) are
|
|
3280
4198
|
// demand-driven like generic-fn instances, not reachability units:
|
|
3281
4199
|
// they are never registered as units, so wantBody's name-keyed gate
|
|
3282
4200
|
// cannot apply — every member of a demanded instantiation lowers.
|
|
3283
|
-
const always = info.genericInstance !== undefined || info.mixinInstance !== undefined;
|
|
4201
|
+
const always = info.genericInstance !== undefined || info.mixinInstance !== undefined || info.localClass !== undefined;
|
|
3284
4202
|
// A FAMILY has no constructor function at all (nothing constructs it;
|
|
3285
4203
|
// construction resolves to instantiations) and declares no instance
|
|
3286
4204
|
// members — only its statics lower below.
|
|
@@ -3290,12 +4208,22 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
3290
4208
|
// signature-blocked function (lowerStaticMethod's rule) instead of
|
|
3291
4209
|
// crashing the whole lowering.
|
|
3292
4210
|
if (!info.generic && (always || lowerer.wantBody(`%${className}.constructor`))) {
|
|
4211
|
+
const diagsBefore = lowerer.diags.length;
|
|
3293
4212
|
try {
|
|
3294
4213
|
out.push(lowerer.lowerClassCtor(info));
|
|
3295
4214
|
}
|
|
3296
4215
|
catch (e) {
|
|
3297
4216
|
if (!(e instanceof PoisonError))
|
|
3298
4217
|
throw e;
|
|
4218
|
+
if (info.decl && isJsSourceFile(info.decl.getSourceFile())) {
|
|
4219
|
+
const types = [{ kind: "object", className }, ...info.ctorParams.map((param) => param.type)];
|
|
4220
|
+
const fallback = lowerer.deferToRuntimeFence(diagsBefore, info.ctor ?? info.decl, {
|
|
4221
|
+
kind: "function", name: `%${className}.constructor`, returnType: VOID,
|
|
4222
|
+
params: types.map((type, index) => ({ localId: `p.${index}`, name: index === 0 ? "this" : `p${index}`, type })),
|
|
4223
|
+
});
|
|
4224
|
+
if (fallback)
|
|
4225
|
+
out.push(fallback);
|
|
4226
|
+
}
|
|
3299
4227
|
}
|
|
3300
4228
|
}
|
|
3301
4229
|
for (const { mName, member } of lowerer.classMethodMembers(info)) {
|
|
@@ -3311,13 +4239,14 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
3311
4239
|
throw e;
|
|
3312
4240
|
}
|
|
3313
4241
|
}
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
4242
|
+
if (info.staticMethods)
|
|
4243
|
+
for (const [name] of info.staticMethods) {
|
|
4244
|
+
if (!lowerer.wantBody(`%${className}.static:${name}`))
|
|
4245
|
+
continue;
|
|
4246
|
+
const fn = lowerStaticMethod(lowerer, info, name);
|
|
4247
|
+
if (fn)
|
|
4248
|
+
out.push(fn);
|
|
4249
|
+
}
|
|
3321
4250
|
for (const prop of info.throwingSetters) {
|
|
3322
4251
|
if (always || lowerer.wantBody(`%${className}.set:${prop}`))
|
|
3323
4252
|
out.push(lowerer.throwingSetterFn(info, prop));
|
|
@@ -3329,14 +4258,29 @@ export function lowerClassMembers(lowerer, info) {
|
|
|
3329
4258
|
* the base's signature — forward every param to super(), then run own
|
|
3330
4259
|
* field initializers. */
|
|
3331
4260
|
export function lowerClassCtor(lowerer, info) {
|
|
4261
|
+
const cached = info.localClass?.bodies.get(`%${info.def.name}.constructor`);
|
|
4262
|
+
if (cached)
|
|
4263
|
+
return cached;
|
|
3332
4264
|
return withInstanceBindings(lowerer, info, () => lowerClassCtorInner(lowerer, info));
|
|
3333
4265
|
}
|
|
4266
|
+
function classCaptureParams(info, context) {
|
|
4267
|
+
if (!info.localClass)
|
|
4268
|
+
return {};
|
|
4269
|
+
const environment = info.localClass.context;
|
|
4270
|
+
if (!environment)
|
|
4271
|
+
throw new InternalCompilerError("local class lowered outside its lexical environment");
|
|
4272
|
+
return { classCaptures: (context.captures ?? []).map((capture, index) => {
|
|
4273
|
+
if (!capture)
|
|
4274
|
+
throw new InternalCompilerError("missing local class capture");
|
|
4275
|
+
return { ...capture, slot: environment.captures.findIndex((entry) => entry.localId === context.captureSources[index]) };
|
|
4276
|
+
}) };
|
|
4277
|
+
}
|
|
3334
4278
|
function lowerClassCtorInner(lowerer, info) {
|
|
3335
4279
|
const className = info.def.name;
|
|
3336
4280
|
const thisType = { kind: "object", className };
|
|
3337
4281
|
const prevClass = lowerer.currentClass;
|
|
3338
4282
|
lowerer.currentClass = info;
|
|
3339
|
-
lowerer.fnStack.push(newFnCtx(
|
|
4283
|
+
lowerer.fnStack.push(newFnCtx(info.localClass !== undefined, null, null, VOID));
|
|
3340
4284
|
try {
|
|
3341
4285
|
const thisLocal = lowerer.declareThis(thisType);
|
|
3342
4286
|
const params = [{ localId: thisLocal.id, name: "this", type: thisType }];
|
|
@@ -3365,8 +4309,13 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
3365
4309
|
// defaults on entry, ahead of everything the body does.
|
|
3366
4310
|
const declared = lowerer.declareParams(info.ctor.parameters, info.ctorParams);
|
|
3367
4311
|
params.push(...declared.params);
|
|
4312
|
+
if (info.ctorParams.at(-1)?.mode === "arguments") {
|
|
4313
|
+
const local = lowerer.declareHiddenLocal("%arguments", DYN);
|
|
4314
|
+
params.push({ localId: local.id, name: local.name, type: DYN });
|
|
4315
|
+
lowerer.ctx.argumentsLocal = local;
|
|
4316
|
+
}
|
|
3368
4317
|
body.push(...declared.prologue);
|
|
3369
|
-
if (!ctorBase) {
|
|
4318
|
+
if (!ctorBase && !info.callableBase) {
|
|
3370
4319
|
// Node's base-class order: field initializers run at the start
|
|
3371
4320
|
// of construction, the parameter-property assignments open the
|
|
3372
4321
|
// constructor body (probed — a field initializer reading a
|
|
@@ -3381,7 +4330,7 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
3381
4330
|
}
|
|
3382
4331
|
}
|
|
3383
4332
|
else {
|
|
3384
|
-
if (ctorBase) {
|
|
4333
|
+
if (ctorBase || info.callableBase) {
|
|
3385
4334
|
// Synthetic forwarding params (the inherited ABI signature).
|
|
3386
4335
|
// Nothing references them by symbol — only the super call below,
|
|
3387
4336
|
// which forwards the already-completed values UNCHANGED (defaults
|
|
@@ -3411,6 +4360,7 @@ function lowerClassCtorInner(lowerer, info) {
|
|
|
3411
4360
|
params,
|
|
3412
4361
|
returnType: VOID,
|
|
3413
4362
|
locals: lowerer.ctx.locals,
|
|
4363
|
+
...classCaptureParams(info, lowerer.ctx),
|
|
3414
4364
|
body,
|
|
3415
4365
|
loc: locOf(info.ctor ?? info.decl),
|
|
3416
4366
|
};
|
|
@@ -3450,7 +4400,7 @@ export function classMemberNameOf(lowerer, name) {
|
|
|
3450
4400
|
return `sym:${member}`;
|
|
3451
4401
|
}
|
|
3452
4402
|
}
|
|
3453
|
-
return lowerer.foldedStringKeyOf(name.expression);
|
|
4403
|
+
return classSymbolKeyOf(lowerer, name.expression)?.fieldName ?? lowerer.foldedStringKeyOf(name.expression);
|
|
3454
4404
|
}
|
|
3455
4405
|
export function classIteratorOf(lowerer, t) {
|
|
3456
4406
|
if (t.kind !== "object")
|
|
@@ -3651,12 +4601,17 @@ export function classIteratorRestDrainCall(lowerer, cit, itVal, loc) {
|
|
|
3651
4601
|
* (accessors are methods with property syntax: "get:x"/"set:x" entries —
|
|
3652
4602
|
* see collectClassShape). */
|
|
3653
4603
|
export function lowerClassMethodMember(lowerer, info, fnLike) {
|
|
4604
|
+
if (info.localClass?.ready) {
|
|
4605
|
+
const member = classMemberNameOf(lowerer, fnLike.name);
|
|
4606
|
+
const name = ts.isMethodDeclaration(fnLike) ? member : `${ts.isGetAccessor(fnLike) ? "get" : "set"}:${member}`;
|
|
4607
|
+
return info.localClass.bodies.get(`%${info.def.name}.${name}`) ?? null;
|
|
4608
|
+
}
|
|
3654
4609
|
return withInstanceBindings(lowerer, info, () => lowerClassMethodMemberInner(lowerer, info, fnLike));
|
|
3655
4610
|
}
|
|
3656
4611
|
function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
3657
4612
|
const className = info.def.name;
|
|
3658
4613
|
const thisType = { kind: "object", className };
|
|
3659
|
-
const memberName =
|
|
4614
|
+
const memberName = classMemberNameOf(lowerer, fnLike.name);
|
|
3660
4615
|
if (memberName === null)
|
|
3661
4616
|
return null;
|
|
3662
4617
|
const mName = ts.isMethodDeclaration(fnLike)
|
|
@@ -3665,6 +4620,21 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
3665
4620
|
const sig = info.methods.get(mName);
|
|
3666
4621
|
if (!sig || !fnLike.body)
|
|
3667
4622
|
return null;
|
|
4623
|
+
const entryFence = info.methodEntryFences?.get(mName);
|
|
4624
|
+
if (entryFence) {
|
|
4625
|
+
lowerer.runtimeFences.push(entryFence);
|
|
4626
|
+
return lowerer.deferToRuntimeFence(lowerer.diags.length, fnLike.name, {
|
|
4627
|
+
kind: "function",
|
|
4628
|
+
name: `%${className}.${mName}`,
|
|
4629
|
+
params: [
|
|
4630
|
+
{ localId: "this.0", name: "this", type: thisType },
|
|
4631
|
+
...sig.params.map((p, i) => ({ localId: `p.${i}`, name: `p${i}`, type: p.type })),
|
|
4632
|
+
],
|
|
4633
|
+
returnType: sig.ret,
|
|
4634
|
+
fallback: entryFence,
|
|
4635
|
+
allowDiagSink: true,
|
|
4636
|
+
});
|
|
4637
|
+
}
|
|
3668
4638
|
const prevClass = lowerer.currentClass;
|
|
3669
4639
|
lowerer.currentClass = info;
|
|
3670
4640
|
// ASYNC methods: the module function is an async IrFunction — its
|
|
@@ -3674,18 +4644,16 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
3674
4644
|
// spawn's argument pack). Dispatch is static by construction — the
|
|
3675
4645
|
// override fence at collection keeps async methods out of vtables.
|
|
3676
4646
|
const isAsync = sig.async === true;
|
|
3677
|
-
//
|
|
3678
|
-
//
|
|
3679
|
-
//
|
|
3680
|
-
// never virtualize) enters through the emitted gen-spawn wrapper with
|
|
3681
|
-
// `this` in the argument pack, answering the suspended generator.
|
|
4647
|
+
// GENERATOR methods: the module function returns the TReturn channel,
|
|
4648
|
+
// yields ride ctx.generator, and direct calls enter through the emitted
|
|
4649
|
+
// gen-spawn wrapper with `this` in the argument pack.
|
|
3682
4650
|
const genCh = sig.gen !== undefined && sig.ret.kind === "generator" ? sig.gen : null;
|
|
3683
4651
|
const bodyReturn = genCh !== null
|
|
3684
4652
|
? lowerer.genBodyReturnType(sig.ret)
|
|
3685
4653
|
: isAsync && sig.ret.kind === "promise"
|
|
3686
4654
|
? sig.ret.inner
|
|
3687
4655
|
: sig.ret;
|
|
3688
|
-
const fnCtx = newFnCtx(
|
|
4656
|
+
const fnCtx = newFnCtx(info.localClass !== undefined, null, null, bodyReturn);
|
|
3689
4657
|
fnCtx.isAsync = isAsync;
|
|
3690
4658
|
if (genCh !== null)
|
|
3691
4659
|
fnCtx.generator = genCh;
|
|
@@ -3697,6 +4665,15 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
3697
4665
|
// (JS allows this in method defaults; it is param 0 here).
|
|
3698
4666
|
const declared = lowerer.declareParams(fnLike.parameters, sig.params);
|
|
3699
4667
|
params.push(...declared.params);
|
|
4668
|
+
// A shorter JS override still implements every inherited ABI slot.
|
|
4669
|
+
// These tail parameters have no source binding or default prologue.
|
|
4670
|
+
for (const shape of sig.params.slice(declared.params.length)) {
|
|
4671
|
+
const name = shape.mode === "arguments" ? "%arguments" : "%ignored";
|
|
4672
|
+
const local = lowerer.declareHiddenLocal(name, shape.type);
|
|
4673
|
+
params.push({ localId: local.id, name, type: shape.type });
|
|
4674
|
+
if (shape.mode === "arguments")
|
|
4675
|
+
fnCtx.argumentsLocal = local;
|
|
4676
|
+
}
|
|
3700
4677
|
const body = [...declared.prologue, ...lowerer.lowerStmts(fnLike.body.statements)];
|
|
3701
4678
|
appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(fnLike));
|
|
3702
4679
|
const fn = {
|
|
@@ -3704,6 +4681,7 @@ function lowerClassMethodMemberInner(lowerer, info, fnLike) {
|
|
|
3704
4681
|
params,
|
|
3705
4682
|
returnType: bodyReturn,
|
|
3706
4683
|
locals: lowerer.ctx.locals,
|
|
4684
|
+
...classCaptureParams(info, lowerer.ctx),
|
|
3707
4685
|
body,
|
|
3708
4686
|
loc: locOf(fnLike),
|
|
3709
4687
|
};
|
|
@@ -3729,18 +4707,31 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
3729
4707
|
const entry = info.staticMethods?.get(name);
|
|
3730
4708
|
if (!entry?.member.body)
|
|
3731
4709
|
return null;
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
4710
|
+
const isAsync = entry.member.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword) === true;
|
|
4711
|
+
const isGenerator = entry.member.asteriskToken !== undefined;
|
|
4712
|
+
if (isGenerator && (entry.ret.kind !== "generator" || (entry.ret.async === true) !== isAsync)) {
|
|
4713
|
+
lowerer.badType(entry.member.name, lowerer.typeOf(entry.member.name));
|
|
4714
|
+
}
|
|
4715
|
+
if (isAsync && !isGenerator && entry.ret.kind !== "promise") {
|
|
4716
|
+
lowerer.badType(entry.member.name, lowerer.typeOf(entry.member.name));
|
|
4717
|
+
}
|
|
4718
|
+
const genCh = isGenerator && entry.ret.kind === "generator" ? generatorMeta(lowerer, entry.ret) : null;
|
|
4719
|
+
const bodyReturn = genCh !== null
|
|
4720
|
+
? lowerer.genBodyReturnType(entry.ret)
|
|
4721
|
+
: isAsync && entry.ret.kind === "promise" ? entry.ret.inner : entry.ret;
|
|
3738
4722
|
const fnCtx = newFnCtx(false, null, null, bodyReturn);
|
|
3739
4723
|
fnCtx.isAsync = isAsync;
|
|
4724
|
+
if (genCh !== null)
|
|
4725
|
+
fnCtx.generator = genCh;
|
|
3740
4726
|
lowerer.fnStack.push(fnCtx);
|
|
3741
4727
|
try {
|
|
3742
4728
|
rejectStaticThis(lowerer, entry.member.body, (keyword) => `'${keyword}' in static methods (it names the RECEIVER class — a dynamic value; reference the class by name instead)`);
|
|
3743
4729
|
const declared = lowerer.declareParams(entry.member.parameters, entry.params);
|
|
4730
|
+
if (entry.params.at(-1)?.mode === "arguments") {
|
|
4731
|
+
const local = lowerer.declareHiddenLocal("%arguments", DYN);
|
|
4732
|
+
declared.params.push({ localId: local.id, name: "%arguments", type: DYN });
|
|
4733
|
+
fnCtx.argumentsLocal = local;
|
|
4734
|
+
}
|
|
3744
4735
|
const body = [...declared.prologue, ...lowerer.lowerStmts(entry.member.body.statements)];
|
|
3745
4736
|
appendImplicitUndefinedReturn(lowerer, body, bodyReturn, locOf(entry.member));
|
|
3746
4737
|
const fn = {
|
|
@@ -3753,6 +4744,8 @@ export function lowerStaticMethod(lowerer, info, name) {
|
|
|
3753
4744
|
};
|
|
3754
4745
|
if (isAsync)
|
|
3755
4746
|
fn.async = true;
|
|
4747
|
+
if (genCh !== null)
|
|
4748
|
+
fn.generator = genCh;
|
|
3756
4749
|
return fn;
|
|
3757
4750
|
}
|
|
3758
4751
|
catch (e) {
|
|
@@ -3827,10 +4820,29 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
3827
4820
|
const out = [];
|
|
3828
4821
|
const thisType = { kind: "object", className: info.def.name };
|
|
3829
4822
|
for (const f of info.fieldOrder) {
|
|
4823
|
+
if (f.errorCause) {
|
|
4824
|
+
const loc = f.initializer ? locOf(f.initializer) : f.undefinedInitializer;
|
|
4825
|
+
const value = f.initializer ? lowerer.lowerExprExpecting(f.initializer, DYN) : dynUndefinedExpr(loc);
|
|
4826
|
+
out.push({ kind: "exprStmt", expr: { kind: "libCall", fn: "error.defineCause",
|
|
4827
|
+
args: [{ kind: "varRef", localId: thisLocal.id, type: thisType, loc }, value], type: VOID, loc }, loc });
|
|
4828
|
+
continue;
|
|
4829
|
+
}
|
|
4830
|
+
if (f.undefinedInitializer) {
|
|
4831
|
+
const loc = f.undefinedInitializer;
|
|
4832
|
+
out.push({
|
|
4833
|
+
kind: "fieldSet",
|
|
4834
|
+
obj: { kind: "varRef", localId: thisLocal.id, type: thisType, loc },
|
|
4835
|
+
className: info.def.name,
|
|
4836
|
+
field: f.name,
|
|
4837
|
+
value: dynUndefinedExpr(loc),
|
|
4838
|
+
loc,
|
|
4839
|
+
});
|
|
4840
|
+
}
|
|
3830
4841
|
if (!f.initializer)
|
|
3831
4842
|
continue;
|
|
3832
4843
|
lowerer.stats.statementsTotal++;
|
|
3833
4844
|
lowerer.bumpFileStat(locOf(f.initializer).file, "total");
|
|
4845
|
+
const diagsBefore = lowerer.diags.length;
|
|
3834
4846
|
try {
|
|
3835
4847
|
const value = lowerer.lowerExprExpecting(f.initializer, f.type);
|
|
3836
4848
|
out.push({
|
|
@@ -3847,6 +4859,11 @@ export function fieldInitStmts(lowerer, info, thisLocal) {
|
|
|
3847
4859
|
throw e;
|
|
3848
4860
|
lowerer.stats.statementsFailed++;
|
|
3849
4861
|
lowerer.bumpFileStat(locOf(f.initializer).file, "failed");
|
|
4862
|
+
if (isJsSourceFile(f.initializer.getSourceFile()) && lowerer.diagSink === null) {
|
|
4863
|
+
const fence = lowerer.deferToRuntimeFence(diagsBefore, f.initializer, { kind: "statement" });
|
|
4864
|
+
if (fence)
|
|
4865
|
+
out.push(fence);
|
|
4866
|
+
}
|
|
3850
4867
|
}
|
|
3851
4868
|
}
|
|
3852
4869
|
return out;
|
|
@@ -3882,80 +4899,93 @@ function paramPropInitStmts(lowerer, info, thisLocal) {
|
|
|
3882
4899
|
}
|
|
3883
4900
|
return out;
|
|
3884
4901
|
}
|
|
3885
|
-
/**
|
|
3886
|
-
*
|
|
3887
|
-
*
|
|
3888
|
-
|
|
3889
|
-
* guarantees a super call exists and runs before any this-use; the
|
|
3890
|
-
* supported form is a top-level expression statement — anywhere else
|
|
3891
|
-
* (conditionals, expression positions) is rejected, not misordered. */
|
|
3892
|
-
export function lowerDerivedCtorBody(lowerer, info, thisLocal,
|
|
3893
|
-
/** Mixin forwarding-constructor mode: `super(...args)` forwards these
|
|
3894
|
-
* pre-declared synthetic params directly (the spread never lowers —
|
|
3895
|
-
* the base's ABI is this constructor's ABI). */
|
|
3896
|
-
forward) {
|
|
3897
|
-
const out = [];
|
|
4902
|
+
/** Super statements initialize the base and then the derived fields on
|
|
4903
|
+
* whichever control-flow path executes. Repeated calls are explicitly
|
|
4904
|
+
* refused until native layouts can allocate a second receiver. */
|
|
4905
|
+
export function lowerDerivedCtorBody(lowerer, info, thisLocal, forward) {
|
|
3898
4906
|
let superSeen = false;
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
4907
|
+
const initialized = lowerer.declareHiddenLocal("%superInitialized", BOOL);
|
|
4908
|
+
initialized.mutable = true;
|
|
4909
|
+
const context = lowerer.ctx;
|
|
4910
|
+
const previous = context.superCall;
|
|
4911
|
+
const previousInitialized = context.superInitialized;
|
|
4912
|
+
context.superInitialized = initialized;
|
|
4913
|
+
context.superCall = (superCall) => {
|
|
4914
|
+
if (!ts.isExpressionStatement(superCall.parent))
|
|
4915
|
+
lowerer.unsupported("SC1090", superCall, "super() in an expression position");
|
|
4916
|
+
superSeen = true;
|
|
4917
|
+
const loc = locOf(superCall);
|
|
4918
|
+
const statements = [{ kind: "if", cond: { kind: "varRef", localId: initialized.id, type: BOOL, loc }, then: [{ kind: "exprStmt", expr: nodeThrowExpr(0, "SC2020", "repeated super() calls require a fresh receiver and are not supported yet", DYN, loc), loc }], else_: null, loc }];
|
|
4919
|
+
if (info.callableBase) {
|
|
4920
|
+
if (superCall.arguments.some(ts.isSpreadElement))
|
|
4921
|
+
lowerer.unsupported("SC1090", superCall, "spreading explicit super arguments into an ordinary constructor");
|
|
4922
|
+
const pack = { kind: "dynArrLit", elems: superCall.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
|
|
4923
|
+
statements.push(lowerer.superCallStmt(info, thisLocal, [pack], loc));
|
|
3908
4924
|
}
|
|
3909
|
-
|
|
3910
|
-
lowerer.stats.statementsTotal++;
|
|
3911
|
-
lowerer.bumpFileStat(locOf(stmt).file, "total");
|
|
3912
|
-
}
|
|
3913
|
-
try {
|
|
3914
|
-
if (superSeen)
|
|
3915
|
-
lowerer.unsupported("SC1090", stmt, "multiple super() calls");
|
|
3916
|
-
superSeen = true;
|
|
4925
|
+
else {
|
|
3917
4926
|
const base = superBaseOf(info);
|
|
3918
|
-
if (base.builtinEmitter && superCall.arguments.length > 0)
|
|
3919
|
-
// @types/node admits super({ captureRejections }) — no lowering.
|
|
4927
|
+
if (base.builtinEmitter && superCall.arguments.length > 0)
|
|
3920
4928
|
lowerer.unsupported("SC1090", superCall, "EventEmitter constructor options ('captureRejections')");
|
|
3921
|
-
}
|
|
3922
4929
|
if (base.builtinStream) {
|
|
3923
|
-
|
|
3924
|
-
// parses the options and binds overridden underscore methods.
|
|
3925
|
-
out.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, locOf(stmt), stmt));
|
|
3926
|
-
out.push(...lowerer.fieldInitStmts(info, thisLocal));
|
|
3927
|
-
out.push(...paramPropInitStmts(lowerer, info, thisLocal));
|
|
3928
|
-
continue;
|
|
4930
|
+
statements.push(...lowerStreamSuperCall(lowerer, info, base, superCall.arguments, thisLocal, loc, superCall));
|
|
3929
4931
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
:
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
4932
|
+
else {
|
|
4933
|
+
const surplusSpread = forward === undefined && !base.builtinError && !base.builtinEmitter &&
|
|
4934
|
+
base.ctorParams.length === 0 && superCall.arguments.some(ts.isSpreadElement);
|
|
4935
|
+
if (surplusSpread) {
|
|
4936
|
+
const evaluated = lowerer.completeArgs(superCall.arguments, [{ mode: "dynRest", type: DYN }], loc, superCall);
|
|
4937
|
+
for (const value of evaluated)
|
|
4938
|
+
statements.push({ kind: "exprStmt", expr: value, loc });
|
|
4939
|
+
}
|
|
4940
|
+
const surplus = forward === undefined && !base.builtinError && !base.builtinEmitter &&
|
|
4941
|
+
!base.ctorParams.some((param) => param.mode === "rest" || param.mode === "dynRest" || param.mode === "islandRest") &&
|
|
4942
|
+
!superCall.arguments.some(ts.isSpreadElement) && superCall.arguments.length > base.ctorParams.length;
|
|
4943
|
+
let args = surplusSpread ? [] : forward !== undefined ? forward : base.builtinError
|
|
4944
|
+
? lowerer.errorConstructorArgs(superCall.arguments, loc, superCall) : base.builtinEmitter ? []
|
|
4945
|
+
: lowerer.completeArgs(surplus ? superCall.arguments.slice(0, base.ctorParams.length) : superCall.arguments, base.ctorParams, loc, superCall);
|
|
4946
|
+
if (surplus) {
|
|
4947
|
+
args = args.map((arg) => {
|
|
4948
|
+
const local = lowerer.declareHiddenLocal("%superArgument", arg.type);
|
|
4949
|
+
statements.push({ kind: "varDecl", localId: local.id, init: arg, loc });
|
|
4950
|
+
return { kind: "varRef", localId: local.id, type: arg.type, loc };
|
|
4951
|
+
});
|
|
4952
|
+
for (const argument of superCall.arguments.slice(base.ctorParams.length)) {
|
|
4953
|
+
statements.push({ kind: "exprStmt", expr: lowerer.lowerExpr(argument), loc: locOf(argument) });
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4956
|
+
statements.push(lowerer.superCallStmt(info, thisLocal, args, loc));
|
|
3949
4957
|
}
|
|
3950
4958
|
}
|
|
4959
|
+
statements.push({ kind: "assign", localId: initialized.id, value: { kind: "boolLit", value: true, type: BOOL, loc }, loc });
|
|
4960
|
+
delete context.superInitialized;
|
|
4961
|
+
try {
|
|
4962
|
+
statements.push(...lowerer.fieldInitStmts(info, thisLocal), ...paramPropInitStmts(lowerer, info, thisLocal));
|
|
4963
|
+
}
|
|
4964
|
+
finally {
|
|
4965
|
+
context.superInitialized = initialized;
|
|
4966
|
+
}
|
|
4967
|
+
const result = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
|
|
4968
|
+
return { kind: "seqExpr", stmts: statements.map((statement) => statement.kind === "runtimeFence"
|
|
4969
|
+
? { kind: "exprStmt", expr: nodeThrowExpr(0, statement.code, statement.message, DYN, statement.loc), loc: statement.loc }
|
|
4970
|
+
: statement), result, type: result.type, loc };
|
|
4971
|
+
};
|
|
4972
|
+
try {
|
|
4973
|
+
const result = lowerer.lowerStmts(info.ctor.body.statements);
|
|
4974
|
+
result.push({ kind: "if", cond: { kind: "unary", op: "!", operand: { kind: "varRef", localId: initialized.id, type: BOOL, loc: locOf(info.ctor) }, type: BOOL, loc: locOf(info.ctor) }, then: [{ kind: "exprStmt", expr: nodeThrowExpr(5, "", "Must call super constructor in derived class before accessing 'this' or returning from derived constructor", DYN, locOf(info.ctor)), loc: locOf(info.ctor) }], else_: null, loc: locOf(info.ctor) });
|
|
4975
|
+
if (!superSeen)
|
|
4976
|
+
lowerer.pushDiag(unsupportedDiag("SC1090", locOf(info.ctor), "derived constructors without a lowered super() call"));
|
|
4977
|
+
return [{ kind: "varDecl", localId: initialized.id, init: { kind: "boolLit", value: false, type: BOOL, loc: locOf(info.ctor) }, loc: locOf(info.ctor) }, ...result];
|
|
3951
4978
|
}
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
4979
|
+
finally {
|
|
4980
|
+
if (previous)
|
|
4981
|
+
context.superCall = previous;
|
|
4982
|
+
else
|
|
4983
|
+
delete context.superCall;
|
|
4984
|
+
if (previousInitialized)
|
|
4985
|
+
context.superInitialized = previousInitialized;
|
|
4986
|
+
else
|
|
4987
|
+
delete context.superInitialized;
|
|
3957
4988
|
}
|
|
3958
|
-
return out;
|
|
3959
4989
|
}
|
|
3960
4990
|
/** `super(args)` → direct call of the base constructor with the SAME
|
|
3961
4991
|
* `this` (upcast; retained by the varRef read — the callee owns and
|
|
@@ -3968,6 +4998,15 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
3968
4998
|
type: { kind: "object", className: info.def.name },
|
|
3969
4999
|
loc,
|
|
3970
5000
|
};
|
|
5001
|
+
if (info.callableBase)
|
|
5002
|
+
return {
|
|
5003
|
+
kind: "exprStmt", expr: { kind: "libCall", fn: "dyn.classSuper",
|
|
5004
|
+
args: [info.localClass ? { kind: "libCall", fn: "dyn.getPrototype", args: [
|
|
5005
|
+
{ kind: "dynFrom", value: { kind: "fieldGet", obj: thisRef, className: info.def.name,
|
|
5006
|
+
field: `%classEnvironment:${info.def.name}`, type: { kind: "classval", className: info.def.name }, loc }, type: DYN, loc },
|
|
5007
|
+
], type: DYN, loc } : { kind: "varRef", localId: info.callableBase.constructorId, type: DYN, loc },
|
|
5008
|
+
lowerer.coerceToExpected(thisRef, DYN), args[0]], type: VOID, loc }, loc,
|
|
5009
|
+
};
|
|
3971
5010
|
if (base.builtinError) {
|
|
3972
5011
|
// super(message) into the runtime-provided Error constructor: stamps
|
|
3973
5012
|
// name/message on the (already-allocated) object. Receiver + message
|
|
@@ -3977,7 +5016,7 @@ export function superCallStmt(lowerer, info, thisLocal, args, loc) {
|
|
|
3977
5016
|
kind: "exprStmt",
|
|
3978
5017
|
expr: {
|
|
3979
5018
|
kind: "libCall",
|
|
3980
|
-
fn: "error.
|
|
5019
|
+
fn: "error.ctorOptions",
|
|
3981
5020
|
args: [lowerer.upcastTo(thisRef, base.def.name), ...args],
|
|
3982
5021
|
type: VOID,
|
|
3983
5022
|
loc,
|
|
@@ -4081,9 +5120,22 @@ export function lowerSuperMethodCall(lowerer, call, access) {
|
|
|
4081
5120
|
const thisLocal = lowerer.resolveThis();
|
|
4082
5121
|
if (!thisLocal)
|
|
4083
5122
|
lowerer.unsupported("SC1080", access);
|
|
4084
|
-
lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
|
|
4085
5123
|
const loc = locOf(call);
|
|
4086
5124
|
const thisRef = { kind: "varRef", localId: thisLocal.id, type: thisLocal.type, loc };
|
|
5125
|
+
if (lowerer.prototypeMethodAccesses.has(access.name.text)) {
|
|
5126
|
+
const prototype = classPrototypeData(lowerer, cls.base, loc);
|
|
5127
|
+
if (prototype) {
|
|
5128
|
+
const callee = { kind: "dynKeyGet", value: prototype,
|
|
5129
|
+
key: { kind: "strLit", value: access.name.text, type: STRING, loc }, type: DYN, loc };
|
|
5130
|
+
const value = { kind: "dynCall", callee, receiver: lowerer.coerceToExpected(thisRef, DYN),
|
|
5131
|
+
calleeName: access.getText(), args: call.arguments.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc };
|
|
5132
|
+
return found.sig.ret.kind === "void" ? value : lowerer.coerceToExpected(value, found.sig.ret);
|
|
5133
|
+
}
|
|
5134
|
+
}
|
|
5135
|
+
if (found.declarer.builtinError) {
|
|
5136
|
+
return { kind: "libCall", fn: "error.toString", args: [lowerer.upcastTo(thisRef, "%Error")], type: STRING, loc };
|
|
5137
|
+
}
|
|
5138
|
+
lowerer.noteEdge(`%${found.declarer.def.name}.${access.name.text}`);
|
|
4087
5139
|
const args = lowerer.completeArgs(call.arguments, found.sig.params, loc, call);
|
|
4088
5140
|
return {
|
|
4089
5141
|
kind: "call",
|
|
@@ -4163,8 +5215,8 @@ export function lowerSuperAccessorWrite(lowerer, access, rhs, loc) {
|
|
|
4163
5215
|
}
|
|
4164
5216
|
/** True when `info`'s EFFECTIVE constructor — its own, or the one
|
|
4165
5217
|
* inherited through ctor-less bases — is a builtin error class's. Such
|
|
4166
|
-
* classes construct with the error
|
|
4167
|
-
* constructors forward
|
|
5218
|
+
* classes construct with the error argument rule, and their synthesized
|
|
5219
|
+
* constructors forward both checked-dynamic values to error.ctorOptions. */
|
|
4168
5220
|
export function inheritsBuiltinErrorCtor(lowerer, info) {
|
|
4169
5221
|
for (let c = info; c; c = c.base) {
|
|
4170
5222
|
if (c.builtinError)
|
|
@@ -4201,25 +5253,18 @@ function inheritsBuiltinStreamCtor(lowerer, info) {
|
|
|
4201
5253
|
}
|
|
4202
5254
|
return false;
|
|
4203
5255
|
}
|
|
4204
|
-
/**
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
const value = lowerer.lowerExpr(args[0]);
|
|
4217
|
-
if (value.type.kind === "string")
|
|
4218
|
-
return value;
|
|
4219
|
-
if (value.kind === "unitLit" && value.unit === "undefined") {
|
|
4220
|
-
return { kind: "strLit", value: "", type: STRING, loc };
|
|
4221
|
-
}
|
|
4222
|
-
lowerer.unsupported("SC1090", args[0], `Error messages of type '${lowerer.fmt(value.type)}' (the message must be a string)`);
|
|
5256
|
+
/** Preserve argument evaluation order and option presence through builtin
|
|
5257
|
+
* and inherited Error constructors. Checked-dynamic conversion retains
|
|
5258
|
+
* Error identity and distinguishes a missing cause from undefined. */
|
|
5259
|
+
export function errorConstructorArgs(lowerer, args, loc, blame) {
|
|
5260
|
+
if (args.length > 2)
|
|
5261
|
+
lowerer.unsupported("SC1090", blame, "Error constructors with more than two arguments");
|
|
5262
|
+
return [0, 1].map((i) => {
|
|
5263
|
+
const arg = args[i];
|
|
5264
|
+
if (!arg)
|
|
5265
|
+
return dynUndefinedExpr(loc);
|
|
5266
|
+
return lowerer.lowerExprExpecting(arg, DYN);
|
|
5267
|
+
});
|
|
4223
5268
|
}
|
|
4224
5269
|
/** `new C(...)` of a registered PROGRAM class — the shared tail of the
|
|
4225
5270
|
* identifier and namespace-qualified construction forms. */
|
|
@@ -4252,6 +5297,8 @@ function fenceDecorationThrows(lowerer, info, blame) {
|
|
|
4252
5297
|
function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
|
|
4253
5298
|
const info = genericNewTarget(lowerer, expr, declaredInfo);
|
|
4254
5299
|
fenceDecorationThrows(lowerer, info, expr);
|
|
5300
|
+
if (info.localClass)
|
|
5301
|
+
lowerer.unsupported("SC1090", expr, "construction through a function-local class's internal name");
|
|
4255
5302
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
4256
5303
|
// A ctor-less chain into an EventEmitter base inherits `new C()` —
|
|
4257
5304
|
// zero arguments (the options bag fences, like the super() form).
|
|
@@ -4263,12 +5310,16 @@ function lowerProgramClassNew(lowerer, expr, declaredInfo, loc) {
|
|
|
4263
5310
|
if (lowerer.inheritsBuiltinEmitterCtor(info) && (expr.arguments ?? []).length > 0) {
|
|
4264
5311
|
lowerer.unsupported("SC1090", expr.arguments[0], "EventEmitter constructor options ('captureRejections')");
|
|
4265
5312
|
}
|
|
4266
|
-
// A ctor-less chain into a builtin error base inherits
|
|
4267
|
-
//
|
|
4268
|
-
// not the general ABI completion.
|
|
5313
|
+
// A ctor-less chain into a builtin error base inherits both arguments;
|
|
5314
|
+
// each synthesized constructor forwards the same pair to its base.
|
|
4269
5315
|
const args = lowerer.inheritsBuiltinErrorCtor(info)
|
|
4270
|
-
?
|
|
5316
|
+
? lowerer.errorConstructorArgs(expr.arguments ?? [], loc, expr)
|
|
4271
5317
|
: lowerer.completeArgs(expr.arguments ?? [], info.ctorParams, loc, expr);
|
|
5318
|
+
for (let current = info; current; current = current.base) {
|
|
5319
|
+
if (current.def.baseValueGlobal)
|
|
5320
|
+
return { kind: "newValue", callee: classValueRef(lowerer, info, expr),
|
|
5321
|
+
args, type: { kind: "object", className: info.def.name }, loc };
|
|
5322
|
+
}
|
|
4272
5323
|
return {
|
|
4273
5324
|
kind: "new",
|
|
4274
5325
|
className: info.def.name,
|
|
@@ -4290,6 +5341,68 @@ function assignedThisFieldType(lowerer, expr) {
|
|
|
4290
5341
|
}
|
|
4291
5342
|
export function lowerNew(lowerer, expr) {
|
|
4292
5343
|
const loc = locOf(expr);
|
|
5344
|
+
const instanceConstructor = lowerInstanceConstructorNew(lowerer, expr);
|
|
5345
|
+
if (instanceConstructor)
|
|
5346
|
+
return instanceConstructor;
|
|
5347
|
+
const objectFactory = lowerObjectFactoryNew(lowerer, expr);
|
|
5348
|
+
if (objectFactory)
|
|
5349
|
+
return objectFactory;
|
|
5350
|
+
if (ts.isIdentifier(expr.expression)) {
|
|
5351
|
+
const symbol = lowerer.resolveValueSymbol(expr.expression);
|
|
5352
|
+
const declaration = symbol && lowerer.checker.declarationsOf(symbol).find((node) => ts.isFunctionDeclaration(node) && node.body !== undefined);
|
|
5353
|
+
if (declaration && ts.isFunctionDeclaration(declaration) && declaration.body) {
|
|
5354
|
+
const last = declaration.body.statements.at(-1);
|
|
5355
|
+
if (last && ts.isReturnStatement(last) && last.expression && ts.isObjectLiteralExpression(last.expression)) {
|
|
5356
|
+
lowerer.unsupported("SC1090", expr, "object-returning constructors that observe this or return mixed primitive/object values");
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
}
|
|
5360
|
+
let selected = expr.expression;
|
|
5361
|
+
while (ts.isParenthesizedExpression(selected))
|
|
5362
|
+
selected = selected.expression;
|
|
5363
|
+
if (ts.isConditionalExpression(selected)) {
|
|
5364
|
+
const yes = exactClassOfReceiver(lowerer, selected.whenTrue);
|
|
5365
|
+
const no = exactClassOfReceiver(lowerer, selected.whenFalse);
|
|
5366
|
+
if (yes && no && !yes.classDecorators && !no.classDecorators) {
|
|
5367
|
+
const yesType = { kind: "object", className: yes.def.name };
|
|
5368
|
+
const noType = { kind: "object", className: no.def.name };
|
|
5369
|
+
const type = yes === no ? yesType : { kind: "union", unionId: lowerer.unions.intern([yesType, noType].sort((a, b) => typeKey(a) < typeKey(b) ? -1 : 1)) };
|
|
5370
|
+
return { kind: "ternary", cond: lowerer.lowerCondition(selected.condition),
|
|
5371
|
+
then: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, yes, loc), type),
|
|
5372
|
+
else_: lowerer.coerceInto(expr, lowerProgramClassNew(lowerer, expr, no, loc), type), type, loc };
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
if (ts.isPropertyAccessExpression(expr.expression) && expr.expression.name.text === "Segmenter" &&
|
|
5376
|
+
lowerer.isStdlibGlobal(expr.expression.expression, "Intl")) {
|
|
5377
|
+
const args = expr.arguments ?? [];
|
|
5378
|
+
const undefinedArg = (arg) => (lowerer.typeOf(arg).flags & ts.TypeFlags.Undefined) !== 0;
|
|
5379
|
+
if (args.length > 2 || (args[0] && !undefinedArg(args[0]))) {
|
|
5380
|
+
lowerer.noLowering("Intl.Segmenter locale negotiation", expr, "omit the locale or pass undefined for default Unicode grapheme segmentation");
|
|
5381
|
+
}
|
|
5382
|
+
const options = args[1];
|
|
5383
|
+
if (options && !undefinedArg(options) &&
|
|
5384
|
+
!(ts.isObjectLiteralExpression(options) && options.properties.every((property) => ts.isPropertyAssignment(property) &&
|
|
5385
|
+
(ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) && property.name.text === "granularity" &&
|
|
5386
|
+
ts.isStringLiteral(property.initializer) && property.initializer.text === "grapheme"))) {
|
|
5387
|
+
lowerer.noLowering("Intl.Segmenter options", options, 'the native segmenter supports default options and { granularity: "grapheme" }; word and sentence segmentation remain unsupported');
|
|
5388
|
+
}
|
|
5389
|
+
// Explicit undefined expressions can carry effects; retain argument order.
|
|
5390
|
+
const stmts = args.map((arg) => {
|
|
5391
|
+
const value = lowerer.lowerExpr(arg);
|
|
5392
|
+
return { kind: "exprStmt", expr: value.type.kind === "void" ? value : lowerer.coerceInto(arg, value, DYN), loc: locOf(arg) };
|
|
5393
|
+
});
|
|
5394
|
+
const result = { kind: "libCall", fn: "intl.segmenterNew", args: [], type: DYN, loc };
|
|
5395
|
+
return stmts.length ? { kind: "seqExpr", stmts, result, type: DYN, loc } : result;
|
|
5396
|
+
}
|
|
5397
|
+
const consoleCtor = ts.isIdentifier(expr.expression)
|
|
5398
|
+
? lowerer.builtinImportOf(expr.expression)
|
|
5399
|
+
: ts.isPropertyAccessExpression(expr.expression) &&
|
|
5400
|
+
lowerer.builtinNamespaceModuleOf(expr.expression.expression) === "console"
|
|
5401
|
+
? { module: "console", member: expr.expression.name.text }
|
|
5402
|
+
: null;
|
|
5403
|
+
if (consoleCtor?.module === "console" && consoleCtor.member === "Console") {
|
|
5404
|
+
lowerer.noLowering("new console.Console", expr, builtinFenceHintOf("console", "Console"));
|
|
5405
|
+
}
|
|
4293
5406
|
// `new X(...)` where X is a package-declared class, in a static build:
|
|
4294
5407
|
// the per-package requires-dynamic diagnostic (the constructor runs in
|
|
4295
5408
|
// the embedded engine). Under --dynamic, X is jsval-typed and lowers
|
|
@@ -4356,9 +5469,11 @@ export function lowerNew(lowerer, expr) {
|
|
|
4356
5469
|
if (info?.classDecorators?.valueGlobalId !== undefined) {
|
|
4357
5470
|
lowerer.unsupported("SC1090", expr, "constructing a decorated class through a qualified name (a replacing decorator rebinds the class name — construct through the bare name)");
|
|
4358
5471
|
}
|
|
4359
|
-
if (info)
|
|
5472
|
+
if (info && !info.localClass)
|
|
4360
5473
|
return lowerProgramClassNew(lowerer, expr, info, loc);
|
|
4361
|
-
|
|
5474
|
+
// A namespace export can hold a class returned by a factory.
|
|
5475
|
+
// Let the class-value path below preserve that constructor's
|
|
5476
|
+
// lexical environment instead of requiring a class declaration.
|
|
4362
5477
|
}
|
|
4363
5478
|
// `new B.C()` where B is an AMBIENT namespace (fundule merges
|
|
4364
5479
|
// included): Node evaluates the callee first and throws
|
|
@@ -4381,7 +5496,7 @@ export function lowerNew(lowerer, expr) {
|
|
|
4381
5496
|
// member-export symbol's; the class collects on demand (a body
|
|
4382
5497
|
// lowering ahead of the assignment statement).
|
|
4383
5498
|
if (!expr.expression.questionDotToken &&
|
|
4384
|
-
((isCjsJsFile(expr.getSourceFile()) &&
|
|
5499
|
+
((isCjsJsFile(expr.getSourceFile(), lowerer.program) &&
|
|
4385
5500
|
(isModuleExportsAccess(expr.expression.expression) ||
|
|
4386
5501
|
(ts.isIdentifier(expr.expression.expression) &&
|
|
4387
5502
|
expr.expression.expression.text === "exports" &&
|
|
@@ -4444,12 +5559,20 @@ export function lowerNew(lowerer, expr) {
|
|
|
4444
5559
|
if (agent)
|
|
4445
5560
|
return agent;
|
|
4446
5561
|
}
|
|
4447
|
-
if (ts.isIdentifier(expr.expression))
|
|
5562
|
+
if (ts.isIdentifier(expr.expression) || ts.isPropertyAccessExpression(expr.expression) && ts.isIdentifier(expr.expression.name) &&
|
|
5563
|
+
lowerer.isStdlibGlobal(expr.expression.expression, "globalThis")) {
|
|
4448
5564
|
// `import C = N.C; new C()` — the alias's own source-order guards
|
|
4449
5565
|
// (a no-op for every non-import= binding).
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
5566
|
+
if (ts.isIdentifier(expr.expression))
|
|
5567
|
+
fenceEarlyAliasUse(lowerer, expr.expression, expr);
|
|
5568
|
+
const identifier = ts.isIdentifier(expr.expression) ? expr.expression : expr.expression.name;
|
|
5569
|
+
const symbol = ts.isIdentifier(identifier) ? lowerer.resolveValueSymbol(identifier) : null;
|
|
5570
|
+
if (ts.isIdentifier(identifier) && lowerer.isStdlibGlobal(identifier, "Array")) {
|
|
5571
|
+
return lowerArrayConstructor(lowerer, expr, expr.arguments ?? []);
|
|
5572
|
+
}
|
|
5573
|
+
if (isNativeProxyInitializer(lowerer, expr))
|
|
5574
|
+
return lowerNativeProxy(lowerer, expr);
|
|
5575
|
+
// `new Error(msg?)` and its standard subclasses: the
|
|
4453
5576
|
// runtime-provided classes construct through one libCall — the result
|
|
4454
5577
|
// TYPE names which builtin, and the message completes to "" exactly
|
|
4455
5578
|
// like Node's message property default.
|
|
@@ -4487,11 +5610,11 @@ export function lowerNew(lowerer, expr) {
|
|
|
4487
5610
|
};
|
|
4488
5611
|
}
|
|
4489
5612
|
if (errInfo) {
|
|
4490
|
-
const
|
|
5613
|
+
const args = lowerer.errorConstructorArgs(expr.arguments ?? [], loc, expr);
|
|
4491
5614
|
return {
|
|
4492
5615
|
kind: "libCall",
|
|
4493
|
-
fn: "error.
|
|
4494
|
-
args
|
|
5616
|
+
fn: "error.newOptions",
|
|
5617
|
+
args,
|
|
4495
5618
|
type: { kind: "object", className: errInfo.def.name },
|
|
4496
5619
|
loc,
|
|
4497
5620
|
};
|
|
@@ -4519,25 +5642,40 @@ export function lowerNew(lowerer, expr) {
|
|
|
4519
5642
|
return lowerStreamNew(lowerer, expr, streamInfo);
|
|
4520
5643
|
// `new URL(input)`: the WHATWG URL class (stdlib/@types provenance —
|
|
4521
5644
|
// a user's own `class URL` resolves through classBySymbol below).
|
|
4522
|
-
//
|
|
4523
|
-
// ("Invalid URL"), like Node. The lib's base-argument form
|
|
4524
|
-
// typechecks and is fenced here.
|
|
5645
|
+
// Invalid input or base throws a catchable TypeError ("Invalid URL").
|
|
4525
5646
|
// `new RegExp(pattern, flags?)`: runtime construction over the same
|
|
4526
5647
|
// libregexp engine the literals ride. The pattern compiles EAGERLY,
|
|
4527
5648
|
// so bad input throws Node's catchable SyntaxError at construction.
|
|
4528
|
-
//
|
|
4529
|
-
// form keeps the fence).
|
|
5649
|
+
// Checked arguments retain native regexes and perform runtime coercion.
|
|
4530
5650
|
if (symbol && symbol.name === "RegExp" && lowerer.isStdlibSymbol(symbol)) {
|
|
4531
5651
|
const args = expr.arguments ?? [];
|
|
4532
5652
|
if (args.length > 2) {
|
|
4533
5653
|
lowerer.noLowering(`new RegExp with ${args.length} arguments`, expr);
|
|
4534
5654
|
}
|
|
5655
|
+
if (args.some(ts.isSpreadElement))
|
|
5656
|
+
lowerer.noLowering("new RegExp with spread arguments", expr);
|
|
5657
|
+
const values = args.map((arg) => lowerer.lowerExpr(arg));
|
|
5658
|
+
if (values.some((value) => value.type.kind === "dyn" || value.type.kind === "regex")) {
|
|
5659
|
+
const checked = [0, 1].map((index) => values[index]
|
|
5660
|
+
? lowerer.coerceInto(args[index], values[index], DYN)
|
|
5661
|
+
: { kind: "dynFrom", value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: DYN, loc });
|
|
5662
|
+
return { kind: "libCall", fn: "regex.newChecked", args: checked, type: { kind: "regex" }, loc };
|
|
5663
|
+
}
|
|
4535
5664
|
const strArg = (a, what) => {
|
|
4536
5665
|
if (!a)
|
|
4537
5666
|
return { kind: "strLit", value: "", type: STRING, loc };
|
|
4538
|
-
const v =
|
|
5667
|
+
const v = values[args.indexOf(a)];
|
|
5668
|
+
const empty = { kind: "strLit", value: "", type: STRING, loc };
|
|
5669
|
+
if (v.type.kind === "undefinedT") {
|
|
5670
|
+
if (v.kind === "unitLit")
|
|
5671
|
+
return empty;
|
|
5672
|
+
return { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: lowerer.coerceToExpected(v, DYN), loc: locOf(a) }], result: empty, type: STRING, loc };
|
|
5673
|
+
}
|
|
5674
|
+
if (v.type.kind === "union" && lowerer.unions.get(v.type.unionId)?.arms.every((arm) => arm.kind === "string" || arm.kind === "undefinedT")) {
|
|
5675
|
+
return { kind: "nullish", left: v, right: empty, type: STRING, loc: locOf(a) };
|
|
5676
|
+
}
|
|
4539
5677
|
if (v.type.kind !== "string") {
|
|
4540
|
-
lowerer.noLowering(`new RegExp with a '${lowerer.fmt(v.type)}' ${what}`, a, "string arguments are the lowered form (a RegExp copy or ToString coercion has no lowering)");
|
|
5678
|
+
lowerer.noLowering(`new RegExp with a '${lowerer.fmt(v.type)}' ${what}`, a, "string or undefined arguments are the lowered form (a RegExp copy or ToString coercion has no lowering)");
|
|
4541
5679
|
}
|
|
4542
5680
|
return v;
|
|
4543
5681
|
};
|
|
@@ -4546,25 +5684,7 @@ export function lowerNew(lowerer, expr) {
|
|
|
4546
5684
|
return { kind: "libCall", fn: "regex.new", args: [pattern, flags], type: { kind: "regex" }, loc };
|
|
4547
5685
|
}
|
|
4548
5686
|
if (symbol && symbol.name === "URL" && lowerer.isStdlibSymbol(symbol)) {
|
|
4549
|
-
|
|
4550
|
-
if (args.length === 2) {
|
|
4551
|
-
const folded = staticForkString(lowerer.program, expr);
|
|
4552
|
-
if (folded === null) {
|
|
4553
|
-
lowerer.noLowering("new URL with a runtime-valued base", expr, "a relative literal or statically resolvable template against import.meta.url compiles", symbol);
|
|
4554
|
-
}
|
|
4555
|
-
return {
|
|
4556
|
-
kind: "libCall",
|
|
4557
|
-
fn: "url.new",
|
|
4558
|
-
args: [{ kind: "strLit", value: folded, type: STRING, loc }],
|
|
4559
|
-
type: URL_T,
|
|
4560
|
-
loc,
|
|
4561
|
-
};
|
|
4562
|
-
}
|
|
4563
|
-
if (args.length !== 1) {
|
|
4564
|
-
lowerer.noLowering(`new URL with ${args.length} argument${args.length === 1 ? "" : "s"}`, expr, "one absolute-URL string, or a static relative input against import.meta.url, is supported", symbol);
|
|
4565
|
-
}
|
|
4566
|
-
const input = lowerer.lowerExprExpecting(args[0], STRING);
|
|
4567
|
-
return { kind: "libCall", fn: "url.new", args: [input], type: URL_T, loc };
|
|
5687
|
+
return lowerUrlNew(lowerer, expr);
|
|
4568
5688
|
}
|
|
4569
5689
|
// `new URLSearchParams(init?)`: the WHATWG list (stdlib provenance —
|
|
4570
5690
|
// see lowerSearchParamsNew for the lowered init shapes).
|
|
@@ -4580,6 +5700,11 @@ export function lowerNew(lowerer, expr) {
|
|
|
4580
5700
|
if (args.some(ts.isSpreadElement) || args.length > 1) {
|
|
4581
5701
|
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);
|
|
4582
5702
|
}
|
|
5703
|
+
if (isJsSourceFile(expr.getSourceFile())) {
|
|
5704
|
+
return { kind: "libCall", fn: "date.nativeNew", args: [
|
|
5705
|
+
{ kind: "dynArrLit", elems: args.map((arg) => lowerer.lowerExprExpecting(arg, DYN)), type: DYN, loc },
|
|
5706
|
+
], type: DYN, loc };
|
|
5707
|
+
}
|
|
4583
5708
|
if (args.length === 0) {
|
|
4584
5709
|
return { kind: "libCall", fn: "date.newNow", args: [], type: DATE_T, loc };
|
|
4585
5710
|
}
|
|
@@ -4620,14 +5745,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
4620
5745
|
loc,
|
|
4621
5746
|
};
|
|
4622
5747
|
}
|
|
4623
|
-
// Encoder objects likewise never exist: lowerTextCodecCall claims
|
|
4624
|
-
// composed calls before the receiver lowers, while the same-scope
|
|
4625
|
-
// const store-then-call declaration is erased before reaching here.
|
|
4626
5748
|
if (symbol && (symbol.name === "TextDecoder" || symbol.name === "TextEncoder") && lowerer.isStdlibSymbol(symbol)) {
|
|
4627
|
-
lowerer
|
|
4628
|
-
(symbol.name === "TextDecoder"
|
|
4629
|
-
? "new TextDecoder().decode(bytes)"
|
|
4630
|
-
: "new TextEncoder().encode(s)"), symbol);
|
|
5749
|
+
return lowerTextCodecNew(lowerer, expr, symbol.name);
|
|
4631
5750
|
}
|
|
4632
5751
|
// `new Uint8Array(...)` / `new Uint32Array(...)` / `new
|
|
4633
5752
|
// Float32Array(...)` / `new Float64Array(...)`: the typed-array
|
|
@@ -4646,7 +5765,7 @@ export function lowerNew(lowerer, expr) {
|
|
|
4646
5765
|
// A rebindable decorated name constructs through its VALUE (the
|
|
4647
5766
|
// classval-typed path below — newValue through the decoration
|
|
4648
5767
|
// result's construct thunk), never the declaration directly.
|
|
4649
|
-
if (info && info.classDecorators?.valueGlobalId === undefined) {
|
|
5768
|
+
if (info && !info.localClass && info.classDecorators?.valueGlobalId === undefined) {
|
|
4650
5769
|
return lowerProgramClassNew(lowerer, expr, info, loc);
|
|
4651
5770
|
}
|
|
4652
5771
|
// `new Map<K, V>()`: the lib Map constructor. The SEEDED forms: an
|
|
@@ -4654,27 +5773,17 @@ export function lowerNew(lowerer, expr) {
|
|
|
4654
5773
|
// (`new Map([[k, v], ...])`) — each pair's key/value lower as
|
|
4655
5774
|
// ordinary K/V-typed expressions and the backend set()s them in
|
|
4656
5775
|
// order, so the tuple array never exists as a value — and a
|
|
4657
|
-
// `[K, V][]`-typed tuple-array VALUE (
|
|
5776
|
+
// `[K, V][]`-typed tuple-array VALUE (lowerMapSeedNew: a
|
|
4658
5777
|
// construct-and-set loop, pairs in array order, duplicates
|
|
4659
|
-
// overwrite).
|
|
4660
|
-
//
|
|
5778
|
+
// overwrite). Matching Maps copy their entries; nullish seeds make
|
|
5779
|
+
// empty Maps. General iterable seeds retain a fence. Unsupported key/value
|
|
4661
5780
|
// types get their half named specifically instead of the component
|
|
4662
5781
|
// fence (SC2009, which names Map slots at value positions elsewhere).
|
|
4663
5782
|
// Both Array() and new Array() share the elements/count lowering.
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
// story with no lowering — so it keeps the constructor fence.
|
|
4669
|
-
if (symbol?.name === "Object" &&
|
|
4670
|
-
lowerer.isStdlibSymbol(symbol) &&
|
|
4671
|
-
(expr.arguments ?? []).length === 0) {
|
|
4672
|
-
return {
|
|
4673
|
-
kind: "recordLit",
|
|
4674
|
-
fields: [],
|
|
4675
|
-
type: { kind: "record", shapeId: lowerer.shapes.intern([]) },
|
|
4676
|
-
loc,
|
|
4677
|
-
};
|
|
5783
|
+
if (symbol?.name === "Object" && lowerer.isStdlibSymbol(symbol)) {
|
|
5784
|
+
const object = lowerObjectConstructor(lowerer, expr.arguments ?? [], loc);
|
|
5785
|
+
if (object)
|
|
5786
|
+
return object;
|
|
4678
5787
|
}
|
|
4679
5788
|
if (symbol?.name === "Array" && lowerer.isStdlibSymbol(symbol)) {
|
|
4680
5789
|
return lowerArrayConstructor(lowerer, expr, expr.arguments ?? []);
|
|
@@ -4688,16 +5797,29 @@ export function lowerNew(lowerer, expr) {
|
|
|
4688
5797
|
: null;
|
|
4689
5798
|
let tsType = lowerer.typeOf(expr);
|
|
4690
5799
|
let mapped = lowerer.mapTypeOf(tsType);
|
|
5800
|
+
if (mapped === null && isJsSourceFile(expr.getSourceFile()))
|
|
5801
|
+
mapped = lowerer.irTypeOf(expr);
|
|
4691
5802
|
const fieldType = assignedThisFieldType(lowerer, expr);
|
|
4692
5803
|
if (mapped?.kind !== "map" && fieldType?.kind === "map")
|
|
4693
5804
|
mapped = fieldType;
|
|
5805
|
+
// A fresh map built from pair literals can use its destination's
|
|
5806
|
+
// layout directly. Inference may otherwise split record values
|
|
5807
|
+
// into incompatible shapes (for example a nullable field), even
|
|
5808
|
+
// though every seed fits the declared value type. Existing map or
|
|
5809
|
+
// tuple-array values retain their own representation.
|
|
5810
|
+
let parent = expr.parent;
|
|
5811
|
+
while (ts.isParenthesizedExpression(parent))
|
|
5812
|
+
parent = parent.parent;
|
|
5813
|
+
// `satisfies` checks a view but retains the expression's own type.
|
|
5814
|
+
const contextualSeed = !ts.isSatisfiesExpression(parent) && (expr.typeArguments?.length ?? 0) === 0 &&
|
|
5815
|
+
(entriesLit !== null || (expr.arguments?.length ?? 0) === 0);
|
|
4694
5816
|
// JavaScript's `new Map()` has no type-argument syntax: the no-arg
|
|
4695
5817
|
// constructor overload pins Map<any, any> whatever the JSDoc says
|
|
4696
5818
|
// (`@type` on the declaration types the VARIABLE, not this
|
|
4697
5819
|
// expression). The CONTEXTUAL type carries the annotation — adopt
|
|
4698
5820
|
// it when it is a supported map. TS type arguments keep winning:
|
|
4699
5821
|
// their expression type already maps.
|
|
4700
|
-
if (mapped?.kind !== "map") {
|
|
5822
|
+
if (mapped?.kind !== "map" || contextualSeed) {
|
|
4701
5823
|
const ctx = lowerer.checker.getContextualType(expr);
|
|
4702
5824
|
const ctxMapped = ctx ? lowerer.mapTypeOf(ctx) : null;
|
|
4703
5825
|
if (ctx && ctxMapped?.kind === "map") {
|
|
@@ -4706,28 +5828,29 @@ export function lowerNew(lowerer, expr) {
|
|
|
4706
5828
|
}
|
|
4707
5829
|
}
|
|
4708
5830
|
if (seedArg && !entriesLit && mapped?.kind === "map") {
|
|
4709
|
-
const seeded =
|
|
5831
|
+
const seeded = lowerMapSeedNew(lowerer, seedArg, mapped);
|
|
4710
5832
|
if (seeded)
|
|
4711
5833
|
return seeded;
|
|
4712
5834
|
}
|
|
4713
5835
|
if ((expr.arguments?.length ?? 0) > 0 && !entriesLit) {
|
|
4714
5836
|
lowerer.noLowering("new Map(entries)", expr, "supported seeds: an array literal of [key, value] pair literals, or a " +
|
|
4715
|
-
"[K, V][]-typed tuple-array value
|
|
4716
|
-
"each entry otherwise");
|
|
5837
|
+
"[K, V][]-typed tuple-array value, a matching Map, or null/undefined");
|
|
4717
5838
|
}
|
|
4718
5839
|
if (mapped?.kind === "map") {
|
|
4719
5840
|
if (!entriesLit)
|
|
4720
5841
|
return { kind: "mapNew", type: mapped, loc };
|
|
4721
5842
|
const seed = entriesLit.map((pair) => ({
|
|
4722
|
-
key: lowerer.
|
|
4723
|
-
value:
|
|
5843
|
+
key: lowerer.lowerCollectionKey(pair.elements[0], mapped.key),
|
|
5844
|
+
value: mapped.value.kind === "dyn"
|
|
5845
|
+
? lowerer.lowerCollectionKey(pair.elements[1], mapped.value)
|
|
5846
|
+
: lowerer.lowerExprExpecting(pair.elements[1], mapped.value),
|
|
4724
5847
|
}));
|
|
4725
5848
|
return { kind: "mapNew", seed, type: mapped, loc };
|
|
4726
5849
|
}
|
|
4727
5850
|
const targs = lowerer.checker.getTypeArguments(tsType);
|
|
4728
5851
|
// JAVASCRIPT `new Map()` whose arguments never resolved past
|
|
4729
5852
|
// Map<any, any> (no annotation, no contextual type, no seed): the
|
|
4730
|
-
//
|
|
5853
|
+
// The VALUE lowers as an opaque dyn object
|
|
4731
5854
|
// (identity and truthiness are real), and every reached METHOD use
|
|
4732
5855
|
// meets its own per-site fence at runtime. The formatter's
|
|
4733
5856
|
// config-cache shape: module init constructs the caches
|
|
@@ -4740,34 +5863,35 @@ export function lowerNew(lowerer, expr) {
|
|
|
4740
5863
|
return { kind: "dynObjLit", type: DYN, loc };
|
|
4741
5864
|
}
|
|
4742
5865
|
const keyIr = targs[0] ? lowerer.mapTypeOf(targs[0]) : null;
|
|
4743
|
-
if (targs[0] && (!keyIr || !isSupportedMapKey(keyIr))) {
|
|
5866
|
+
if (targs[0] && (!keyIr || !isSupportedMapKey(keyIr, keyIr.kind === "union" ? lowerer.unions.get(keyIr.unionId)?.arms : undefined))) {
|
|
4744
5867
|
lowerer.unsupported("SC1090", expr, `Map keys of type '${lowerer.checker.typeToString(targs[0])}' ` +
|
|
4745
|
-
`(Map keys must be
|
|
5868
|
+
`(Map keys must be numbers, strings, identity references, or unions of identity references)`);
|
|
4746
5869
|
}
|
|
4747
5870
|
if (targs[1]) {
|
|
4748
5871
|
lowerer.unsupported("SC1090", expr, `Map values of type '${lowerer.checker.typeToString(targs[1])}' ` +
|
|
4749
5872
|
`(Map values must be number, string, boolean, records, class instances, ` +
|
|
4750
|
-
`arrays, promises, or unions of those — not functions,
|
|
5873
|
+
`arrays, promises, Maps, Sets, or unions of those — not functions, 'unknown', or 'any')`);
|
|
4751
5874
|
}
|
|
4752
5875
|
lowerer.badType(expr, tsType);
|
|
4753
5876
|
}
|
|
4754
|
-
//
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
return { kind: "dynObjLit", type: DYN, loc };
|
|
5877
|
+
// Weak containers share checked native key identities and lifetime hooks.
|
|
5878
|
+
if ((symbol?.name === "WeakMap" || symbol?.name === "WeakSet") && lowerer.isStdlibSymbol(symbol)) {
|
|
5879
|
+
const args = expr.arguments ?? [];
|
|
5880
|
+
if (args.length > 1 || args.some(ts.isSpreadElement)) {
|
|
5881
|
+
lowerer.unsupported("SC1090", expr, `${symbol.name} construction with surplus or spread arguments`);
|
|
5882
|
+
}
|
|
5883
|
+
if (lowerer.dynamic) {
|
|
5884
|
+
const ctor = { kind: "jsOp", op: "globalGet", name: symbol.name, args: [], type: JSVAL, loc };
|
|
5885
|
+
return { kind: "jsOp", op: "construct", args: [ctor, ...args.map((arg) => lowerer.jsvalIn(lowerer.lowerExpr(arg), arg))], type: JSVAL, loc };
|
|
5886
|
+
}
|
|
5887
|
+
return {
|
|
5888
|
+
kind: "libCall", fn: symbol.name === "WeakMap" ? "weakMap.new" : "weakSet.new",
|
|
5889
|
+
args: [args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc)],
|
|
5890
|
+
type: DYN, loc,
|
|
5891
|
+
};
|
|
4770
5892
|
}
|
|
5893
|
+
// `new Set<T>()`: construct + bulk add from native arrays, tuples,
|
|
5894
|
+
// or strings. Duplicates collapse in insertion order.
|
|
4771
5895
|
if (symbol?.name === "Set" && lowerer.isStdlibSymbol(symbol)) {
|
|
4772
5896
|
const tsType = lowerer.typeOf(expr);
|
|
4773
5897
|
let mapped = lowerer.mapTypeOf(tsType);
|
|
@@ -4775,55 +5899,13 @@ export function lowerNew(lowerer, expr) {
|
|
|
4775
5899
|
if (mapped?.kind !== "set" && fieldType?.kind === "set")
|
|
4776
5900
|
mapped = fieldType;
|
|
4777
5901
|
if (mapped?.kind === "set" && (expr.arguments?.length ?? 0) === 1) {
|
|
4778
|
-
const
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
4785
|
-
const seed = { kind: "arrayLit", elems, type: arrayOf(mapped.elem), loc };
|
|
4786
|
-
return { kind: "setNew", seed, type: mapped, loc };
|
|
4787
|
-
}
|
|
4788
|
-
if (!ts.isSpreadElement(argNode)) {
|
|
4789
|
-
const argIr = lowerer.mapTypeOf(lowerer.typeOf(argNode));
|
|
4790
|
-
if (argIr?.kind === "array" && typeEquals(argIr.elem, mapped.elem)) {
|
|
4791
|
-
let seed = lowerer.lowerExpr(argNode);
|
|
4792
|
-
// A T[]-DECLARED seed whose value is an island handle (a
|
|
4793
|
-
// package's exported array — the binding never held a
|
|
4794
|
-
// static array): the VALIDATED exit copies the engine
|
|
4795
|
-
// array out (strict elements, the catchable TypeError on a
|
|
4796
|
-
// lying handle), and the bulk add proceeds on the copy —
|
|
4797
|
-
// construction reads the seed once, so the aliasing
|
|
4798
|
-
// divergence has nothing to observe.
|
|
4799
|
-
if (seed.type.kind === "jsval" && lowerer.boundaryExitSafe(arrayOf(mapped.elem))) {
|
|
4800
|
-
seed = { kind: "jsExit", value: seed, type: arrayOf(mapped.elem), loc: seed.loc };
|
|
4801
|
-
}
|
|
4802
|
-
if (typeEquals(seed.type, arrayOf(mapped.elem))) {
|
|
4803
|
-
return { kind: "setNew", seed, type: mapped, loc };
|
|
4804
|
-
}
|
|
4805
|
-
// Any other lowered kind falls through to the named fence
|
|
4806
|
-
// below — never a mistyped seed into the validator.
|
|
4807
|
-
}
|
|
4808
|
-
// Fixed tuples use record storage, not T[] storage. Snapshot
|
|
4809
|
-
// their legal elements into an array before bulk insertion;
|
|
4810
|
-
// the helper takes the tuple as one argument, so an effectful
|
|
4811
|
-
// seed expression is evaluated exactly once.
|
|
4812
|
-
if (argIr?.kind === "record") {
|
|
4813
|
-
const shape = lowerer.shapes.get(argIr.shapeId);
|
|
4814
|
-
if (shape?.tuple && shape.fields.every((field) => typeEquals(field.type, mapped.elem))) {
|
|
4815
|
-
const seedType = { kind: "array", elem: mapped.elem };
|
|
4816
|
-
const helper = lowerer.tupleArrayWidthHelper(argIr.shapeId, seedType, loc);
|
|
4817
|
-
if (helper) {
|
|
4818
|
-
const tuple = lowerer.lowerExpr(argNode);
|
|
4819
|
-
if (typeEquals(tuple.type, argIr)) {
|
|
4820
|
-
const seed = { kind: "call", callee: helper, args: [tuple], type: seedType, loc };
|
|
4821
|
-
return { kind: "setNew", seed, type: mapped, loc };
|
|
4822
|
-
}
|
|
4823
|
-
}
|
|
4824
|
-
}
|
|
4825
|
-
}
|
|
4826
|
-
}
|
|
5902
|
+
const seeded = lowerSetSeedNew(lowerer, expr.arguments[0], mapped);
|
|
5903
|
+
if (seeded)
|
|
5904
|
+
return seeded;
|
|
5905
|
+
}
|
|
5906
|
+
if (!mapped && isJsSourceFile(expr.getSourceFile()) && (expr.arguments?.length ?? 0) <= 1 && !expr.arguments?.some(ts.isSpreadElement)) {
|
|
5907
|
+
return { kind: "libCall", fn: "dyn.nativeSetNew", args: [expr.arguments?.[0]
|
|
5908
|
+
? lowerer.lowerExprExpecting(expr.arguments[0], DYN) : dynUndefinedExpr(loc)], type: DYN, loc };
|
|
4827
5909
|
}
|
|
4828
5910
|
// JavaScript's identity-Set idiom: `new Set([setTimeout, atob,
|
|
4829
5911
|
// ...])` — the element TYPE (a union of stdlib signatures) has no
|
|
@@ -4847,15 +5929,15 @@ export function lowerNew(lowerer, expr) {
|
|
|
4847
5929
|
}
|
|
4848
5930
|
}
|
|
4849
5931
|
if ((expr.arguments?.length ?? 0) > 0) {
|
|
4850
|
-
lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only
|
|
4851
|
-
"already-legal elements (
|
|
5932
|
+
lowerer.noLowering("new Set(values)", expr, "construct the Set empty and add() each value — only nullish values or a matching Set, string, array, or fixed tuple of " +
|
|
5933
|
+
"already-legal elements (numbers, strings, or identity references) seeds a Set");
|
|
4852
5934
|
}
|
|
4853
5935
|
if (mapped?.kind === "set")
|
|
4854
5936
|
return { kind: "setNew", type: mapped, loc };
|
|
4855
5937
|
const targs = lowerer.checker.getTypeArguments(tsType);
|
|
4856
5938
|
if (targs[0]) {
|
|
4857
5939
|
lowerer.unsupported("SC1090", expr, `Set elements of type '${lowerer.checker.typeToString(targs[0])}' ` +
|
|
4858
|
-
`(Set elements must be
|
|
5940
|
+
`(Set elements must be numbers, strings, identity references, or unions of identity references)`);
|
|
4859
5941
|
}
|
|
4860
5942
|
lowerer.badType(expr, tsType);
|
|
4861
5943
|
}
|
|
@@ -4961,16 +6043,14 @@ export function lowerNew(lowerer, expr) {
|
|
|
4961
6043
|
String: "boxed wrapper objects have no lowering — use the string primitive (the box is only distinguishable via typeof/identity, which nothing here can honor)",
|
|
4962
6044
|
Number: "boxed wrapper objects have no lowering — use the number primitive",
|
|
4963
6045
|
Boolean: "boxed wrapper objects have no lowering — use the boolean primitive",
|
|
4964
|
-
WeakMap: "weak collections observe garbage collection, which reference counting never exposes — a strong Map behaves identically in-language: use Map",
|
|
4965
|
-
WeakSet: "weak collections observe garbage collection, which reference counting never exposes — a strong Set behaves identically in-language: use Set",
|
|
4966
6046
|
WeakRef: "deref()-after-collect exposes GC timing — genuinely dynamic; hold a strong reference instead",
|
|
4967
6047
|
FinalizationRegistry: "finalization callbacks expose GC timing — genuinely dynamic; release resources explicitly instead",
|
|
4968
6048
|
SharedArrayBuffer: "no shared-memory threads exist in a compiled program — Uint8Array is the byte storage",
|
|
4969
|
-
ArrayBuffer: "
|
|
4970
|
-
Proxy: "
|
|
6049
|
+
ArrayBuffer: "native ArrayBuffer construction supports fixed-length storage; resizable buffers remain unsupported",
|
|
6050
|
+
Proxy: "native Proxy construction requires checked-native plain targets and handlers",
|
|
4971
6051
|
Function: "runtime code generation cannot be compiled ahead of time (the eval stance) — write the function",
|
|
4972
6052
|
};
|
|
4973
|
-
lowerer.noLowering(`new ${expr.expression.text}`, expr, ctorHints[expr.expression.text], symbol);
|
|
6053
|
+
lowerer.noLowering(`new ${expr.expression.text}`, expr, ctorHints[ts.isIdentifier(expr.expression) ? expr.expression.text : expr.expression.name.text], symbol);
|
|
4974
6054
|
}
|
|
4975
6055
|
}
|
|
4976
6056
|
// `new crypto.X509Certificate(data)` — the Dirent-style data record:
|
|
@@ -5055,7 +6135,7 @@ export function lowerNew(lowerer, expr) {
|
|
|
5055
6135
|
// callee (unannotated heterogeneous registries) keeps a pointed
|
|
5056
6136
|
// fence — annotate the slot with the common constructor type.
|
|
5057
6137
|
{
|
|
5058
|
-
const calleeT =
|
|
6138
|
+
const calleeT = storedClassValueType(lowerer, expr.expression);
|
|
5059
6139
|
if (calleeT?.kind === "classval") {
|
|
5060
6140
|
let info = lowerer.classes.get(calleeT.className);
|
|
5061
6141
|
if (!info && ts.isPropertyAccessExpression(expr.expression) && ts.isIdentifier(expr.expression.name)) {
|
|
@@ -5083,6 +6163,8 @@ export function lowerNew(lowerer, expr) {
|
|
|
5083
6163
|
lowerer.unsupported("SC1090", expr, "constructing through a class value of an uninstantiated generic type (annotate the slot with a concrete instantiation — e.g. 'new (v: number) => Box<number>')");
|
|
5084
6164
|
}
|
|
5085
6165
|
const callee = lowerer.lowerExpr(expr.expression);
|
|
6166
|
+
if (callee.type.kind === "dyn")
|
|
6167
|
+
return checkedClassConstruction(lowerer, callee, (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
|
|
5086
6168
|
if (callee.type.kind !== "classval")
|
|
5087
6169
|
lowerer.badType(expr.expression, lowerer.typeOf(expr.expression));
|
|
5088
6170
|
lowerer.noteEdge(`%${info.def.name}.constructor`);
|
|
@@ -5132,6 +6214,11 @@ export function lowerNew(lowerer, expr) {
|
|
|
5132
6214
|
}
|
|
5133
6215
|
}
|
|
5134
6216
|
}
|
|
6217
|
+
// Checked construction supports emitted classes and builtin typed arrays.
|
|
6218
|
+
const callee = tryLowerExpression(lowerer, expr.expression);
|
|
6219
|
+
if (callee && (callee.type.kind === "dyn" || callee.type.kind === "func" && lowerer.dynConvertible(callee.type)) && !(expr.arguments ?? []).some(ts.isSpreadElement)) {
|
|
6220
|
+
return checkedClassConstruction(lowerer, lowerer.coerceToExpected(callee, DYN), (expr.arguments ?? []).map((arg) => lowerer.lowerExprExpecting(arg, DYN)), loc);
|
|
6221
|
+
}
|
|
5135
6222
|
lowerer.unsupported("SC1090", expr, "constructing values other than classes declared in the program");
|
|
5136
6223
|
}
|
|
5137
6224
|
/** A getter/setter invocation over an accessor target's receiver — the
|