@scriptc/compiler 0.2.6 → 0.2.7
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 +5 -18
- package/dist/backend/cycle-analysis.d.ts +21 -9
- package/dist/backend/cycle-analysis.js +139 -67
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +283 -3
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +39 -0
- package/dist/backend/cycle-mutability.js +205 -0
- package/dist/backend/cycle-mutability.js.map +1 -0
- package/dist/backend/link-plan-core.d.ts +2 -1
- package/dist/backend/link-plan-core.js +15 -3
- package/dist/backend/link-plan-core.js.map +1 -1
- package/dist/backend/link-plan.d.ts +2 -1
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +40 -0
- package/dist/backend/llvm/alloc.js +205 -0
- package/dist/backend/llvm/alloc.js.map +1 -0
- package/dist/backend/llvm/alloc.test.d.ts +1 -0
- package/dist/backend/llvm/alloc.test.js +102 -0
- package/dist/backend/llvm/alloc.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +15 -3
- package/dist/backend/llvm/call-lifetimes.js +42 -18
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +170 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +4 -1
- package/dist/backend/llvm/classes.js +35 -32
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +36 -3
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +13 -0
- package/dist/backend/llvm/common.js +30 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +19 -3
- package/dist/backend/llvm/constant-callbacks.js +289 -52
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +140 -3
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +29 -0
- package/dist/backend/llvm/dense-array-access.js +335 -0
- package/dist/backend/llvm/dense-array-access.js.map +1 -0
- package/dist/backend/llvm/dense-array-access.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-access.test.js +149 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +34 -0
- package/dist/backend/llvm/dyn.js +189 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +124 -4
- package/dist/backend/llvm/emitter.js +623 -105
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +68 -6
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +58 -4
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.d.ts +1 -0
- package/dist/backend/llvm/expr-async.test.js +62 -0
- package/dist/backend/llvm/expr-async.test.js.map +1 -0
- package/dist/backend/llvm/expr-calls.js +64 -6
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +16 -5
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +92 -2
- package/dist/backend/llvm/expr-control.js.map +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 +174 -25
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +52 -24
- 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.js +3 -3
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +59 -2
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
- package/dist/backend/llvm/integer-remainder.d.ts +11 -0
- package/dist/backend/llvm/integer-remainder.js +91 -0
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +2 -1
- package/dist/backend/llvm/layouts.js +3 -2
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lazy-captures.d.ts +16 -0
- package/dist/backend/llvm/lazy-captures.js +96 -0
- package/dist/backend/llvm/lazy-captures.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.test.d.ts +1 -0
- package/dist/backend/llvm/lazy-captures.test.js +78 -0
- package/dist/backend/llvm/lazy-captures.test.js.map +1 -0
- package/dist/backend/llvm/lib-filesystem.js +3 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.d.ts +5 -1
- package/dist/backend/llvm/local-array-reads.js +78 -17
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +78 -1
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +5 -1
- package/dist/backend/llvm/local-union-storage.js +48 -6
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +91 -4
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +1 -1
- package/dist/backend/llvm/nullable-fields.d.ts +28 -0
- package/dist/backend/llvm/nullable-fields.js +45 -0
- package/dist/backend/llvm/nullable-fields.js.map +1 -0
- package/dist/backend/llvm/nullable-fields.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-fields.test.js +48 -0
- package/dist/backend/llvm/nullable-fields.test.js.map +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.d.ts +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +52 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +69 -2
- package/dist/backend/llvm/shapes.js +259 -27
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +114 -5
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-callbacks.js +2 -3
- package/dist/backend/llvm/stack-callbacks.js.map +1 -1
- package/dist/backend/llvm/stack-captures.d.ts +3 -1
- package/dist/backend/llvm/stack-captures.js +5 -3
- package/dist/backend/llvm/stack-captures.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +38 -1
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +8 -0
- package/dist/backend/llvm/string-key-hash.js +59 -0
- package/dist/backend/llvm/string-key-hash.js.map +1 -0
- package/dist/backend/llvm/string-key-hash.test.d.ts +1 -0
- package/dist/backend/llvm/string-key-hash.test.js +34 -0
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -0
- package/dist/backend/llvm/string-lifetimes.test.js +41 -4
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.js +1 -1
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +2 -2
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/may-throw.js +3 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +1 -1
- package/dist/backend/native/cache-warm.d.ts +2 -1
- package/dist/backend/native/cache-warm.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +3 -2
- package/dist/backend/native/contracts.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +2 -1
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +5 -0
- package/dist/backend/native-codegen.js +4 -0
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +23 -0
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +3 -2
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-link-info.d.ts +2 -1
- package/dist/backend/native-link-info.js.map +1 -1
- package/dist/backend/native-link-info.test.js +2 -2
- package/dist/backend/native-link-info.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +3 -1
- package/dist/backend/native-tools.js +0 -1
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/optimization.d.ts +25 -0
- package/dist/backend/optimization.js +21 -0
- package/dist/backend/optimization.js.map +1 -0
- package/dist/backend/optimization.test.d.ts +1 -0
- package/dist/backend/optimization.test.js +24 -0
- package/dist/backend/optimization.test.js.map +1 -0
- 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 +15 -4
- package/dist/backend/runtime-pack-core.js +23 -12
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.d.ts +7 -3
- package/dist/backend/runtime-pack-native.js +0 -3
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.d.ts +20 -2
- package/dist/backend/runtime-pack.js +23 -0
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +115 -2
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/targets.d.ts +2 -1
- package/dist/backend/targets.js +1 -1
- package/dist/backend/targets.js.map +1 -1
- package/dist/cli/command.js +5 -4
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/host.d.ts +2 -1
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +5 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +5 -2
- package/dist/diagnostics/diagnostic.js +10 -8
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +2 -2
- package/dist/executable/executable-cache.js +7 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +20 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/lowering/abstract-equality.js +5 -49
- package/dist/frontend/lowering/abstract-equality.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +23 -0
- package/dist/frontend/lowering/array-values.js +129 -0
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +17 -2
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +6 -17
- package/dist/frontend/lowering/builtins/process.js +56 -29
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +11 -0
- package/dist/frontend/lowering/caught-value-dispatch.js +87 -0
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -0
- package/dist/frontend/lowering/class-assertions.d.ts +4 -0
- package/dist/frontend/lowering/class-assertions.js +12 -4
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -3
- package/dist/frontend/lowering/class-callbacks.js +18 -5
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +4 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.d.ts +5 -0
- package/dist/frontend/lowering/class-method-mutations.js +472 -0
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -0
- package/dist/frontend/lowering/class-method-values.js +25 -5
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.js +8 -2
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-unions.d.ts +16 -0
- package/dist/frontend/lowering/class-unions.js +127 -0
- package/dist/frontend/lowering/class-unions.js.map +1 -0
- package/dist/frontend/lowering/coercions/builders.js +8 -1
- package/dist/frontend/lowering/coercions/builders.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +2 -0
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/identity.d.ts +7 -0
- package/dist/frontend/lowering/coercions/identity.js +26 -0
- package/dist/frontend/lowering/coercions/identity.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural.js +9 -6
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/collection-narrowing.d.ts +6 -0
- package/dist/frontend/lowering/collection-narrowing.js +31 -0
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +52 -0
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +363 -49
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-concat.js +130 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -0
- package/dist/frontend/lowering/containers/array-construction.d.ts +2 -0
- package/dist/frontend/lowering/containers/array-construction.js +95 -3
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.d.ts +1 -11
- package/dist/frontend/lowering/containers/array-methods.js +43 -132
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +10 -1
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +56 -70
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +41 -0
- package/dist/frontend/lowering/cycle-initialization.js +277 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +138 -32
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-field-write.d.ts +4 -4
- package/dist/frontend/lowering/expressions/union-field-write.js +54 -44
- package/dist/frontend/lowering/expressions/union-field-write.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.d.ts +20 -0
- package/dist/frontend/lowering/iterator-adapters.js +605 -0
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +1 -1
- package/dist/frontend/lowering/lower-array-sort.js +44 -5
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.d.ts +1 -0
- package/dist/frontend/lowering/lower-array-sort.test.js +31 -0
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -0
- package/dist/frontend/lowering/lower-assert.js +7 -0
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.js +1 -0
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +3 -3
- package/dist/frontend/lowering/lower-calls.js +162 -121
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +2 -0
- package/dist/frontend/lowering/lower-classes.js +45 -43
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +9 -2
- package/dist/frontend/lowering/lower-exprs.js +390 -157
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +32 -19
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +26 -2
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +10 -2
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +46 -58
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +37 -0
- package/dist/frontend/lowering/lowerer.js +283 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +3 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +15 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js +40 -0
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -0
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/strict-equality.d.ts +9 -0
- package/dist/frontend/lowering/strict-equality.js +116 -0
- package/dist/frontend/lowering/strict-equality.js.map +1 -0
- package/dist/frontend/lowering/surfaces.js +3 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/union-comparison.d.ts +5 -0
- package/dist/frontend/lowering/union-comparison.js +47 -0
- package/dist/frontend/lowering/union-comparison.js.map +1 -0
- package/dist/frontend/program.d.ts +38 -2
- package/dist/frontend/program.js +440 -59
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +59 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +1 -1
- package/dist/frontend/type-mapper.js +89 -14
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +15 -3
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/index.js +25 -9
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +3 -1
- package/dist/ir/analysis.js +4 -0
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/builtin-signatures.js +2 -3
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/ir.d.ts +78 -15
- package/dist/ir/ir.js +20 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +3 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +8 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +118 -20
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +269 -8
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +2 -1
- package/dist/library/library-profile.js +4 -3
- package/dist/library/library-profile.js.map +1 -1
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +2 -2
- package/dist/native/library.d.ts +2 -1
- package/dist/native/library.js.map +1 -1
- package/dist/native/prepare.js +27 -3
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.d.ts +3 -2
- package/dist/native/sanitizer.js +3 -13
- package/dist/native/sanitizer.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +8 -2
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { generatorDrain } from "./iterator-adapters.js";
|
|
2
|
+
import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js";
|
|
3
|
+
import { isOptionalProcessStreamProperty } from "./builtins/process.js";
|
|
1
4
|
import { lowerWorkerMetadata } from "./builtins/workers.js";
|
|
2
|
-
import { dynUndefinedExpr, nodeThrowExpr,
|
|
5
|
+
import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../ir/build.js";
|
|
3
6
|
import { InternalCompilerError } from "../../errors.js";
|
|
4
7
|
import { SYMBOL_T } from "../../ir/ir.js";
|
|
5
8
|
import { literalValues } from "../literal-values.js";
|
|
@@ -11,9 +14,12 @@ import { literalUnionArm } from "../union-discriminants.js";
|
|
|
11
14
|
* ToBoolean/ToString coercion helpers, and field/element reads and writes
|
|
12
15
|
* (FieldTarget). */
|
|
13
16
|
import * as ts from "../ts7/adapter.js";
|
|
17
|
+
import { constituentTypes } from "../ts7/checker.js";
|
|
14
18
|
import { dirname } from "node:path";
|
|
15
19
|
import * as posix from "node:path/posix";
|
|
16
20
|
import { checkedClassAssertion } from "./class-assertions.js";
|
|
21
|
+
import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
|
|
22
|
+
import { lowerUnionFieldWrite } from "./expressions/union-field-write.js";
|
|
17
23
|
import { captureContextArguments } from "./function-context.js";
|
|
18
24
|
import { OBJECT_CALLABLE_VALUES } from "./surfaces.js";
|
|
19
25
|
import { wasiGuestPath } from "../../wasi-paths.js";
|
|
@@ -23,9 +29,8 @@ import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstO
|
|
|
23
29
|
import { UNSUPPORTED, blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
24
30
|
import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
|
|
25
31
|
import { lowerCollectionSpread } from "./containers/collection-methods.js";
|
|
26
|
-
import {
|
|
32
|
+
import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, } from "./array-values.js";
|
|
27
33
|
import { strCharsCall } from "./containers/array-construction.js";
|
|
28
|
-
import { arrayValueRead, arrayValueStore, arrayValueType } from "./array-values.js";
|
|
29
34
|
import { lowerOptionalStringIndex } from "./string-index.js";
|
|
30
35
|
import { tryLowerIndexedComparison } from "./indexed-comparison.js";
|
|
31
36
|
import { npmStaticPackageOfPath } from "../npm-static.js";
|
|
@@ -98,8 +103,8 @@ export function templateRawTextOf(node) {
|
|
|
98
103
|
const LOWER_EXPR_MAX_DEPTH = 200;
|
|
99
104
|
let lowerExprDepth = 0;
|
|
100
105
|
/** True when a property access names an ABSTRACT property declaration
|
|
101
|
-
* (`abstract p: number` — a PropertyDeclaration, not an accessor)
|
|
102
|
-
*
|
|
106
|
+
* (`abstract p: number` — a PropertyDeclaration, not an accessor).
|
|
107
|
+
* These uses need concrete property dispatch because the base has no slot. */
|
|
103
108
|
export function abstractPropertyDeclOf(lowerer, expr) {
|
|
104
109
|
const sym = lowerer.checker.getSymbolAtLocation(expr.name);
|
|
105
110
|
if (!sym)
|
|
@@ -161,7 +166,10 @@ export function lowerExpr(lowerer, expr) {
|
|
|
161
166
|
}
|
|
162
167
|
lowerExprDepth++;
|
|
163
168
|
try {
|
|
164
|
-
|
|
169
|
+
const lowered = lowerExprInner(lowerer, expr);
|
|
170
|
+
if (lowered.type.kind === "void" && (lowerer.typeOf(expr).flags & ts.TypeFlags.Never) !== 0)
|
|
171
|
+
lowerer.neverValued.add(lowered);
|
|
172
|
+
return lowered;
|
|
165
173
|
}
|
|
166
174
|
finally {
|
|
167
175
|
lowerExprDepth--;
|
|
@@ -288,6 +296,11 @@ function lowerExprInner(lowerer, expr) {
|
|
|
288
296
|
if (ts.isNonNullExpression(expr)) {
|
|
289
297
|
const inner = lowerer.lowerExpr(expr.expression);
|
|
290
298
|
if (inner.type.kind === "union") {
|
|
299
|
+
// `!` performs no runtime check: a missing array element stays
|
|
300
|
+
// undefined where its destination can hold it.
|
|
301
|
+
if (ts.isElementAccessExpression(expr.expression) &&
|
|
302
|
+
assertedElementKeepsUndefined(lowerer, expr))
|
|
303
|
+
return inner;
|
|
291
304
|
const use = runtimeOptionalUseOf(expr);
|
|
292
305
|
if (runtimeOptionalAssertionErases(lowerer, expr, inner, use))
|
|
293
306
|
return inner;
|
|
@@ -3075,6 +3088,11 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3075
3088
|
// same trust-the-checker contract as the union bridge below.
|
|
3076
3089
|
if (expr.type.kind === "object") {
|
|
3077
3090
|
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
3091
|
+
if (narrowed?.kind === "union") {
|
|
3092
|
+
const union = narrowClassUnion(lowerer, expr, narrowed);
|
|
3093
|
+
if (union)
|
|
3094
|
+
return union;
|
|
3095
|
+
}
|
|
3078
3096
|
if (narrowed?.kind === "object" &&
|
|
3079
3097
|
narrowed.className !== expr.type.className &&
|
|
3080
3098
|
lowerer.isSubclassOf(narrowed.className, expr.type.className)) {
|
|
@@ -3084,6 +3102,8 @@ export function maybeNarrow(lowerer, expr, node) {
|
|
|
3084
3102
|
}
|
|
3085
3103
|
if (expr.type.kind !== "union")
|
|
3086
3104
|
return expr;
|
|
3105
|
+
if (ts.isPropertyAccessExpression(node) && isOptionalProcessStreamProperty(lowerer, node))
|
|
3106
|
+
return expr;
|
|
3087
3107
|
// Represented fields and index values can include undefined even when
|
|
3088
3108
|
// checker inference or lib.d.ts declares strings (RegExp captures).
|
|
3089
3109
|
// Only a declaration that represents the optional arm can provide a
|
|
@@ -3228,6 +3248,9 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3228
3248
|
lowerer.unsupported("SC1090", expr, "a runtime-optional capture whose narrowed value type is not representable");
|
|
3229
3249
|
}
|
|
3230
3250
|
if (narrowed.kind === "union") {
|
|
3251
|
+
const classView = narrowStoredClassValue(lowerer, varRef(local.id, local.type, loc), narrowed);
|
|
3252
|
+
if (classView)
|
|
3253
|
+
return classView;
|
|
3231
3254
|
// The checker may keep the receiver at the storage union unchanged
|
|
3232
3255
|
// (`string | undefined` on a JS `.match()` call). There is no
|
|
3233
3256
|
// sub-union to re-tag: preserve the value for the downstream
|
|
@@ -3254,6 +3277,13 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3254
3277
|
loc,
|
|
3255
3278
|
};
|
|
3256
3279
|
}
|
|
3280
|
+
if (narrowed.kind === "object") {
|
|
3281
|
+
const view = checkedClassAssertion(lowerer, varRef(local.id, local.type, loc), narrowed, loc);
|
|
3282
|
+
// Preserve the member-specific missing-value error on the two-arm
|
|
3283
|
+
// path below; mixed storage also needs to validate its concrete class.
|
|
3284
|
+
if (view && (lowerer.unions.get(local.type.unionId)?.arms.length ?? 0) > 2)
|
|
3285
|
+
return view;
|
|
3286
|
+
}
|
|
3257
3287
|
const undefTag = lowerer.armTag(local.type.unionId, UNDEFINED_T);
|
|
3258
3288
|
const def = lowerer.unions.get(local.type.unionId);
|
|
3259
3289
|
if (!def || undefTag < 0)
|
|
@@ -3408,6 +3438,45 @@ function runtimeOptionalElementKey(expr) {
|
|
|
3408
3438
|
return expr.text;
|
|
3409
3439
|
return null;
|
|
3410
3440
|
}
|
|
3441
|
+
/** Whether `xs[i]!` lands where an absent element's undefined is
|
|
3442
|
+
* representable: array storage (a literal element, a push/unshift
|
|
3443
|
+
* argument, an element assignment — arrays record the undefined state),
|
|
3444
|
+
* an equality operand, or a slot whose contextual type admits undefined.
|
|
3445
|
+
* TypeScript's `!` has no runtime effect, so such reads stay optional. */
|
|
3446
|
+
function assertedElementKeepsUndefined(lowerer, node) {
|
|
3447
|
+
let outer = node;
|
|
3448
|
+
while (ts.isParenthesizedExpression(outer.parent))
|
|
3449
|
+
outer = outer.parent;
|
|
3450
|
+
const parent = outer.parent;
|
|
3451
|
+
if (ts.isArrayLiteralExpression(parent))
|
|
3452
|
+
return true;
|
|
3453
|
+
// An equality test observes the missing element itself.
|
|
3454
|
+
if (ts.isBinaryExpression(parent) &&
|
|
3455
|
+
(parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
3456
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
3457
|
+
parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
|
|
3458
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken))
|
|
3459
|
+
return true;
|
|
3460
|
+
const isArray = (receiver) => lowerer.checker.isArrayType(lowerer.typeOf(receiver));
|
|
3461
|
+
if (ts.isCallExpression(parent) &&
|
|
3462
|
+
parent.arguments.includes(outer) &&
|
|
3463
|
+
ts.isPropertyAccessExpression(parent.expression) &&
|
|
3464
|
+
(parent.expression.name.text === "push" || parent.expression.name.text === "unshift") &&
|
|
3465
|
+
isArray(parent.expression.expression))
|
|
3466
|
+
return true;
|
|
3467
|
+
if (ts.isBinaryExpression(parent) &&
|
|
3468
|
+
parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
|
|
3469
|
+
parent.right === outer &&
|
|
3470
|
+
ts.isElementAccessExpression(parent.left) &&
|
|
3471
|
+
isArray(parent.left.expression))
|
|
3472
|
+
return true;
|
|
3473
|
+
const contextual = lowerer.checker.getContextualType(outer);
|
|
3474
|
+
if (!contextual)
|
|
3475
|
+
return false;
|
|
3476
|
+
const admits = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Undefined)) !== 0;
|
|
3477
|
+
return (admits(contextual) ||
|
|
3478
|
+
((contextual.flags & ts.TypeFlags.Union) !== 0 && constituentTypes(contextual).some(admits)));
|
|
3479
|
+
}
|
|
3411
3480
|
function runtimeOptionalAssertionErases(lowerer, expr, inner, use) {
|
|
3412
3481
|
if (inner.type.kind !== "union" ||
|
|
3413
3482
|
!use?.optional ||
|
|
@@ -3655,6 +3724,32 @@ export function lowerNullishCoalesce(lowerer, expr, loc) {
|
|
|
3655
3724
|
}
|
|
3656
3725
|
return result;
|
|
3657
3726
|
}
|
|
3727
|
+
/** A plain value read that may be runtime-optional: an unchecked element
|
|
3728
|
+
* read, or a binding, member or call that carries one. Lowering these
|
|
3729
|
+
* without a destination type is the same as lowering them into one. */
|
|
3730
|
+
function isPlainValueRead(node) {
|
|
3731
|
+
while (ts.isParenthesizedExpression(node))
|
|
3732
|
+
node = node.expression;
|
|
3733
|
+
return (ts.isElementAccessExpression(node) ||
|
|
3734
|
+
ts.isIdentifier(node) ||
|
|
3735
|
+
ts.isPropertyAccessExpression(node) ||
|
|
3736
|
+
ts.isCallExpression(node));
|
|
3737
|
+
}
|
|
3738
|
+
/** A member access or call receiver needs the present value itself (JS
|
|
3739
|
+
* throws a TypeError reading a member of undefined). */
|
|
3740
|
+
function isMemberReceiver(node) {
|
|
3741
|
+
let child = node;
|
|
3742
|
+
let parent = node.parent;
|
|
3743
|
+
while (ts.isParenthesizedExpression(parent)) {
|
|
3744
|
+
child = parent;
|
|
3745
|
+
parent = parent.parent;
|
|
3746
|
+
}
|
|
3747
|
+
return (((ts.isPropertyAccessExpression(parent) ||
|
|
3748
|
+
ts.isElementAccessExpression(parent) ||
|
|
3749
|
+
ts.isCallExpression(parent)) &&
|
|
3750
|
+
parent.expression === child) ||
|
|
3751
|
+
(ts.isTaggedTemplateExpression(parent) && parent.tag === child));
|
|
3752
|
+
}
|
|
3658
3753
|
function lowerNullishPair(lowerer, expr, loc, left) {
|
|
3659
3754
|
if (left.type.kind === "dyn") {
|
|
3660
3755
|
// `a ?? b` on a CHECKED-DYNAMIC left: the deciding test is the
|
|
@@ -3691,7 +3786,24 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3691
3786
|
const fresh = rest.length === 1 ? lowerer.emptyCollectionFor(expr.right, rest[0]) : null;
|
|
3692
3787
|
if (fresh)
|
|
3693
3788
|
return { kind: "nullish", left, right: fresh, type: fresh.type, loc };
|
|
3694
|
-
|
|
3789
|
+
let type = lowerer.irTypeOf(expr);
|
|
3790
|
+
// A runtime-optional read can reach the default even when declarations
|
|
3791
|
+
// call the left side present. Preserve a differently typed primitive
|
|
3792
|
+
// fallback rather than checking it against that incomplete result type.
|
|
3793
|
+
const rightType = lowerer.mapTypeOf(lowerer.typeOf(expr.right));
|
|
3794
|
+
const primitive = (t) => t.kind === "f64" || t.kind === "string" || t.kind === "bool";
|
|
3795
|
+
if (rightType &&
|
|
3796
|
+
primitive(type) &&
|
|
3797
|
+
primitive(rightType) &&
|
|
3798
|
+
!typeEquals(type, rightType) &&
|
|
3799
|
+
rest.every(primitive)) {
|
|
3800
|
+
const arms = [...rest];
|
|
3801
|
+
if (!arms.some((arm) => typeEquals(arm, rightType)))
|
|
3802
|
+
arms.push(rightType);
|
|
3803
|
+
arms.sort((a, b) => (typeKey(a) < typeKey(b) ? -1 : 1));
|
|
3804
|
+
type = { kind: "union", unionId: lowerer.unions.intern(arms) };
|
|
3805
|
+
lowerer.runtimeOptionalArithmeticTypes.set(expr, type);
|
|
3806
|
+
}
|
|
3695
3807
|
if (type.kind === "dyn" && lowerer.dynConvertible(left.type)) {
|
|
3696
3808
|
return {
|
|
3697
3809
|
kind: "nullish",
|
|
@@ -3701,6 +3813,27 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3701
3813
|
loc,
|
|
3702
3814
|
};
|
|
3703
3815
|
}
|
|
3816
|
+
// A runtime-optional default (`name ?? names[0]`): the checker types an
|
|
3817
|
+
// unchecked element read as the bare element type, but an out-of-range
|
|
3818
|
+
// read is undefined at runtime. When the default shares the left's
|
|
3819
|
+
// optional union, that union is the result, so the undefined state
|
|
3820
|
+
// reaches the consumer (an optional return or parameter takes it as its
|
|
3821
|
+
// undefined arm; a plain slot still extracts the element with its
|
|
3822
|
+
// checked narrow).
|
|
3823
|
+
if (rest.length === 1 &&
|
|
3824
|
+
typeEquals(type, rest[0]) &&
|
|
3825
|
+
isPlainValueRead(expr.right) &&
|
|
3826
|
+
!isMemberReceiver(expr)) {
|
|
3827
|
+
const raw = lowerer.lowerExpr(expr.right);
|
|
3828
|
+
if (typeEquals(raw.type, left.type))
|
|
3829
|
+
return { kind: "nullish", left, right: raw, type: left.type, loc };
|
|
3830
|
+
// `names[0] ?? undefined`: an explicit unit default stays the left's arm.
|
|
3831
|
+
if (isUnitType(raw.type) && lowerer.armTag(left.type.unionId, raw.type) >= 0) {
|
|
3832
|
+
const right = lowerer.coerceInto(expr.right, raw, left.type);
|
|
3833
|
+
return { kind: "nullish", left, right, type: left.type, loc };
|
|
3834
|
+
}
|
|
3835
|
+
return { kind: "nullish", left, right: lowerer.coerceInto(expr.right, raw, type), type, loc };
|
|
3836
|
+
}
|
|
3704
3837
|
if (typeEquals(type, left.type) || (rest.length === 1 && typeEquals(type, rest[0]))) {
|
|
3705
3838
|
const right = lowerer.lowerExprExpecting(expr.right, type);
|
|
3706
3839
|
return { kind: "nullish", left, right, type, loc };
|
|
@@ -3824,7 +3957,8 @@ export function lowerCondition(lowerer, expr) {
|
|
|
3824
3957
|
};
|
|
3825
3958
|
}
|
|
3826
3959
|
}
|
|
3827
|
-
|
|
3960
|
+
const value = lowerAbsenceProbe(lowerer, expr) ?? lowerer.lowerExpr(expr);
|
|
3961
|
+
return (tryLowerIndexTruthiness(lowerer, value, expr, locOf(expr)) ?? lowerer.ensureBool(value, expr));
|
|
3828
3962
|
}
|
|
3829
3963
|
function lowerPromiseThenPresence(lowerer, access, result) {
|
|
3830
3964
|
if (access.name.text !== "then")
|
|
@@ -5031,6 +5165,13 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5031
5165
|
loc: locOf(el),
|
|
5032
5166
|
};
|
|
5033
5167
|
}
|
|
5168
|
+
// `[...it]` over a generator (or an iterator adapted into one):
|
|
5169
|
+
// drain it once, in order, into a fresh element array.
|
|
5170
|
+
if (src.type.kind === "generator") {
|
|
5171
|
+
const drained = generatorDrain(lowerer, src, type.elem, locOf(el));
|
|
5172
|
+
if (drained)
|
|
5173
|
+
src = drained;
|
|
5174
|
+
}
|
|
5034
5175
|
// A native checked iterable can supply scalar elements even when
|
|
5035
5176
|
// the checker inferred a typed array from its producer. Drain once
|
|
5036
5177
|
// and validate the elements before the ordinary spread copy.
|
|
@@ -5554,7 +5695,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5554
5695
|
// declared number type.
|
|
5555
5696
|
if (recv.type.kind === "jsval")
|
|
5556
5697
|
return islandElementRead(lowerer, expr, recv);
|
|
5557
|
-
const index = lowerer.lowerExpr(expr.argumentExpression);
|
|
5698
|
+
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5558
5699
|
if (isJsSourceFile(expr.getSourceFile()) && recv.type.kind === "bytes") {
|
|
5559
5700
|
return {
|
|
5560
5701
|
kind: "dynKeyGet",
|
|
@@ -5811,36 +5952,12 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5811
5952
|
}
|
|
5812
5953
|
}
|
|
5813
5954
|
if (receiverIr?.kind === "string") {
|
|
5814
|
-
//
|
|
5815
|
-
//
|
|
5816
|
-
// noUncheckedIndexedAccess the checker types the read `string`,
|
|
5817
|
-
// and charAt's "" is the only string-typed answer for an
|
|
5818
|
-
// out-of-range or fractional index where JS reads `undefined` —
|
|
5819
|
-
// SEMANTICS.md documents the divergence; in-range integer reads
|
|
5820
|
-
// (the loop pattern) are JS-exact. Optional results instead retain
|
|
5821
|
-
// undefined for missing string properties.
|
|
5955
|
+
// An indexed string property is absent for non-integer and missing
|
|
5956
|
+
// indexes. charAt has different coercion and out-of-range semantics.
|
|
5822
5957
|
const recv = lowerer.lowerExpr(expr.expression);
|
|
5823
|
-
const index = lowerer.lowerExpr(expr.argumentExpression);
|
|
5824
|
-
const resultType = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
5958
|
+
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5825
5959
|
if (index.type.kind === "f64" && recv.type.kind === "string") {
|
|
5826
|
-
|
|
5827
|
-
return {
|
|
5828
|
-
kind: "strIntrinsic",
|
|
5829
|
-
method: "charAt",
|
|
5830
|
-
receiver: recv,
|
|
5831
|
-
args: [index],
|
|
5832
|
-
type: STRING,
|
|
5833
|
-
loc: locOf(expr),
|
|
5834
|
-
};
|
|
5835
|
-
}
|
|
5836
|
-
if (resultType?.kind === "union") {
|
|
5837
|
-
const arms = lowerer.unions.get(resultType.unionId)?.arms;
|
|
5838
|
-
if (arms?.length === 2 &&
|
|
5839
|
-
lowerer.armTag(resultType.unionId, STRING) >= 0 &&
|
|
5840
|
-
lowerer.armTag(resultType.unionId, UNDEFINED_T) >= 0) {
|
|
5841
|
-
return lowerOptionalStringIndex(lowerer, recv, index, resultType, locOf(expr));
|
|
5842
|
-
}
|
|
5843
|
-
}
|
|
5960
|
+
return lowerOptionalStringIndex(lowerer, recv, index, lowerer.withUndefinedArm(STRING), locOf(expr));
|
|
5844
5961
|
}
|
|
5845
5962
|
lowerer.unsupported("SC1090", expr, "string indexing with this index/result shape (expected a number index and a string or string | undefined result)");
|
|
5846
5963
|
}
|
|
@@ -5962,10 +6079,13 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5962
6079
|
// change the storage representation or the low-level getter itself.
|
|
5963
6080
|
if (arr.type.kind === "array") {
|
|
5964
6081
|
// A non-null assertion is the explicit proven-present form. Preserve
|
|
5965
|
-
// the dense getter's established bounds trap
|
|
5966
|
-
//
|
|
5967
|
-
//
|
|
5968
|
-
|
|
6082
|
+
// the dense getter's established bounds trap where the asserted value
|
|
6083
|
+
// must be the element type (library ABI checks and the catchable
|
|
6084
|
+
// RangeError contract for an out-of-bounds assert). Where undefined is
|
|
6085
|
+
// representable, the assertion keeps JavaScript's unchecked read.
|
|
6086
|
+
const provenPresent = ts.isNonNullExpression(expr.parent) &&
|
|
6087
|
+
expr.parent.expression === expr &&
|
|
6088
|
+
!assertedElementKeepsUndefined(lowerer, expr.parent);
|
|
5969
6089
|
if (provenPresent) {
|
|
5970
6090
|
return lowerer.maybeNarrow({ kind: "arrayGet", arr, index, type: elemT, loc: locOf(expr) }, expr);
|
|
5971
6091
|
}
|
|
@@ -5979,7 +6099,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5979
6099
|
arr.kind === "arrIntrinsic" &&
|
|
5980
6100
|
arr.method === "slice" &&
|
|
5981
6101
|
npmStaticPackageOfPath(expr.getSourceFile().fileName) !== null) {
|
|
5982
|
-
const safe =
|
|
6102
|
+
const safe = lowerSafeIndexRead(lowerer, arr, index, locOf(expr));
|
|
5983
6103
|
if (safe)
|
|
5984
6104
|
return safe;
|
|
5985
6105
|
}
|
|
@@ -6225,6 +6345,10 @@ export function lowerAbsenceProbe(lowerer, node) {
|
|
|
6225
6345
|
expr = expr.expression;
|
|
6226
6346
|
}
|
|
6227
6347
|
if (ts.isPropertyAccessExpression(expr)) {
|
|
6348
|
+
// Namespace members are bindings, not fields of a runtime namespace
|
|
6349
|
+
// object. Their ordinary read already preserves optional storage.
|
|
6350
|
+
if (!expr.questionDotToken && nsMemberIdentOf(lowerer, expr))
|
|
6351
|
+
return null;
|
|
6228
6352
|
const target = lowerer.fieldTarget(expr);
|
|
6229
6353
|
if (target?.container === "class" &&
|
|
6230
6354
|
target.fieldType.kind === "union" &&
|
|
@@ -7187,6 +7311,19 @@ export function ensureString(lowerer, e, node) {
|
|
|
7187
7311
|
return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
|
|
7188
7312
|
}
|
|
7189
7313
|
}
|
|
7314
|
+
if (narrowed?.kind === "union" &&
|
|
7315
|
+
!typeEquals(narrowed, e.type) &&
|
|
7316
|
+
lowerer.unions
|
|
7317
|
+
.get(narrowed.unionId)
|
|
7318
|
+
?.arms.every((arm) => isUnitType(arm) ||
|
|
7319
|
+
arm.kind === "string" ||
|
|
7320
|
+
arm.kind === "f64" ||
|
|
7321
|
+
arm.kind === "bool" ||
|
|
7322
|
+
arm.kind === "bigint")) {
|
|
7323
|
+
const helper = lowerer.narrowedRetagHelper(node, e.type.unionId, narrowed.unionId, e.loc);
|
|
7324
|
+
if (helper)
|
|
7325
|
+
return ensureString(lowerer, { kind: "call", callee: helper, args: [e], type: narrowed, loc: e.loc }, node);
|
|
7326
|
+
}
|
|
7190
7327
|
lowerer.unsupported("SC1090", node, `string conversions of unions with object arms (${NARROW_FIRST})`);
|
|
7191
7328
|
}
|
|
7192
7329
|
if (e.type.kind === "symbol") {
|
|
@@ -7360,20 +7497,16 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7360
7497
|
};
|
|
7361
7498
|
}
|
|
7362
7499
|
}
|
|
7363
|
-
//
|
|
7364
|
-
//
|
|
7365
|
-
//
|
|
7366
|
-
// (`/** @type {T} */ (e)` — JS has no `as`); 5.9.3 parsed that as a
|
|
7367
|
-
// plain parenthesized read, which lowered caught→dyn and met the
|
|
7368
|
-
// target through the ordinary checked-cast coercion — so the dyn
|
|
7369
|
-
// bridge stays open here exactly for that shape.
|
|
7500
|
+
// Structural assertions use the ordinary checked dynamic bridge. It
|
|
7501
|
+
// retains primitive values and native class identity before validating
|
|
7502
|
+
// the requested shape; an assertion does not bypass runtime checks.
|
|
7370
7503
|
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(expr.expression));
|
|
7371
7504
|
const bridged = narrowed &&
|
|
7372
7505
|
(narrowed.kind === "f64" ||
|
|
7373
7506
|
narrowed.kind === "bool" ||
|
|
7374
7507
|
narrowed.kind === "string" ||
|
|
7375
7508
|
narrowed.kind === "object" ||
|
|
7376
|
-
|
|
7509
|
+
narrowed.kind === "dyn");
|
|
7377
7510
|
if (!bridged)
|
|
7378
7511
|
lowerer.unsupported("SC1063", expr);
|
|
7379
7512
|
}
|
|
@@ -7625,11 +7758,11 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7625
7758
|
}
|
|
7626
7759
|
fenceNodeModuleMutation(lowerer, access, "assignment");
|
|
7627
7760
|
if (ts.isPropertyAccessExpression(access)) {
|
|
7628
|
-
const target = staticFieldWriteTarget(lowerer, access)
|
|
7761
|
+
const target = staticFieldWriteTarget(lowerer, access) ??
|
|
7762
|
+
expandoWritableTarget(lowerer, access) ??
|
|
7763
|
+
nsWritableTarget(lowerer, access);
|
|
7629
7764
|
if (target) {
|
|
7630
|
-
|
|
7631
|
-
lowerer.unsupported("SC1043", expr);
|
|
7632
|
-
return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
|
|
7765
|
+
return lowerIncDecTarget(lowerer, expr, target, prefix);
|
|
7633
7766
|
}
|
|
7634
7767
|
}
|
|
7635
7768
|
const stmts = [];
|
|
@@ -7741,10 +7874,18 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7741
7874
|
if (!target) {
|
|
7742
7875
|
lowerer.rejectUnresolved(expr.operand, `increment/decrement of '${expr.operand.text}' (not a writable local or module global)`);
|
|
7743
7876
|
}
|
|
7877
|
+
return lowerIncDecTarget(lowerer, expr, target, prefix);
|
|
7878
|
+
}
|
|
7879
|
+
/** Numeric updates read the represented slot once and write the computed
|
|
7880
|
+
* value back in that same representation. In particular, an unchecked
|
|
7881
|
+
* indexed initializer can leave undefined in an otherwise numeric binding. */
|
|
7882
|
+
export function lowerIncDecTarget(lowerer, expr, target, prefix) {
|
|
7883
|
+
const loc = locOf(expr);
|
|
7884
|
+
const op = expr.operator === ts.SyntaxKind.PlusPlusToken ? "+" : "-";
|
|
7744
7885
|
if (target.type.kind === "dyn") {
|
|
7745
7886
|
const old = lowerer.declareHiddenLocal("%numericOld", DYN);
|
|
7746
7887
|
const next = lowerer.declareHiddenLocal("%numericNext", DYN);
|
|
7747
|
-
const read =
|
|
7888
|
+
const read = varRef(target.id, target.type, loc);
|
|
7748
7889
|
return {
|
|
7749
7890
|
kind: "seqExpr",
|
|
7750
7891
|
stmts: [
|
|
@@ -7776,6 +7917,42 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7776
7917
|
loc,
|
|
7777
7918
|
};
|
|
7778
7919
|
}
|
|
7920
|
+
if (target.type.kind === "union") {
|
|
7921
|
+
const read = lowerOptionalNumber(lowerer, varRef(target.id, target.type, loc), loc, expr.operand);
|
|
7922
|
+
if (read.type.kind === "f64") {
|
|
7923
|
+
const old = lowerer.declareHiddenLocal("%numericOld", F64);
|
|
7924
|
+
const next = lowerer.declareHiddenLocal("%numericNext", F64);
|
|
7925
|
+
const result = varRef(prefix ? next.id : old.id, F64, loc);
|
|
7926
|
+
return {
|
|
7927
|
+
kind: "seqExpr",
|
|
7928
|
+
stmts: [
|
|
7929
|
+
{ kind: "varDecl", localId: old.id, init: read, loc },
|
|
7930
|
+
{
|
|
7931
|
+
kind: "varDecl",
|
|
7932
|
+
localId: next.id,
|
|
7933
|
+
init: {
|
|
7934
|
+
kind: "bin",
|
|
7935
|
+
op,
|
|
7936
|
+
left: varRef(old.id, F64, loc),
|
|
7937
|
+
right: numLit(1, loc),
|
|
7938
|
+
type: F64,
|
|
7939
|
+
loc,
|
|
7940
|
+
},
|
|
7941
|
+
loc,
|
|
7942
|
+
},
|
|
7943
|
+
{
|
|
7944
|
+
kind: "assign",
|
|
7945
|
+
localId: target.id,
|
|
7946
|
+
value: lowerer.coerceInto(expr.operand, varRef(next.id, F64, loc), target.type),
|
|
7947
|
+
loc,
|
|
7948
|
+
},
|
|
7949
|
+
],
|
|
7950
|
+
result,
|
|
7951
|
+
type: F64,
|
|
7952
|
+
loc,
|
|
7953
|
+
};
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7779
7956
|
if (target.type.kind !== "f64")
|
|
7780
7957
|
lowerer.unsupported("SC1043", expr);
|
|
7781
7958
|
return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
|
|
@@ -8136,6 +8313,9 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8136
8313
|
const recv = tryLowerExpression(lowerer, expr.left.expression);
|
|
8137
8314
|
if (recv && recv.type.kind === "dyn")
|
|
8138
8315
|
return lowerDynMemberAssignment(lowerer, expr, recv);
|
|
8316
|
+
const unionWrite = lowerUnionFieldWrite(lowerer, expr.left, expr.right);
|
|
8317
|
+
if (unionWrite)
|
|
8318
|
+
return unionWrite;
|
|
8139
8319
|
const field = lowerer.fieldTarget(expr.left);
|
|
8140
8320
|
if (field) {
|
|
8141
8321
|
const recvTmp = lowerer.declareHiddenLocal("%setReceiver", field.obj.type);
|
|
@@ -8721,7 +8901,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8721
8901
|
const optionalStringPlus = lowerOptionalStringPlus();
|
|
8722
8902
|
if (optionalStringPlus)
|
|
8723
8903
|
return optionalStringPlus;
|
|
8724
|
-
|
|
8904
|
+
{
|
|
8725
8905
|
const primitive = (type) => type.kind === "f64" ||
|
|
8726
8906
|
type.kind === "string" ||
|
|
8727
8907
|
type.kind === "bool" ||
|
|
@@ -8827,6 +9007,13 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8827
9007
|
if (unitTest)
|
|
8828
9008
|
return unitTest;
|
|
8829
9009
|
if (left.type.kind === "union" || right.type.kind === "union") {
|
|
9010
|
+
const compared = lowerUnionEquality(lowerer, left, right, negated, false, loc);
|
|
9011
|
+
if (compared)
|
|
9012
|
+
return compared;
|
|
9013
|
+
const aliasRefusal = (type) => {
|
|
9014
|
+
if (tagEqualityMayMissAlias(lowerer, type))
|
|
9015
|
+
lowerer.unsupported("SC1090", expr, `comparisons of related class values beside structural union members (${NARROW_FIRST})`);
|
|
9016
|
+
};
|
|
8830
9017
|
// JS strict equality of the ARM values, per union tag (a
|
|
8831
9018
|
// per-union helper): equal tags compare payloads (f64 ==, string
|
|
8832
9019
|
// bytes, bool ==, ref-arm POINTER identity), different tags are
|
|
@@ -8862,6 +9049,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8862
9049
|
};
|
|
8863
9050
|
}
|
|
8864
9051
|
if ((sameUnion || !bothUnion) && lowerer.eqComparableUnion(ut.unionId)) {
|
|
9052
|
+
aliasRefusal(ut);
|
|
8865
9053
|
return {
|
|
8866
9054
|
kind: "unionEq",
|
|
8867
9055
|
unionId: ut.unionId,
|
|
@@ -8892,6 +9080,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8892
9080
|
kind: "union",
|
|
8893
9081
|
unionId: lowerer.unions.intern(arms),
|
|
8894
9082
|
};
|
|
9083
|
+
aliasRefusal(common);
|
|
8895
9084
|
return {
|
|
8896
9085
|
kind: "unionEq",
|
|
8897
9086
|
unionId: common.unionId,
|
|
@@ -10037,17 +10226,30 @@ export function caughtRead(lowerer, node, local, loc) {
|
|
|
10037
10226
|
}
|
|
10038
10227
|
if (narrowed?.kind === "object") {
|
|
10039
10228
|
const info = lowerer.classes.get(narrowed.className);
|
|
10040
|
-
if (info
|
|
10041
|
-
|
|
10229
|
+
if (info) {
|
|
10230
|
+
const value = { kind: "caughtNarrow", value: ref, type: narrowed, loc };
|
|
10231
|
+
if (lowerer.inHierarchy(info))
|
|
10232
|
+
return value;
|
|
10233
|
+
return {
|
|
10234
|
+
kind: "ternary",
|
|
10235
|
+
cond: {
|
|
10236
|
+
kind: "caughtTest",
|
|
10237
|
+
value: ref,
|
|
10238
|
+
test: "instanceof",
|
|
10239
|
+
className: info.def.name,
|
|
10240
|
+
type: BOOL,
|
|
10241
|
+
loc,
|
|
10242
|
+
},
|
|
10243
|
+
then: value,
|
|
10244
|
+
else_: lowerer.coerceInto(node, { kind: "caughtToDyn", value: ref, type: DYN, loc }, narrowed),
|
|
10245
|
+
type: narrowed,
|
|
10246
|
+
loc,
|
|
10247
|
+
};
|
|
10042
10248
|
}
|
|
10043
10249
|
}
|
|
10044
|
-
//
|
|
10045
|
-
//
|
|
10046
|
-
//
|
|
10047
|
-
// extended to exception payloads. Error payloads keep their
|
|
10048
|
-
// observability (instanceof Error / .message / String() — the checked-dynamic tree's
|
|
10049
|
-
// error encoding); other object payloads are type-erased at runtime and
|
|
10050
|
-
// convert to the "[object Object]" approximation — SEMANTICS.md 67.
|
|
10250
|
+
// Unnarrowed reads cross into unknown. The caught-value dispatch pass
|
|
10251
|
+
// retains known native class payloads through live identity capsules;
|
|
10252
|
+
// other payload kinds use the runtime's ordinary conversion.
|
|
10051
10253
|
if (narrowed?.kind === "dyn") {
|
|
10052
10254
|
return { kind: "caughtToDyn", value: ref, type: DYN, loc };
|
|
10053
10255
|
}
|
|
@@ -10113,6 +10315,38 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10113
10315
|
(lowerer.isStdlibGlobal(expr.right, "Set") || lowerer.isStdlibGlobal(expr.right, "Map"))) {
|
|
10114
10316
|
const collection = lowerer.isStdlibGlobal(expr.right, "Map") ? "map" : "set";
|
|
10115
10317
|
const value = lowerer.lowerExpr(expr.left);
|
|
10318
|
+
if (value.type.kind === "union") {
|
|
10319
|
+
const union = lowerer.unions.get(value.type.unionId);
|
|
10320
|
+
if (union) {
|
|
10321
|
+
const local = lowerer.declareHiddenLocal("%collectionTest", value.type);
|
|
10322
|
+
const reference = varRef(local.id, value.type, loc);
|
|
10323
|
+
let result = { kind: "boolLit", value: false, type: BOOL, loc };
|
|
10324
|
+
union.arms.forEach((arm, tag) => {
|
|
10325
|
+
if (arm.kind !== collection)
|
|
10326
|
+
return;
|
|
10327
|
+
const test = {
|
|
10328
|
+
kind: "unionIsTag",
|
|
10329
|
+
unionId: union.id,
|
|
10330
|
+
value: reference,
|
|
10331
|
+
tag,
|
|
10332
|
+
negated: false,
|
|
10333
|
+
type: BOOL,
|
|
10334
|
+
loc,
|
|
10335
|
+
};
|
|
10336
|
+
result =
|
|
10337
|
+
result.kind === "boolLit"
|
|
10338
|
+
? test
|
|
10339
|
+
: { kind: "logical", op: "||", left: result, right: test, type: BOOL, loc };
|
|
10340
|
+
});
|
|
10341
|
+
return {
|
|
10342
|
+
kind: "seqExpr",
|
|
10343
|
+
stmts: [{ kind: "varDecl", localId: local.id, init: value, loc }],
|
|
10344
|
+
result,
|
|
10345
|
+
type: BOOL,
|
|
10346
|
+
loc,
|
|
10347
|
+
};
|
|
10348
|
+
}
|
|
10349
|
+
}
|
|
10116
10350
|
if (value.type.kind === "dyn")
|
|
10117
10351
|
return {
|
|
10118
10352
|
kind: "libCall",
|
|
@@ -10390,8 +10624,22 @@ export function lowerInstanceOf(lowerer, expr, loc) {
|
|
|
10390
10624
|
const caughtLocal = lowerer.caughtLocalOf(expr.left);
|
|
10391
10625
|
if (caughtLocal) {
|
|
10392
10626
|
if (!lowerer.inHierarchy(target)) {
|
|
10393
|
-
|
|
10394
|
-
|
|
10627
|
+
const value = varRef(caughtLocal.id, CAUGHT, loc);
|
|
10628
|
+
return {
|
|
10629
|
+
kind: "ternary",
|
|
10630
|
+
cond: {
|
|
10631
|
+
kind: "caughtTest",
|
|
10632
|
+
value,
|
|
10633
|
+
test: "instanceof",
|
|
10634
|
+
className: target.def.name,
|
|
10635
|
+
type: BOOL,
|
|
10636
|
+
loc,
|
|
10637
|
+
},
|
|
10638
|
+
then: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
10639
|
+
else_: classInstanceOf(lowerer, { kind: "caughtToDyn", value, type: DYN, loc }, target, loc),
|
|
10640
|
+
type: BOOL,
|
|
10641
|
+
loc,
|
|
10642
|
+
};
|
|
10395
10643
|
}
|
|
10396
10644
|
return {
|
|
10397
10645
|
kind: "caughtTest",
|
|
@@ -10689,11 +10937,10 @@ function lowerPrivateIn(lowerer, expr, priv, loc) {
|
|
|
10689
10937
|
* type-directed: a declared non-optional field is a compile-time `true`,
|
|
10690
10938
|
* a missing field (no index signature) a compile-time `false` — both
|
|
10691
10939
|
* folds limited to side-effect-free receivers, the lowerInstanceOf rule —
|
|
10692
|
-
* and an OPTIONAL field (undefined-armed union) is a runtime
|
|
10693
|
-
* the slot:
|
|
10694
|
-
*
|
|
10695
|
-
*
|
|
10696
|
-
* false here; SEMANTICS.md 55). Union receivers (the `in`-narrowing
|
|
10940
|
+
* and an OPTIONAL field (undefined-armed union) is a runtime presence
|
|
10941
|
+
* test on the slot: an omitted or deleted property is absent, while a
|
|
10942
|
+
* property explicitly holding `undefined` is present, as in JS
|
|
10943
|
+
* (`"a" in {a: undefined}` is true). Union receivers (the `in`-narrowing
|
|
10697
10944
|
* idiom over multiple shapes), index-signature keys, class instances,
|
|
10698
10945
|
* and dyn/unknown stay fenced. Keys are literal strings — a computed key
|
|
10699
10946
|
* over a shape would need the runtime key table. */
|
|
@@ -10737,13 +10984,42 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
10737
10984
|
}
|
|
10738
10985
|
}
|
|
10739
10986
|
}
|
|
10987
|
+
// A RUNTIME numeric key over an ARRAY receiver (`if (i in arr)` in a
|
|
10988
|
+
// loop) asks the same slot/property presence query as the literal fold
|
|
10989
|
+
// above and `Object.hasOwn`. The checked-dynamic fallback below would
|
|
10990
|
+
// box the receiver and materialize every element on each evaluation,
|
|
10991
|
+
// which makes such loops quadratic. A Number key never names an
|
|
10992
|
+
// inherited property: neither Array.prototype nor Object.prototype has
|
|
10993
|
+
// index-like or numeric-string keys. JS evaluates the key before the
|
|
10994
|
+
// receiver, so the key is stabilized in a hidden local first.
|
|
10995
|
+
if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind === "f64" &&
|
|
10996
|
+
lowerer.mapTypeOf(lowerer.typeOf(expr.right))?.kind === "array") {
|
|
10997
|
+
const k = lowerer.lowerExpr(expr.left);
|
|
10998
|
+
const recvArr = lowerer.lowerExpr(expr.right);
|
|
10999
|
+
if (k.type.kind === "f64" && recvArr.type.kind === "array") {
|
|
11000
|
+
const keyLocal = lowerer.declareHiddenLocal("%inIndex", F64);
|
|
11001
|
+
return {
|
|
11002
|
+
kind: "seqExpr",
|
|
11003
|
+
stmts: [{ kind: "varDecl", localId: keyLocal.id, init: k, loc }],
|
|
11004
|
+
result: {
|
|
11005
|
+
kind: "arrayHas",
|
|
11006
|
+
arr: recvArr,
|
|
11007
|
+
index: varRef(keyLocal.id, F64, loc),
|
|
11008
|
+
type: BOOL,
|
|
11009
|
+
loc,
|
|
11010
|
+
},
|
|
11011
|
+
type: BOOL,
|
|
11012
|
+
loc,
|
|
11013
|
+
};
|
|
11014
|
+
}
|
|
11015
|
+
}
|
|
10740
11016
|
const key = foldedStringKeyOf(lowerer, expr.left);
|
|
10741
11017
|
if (key === null) {
|
|
10742
11018
|
// A RUNTIME string key over an INDEX-SIGNATURE record receiver (the
|
|
10743
11019
|
// `names.filter((k) => k in config)` idiom): the interned key-
|
|
10744
11020
|
// presence helper — declared fields answer statically per name
|
|
10745
|
-
// (optional slots
|
|
10746
|
-
//
|
|
11021
|
+
// (optional slots by their runtime presence), then the overflow
|
|
11022
|
+
// map's live keys. Other receivers keep the
|
|
10747
11023
|
// fence: fixed shapes want the literal folds above, and there is no
|
|
10748
11024
|
// runtime key table to ask.
|
|
10749
11025
|
const rIn = lowerRuntimeKeyIn(lowerer, expr, loc);
|
|
@@ -10986,24 +11262,9 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
10986
11262
|
const field = shape.fields.find((f) => f.name === key);
|
|
10987
11263
|
if (field) {
|
|
10988
11264
|
if (field.type.kind === "union" && lowerer.armTag(field.type.unionId, UNDEFINED_T) >= 0) {
|
|
10989
|
-
// Optional slot: the key is present
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
obj: recv,
|
|
10993
|
-
shapeId: recv.type.shapeId,
|
|
10994
|
-
field: key,
|
|
10995
|
-
type: field.type,
|
|
10996
|
-
loc,
|
|
10997
|
-
};
|
|
10998
|
-
return {
|
|
10999
|
-
kind: "unionIsTag",
|
|
11000
|
-
unionId: field.type.unionId,
|
|
11001
|
-
tag: lowerer.armTag(field.type.unionId, UNDEFINED_T),
|
|
11002
|
-
negated: true,
|
|
11003
|
-
value: read,
|
|
11004
|
-
type: BOOL,
|
|
11005
|
-
loc,
|
|
11006
|
-
};
|
|
11265
|
+
// Optional slot: the key is present unless the field is absent
|
|
11266
|
+
// (omitted or deleted); an explicit undefined is present.
|
|
11267
|
+
return lowerer.recordFieldPresent(recv, recv.type.shapeId, key, loc);
|
|
11007
11268
|
}
|
|
11008
11269
|
// A declared non-optional field always exists on every value of the
|
|
11009
11270
|
// shape — statically true, but folding may only drop a
|
|
@@ -11043,9 +11304,9 @@ function lowerInExpression(lowerer, expr, loc) {
|
|
|
11043
11304
|
* runtime string and r an index-signature record — an interned
|
|
11044
11305
|
* `%rec.haskey.<n>(k, r)` walks the declared names (a string-equality
|
|
11045
11306
|
* chain: non-optional fields and accessor slots answer true, optional
|
|
11046
|
-
* slots answer their per-value tag test) and then the overflow
|
|
11047
|
-
*
|
|
11048
|
-
* its fence). */
|
|
11307
|
+
* slots answer their per-value tag test) and then probes the overflow
|
|
11308
|
+
* map's hashed key set. Null when the pair is outside that shape (the
|
|
11309
|
+
* caller keeps its fence). */
|
|
11049
11310
|
function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
11050
11311
|
if (lowerer.mapTypeOf(lowerer.typeOf(expr.left))?.kind !== "string")
|
|
11051
11312
|
return null;
|
|
@@ -11080,62 +11341,15 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
|
11080
11341
|
type: BOOL,
|
|
11081
11342
|
loc,
|
|
11082
11343
|
};
|
|
11083
|
-
const
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
kind: "unionIsTag",
|
|
11087
|
-
unionId: f.type.unionId,
|
|
11088
|
-
tag: utag,
|
|
11089
|
-
negated: true,
|
|
11090
|
-
value: {
|
|
11091
|
-
kind: "recordGet",
|
|
11092
|
-
obj: r,
|
|
11093
|
-
shapeId: recvT.shapeId,
|
|
11094
|
-
field: f.name,
|
|
11095
|
-
type: f.type,
|
|
11096
|
-
loc,
|
|
11097
|
-
},
|
|
11098
|
-
type: BOOL,
|
|
11099
|
-
loc,
|
|
11100
|
-
}
|
|
11101
|
-
: { kind: "boolLit", value: true, type: BOOL, loc };
|
|
11344
|
+
const answer = accessor
|
|
11345
|
+
? { kind: "boolLit", value: true, type: BOOL, loc }
|
|
11346
|
+
: lowerer.recordFieldPresent(r, recvT.shapeId, f.name, loc);
|
|
11102
11347
|
body.push({ kind: "if", cond: eq, then: [ret(answer)], else_: null, loc });
|
|
11103
11348
|
}
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
init: { kind: "recordOvfKeys", obj: r, shapeId: recvT.shapeId, type: ksT, loc },
|
|
11109
|
-
loc,
|
|
11110
|
-
}, countedFor(loc, {
|
|
11111
|
-
kind: "arrIntrinsic",
|
|
11112
|
-
method: "length",
|
|
11113
|
-
receiver: varRef("ks.0", ksT, loc),
|
|
11114
|
-
args: [],
|
|
11115
|
-
type: F64,
|
|
11116
|
-
loc,
|
|
11117
|
-
}, () => [
|
|
11118
|
-
{
|
|
11119
|
-
kind: "if",
|
|
11120
|
-
cond: {
|
|
11121
|
-
kind: "strEq",
|
|
11122
|
-
negated: false,
|
|
11123
|
-
left: k,
|
|
11124
|
-
right: {
|
|
11125
|
-
kind: "arrayGet",
|
|
11126
|
-
arr: varRef("ks.0", ksT, loc),
|
|
11127
|
-
index: varRef("i.0", F64, loc),
|
|
11128
|
-
type: STRING,
|
|
11129
|
-
loc,
|
|
11130
|
-
},
|
|
11131
|
-
type: BOOL,
|
|
11132
|
-
loc,
|
|
11133
|
-
},
|
|
11134
|
-
then: [ret({ kind: "boolLit", value: true, type: BOOL, loc })],
|
|
11135
|
-
else_: null,
|
|
11136
|
-
loc,
|
|
11137
|
-
},
|
|
11138
|
-
]), ret({ kind: "boolLit", value: false, type: BOOL, loc }));
|
|
11349
|
+
// Overflow keys answer through the map's hashed presence probe (a
|
|
11350
|
+
// stored undefined value is still present), not a scan over a fresh
|
|
11351
|
+
// key snapshot, which made `k in dict` loops quadratic.
|
|
11352
|
+
body.push(ret({ kind: "recordOvfHas", obj: r, shapeId: recvT.shapeId, key: k, type: BOOL, loc }));
|
|
11139
11353
|
lowerer.liftedFns.push({
|
|
11140
11354
|
name: helper,
|
|
11141
11355
|
params: [
|
|
@@ -11146,8 +11360,6 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
|
|
|
11146
11360
|
locals: [
|
|
11147
11361
|
{ id: "k.0", name: "k", type: STRING, mutable: true },
|
|
11148
11362
|
{ id: "r.0", name: "r", type: recT, mutable: true },
|
|
11149
|
-
{ id: "ks.0", name: "ks", type: ksT, mutable: false },
|
|
11150
|
-
{ id: "i.0", name: "i", type: F64, mutable: true },
|
|
11151
11363
|
],
|
|
11152
11364
|
body,
|
|
11153
11365
|
loc,
|
|
@@ -11835,7 +12047,7 @@ export function lowerUnionProperty(lowerer, expr) {
|
|
|
11835
12047
|
return null;
|
|
11836
12048
|
}
|
|
11837
12049
|
if (value.type.kind !== "union") {
|
|
11838
|
-
|
|
12050
|
+
lowerer.unsupported("SC1090", expr, "shared property access without a represented union receiver");
|
|
11839
12051
|
}
|
|
11840
12052
|
const def = lowerer.unions.get(value.type.unionId);
|
|
11841
12053
|
if (!def)
|
|
@@ -12212,11 +12424,32 @@ export function fieldTarget(lowerer, access) {
|
|
|
12212
12424
|
const stored = ts.isIdentifier(access.expression)
|
|
12213
12425
|
? (lowerer.peekLocal(access.expression)?.type ?? lowerer.globalOf(access.expression)?.type)
|
|
12214
12426
|
: undefined;
|
|
12215
|
-
const
|
|
12427
|
+
const narrowed = lowerer.mapTypeOf(lowerer.typeOf(access.expression));
|
|
12428
|
+
// Structural record views retain their storage layout, while a nominal
|
|
12429
|
+
// subclass guard proves a more specific layout of the same object.
|
|
12430
|
+
const receiverIr = stored?.kind === "record"
|
|
12216
12431
|
? stored
|
|
12217
|
-
:
|
|
12432
|
+
: stored?.kind === "object" &&
|
|
12433
|
+
!(narrowed?.kind === "object" &&
|
|
12434
|
+
lowerer.isSubclassOf(narrowed.className, stored.className))
|
|
12435
|
+
? stored
|
|
12436
|
+
: narrowed;
|
|
12218
12437
|
if (receiverIr?.kind === "object") {
|
|
12219
|
-
|
|
12438
|
+
const target = classFieldTarget(lowerer, access.expression, receiverIr, access.name.text);
|
|
12439
|
+
if (target)
|
|
12440
|
+
return target;
|
|
12441
|
+
// Abstract properties declare no base storage. Resolve the concrete
|
|
12442
|
+
// instance's live field or accessor through the existing class bridge;
|
|
12443
|
+
// inventing a shared field offset would misread subclass layouts.
|
|
12444
|
+
if (abstractPropertyDeclOf(lowerer, access)) {
|
|
12445
|
+
return {
|
|
12446
|
+
container: "dynamic",
|
|
12447
|
+
obj: lowerer.coerceInto(access.expression, lowerer.lowerExpr(access.expression), DYN),
|
|
12448
|
+
field: access.name.text,
|
|
12449
|
+
fieldType: lowerer.irTypeOf(access),
|
|
12450
|
+
};
|
|
12451
|
+
}
|
|
12452
|
+
return null;
|
|
12220
12453
|
}
|
|
12221
12454
|
if (receiverIr?.kind === "union" && hasClassPayload(lowerer, receiverIr)) {
|
|
12222
12455
|
return representedClassFieldTarget(lowerer, access.expression, access.name.text, lowerer.lowerExpr(access.expression));
|
|
@@ -12457,13 +12690,13 @@ function symbolFieldTarget(lowerer, expr) {
|
|
|
12457
12690
|
* undefined, which these property types cannot represent. */
|
|
12458
12691
|
export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
12459
12692
|
if (target.container === "dynamic")
|
|
12460
|
-
return {
|
|
12693
|
+
return lowerer.coerceInto(blame, {
|
|
12461
12694
|
kind: "dynKeyGet",
|
|
12462
12695
|
value: target.obj,
|
|
12463
12696
|
key: { kind: "strLit", value: target.field, type: STRING, loc },
|
|
12464
12697
|
type: DYN,
|
|
12465
12698
|
loc,
|
|
12466
|
-
};
|
|
12699
|
+
}, target.fieldType);
|
|
12467
12700
|
if (target.container === "class" &&
|
|
12468
12701
|
(target.field === "message" || target.field === "name") &&
|
|
12469
12702
|
(target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
|