@scriptc/compiler 0.2.7 → 0.2.8
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 +2 -0
- package/dist/backend/llvm/alloc.d.ts +3 -0
- package/dist/backend/llvm/alloc.js +54 -13
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +9 -0
- package/dist/backend/llvm/blocks.js +9 -0
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/borrowed-receivers.d.ts +7 -0
- package/dist/backend/llvm/borrowed-receivers.js +39 -0
- package/dist/backend/llvm/borrowed-receivers.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.d.ts +4 -1
- package/dist/backend/llvm/call-lifetimes.js +14 -3
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +8 -3
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.d.ts +24 -0
- package/dist/backend/llvm/checked-narrows.js +108 -0
- package/dist/backend/llvm/checked-narrows.js.map +1 -0
- package/dist/backend/llvm/checked-narrows.test.d.ts +1 -0
- package/dist/backend/llvm/checked-narrows.test.js +208 -0
- package/dist/backend/llvm/checked-narrows.test.js.map +1 -0
- package/dist/backend/llvm/classes.d.ts +13 -1
- package/dist/backend/llvm/classes.js +26 -18
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +32 -3
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/debug-info.d.ts +6 -2
- package/dist/backend/llvm/debug-info.js +11 -1
- package/dist/backend/llvm/debug-info.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +89 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +4 -0
- package/dist/backend/llvm/dyn.js +31 -20
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +184 -11
- package/dist/backend/llvm/emitter.js +1189 -125
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +21 -1
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +4 -4
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +1 -1
- package/dist/backend/llvm/expr-bytes.js +85 -8
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +29 -21
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +5 -0
- package/dist/backend/llvm/expr-calls.js +55 -10
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +7 -1
- package/dist/backend/llvm/expr-containers.js +230 -27
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +25 -10
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +72 -21
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-island.js +3 -8
- package/dist/backend/llvm/expr-island.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +41 -12
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +50 -2
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +28 -14
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +41 -31
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.js +6 -3
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/layouts.d.ts +2 -1
- package/dist/backend/llvm/layouts.js +2 -2
- package/dist/backend/llvm/layouts.js.map +1 -1
- package/dist/backend/llvm/lib-abi.js +10 -0
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +7 -11
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +8 -8
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +1 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +73 -13
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +7 -3
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.js +10 -6
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +3 -2
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +18 -0
- package/dist/backend/llvm/map-number-lookup.js +62 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +6 -0
- package/dist/backend/llvm/map-read-lifetimes.js +24 -3
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +38 -19
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +68 -0
- package/dist/backend/llvm/nullable-unions.js +132 -0
- package/dist/backend/llvm/nullable-unions.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +58 -0
- package/dist/backend/llvm/publish.js +286 -0
- package/dist/backend/llvm/publish.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.d.ts +12 -0
- package/dist/backend/llvm/rebound-parameters.js +72 -0
- package/dist/backend/llvm/rebound-parameters.js.map +1 -0
- package/dist/backend/llvm/rebound-parameters.test.d.ts +1 -0
- package/dist/backend/llvm/rebound-parameters.test.js +67 -0
- package/dist/backend/llvm/rebound-parameters.test.js.map +1 -0
- package/dist/backend/llvm/reference-effects.d.ts +18 -2
- package/dist/backend/llvm/reference-effects.js +106 -16
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-effects.test.js +52 -1
- package/dist/backend/llvm/reference-effects.test.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +45 -17
- package/dist/backend/llvm/shapes.js +131 -53
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +33 -8
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +5 -2
- package/dist/backend/llvm/stack-unions.test.js.map +1 -1
- package/dist/backend/llvm/string-construction.d.ts +10 -0
- package/dist/backend/llvm/string-construction.js +42 -0
- package/dist/backend/llvm/string-construction.js.map +1 -1
- package/dist/backend/llvm/string-key-hash.d.ts +9 -2
- package/dist/backend/llvm/string-key-hash.js +20 -3
- package/dist/backend/llvm/string-key-hash.js.map +1 -1
- package/dist/backend/llvm/string-key-hash.test.js +14 -3
- package/dist/backend/llvm/string-key-hash.test.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +24 -11
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +7 -0
- package/dist/backend/llvm/string-reads.js +76 -0
- package/dist/backend/llvm/string-reads.js.map +1 -0
- package/dist/backend/llvm/switch-dispatch.test.js +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js.map +1 -1
- package/dist/backend/llvm/test-boxed-unions.d.ts +5 -0
- package/dist/backend/llvm/test-boxed-unions.js +13 -0
- package/dist/backend/llvm/test-boxed-unions.js.map +1 -0
- package/dist/backend/llvm/union-repr.d.ts +15 -0
- package/dist/backend/llvm/union-repr.js +89 -0
- package/dist/backend/llvm/union-repr.js.map +1 -0
- package/dist/backend/llvm/virtual-borrows.d.ts +31 -0
- package/dist/backend/llvm/virtual-borrows.js +82 -0
- package/dist/backend/llvm/virtual-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.d.ts +43 -0
- package/dist/backend/llvm/walk-borrows.js +150 -0
- package/dist/backend/llvm/walk-borrows.js.map +1 -0
- package/dist/backend/llvm/walk-borrows.test.d.ts +1 -0
- package/dist/backend/llvm/walk-borrows.test.js +119 -0
- package/dist/backend/llvm/walk-borrows.test.js.map +1 -0
- package/dist/backend/llvm/walkers.d.ts +5 -1
- package/dist/backend/llvm/walkers.js +24 -21
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.d.ts +29 -1
- package/dist/backend/may-throw.js +346 -3
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +113 -1
- package/dist/backend/may-throw.test.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 +7 -5
- package/dist/backend/native-codegen-core.js +14 -9
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.d.ts +4 -0
- package/dist/backend/native-codegen.js +49 -2
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +41 -10
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-tools.d.ts +2 -0
- package/dist/backend/native-tools.js +3 -0
- package/dist/backend/native-tools.js.map +1 -1
- package/dist/backend/publication.d.ts +28 -0
- package/dist/backend/publication.js +155 -0
- package/dist/backend/publication.js.map +1 -0
- package/dist/backend/publication.test.d.ts +1 -0
- package/dist/backend/publication.test.js +72 -0
- package/dist/backend/publication.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-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +1 -1
- package/dist/cli/command.js +70 -7
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -1
- package/dist/cli/usage.js +8 -1
- package/dist/cli/usage.js.map +1 -1
- package/dist/compile-types.d.ts +12 -3
- package/dist/coverage/report.d.ts +25 -2
- package/dist/coverage/report.js +161 -33
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +63 -0
- package/dist/coverage/verdict-cache.js +193 -0
- package/dist/coverage/verdict-cache.js.map +1 -0
- package/dist/coverage/verdict-cache.test.d.ts +1 -0
- package/dist/coverage/verdict-cache.test.js +52 -0
- package/dist/coverage/verdict-cache.test.js.map +1 -0
- package/dist/coverage/verdict-semantic.d.ts +2 -0
- package/dist/coverage/verdict-semantic.js +24 -0
- package/dist/coverage/verdict-semantic.js.map +1 -0
- package/dist/coverage/verdict-startup.d.ts +15 -0
- package/dist/coverage/verdict-startup.js +66 -0
- package/dist/coverage/verdict-startup.js.map +1 -0
- package/dist/diagnostics/diagnostic.d.ts +29 -1
- package/dist/diagnostics/diagnostic.js +74 -4
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +130 -0
- package/dist/diagnostics/envelope.js +257 -0
- package/dist/diagnostics/envelope.js.map +1 -0
- package/dist/diagnostics/envelope.test.d.ts +1 -0
- package/dist/diagnostics/envelope.test.js +91 -0
- package/dist/diagnostics/envelope.test.js.map +1 -0
- package/dist/diagnostics/render.d.ts +3 -0
- package/dist/diagnostics/render.js +13 -2
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/executable/prepare.d.ts +4 -0
- package/dist/executable/prepare.js +7 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +1 -0
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +7 -0
- package/dist/frontend/lowering/array-values.js +120 -4
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +29 -1
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +4 -0
- package/dist/frontend/lowering/builtins/process.js +10 -0
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.js +4 -2
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/class-assertions.d.ts +8 -0
- package/dist/frontend/lowering/class-assertions.js +217 -1
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.js +8 -5
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/coercions/state.d.ts +6 -0
- package/dist/frontend/lowering/coercions/state.js +2 -0
- package/dist/frontend/lowering/coercions/state.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +8 -0
- package/dist/frontend/lowering/coercions/unions.js +67 -2
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collation-repertoire.d.ts +1 -0
- package/dist/frontend/lowering/collation-repertoire.js +19 -0
- package/dist/frontend/lowering/collation-repertoire.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.d.ts +38 -0
- package/dist/frontend/lowering/construction-escapes.js +146 -0
- package/dist/frontend/lowering/construction-escapes.js.map +1 -0
- package/dist/frontend/lowering/construction-escapes.test.d.ts +1 -0
- package/dist/frontend/lowering/construction-escapes.test.js +150 -0
- package/dist/frontend/lowering/construction-escapes.test.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +81 -44
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +15 -2
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +231 -12
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +43 -1
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +7 -63
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +6 -1
- package/dist/frontend/lowering/cycle-initialization.js +59 -33
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/divergences.d.ts +9 -0
- package/dist/frontend/lowering/divergences.js +630 -0
- package/dist/frontend/lowering/divergences.js.map +1 -0
- package/dist/frontend/lowering/expressions/object-literals.js +40 -2
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +5 -0
- package/dist/frontend/lowering/lower-calls.js +226 -157
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +4 -0
- package/dist/frontend/lowering/lower-classes.js +72 -22
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +13 -0
- package/dist/frontend/lowering/lower-exprs.js +431 -107
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +19 -13
- package/dist/frontend/lowering/lower-generators.js +67 -44
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +3 -2
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +1 -1
- package/dist/frontend/lowering/lower-island.js +24 -7
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +90 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +36 -6
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +78 -2
- package/dist/frontend/lowering/lowerer.js +986 -73
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-bounds.d.ts +19 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js +354 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js +66 -0
- package/dist/frontend/lowering/runtime-optional-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +117 -0
- package/dist/frontend/lowering/runtime-optional-elements.js +738 -0
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.d.ts +36 -0
- package/dist/frontend/lowering/runtime-optional-guards.js +375 -0
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js +92 -0
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-ownership.d.ts +63 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js +382 -0
- package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-provenance.d.ts +2 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js +2 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -1
- package/dist/frontend/lowering/string-index-bounds.d.ts +36 -0
- package/dist/frontend/lowering/string-index-bounds.js +537 -0
- package/dist/frontend/lowering/string-index-bounds.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.d.ts +1 -0
- package/dist/frontend/lowering/string-index-bounds.test.js +223 -0
- package/dist/frontend/lowering/string-index-bounds.test.js.map +1 -0
- package/dist/frontend/lowering/union-narrow.d.ts +2 -0
- package/dist/frontend/lowering/union-narrow.js +10 -6
- package/dist/frontend/lowering/union-narrow.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +10 -0
- package/dist/frontend/program-analysis.js +7 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +25 -0
- package/dist/frontend/program.js +613 -17
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +64 -1
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.d.ts +6 -0
- package/dist/frontend/resolve.js +14 -0
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/threads-import.d.ts +5 -0
- package/dist/frontend/threads-import.js +21 -0
- package/dist/frontend/threads-import.js.map +1 -0
- package/dist/frontend/type-mapper.d.ts +3 -0
- package/dist/frontend/type-mapper.js +72 -6
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/worker-target.d.ts +4 -0
- package/dist/frontend/worker-target.js +8 -1
- package/dist/frontend/worker-target.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +47 -9
- package/dist/index.js.map +1 -1
- package/dist/ir/build.d.ts +5 -0
- package/dist/ir/build.js +7 -0
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +3 -0
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/int32-slots.d.ts +72 -0
- package/dist/ir/int32-slots.js +837 -0
- package/dist/ir/int32-slots.js.map +1 -0
- package/dist/ir/int32-slots.test.d.ts +1 -0
- package/dist/ir/int32-slots.test.js +222 -0
- package/dist/ir/int32-slots.test.js.map +1 -0
- package/dist/ir/integer-ranges.d.ts +19 -3
- package/dist/ir/integer-ranges.js +168 -23
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +74 -2
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +24 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/validate.js +21 -2
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +39 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/native/cache.d.ts +3 -0
- package/dist/native/cache.js +49 -1
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +21 -1
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +1 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.d.ts +5 -0
- package/dist/native/compiler.js +51 -4
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/prepare.d.ts +4 -0
- package/dist/native/prepare.js +2 -1
- package/dist/native/prepare.js.map +1 -1
- package/dist/startup-cache.d.ts +2 -0
- package/dist/startup-cache.js +2 -0
- package/dist/startup-cache.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +1 -1
|
@@ -2,6 +2,7 @@ import { generatorDrain } from "./iterator-adapters.js";
|
|
|
2
2
|
import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js";
|
|
3
3
|
import { isOptionalProcessStreamProperty } from "./builtins/process.js";
|
|
4
4
|
import { lowerWorkerMetadata } from "./builtins/workers.js";
|
|
5
|
+
import { threadsImportOf } from "../threads-import.js";
|
|
5
6
|
import { dynUndefinedExpr, nodeThrowExpr, numLit, strLit, varRef } from "../../ir/build.js";
|
|
6
7
|
import { InternalCompilerError } from "../../errors.js";
|
|
7
8
|
import { SYMBOL_T } from "../../ir/ir.js";
|
|
@@ -17,7 +18,7 @@ import * as ts from "../ts7/adapter.js";
|
|
|
17
18
|
import { constituentTypes } from "../ts7/checker.js";
|
|
18
19
|
import { dirname } from "node:path";
|
|
19
20
|
import * as posix from "node:path/posix";
|
|
20
|
-
import { checkedClassAssertion } from "./class-assertions.js";
|
|
21
|
+
import { checkedClassAssertion, checkedClassUnionAssertion } from "./class-assertions.js";
|
|
21
22
|
import { narrowClassUnion, narrowStoredClassValue } from "./class-unions.js";
|
|
22
23
|
import { lowerUnionFieldWrite } from "./expressions/union-field-write.js";
|
|
23
24
|
import { captureContextArguments } from "./function-context.js";
|
|
@@ -29,7 +30,7 @@ import { ARRAY_METHODS, builtinConstLit, builtinFenceHintOf, builtinModuleConstO
|
|
|
29
30
|
import { UNSUPPORTED, blockedBindingUseDiag, requiresDynamicPackageDiag, unsupportedDiag, } from "../../diagnostics/diagnostic.js";
|
|
30
31
|
import { PoisonError, dynFallbackType, jsFuncNameOf, neverTaintedJsType, own } from "./lowerer.js";
|
|
31
32
|
import { lowerCollectionSpread } from "./containers/collection-methods.js";
|
|
32
|
-
import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, } from "./array-values.js";
|
|
33
|
+
import { arrayValueRead, arrayValueStore, arrayValueType, lowerSafeIndexRead, tryLowerIndexTruthiness, tryLowerNumericIndexRead, lowerSafeBytesRead, } from "./array-values.js";
|
|
33
34
|
import { strCharsCall } from "./containers/array-construction.js";
|
|
34
35
|
import { lowerOptionalStringIndex } from "./string-index.js";
|
|
35
36
|
import { tryLowerIndexedComparison } from "./indexed-comparison.js";
|
|
@@ -294,6 +295,14 @@ function lowerExprInner(lowerer, expr) {
|
|
|
294
295
|
// traps. Sub-union assertions and non-union inners keep their
|
|
295
296
|
// historic erasure (the widening sites re-tag with traps already).
|
|
296
297
|
if (ts.isNonNullExpression(expr)) {
|
|
298
|
+
// An asserted element read forwarded into a slot that holds undefined
|
|
299
|
+
// (see analyzeRuntimeOptionalArrayReads) reads without the bounds trap.
|
|
300
|
+
if (lowerer.runtimeOptionalAssertions.has(expr) &&
|
|
301
|
+
ts.isElementAccessExpression(expr.expression)) {
|
|
302
|
+
const probe = lowerAbsenceProbe(lowerer, expr.expression);
|
|
303
|
+
if (probe?.type.kind === "union")
|
|
304
|
+
return probe;
|
|
305
|
+
}
|
|
297
306
|
const inner = lowerer.lowerExpr(expr.expression);
|
|
298
307
|
if (inner.type.kind === "union") {
|
|
299
308
|
// `!` performs no runtime check: a missing array element stays
|
|
@@ -301,14 +310,20 @@ function lowerExprInner(lowerer, expr) {
|
|
|
301
310
|
if (ts.isElementAccessExpression(expr.expression) &&
|
|
302
311
|
assertedElementKeepsUndefined(lowerer, expr))
|
|
303
312
|
return inner;
|
|
313
|
+
// A forwarded assertion whose destination was promoted to hold
|
|
314
|
+
// undefined (see analyzeRuntimeOptionalArrayReads), or an equality
|
|
315
|
+
// operand, keeps the value: `!` performs no runtime check.
|
|
316
|
+
const target = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
317
|
+
if (lowerer.runtimeOptionalAssertions.has(expr) ||
|
|
318
|
+
(target?.kind === "object" && isEqualityOperand(expr)))
|
|
319
|
+
return inner;
|
|
304
320
|
const use = runtimeOptionalUseOf(expr);
|
|
305
321
|
if (runtimeOptionalAssertionErases(lowerer, expr, inner, use))
|
|
306
322
|
return inner;
|
|
307
|
-
const target = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
308
323
|
if (target && target.kind !== "union" && !typeEquals(target, inner.type)) {
|
|
309
324
|
const helper = lowerer.narrowedArmHelper(inner.type.unionId, target, loc);
|
|
310
325
|
if (helper) {
|
|
311
|
-
return
|
|
326
|
+
return lowerer.checkedNarrowCall(helper, inner, target, loc);
|
|
312
327
|
}
|
|
313
328
|
}
|
|
314
329
|
return inner;
|
|
@@ -730,7 +745,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
730
745
|
// A known static result type fixes typeof's answer, but its producer
|
|
731
746
|
// still evaluates: calls, getters, and checked reads can have effects
|
|
732
747
|
// or throw. Only trivial operands may disappear.
|
|
733
|
-
let operand = lowerer.lowerExpr(expr.expression);
|
|
748
|
+
let operand = deferredSlotOr(lowerer, runtimeOptionalStorageOperand(lowerer, expr.expression) ?? lowerer.lowerExpr(expr.expression));
|
|
734
749
|
if (operand.type.kind === "jsval") {
|
|
735
750
|
return { kind: "jsOp", op: "typeof", args: [operand], type: STRING, loc };
|
|
736
751
|
}
|
|
@@ -949,13 +964,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
949
964
|
? lowerer.narrowedArmHelper(local.type.unionId, narrowed, loc)
|
|
950
965
|
: null;
|
|
951
966
|
if (helper) {
|
|
952
|
-
return
|
|
953
|
-
kind: "call",
|
|
954
|
-
callee: helper,
|
|
955
|
-
args: [varRef(local.id, local.type, loc)],
|
|
956
|
-
type: narrowed,
|
|
957
|
-
loc,
|
|
958
|
-
};
|
|
967
|
+
return lowerer.checkedNarrowCall(helper, varRef(local.id, local.type, loc), narrowed, loc);
|
|
959
968
|
}
|
|
960
969
|
}
|
|
961
970
|
}
|
|
@@ -993,7 +1002,10 @@ function lowerExprInner(lowerer, expr) {
|
|
|
993
1002
|
// that does not exist. The blocked-binding cascade names the use;
|
|
994
1003
|
// without this the validator's registration check ICEs on the live
|
|
995
1004
|
// reference (`@this {T}` inference — signature 07).
|
|
996
|
-
|
|
1005
|
+
const unregistered = lowerer.unregisteredClassOf(g.type, new Set());
|
|
1006
|
+
if (unregistered !== null) {
|
|
1007
|
+
// The class's own rejection is the root cause the cascade names.
|
|
1008
|
+
lowerer.flushDeferredClass(unregistered);
|
|
997
1009
|
lowerer.pushDiag(blockedBindingUseDiag(expr.text, loc));
|
|
998
1010
|
throw new PoisonError();
|
|
999
1011
|
}
|
|
@@ -1026,7 +1038,7 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1026
1038
|
lowerer.armTag(g.type.unionId, narrowed) >= 0) {
|
|
1027
1039
|
const helper = lowerer.narrowedArmHelper(g.type.unionId, narrowed, loc);
|
|
1028
1040
|
if (helper)
|
|
1029
|
-
return
|
|
1041
|
+
return lowerer.checkedNarrowCall(helper, ref, narrowed, loc);
|
|
1030
1042
|
}
|
|
1031
1043
|
const use = runtimeOptionalUseOf(expr);
|
|
1032
1044
|
// The enclosing logical/conditional expression consumes the union
|
|
@@ -1124,6 +1136,14 @@ function lowerExprInner(lowerer, expr) {
|
|
|
1124
1136
|
// as interned string literals; functions have no closure
|
|
1125
1137
|
// representation (they lower to libCall at call sites only); members
|
|
1126
1138
|
// with no lowering at all fence with the module-qualified name.
|
|
1139
|
+
{
|
|
1140
|
+
const member = threadsImportOf(lowerer.program, expr);
|
|
1141
|
+
// scriptc delivers published graphs by reference.
|
|
1142
|
+
if (member === "sharesPublishedGraphs")
|
|
1143
|
+
return { kind: "boolLit", value: true, type: BOOL, loc };
|
|
1144
|
+
if (member === "publish")
|
|
1145
|
+
lowerer.noLowering("publish (@scriptc/threads) as a value", expr, "call publish(value) directly");
|
|
1146
|
+
}
|
|
1127
1147
|
{
|
|
1128
1148
|
const bi = lowerer.builtinImportOf(expr);
|
|
1129
1149
|
if (bi) {
|
|
@@ -3299,13 +3319,7 @@ function runtimeOptionalReceiverRead(lowerer, expr, local, property, loc) {
|
|
|
3299
3319
|
if (!helper) {
|
|
3300
3320
|
lowerer.unsupported("SC1090", expr, "a direct read from a runtime-optional capture with multiple value arms");
|
|
3301
3321
|
}
|
|
3302
|
-
return
|
|
3303
|
-
kind: "call",
|
|
3304
|
-
callee: helper,
|
|
3305
|
-
args: [varRef(local.id, local.type, loc)],
|
|
3306
|
-
type: narrowed,
|
|
3307
|
-
loc,
|
|
3308
|
-
};
|
|
3322
|
+
return lowerer.checkedNarrowCall(helper, varRef(local.id, local.type, loc), narrowed, loc);
|
|
3309
3323
|
}
|
|
3310
3324
|
// A predicate can strengthen a record's fields or narrow a base class
|
|
3311
3325
|
// to a subclass without changing the slot's stored value arm. Extract
|
|
@@ -3438,6 +3452,18 @@ function runtimeOptionalElementKey(expr) {
|
|
|
3438
3452
|
return expr.text;
|
|
3439
3453
|
return null;
|
|
3440
3454
|
}
|
|
3455
|
+
/** An operand of `===`, `!==`, `==` or `!=` (through parentheses). */
|
|
3456
|
+
function isEqualityOperand(node) {
|
|
3457
|
+
let outer = node;
|
|
3458
|
+
while (ts.isParenthesizedExpression(outer.parent))
|
|
3459
|
+
outer = outer.parent;
|
|
3460
|
+
const parent = outer.parent;
|
|
3461
|
+
return (ts.isBinaryExpression(parent) &&
|
|
3462
|
+
(parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
3463
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
3464
|
+
parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
|
|
3465
|
+
parent.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken));
|
|
3466
|
+
}
|
|
3441
3467
|
/** Whether `xs[i]!` lands where an absent element's undefined is
|
|
3442
3468
|
* representable: array storage (a literal element, a push/unshift
|
|
3443
3469
|
* argument, an element assignment — arrays record the undefined state),
|
|
@@ -3505,6 +3531,17 @@ export function lowerUnitComparison(lowerer, left, right, negated, loc) {
|
|
|
3505
3531
|
// Two unit literals (`undefined === undefined`): statically decided.
|
|
3506
3532
|
return { kind: "boolLit", value: (other.unit === unit.unit) !== negated, type: BOOL, loc };
|
|
3507
3533
|
}
|
|
3534
|
+
const slot = lowerer.deferredFieldSlot(other);
|
|
3535
|
+
if (slot)
|
|
3536
|
+
return lowerUnitComparison(lowerer, slot, unit, negated, loc);
|
|
3537
|
+
// A binding the checker narrowed past the unit can still hold it at
|
|
3538
|
+
// runtime when its value came from an unassigned deferred-init field;
|
|
3539
|
+
// the stored tag answers either way.
|
|
3540
|
+
if (other.kind === "unionNarrow" &&
|
|
3541
|
+
other.value.kind === "varRef" &&
|
|
3542
|
+
other.value.type.kind === "union" &&
|
|
3543
|
+
lowerer.armTag(other.value.type.unionId, unit.type) >= 0)
|
|
3544
|
+
return lowerUnitComparison(lowerer, other.value, unit, negated, loc);
|
|
3508
3545
|
if (other.type.kind === "union") {
|
|
3509
3546
|
const tag = lowerer.armTag(other.type.unionId, unit.type);
|
|
3510
3547
|
if (tag < 0) {
|
|
@@ -3612,7 +3649,7 @@ function lowerLooseNullCompare(lowerer, expr, loc) {
|
|
|
3612
3649
|
if (!leftIsNull && right.kind !== ts.SyntaxKind.NullKeyword)
|
|
3613
3650
|
return null;
|
|
3614
3651
|
const otherNode = leftIsNull ? right : left;
|
|
3615
|
-
const other = lowerer
|
|
3652
|
+
const other = lowerPresenceOperand(lowerer, otherNode);
|
|
3616
3653
|
if (isUnitType(other.type)) {
|
|
3617
3654
|
// `null == null`, `undefined == null`: units are mutually loose-equal.
|
|
3618
3655
|
return { kind: "boolLit", value: !negated, type: BOOL, loc };
|
|
@@ -3717,13 +3754,84 @@ export function lowerNullishCoalesce(lowerer, expr, loc) {
|
|
|
3717
3754
|
parents.push(first);
|
|
3718
3755
|
first = first.left;
|
|
3719
3756
|
}
|
|
3720
|
-
let result = lowerNullishPair(lowerer, first, first === expr ? loc : locOf(first),
|
|
3757
|
+
let result = lowerNullishPair(lowerer, first, first === expr ? loc : locOf(first), assertedPresenceOperand(lowerer, first.left));
|
|
3721
3758
|
for (let i = parents.length - 1; i >= 0; i--) {
|
|
3722
3759
|
const parent = parents[i];
|
|
3723
3760
|
result = lowerNullishPair(lowerer, parent, parent === expr ? loc : locOf(parent), result);
|
|
3724
3761
|
}
|
|
3725
3762
|
return result;
|
|
3726
3763
|
}
|
|
3764
|
+
/** The left side of `??` (see lowerPresenceOperand). The absence probe
|
|
3765
|
+
* reads optional storage beneath erased assertions; a union assertion that
|
|
3766
|
+
* narrows a stored class arm still applies its checked class view, so
|
|
3767
|
+
* `(node.parent as Sub | undefined) ?? node` sees the asserted arm on both
|
|
3768
|
+
* sides of the default. */
|
|
3769
|
+
function assertedPresenceOperand(lowerer, node) {
|
|
3770
|
+
const probe = lowerAbsenceProbe(lowerer, node);
|
|
3771
|
+
if (probe === null)
|
|
3772
|
+
return runtimeOptionalStorageOperand(lowerer, node) ?? lowerer.lowerExpr(node);
|
|
3773
|
+
if (probe.type.kind !== "union" && probe.type.kind !== "object")
|
|
3774
|
+
return probe;
|
|
3775
|
+
let outer = node;
|
|
3776
|
+
while (ts.isParenthesizedExpression(outer))
|
|
3777
|
+
outer = outer.expression;
|
|
3778
|
+
if (!ts.isAsExpression(outer) && !ts.isTypeAssertion(outer))
|
|
3779
|
+
return probe;
|
|
3780
|
+
const target = lowerer.mapTypeOf(lowerer.checker.getTypeFromTypeNode(outer.type));
|
|
3781
|
+
if (target?.kind !== "union" || typeEquals(target, probe.type))
|
|
3782
|
+
return probe;
|
|
3783
|
+
return checkedClassUnionAssertion(lowerer, probe, target, locOf(outer)) ?? probe;
|
|
3784
|
+
}
|
|
3785
|
+
/** Read-modify-write updates read the member first: an unassigned
|
|
3786
|
+
* deferred-init receiver throws Node's member-read TypeError. */
|
|
3787
|
+
function checkDeferredMemberReceiver(lowerer, target, access) {
|
|
3788
|
+
if (target.container !== "class" ||
|
|
3789
|
+
!ts.isPropertyAccessExpression(access) ||
|
|
3790
|
+
target.obj.type.kind !== "object" ||
|
|
3791
|
+
lowerer.deferredFieldSlot(target.obj) === null)
|
|
3792
|
+
return;
|
|
3793
|
+
target.obj =
|
|
3794
|
+
lowerer.runtimeOptionalPropertyReceiver(access.expression, target.obj, target.obj.type, target.field) ?? target.obj;
|
|
3795
|
+
}
|
|
3796
|
+
/** Whether evaluating `expr` cannot store anything or run other code:
|
|
3797
|
+
* reads, arithmetic, tests and checked extractions (which at most throw). */
|
|
3798
|
+
function writeFree(expr) {
|
|
3799
|
+
switch (expr.kind) {
|
|
3800
|
+
case "numLit":
|
|
3801
|
+
case "strLit":
|
|
3802
|
+
case "boolLit":
|
|
3803
|
+
case "unitLit":
|
|
3804
|
+
case "varRef":
|
|
3805
|
+
return true;
|
|
3806
|
+
case "fieldGet":
|
|
3807
|
+
case "recordGet":
|
|
3808
|
+
return writeFree(expr.obj);
|
|
3809
|
+
case "bin":
|
|
3810
|
+
case "logical":
|
|
3811
|
+
return writeFree(expr.left) && writeFree(expr.right);
|
|
3812
|
+
case "unary":
|
|
3813
|
+
case "toBool":
|
|
3814
|
+
return writeFree(expr.operand);
|
|
3815
|
+
case "ternary":
|
|
3816
|
+
return writeFree(expr.cond) && writeFree(expr.then) && writeFree(expr.else_);
|
|
3817
|
+
case "unionIsTag":
|
|
3818
|
+
case "unionNarrow":
|
|
3819
|
+
case "unionWrap":
|
|
3820
|
+
return writeFree(expr.value);
|
|
3821
|
+
case "libCall":
|
|
3822
|
+
return expr.fn === "error.nodeThrow";
|
|
3823
|
+
default:
|
|
3824
|
+
return false;
|
|
3825
|
+
}
|
|
3826
|
+
}
|
|
3827
|
+
/** The TypeError of a deferred-init field read that finds the field
|
|
3828
|
+
* unassigned where its declared type cannot hold undefined. */
|
|
3829
|
+
export const DEFERRED_READ_MESSAGE = "undefined is not representable in the target union (a value narrowed or asserted past it still held it)";
|
|
3830
|
+
/** The undefined-armed slot behind a checked deferred-init field read, or
|
|
3831
|
+
* the value itself (Lowerer.deferredFieldSlot). */
|
|
3832
|
+
function deferredSlotOr(lowerer, value) {
|
|
3833
|
+
return lowerer.deferredFieldSlot(value) ?? value;
|
|
3834
|
+
}
|
|
3727
3835
|
/** A plain value read that may be runtime-optional: an unchecked element
|
|
3728
3836
|
* read, or a binding, member or call that carries one. Lowering these
|
|
3729
3837
|
* without a destination type is the same as lowering them into one. */
|
|
@@ -3844,6 +3952,24 @@ function lowerNullishPair(lowerer, expr, loc, left) {
|
|
|
3844
3952
|
return nullishBranches(lowerer, left, left.type, def.arms, type, loc, () => lowerer.lowerExprExpecting(expr.right, type), (stable) => ({ kind: "call", callee: helper, args: [stable], type, loc }));
|
|
3845
3953
|
}
|
|
3846
3954
|
}
|
|
3955
|
+
// A subclass value defaulted to a base-class value (`circle ?? shape`):
|
|
3956
|
+
// the present arm upcasts after the original nullish test, and the
|
|
3957
|
+
// default lowers lazily into the base-class result.
|
|
3958
|
+
const present = rest.length === 1 ? rest[0] : null;
|
|
3959
|
+
if (present?.kind === "object" &&
|
|
3960
|
+
type.kind === "object" &&
|
|
3961
|
+
present.className !== type.className &&
|
|
3962
|
+
lowerer.isSubclassOf(present.className, type.className)) {
|
|
3963
|
+
const helper = lowerer.narrowedArmHelper(left.type.unionId, present, loc);
|
|
3964
|
+
if (helper !== null) {
|
|
3965
|
+
return nullishBranches(lowerer, left, left.type, def.arms, type, loc, () => lowerer.lowerExprExpecting(expr.right, type), (stable) => ({
|
|
3966
|
+
kind: "upcast",
|
|
3967
|
+
value: { kind: "call", callee: helper, args: [stable], type: present, loc },
|
|
3968
|
+
type,
|
|
3969
|
+
loc,
|
|
3970
|
+
}));
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3847
3973
|
// A default may change the union or widen its records. Test the
|
|
3848
3974
|
// original tag before coercing: converting the whole left first can
|
|
3849
3975
|
// lose nullish arms, and evaluating the default eagerly loses laziness.
|
|
@@ -3957,7 +4083,7 @@ export function lowerCondition(lowerer, expr) {
|
|
|
3957
4083
|
};
|
|
3958
4084
|
}
|
|
3959
4085
|
}
|
|
3960
|
-
const value =
|
|
4086
|
+
const value = lowerPresenceOperand(lowerer, expr);
|
|
3961
4087
|
return (tryLowerIndexTruthiness(lowerer, value, expr, locOf(expr)) ?? lowerer.ensureBool(value, expr));
|
|
3962
4088
|
}
|
|
3963
4089
|
function lowerPromiseThenPresence(lowerer, access, result) {
|
|
@@ -3997,13 +4123,7 @@ function lowerPromiseThenPresence(lowerer, access, result) {
|
|
|
3997
4123
|
const helper = lowerer.narrowedArmHelper(receiver.type.unionId, promiseType, receiver.loc);
|
|
3998
4124
|
if (helper === null)
|
|
3999
4125
|
return null;
|
|
4000
|
-
receiver =
|
|
4001
|
-
kind: "call",
|
|
4002
|
-
callee: helper,
|
|
4003
|
-
args: [receiver],
|
|
4004
|
-
type: promiseType,
|
|
4005
|
-
loc: receiver.loc,
|
|
4006
|
-
};
|
|
4126
|
+
receiver = lowerer.checkedNarrowCall(helper, receiver, promiseType, receiver.loc);
|
|
4007
4127
|
}
|
|
4008
4128
|
}
|
|
4009
4129
|
if (receiver.type.kind === "dyn") {
|
|
@@ -4691,13 +4811,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4691
4811
|
? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(expr.expression))
|
|
4692
4812
|
: null;
|
|
4693
4813
|
receiver = helper
|
|
4694
|
-
?
|
|
4695
|
-
kind: "call",
|
|
4696
|
-
callee: helper,
|
|
4697
|
-
args: [receiver],
|
|
4698
|
-
type: present,
|
|
4699
|
-
loc: locOf(expr.expression),
|
|
4700
|
-
}
|
|
4814
|
+
? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
|
|
4701
4815
|
: lowerer.maybeNarrow(receiver, expr.expression);
|
|
4702
4816
|
}
|
|
4703
4817
|
// An island handle behind a typed-array .d.ts surface: the engine
|
|
@@ -4791,13 +4905,7 @@ export function lowerIntrinsicProperty(lowerer, expr) {
|
|
|
4791
4905
|
? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(expr.expression))
|
|
4792
4906
|
: null;
|
|
4793
4907
|
receiver = helper
|
|
4794
|
-
?
|
|
4795
|
-
kind: "call",
|
|
4796
|
-
callee: helper,
|
|
4797
|
-
args: [receiver],
|
|
4798
|
-
type: present,
|
|
4799
|
-
loc: locOf(expr.expression),
|
|
4800
|
-
}
|
|
4908
|
+
? lowerer.checkedNarrowCall(helper, receiver, present, locOf(expr.expression))
|
|
4801
4909
|
: lowerer.maybeNarrow(receiver, expr.expression);
|
|
4802
4910
|
}
|
|
4803
4911
|
// An island handle behind an array-typed .d.ts surface
|
|
@@ -5097,7 +5205,30 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5097
5205
|
}
|
|
5098
5206
|
lowerer.badType(expr, tsType);
|
|
5099
5207
|
}
|
|
5100
|
-
|
|
5208
|
+
let type = mapped;
|
|
5209
|
+
// An inferred array of records takes the layout of an element literal
|
|
5210
|
+
// whose fields widened for missing-element reads; the other elements
|
|
5211
|
+
// build that layout directly. An explicit destination keeps its own.
|
|
5212
|
+
if (!expected && type.elem.kind === "record") {
|
|
5213
|
+
let variant = null;
|
|
5214
|
+
for (const candidate of expr.elements) {
|
|
5215
|
+
let x = candidate;
|
|
5216
|
+
while (ts.isParenthesizedExpression(x))
|
|
5217
|
+
x = x.expression;
|
|
5218
|
+
if (!ts.isObjectLiteralExpression(x))
|
|
5219
|
+
continue;
|
|
5220
|
+
const probe = tryLowerExpression(lowerer, x);
|
|
5221
|
+
if (!probe || !lowerer.isRuntimeOptionalRecordVariant(probe.type, type.elem))
|
|
5222
|
+
continue;
|
|
5223
|
+
if (variant !== null && !typeEquals(variant, probe.type)) {
|
|
5224
|
+
variant = null;
|
|
5225
|
+
break;
|
|
5226
|
+
}
|
|
5227
|
+
variant = probe.type;
|
|
5228
|
+
}
|
|
5229
|
+
if (variant !== null)
|
|
5230
|
+
type = arrayOf(variant);
|
|
5231
|
+
}
|
|
5101
5232
|
// Keep the array payload type fixed. Optional reads are stored through
|
|
5102
5233
|
// arrayValueStore, which records UNDEFINED in the state byte while the
|
|
5103
5234
|
// payload remains number/string/etc.; widening the array element here
|
|
@@ -5262,8 +5393,21 @@ export function lowerArrayLiteral(lowerer, expr, expected) {
|
|
|
5262
5393
|
}
|
|
5263
5394
|
const out = lowerer.declareHiddenLocal("%arrayLit", type);
|
|
5264
5395
|
const outRef = varRef(out.id, type, loc);
|
|
5396
|
+
// Dense capacity for the elements the statements below store.
|
|
5397
|
+
const capacity = Math.min(elems.length - spreads.length, 1024);
|
|
5265
5398
|
const body = [
|
|
5266
|
-
{
|
|
5399
|
+
{
|
|
5400
|
+
kind: "varDecl",
|
|
5401
|
+
localId: out.id,
|
|
5402
|
+
init: {
|
|
5403
|
+
kind: "arrayLit",
|
|
5404
|
+
elems: [],
|
|
5405
|
+
...(capacity > 0 ? { capacity } : {}),
|
|
5406
|
+
type,
|
|
5407
|
+
loc,
|
|
5408
|
+
},
|
|
5409
|
+
loc,
|
|
5410
|
+
},
|
|
5267
5411
|
];
|
|
5268
5412
|
const spreadSet = new Set(spreads);
|
|
5269
5413
|
const currentLength = () => ({
|
|
@@ -5686,7 +5830,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5686
5830
|
? lowerer.narrowedArmHelper(recv.type.unionId, present, locOf(expr.expression))
|
|
5687
5831
|
: null;
|
|
5688
5832
|
recv = helper
|
|
5689
|
-
?
|
|
5833
|
+
? lowerer.checkedNarrowCall(helper, recv, present, locOf(expr.expression))
|
|
5690
5834
|
: lowerer.maybeNarrow(recv, expr.expression);
|
|
5691
5835
|
}
|
|
5692
5836
|
// A typed-array .d.ts surface whose VALUE is an island handle
|
|
@@ -5719,14 +5863,21 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5719
5863
|
if (index.type.kind !== "f64") {
|
|
5720
5864
|
lowerer.unsupported("SC1090", expr.argumentExpression, "indexing with non-number keys");
|
|
5721
5865
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5866
|
+
// `t[i]!` asserts presence: the numeric element read (NaN when
|
|
5867
|
+
// invalid). Every other read answers undefined for an invalid index,
|
|
5868
|
+
// like Node.
|
|
5869
|
+
if (ts.isNonNullExpression(expr.parent) && expr.parent.expression === expr) {
|
|
5870
|
+
return {
|
|
5871
|
+
kind: "bytesIntrinsic",
|
|
5872
|
+
method: "get",
|
|
5873
|
+
receiver: recv,
|
|
5874
|
+
args: [index],
|
|
5875
|
+
type: F64,
|
|
5876
|
+
loc: locOf(expr),
|
|
5877
|
+
invalidNaN: true,
|
|
5878
|
+
};
|
|
5879
|
+
}
|
|
5880
|
+
return lowerSafeBytesRead(lowerer, recv, index, locOf(expr));
|
|
5730
5881
|
}
|
|
5731
5882
|
// Tuple element read `t[0]`: a positional-field read of the tuple's
|
|
5732
5883
|
// record shape — LITERAL indices only (the checker's per-index types
|
|
@@ -5769,13 +5920,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5769
5920
|
? lowerer.narrowedArmHelper(obj.type.unionId, present, locOf(expr.expression))
|
|
5770
5921
|
: null;
|
|
5771
5922
|
obj = helper
|
|
5772
|
-
?
|
|
5773
|
-
kind: "call",
|
|
5774
|
-
callee: helper,
|
|
5775
|
-
args: [obj],
|
|
5776
|
-
type: present,
|
|
5777
|
-
loc: locOf(expr.expression),
|
|
5778
|
-
}
|
|
5923
|
+
? lowerer.checkedNarrowCall(helper, obj, present, locOf(expr.expression))
|
|
5779
5924
|
: lowerer.maybeNarrow(obj, expr.expression);
|
|
5780
5925
|
}
|
|
5781
5926
|
const idx = tupleLiteralIndex(expr.argumentExpression);
|
|
@@ -5957,6 +6102,17 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
5957
6102
|
const recv = lowerer.lowerExpr(expr.expression);
|
|
5958
6103
|
const index = lowerOptionalNumber(lowerer, lowerer.lowerExpr(expr.argumentExpression), locOf(expr.argumentExpression), expr.argumentExpression);
|
|
5959
6104
|
if (index.type.kind === "f64" && recv.type.kind === "string") {
|
|
6105
|
+
// A proven in-bounds integer index always names a code unit, where
|
|
6106
|
+
// charAt and the property read agree.
|
|
6107
|
+
if (lowerer.stringIndexBounds.inBounds(expr))
|
|
6108
|
+
return {
|
|
6109
|
+
kind: "strIntrinsic",
|
|
6110
|
+
method: "charAt",
|
|
6111
|
+
receiver: recv,
|
|
6112
|
+
args: [index],
|
|
6113
|
+
type: STRING,
|
|
6114
|
+
loc: locOf(expr),
|
|
6115
|
+
};
|
|
5960
6116
|
return lowerOptionalStringIndex(lowerer, recv, index, lowerer.withUndefinedArm(STRING), locOf(expr));
|
|
5961
6117
|
}
|
|
5962
6118
|
lowerer.unsupported("SC1090", expr, "string indexing with this index/result shape (expected a number index and a string or string | undefined result)");
|
|
@@ -6020,7 +6176,7 @@ export function lowerElementAccess(lowerer, expr) {
|
|
|
6020
6176
|
? lowerer.narrowedArmHelper(arr.type.unionId, present, locOf(expr.expression))
|
|
6021
6177
|
: null;
|
|
6022
6178
|
arr = helper
|
|
6023
|
-
?
|
|
6179
|
+
? lowerer.checkedNarrowCall(helper, arr, present, locOf(expr.expression))
|
|
6024
6180
|
: lowerer.maybeNarrow(arr, expr.expression);
|
|
6025
6181
|
}
|
|
6026
6182
|
// The checker sees an array but the VALUE is an island handle (an
|
|
@@ -6330,6 +6486,57 @@ function lowerRecordPropertyKey(lowerer, key, node) {
|
|
|
6330
6486
|
}
|
|
6331
6487
|
return key;
|
|
6332
6488
|
}
|
|
6489
|
+
/** The stored value of an identifier whose storage holds an undefined arm
|
|
6490
|
+
* that the checker's type at this use has dropped. An assignment from an
|
|
6491
|
+
* unchecked indexed read narrows the declared type even though the value
|
|
6492
|
+
* can be absent at runtime, so presence tests (`=== undefined`, `== null`,
|
|
6493
|
+
* truthiness, `??`, `typeof`) read the storage tag instead of trusting
|
|
6494
|
+
* that narrowing. A guard-proven use answers the same way at runtime. */
|
|
6495
|
+
export function runtimeOptionalStorageOperand(lowerer, node) {
|
|
6496
|
+
let expr = node;
|
|
6497
|
+
while (ts.isParenthesizedExpression(expr))
|
|
6498
|
+
expr = expr.expression;
|
|
6499
|
+
if (!ts.isIdentifier(expr))
|
|
6500
|
+
return null;
|
|
6501
|
+
// Only storage that can actually receive an absent value without the
|
|
6502
|
+
// checker seeing it qualifies; other declared-optional bindings keep the
|
|
6503
|
+
// checker's assignment and guard narrowing.
|
|
6504
|
+
const symbol = lowerer.resolveValueSymbol(expr);
|
|
6505
|
+
const local = lowerer.resolveLocal(expr);
|
|
6506
|
+
const global = local ? undefined : lowerer.globalOf(expr);
|
|
6507
|
+
const root = local ? lowerer.runtimeOptionalRootOf(local) : null;
|
|
6508
|
+
if (root && lowerer.runtimeOptionalStorageLocals.has(root)) {
|
|
6509
|
+
// These locals track guards: a branch that proved presence removes
|
|
6510
|
+
// the binding from the active set, and its reads stay narrowed. A
|
|
6511
|
+
// captured binding can be reassigned between calls, so a capture
|
|
6512
|
+
// never inherits a guard (the identifier read's own rule).
|
|
6513
|
+
const captured = local.boxed === true ||
|
|
6514
|
+
(!!symbol && lowerer.ctx.captureBySymbol.get(symbol) === local) ||
|
|
6515
|
+
root !== local;
|
|
6516
|
+
if (!captured && !lowerer.runtimeOptionalLocals.has(root))
|
|
6517
|
+
return null;
|
|
6518
|
+
}
|
|
6519
|
+
else if (!(symbol && lowerer.runtimeOptionalAssignedSymbols.has(symbol)) &&
|
|
6520
|
+
!(symbol && lowerer.runtimeOptionalBindingTypes.has(symbol)) &&
|
|
6521
|
+
!(global && lowerer.isRuntimeOptionalGlobal(global)))
|
|
6522
|
+
return null;
|
|
6523
|
+
const optional = lowerer.runtimeOptionalIdentifierValue(expr);
|
|
6524
|
+
if (optional === null)
|
|
6525
|
+
return null;
|
|
6526
|
+
const checked = lowerer.mapTypeOf(lowerer.typeOf(expr));
|
|
6527
|
+
if (checked === null ||
|
|
6528
|
+
(checked.kind === "union" && lowerer.armTag(checked.unionId, UNDEFINED_T) >= 0))
|
|
6529
|
+
return null;
|
|
6530
|
+
return optional.value;
|
|
6531
|
+
}
|
|
6532
|
+
/** A presence-test operand: an absence-aware element or field read, an
|
|
6533
|
+
* identifier's runtime-optional storage, or the ordinary lowering. */
|
|
6534
|
+
export function lowerPresenceOperand(lowerer, node) {
|
|
6535
|
+
// An unassigned deferred-init field observes its undefined slot too.
|
|
6536
|
+
return deferredSlotOr(lowerer, lowerAbsenceProbe(lowerer, node) ??
|
|
6537
|
+
runtimeOptionalStorageOperand(lowerer, node) ??
|
|
6538
|
+
lowerer.lowerExpr(node));
|
|
6539
|
+
}
|
|
6333
6540
|
/** A keyed read used only to observe absence (`if (map[k])`, or the left
|
|
6334
6541
|
* side of `||`/`??`). JavaScript answers undefined for missing record keys
|
|
6335
6542
|
* and array indices even when noUncheckedIndexedAccess is disabled. Keep
|
|
@@ -6542,13 +6749,7 @@ export function lowerElementCompound(lowerer, expr, op) {
|
|
|
6542
6749
|
? lowerer.narrowedArmHelper(receiver.type.unionId, present, locOf(target.expression))
|
|
6543
6750
|
: null;
|
|
6544
6751
|
if (helper)
|
|
6545
|
-
receiver =
|
|
6546
|
-
kind: "call",
|
|
6547
|
-
callee: helper,
|
|
6548
|
-
args: [receiver],
|
|
6549
|
-
type: present,
|
|
6550
|
-
loc: locOf(target.expression),
|
|
6551
|
-
};
|
|
6752
|
+
receiver = lowerer.checkedNarrowCall(helper, receiver, present, locOf(target.expression));
|
|
6552
6753
|
}
|
|
6553
6754
|
if (receiver.type.kind !== receiverType.kind) {
|
|
6554
6755
|
lowerer.unsupported("SC1090", target.expression, "compound assignment through a non-native array or byte view");
|
|
@@ -6563,12 +6764,15 @@ export function lowerElementCompound(lowerer, expr, op) {
|
|
|
6563
6764
|
const oldValue = receiver.type.kind === "array"
|
|
6564
6765
|
? arrayValueRead(lowerer, receiverRef(), indexRef(), receiver.type.elem, locOf(target))
|
|
6565
6766
|
: {
|
|
6767
|
+
// An invalid index reads undefined in Node, which every numeric
|
|
6768
|
+
// compound operator turns into NaN; the write is then ignored.
|
|
6566
6769
|
kind: "bytesIntrinsic",
|
|
6567
6770
|
method: "get",
|
|
6568
6771
|
receiver: receiverRef(),
|
|
6569
6772
|
args: [indexRef()],
|
|
6570
6773
|
type: F64,
|
|
6571
6774
|
loc: locOf(target),
|
|
6775
|
+
invalidNaN: true,
|
|
6572
6776
|
};
|
|
6573
6777
|
const oldLocal = lowerer.declareHiddenLocal("%compoundOld", oldValue.type);
|
|
6574
6778
|
const oldRef = () => varRef(oldLocal.id, oldValue.type, loc);
|
|
@@ -7184,13 +7388,7 @@ export function lowerElementWrite(lowerer, expr) {
|
|
|
7184
7388
|
? lowerer.narrowedArmHelper(arr.type.unionId, present, locOf(target.expression))
|
|
7185
7389
|
: null;
|
|
7186
7390
|
if (helper) {
|
|
7187
|
-
arr =
|
|
7188
|
-
kind: "call",
|
|
7189
|
-
callee: helper,
|
|
7190
|
-
args: [arr],
|
|
7191
|
-
type: present,
|
|
7192
|
-
loc: locOf(target.expression),
|
|
7193
|
-
};
|
|
7391
|
+
arr = lowerer.checkedNarrowCall(helper, arr, present, locOf(target.expression));
|
|
7194
7392
|
}
|
|
7195
7393
|
}
|
|
7196
7394
|
if (arr.type.kind !== "array") {
|
|
@@ -7308,7 +7506,7 @@ export function ensureString(lowerer, e, node) {
|
|
|
7308
7506
|
narrowed.kind === "bigint")) {
|
|
7309
7507
|
const helper = lowerer.narrowedArmHelper(e.type.unionId, narrowed, e.loc);
|
|
7310
7508
|
if (helper) {
|
|
7311
|
-
return ensureString(lowerer,
|
|
7509
|
+
return ensureString(lowerer, lowerer.checkedNarrowCall(helper, e, narrowed, e.loc), node);
|
|
7312
7510
|
}
|
|
7313
7511
|
}
|
|
7314
7512
|
if (narrowed?.kind === "union" &&
|
|
@@ -7581,10 +7779,20 @@ export function lowerAsExpression(lowerer, expr) {
|
|
|
7581
7779
|
if (target && target.kind !== "union" && !typeEquals(target, inner.type)) {
|
|
7582
7780
|
const helper = lowerer.narrowedArmHelper(inner.type.unionId, target, locOf(expr));
|
|
7583
7781
|
if (helper) {
|
|
7584
|
-
return
|
|
7782
|
+
return lowerer.checkedNarrowCall(helper, inner, target, locOf(expr));
|
|
7585
7783
|
}
|
|
7586
7784
|
}
|
|
7587
7785
|
}
|
|
7786
|
+
// `node.parent as Sub | undefined`: a union target whose class arm is
|
|
7787
|
+
// narrower than the stored class gets the same checked class view as
|
|
7788
|
+
// `node.parent as Sub`; the other arms keep their identical tags.
|
|
7789
|
+
if (target?.kind === "union" &&
|
|
7790
|
+
(inner.type.kind === "union" || inner.type.kind === "object") &&
|
|
7791
|
+
!typeEquals(target, inner.type)) {
|
|
7792
|
+
const asserted = checkedClassUnionAssertion(lowerer, inner, target, locOf(expr));
|
|
7793
|
+
if (asserted)
|
|
7794
|
+
return asserted;
|
|
7795
|
+
}
|
|
7588
7796
|
return inner; // erasure, unchanged
|
|
7589
7797
|
}
|
|
7590
7798
|
if (inner.type.kind === "jsval") {
|
|
@@ -7711,7 +7919,7 @@ export function lowerPrefixUnary(lowerer, expr) {
|
|
|
7711
7919
|
}
|
|
7712
7920
|
case ts.SyntaxKind.ExclamationToken: {
|
|
7713
7921
|
// `!x` is ToBoolean-then-negate: f64/string operands go through toBool.
|
|
7714
|
-
const operand = lowerer.ensureBool(lowerer.lowerExpr(expr.operand), expr.operand);
|
|
7922
|
+
const operand = lowerer.ensureBool(deferredSlotOr(lowerer, runtimeOptionalStorageOperand(lowerer, expr.operand) ?? lowerer.lowerExpr(expr.operand)), expr.operand);
|
|
7715
7923
|
return { kind: "unary", op: "!", operand, type: BOOL, loc };
|
|
7716
7924
|
}
|
|
7717
7925
|
case ts.SyntaxKind.TildeToken: {
|
|
@@ -7816,7 +8024,15 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7816
8024
|
const type = raw.type;
|
|
7817
8025
|
const read = type.kind === "array"
|
|
7818
8026
|
? arrayValueRead(lowerer, receiver, index, type.elem, loc)
|
|
7819
|
-
: {
|
|
8027
|
+
: {
|
|
8028
|
+
kind: "bytesIntrinsic",
|
|
8029
|
+
method: "get",
|
|
8030
|
+
receiver,
|
|
8031
|
+
args: [index],
|
|
8032
|
+
type: F64,
|
|
8033
|
+
loc,
|
|
8034
|
+
invalidNaN: true,
|
|
8035
|
+
};
|
|
7820
8036
|
return finish(read, (value) => type.kind === "array"
|
|
7821
8037
|
? arrayValueStore(lowerer, receiver, index, lowerer.coerceInto(access, value, type.elem), type.elem, loc)
|
|
7822
8038
|
: {
|
|
@@ -7848,6 +8064,7 @@ export function lowerIncDec(lowerer, expr, prefix) {
|
|
|
7848
8064
|
? lowerer.fieldTarget(access)
|
|
7849
8065
|
: symbolFieldTarget(lowerer, access);
|
|
7850
8066
|
if (target && lowerer.dynConvertible(target.fieldType)) {
|
|
8067
|
+
checkDeferredMemberReceiver(lowerer, target, access);
|
|
7851
8068
|
target.obj = save(target.obj, "%incrementReceiver");
|
|
7852
8069
|
return finish(lowerer.fieldGetExpr(target, loc, access), (value) => lowerer.fieldSetStmt(target, lowerer.coerceInto(access, value, target.fieldType), loc, access));
|
|
7853
8070
|
}
|
|
@@ -8362,7 +8579,7 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8362
8579
|
const nullTest = lowerLooseNullCompare(lowerer, expr, loc);
|
|
8363
8580
|
if (nullTest)
|
|
8364
8581
|
return nullTest;
|
|
8365
|
-
const loose = lowerAbstractEquality(lowerer, lowerer.lowerExpr(expr.left), lowerer.lowerExpr(expr.right), op === ts.SyntaxKind.ExclamationEqualsToken, loc);
|
|
8582
|
+
const loose = lowerAbstractEquality(lowerer, deferredSlotOr(lowerer, lowerer.lowerExpr(expr.left)), deferredSlotOr(lowerer, lowerer.lowerExpr(expr.right)), op === ts.SyntaxKind.ExclamationEqualsToken, loc);
|
|
8366
8583
|
if (loose)
|
|
8367
8584
|
return loose;
|
|
8368
8585
|
lowerer.unsupported("SC1040", expr, undefined, "object-to-primitive loose equality can call user-defined valueOf/toString methods — compare explicit primitive conversions instead");
|
|
@@ -8409,12 +8626,26 @@ export function lowerBinary(lowerer, expr) {
|
|
|
8409
8626
|
}
|
|
8410
8627
|
const strictEquality = op === ts.SyntaxKind.EqualsEqualsEqualsToken ||
|
|
8411
8628
|
op === ts.SyntaxKind.ExclamationEqualsEqualsToken;
|
|
8629
|
+
// An identifier whose storage is runtime-optional is compared by its
|
|
8630
|
+
// stored value: the checker's narrowing to the present arm is not a
|
|
8631
|
+
// runtime proof. Identifier reads are pure, so taking the stored value
|
|
8632
|
+
// after both operands lowered keeps the evaluation order. A union on
|
|
8633
|
+
// the other side keeps the narrowed read (union-to-union comparison
|
|
8634
|
+
// has no lowering).
|
|
8412
8635
|
let left = strictEquality
|
|
8413
8636
|
? (lowerAbsenceProbe(lowerer, expr.left) ?? lowerer.lowerExpr(expr.left))
|
|
8414
8637
|
: lowerer.lowerExpr(expr.left);
|
|
8415
8638
|
let right = strictEquality
|
|
8416
8639
|
? (lowerAbsenceProbe(lowerer, expr.right) ?? lowerer.lowerExpr(expr.right))
|
|
8417
8640
|
: lowerer.lowerExpr(expr.right);
|
|
8641
|
+
if (strictEquality) {
|
|
8642
|
+
const storedLeft = runtimeOptionalStorageOperand(lowerer, expr.left);
|
|
8643
|
+
const storedRight = runtimeOptionalStorageOperand(lowerer, expr.right);
|
|
8644
|
+
if (storedLeft !== null && right.type.kind !== "union")
|
|
8645
|
+
left = storedLeft;
|
|
8646
|
+
if (storedRight !== null && left.type.kind !== "union")
|
|
8647
|
+
right = storedRight;
|
|
8648
|
+
}
|
|
8418
8649
|
if (strictEquality && (left.type.kind === "caught" || right.type.kind === "caught")) {
|
|
8419
8650
|
if (left.type.kind === "caught")
|
|
8420
8651
|
left = { kind: "caughtToDyn", value: left, type: DYN, loc: left.loc };
|
|
@@ -9266,7 +9497,9 @@ function lowerLogicalChain(lowerer, expr) {
|
|
|
9266
9497
|
current = left;
|
|
9267
9498
|
continue;
|
|
9268
9499
|
}
|
|
9269
|
-
result = lowerLogicalPair(lowerer, current,
|
|
9500
|
+
result = lowerLogicalPair(lowerer, current, current.operatorToken.kind === ts.SyntaxKind.BarBarToken
|
|
9501
|
+
? lowerPresenceOperand(lowerer, left)
|
|
9502
|
+
: (lowerAbsenceProbe(lowerer, left) ?? lowerer.lowerExpr(left)));
|
|
9270
9503
|
break;
|
|
9271
9504
|
}
|
|
9272
9505
|
for (let i = parents.length - 1; i >= 0; i--) {
|
|
@@ -9921,11 +10154,12 @@ function lowerUnionTypeofTest(lowerer, expr, loc) {
|
|
|
9921
10154
|
for (const [a, b] of operandPairs(expr)) {
|
|
9922
10155
|
if (!ts.isTypeOfExpression(a))
|
|
9923
10156
|
continue;
|
|
9924
|
-
|
|
10157
|
+
const stored = runtimeOptionalStorageOperand(lowerer, a.expression);
|
|
10158
|
+
if (stored === null && lowerer.mapTypeOf(lowerer.typeOf(a.expression))?.kind !== "union")
|
|
9925
10159
|
continue;
|
|
9926
10160
|
if (!ts.isStringLiteral(b))
|
|
9927
10161
|
continue; // bare-typeof + strEq handles pure operands
|
|
9928
|
-
const value = lowerer.lowerExpr(a.expression);
|
|
10162
|
+
const value = stored ?? lowerer.lowerExpr(a.expression);
|
|
9929
10163
|
if (value.type.kind !== "union")
|
|
9930
10164
|
continue; // defensive: an already-narrowed use
|
|
9931
10165
|
const unionId = value.type.unionId;
|
|
@@ -12088,13 +12322,7 @@ export function lowerUnionProperty(lowerer, expr) {
|
|
|
12088
12322
|
if (receiver === null) {
|
|
12089
12323
|
const helper = lowerer.narrowedArmHelper(value.type.unionId, objectType, locOf(expr.expression));
|
|
12090
12324
|
if (helper !== null)
|
|
12091
|
-
receiver =
|
|
12092
|
-
kind: "call",
|
|
12093
|
-
callee: helper,
|
|
12094
|
-
args: [value],
|
|
12095
|
-
type: objectType,
|
|
12096
|
-
loc: locOf(expr.expression),
|
|
12097
|
-
};
|
|
12325
|
+
receiver = lowerer.checkedNarrowCall(helper, value, objectType, locOf(expr.expression));
|
|
12098
12326
|
}
|
|
12099
12327
|
if (receiver !== null) {
|
|
12100
12328
|
return {
|
|
@@ -12306,13 +12534,7 @@ function classFieldTarget(lowerer, receiverNode, receiverType, fieldName, saved)
|
|
|
12306
12534
|
if (obj.type.kind === "union") {
|
|
12307
12535
|
const helper = lowerer.narrowedArmHelper(obj.type.unionId, receiverType, locOf(receiverNode));
|
|
12308
12536
|
obj = helper
|
|
12309
|
-
?
|
|
12310
|
-
kind: "call",
|
|
12311
|
-
callee: helper,
|
|
12312
|
-
args: [obj],
|
|
12313
|
-
type: receiverType,
|
|
12314
|
-
loc: locOf(receiverNode),
|
|
12315
|
-
}
|
|
12537
|
+
? lowerer.checkedNarrowCall(helper, obj, receiverType, locOf(receiverNode))
|
|
12316
12538
|
: lowerer.maybeNarrow(obj, receiverNode);
|
|
12317
12539
|
}
|
|
12318
12540
|
return lowerer.coerceInto(receiverNode, obj, receiverType);
|
|
@@ -12476,13 +12698,7 @@ export function fieldTarget(lowerer, access) {
|
|
|
12476
12698
|
? lowerer.narrowedArmHelper(obj.type.unionId, present, locOf(access.expression))
|
|
12477
12699
|
: null;
|
|
12478
12700
|
obj = helper
|
|
12479
|
-
?
|
|
12480
|
-
kind: "call",
|
|
12481
|
-
callee: helper,
|
|
12482
|
-
args: [obj],
|
|
12483
|
-
type: present,
|
|
12484
|
-
loc: locOf(access.expression),
|
|
12485
|
-
}
|
|
12701
|
+
? lowerer.checkedNarrowCall(helper, obj, present, locOf(access.expression))
|
|
12486
12702
|
: lowerer.maybeNarrow(obj, access.expression);
|
|
12487
12703
|
}
|
|
12488
12704
|
if (obj.type.kind !== "record")
|
|
@@ -12689,6 +12905,16 @@ function symbolFieldTarget(lowerer, expr) {
|
|
|
12689
12905
|
* tsc-clean (the property types as the setter's param), but Node yields
|
|
12690
12906
|
* undefined, which these property types cannot represent. */
|
|
12691
12907
|
export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
12908
|
+
// A member read through an unassigned deferred-init field throws Node's
|
|
12909
|
+
// member-read TypeError instead of the generic checked extraction.
|
|
12910
|
+
if (target.container === "class" &&
|
|
12911
|
+
ts.isPropertyAccessExpression(blame) &&
|
|
12912
|
+
target.obj.type.kind === "object" &&
|
|
12913
|
+
lowerer.deferredFieldSlot(target.obj) !== null) {
|
|
12914
|
+
const checked = lowerer.runtimeOptionalPropertyReceiver(blame.expression, target.obj, target.obj.type, target.field);
|
|
12915
|
+
if (checked)
|
|
12916
|
+
target = { ...target, obj: checked };
|
|
12917
|
+
}
|
|
12692
12918
|
if (target.container === "dynamic")
|
|
12693
12919
|
return lowerer.coerceInto(blame, {
|
|
12694
12920
|
kind: "dynKeyGet",
|
|
@@ -12812,6 +13038,34 @@ export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
|
12812
13038
|
if (lowerer.classes.get(target.className)?.deferredInitFields?.has(target.field) === true &&
|
|
12813
13039
|
target.fieldType.kind === "union") {
|
|
12814
13040
|
const inner = lowerer.stripUndefinedArm(target.fieldType);
|
|
13041
|
+
// Reference arms over a stable receiver check inline: the present
|
|
13042
|
+
// arm is a plain projection of the slot, so ordinary reads keep their
|
|
13043
|
+
// borrowed form and only an unassigned slot reaches the throw.
|
|
13044
|
+
const unionId = target.fieldType.unionId;
|
|
13045
|
+
const presentTag = lowerer.armTag(unionId, inner);
|
|
13046
|
+
const undefTag = lowerer.armTag(unionId, UNDEFINED_T);
|
|
13047
|
+
if (inner.kind === "object" &&
|
|
13048
|
+
presentTag >= 0 &&
|
|
13049
|
+
undefTag >= 0 &&
|
|
13050
|
+
lowerer.unions.get(unionId)?.arms.length === 2 &&
|
|
13051
|
+
isSafeToRepeat(read)) {
|
|
13052
|
+
return {
|
|
13053
|
+
kind: "ternary",
|
|
13054
|
+
cond: {
|
|
13055
|
+
kind: "unionIsTag",
|
|
13056
|
+
unionId,
|
|
13057
|
+
tag: undefTag,
|
|
13058
|
+
negated: false,
|
|
13059
|
+
value: read,
|
|
13060
|
+
type: BOOL,
|
|
13061
|
+
loc,
|
|
13062
|
+
},
|
|
13063
|
+
then: nodeThrowExpr(1, "", DEFERRED_READ_MESSAGE, inner, loc),
|
|
13064
|
+
else_: { kind: "unionNarrow", unionId, tag: presentTag, value: read, type: inner, loc },
|
|
13065
|
+
type: inner,
|
|
13066
|
+
loc,
|
|
13067
|
+
};
|
|
13068
|
+
}
|
|
12815
13069
|
const helper = lowerer.deferredReadHelper(target.fieldType.unionId, inner, loc);
|
|
12816
13070
|
if (helper)
|
|
12817
13071
|
return { kind: "call", callee: helper, args: [read], type: inner, loc };
|
|
@@ -12831,6 +13085,75 @@ export function fieldGetExpr(lowerer, target, loc, blame) {
|
|
|
12831
13085
|
* call). A write to a getter-only property never gets here in a clean
|
|
12832
13086
|
* program (tsc's TS2540 is the fence); the rejection is the backstop. */
|
|
12833
13087
|
export function fieldSetStmt(lowerer, target, value, loc, blame) {
|
|
13088
|
+
// A member write through an unassigned deferred-init field: the value
|
|
13089
|
+
// still evaluates first, then the write throws Node's TypeError.
|
|
13090
|
+
const deferredSlot = target.container === "class" &&
|
|
13091
|
+
!((target.field === "message" || target.field === "name") &&
|
|
13092
|
+
(target.className === "%Error" || lowerer.isSubclassOf(target.className, "%Error")))
|
|
13093
|
+
? lowerer.deferredFieldSlot(target.obj)
|
|
13094
|
+
: null;
|
|
13095
|
+
if (target.container === "class" && deferredSlot?.type.kind === "union") {
|
|
13096
|
+
const unionId = deferredSlot.type.unionId;
|
|
13097
|
+
const undefTag = lowerer.armTag(unionId, UNDEFINED_T);
|
|
13098
|
+
const presentTag = lowerer.armTag(unionId, target.obj.type);
|
|
13099
|
+
if (undefTag >= 0 && presentTag >= 0) {
|
|
13100
|
+
// A value that cannot write anything leaves the field unchanged, so
|
|
13101
|
+
// the field is read after it (no snapshot of the slot).
|
|
13102
|
+
const late = isSafeToRepeat(deferredSlot) && writeFree(value);
|
|
13103
|
+
const receiver = late
|
|
13104
|
+
? null
|
|
13105
|
+
: lowerer.declareHiddenLocal("%deferredWriteObject", deferredSlot.type);
|
|
13106
|
+
const stored = lowerer.declareHiddenLocal("%deferredWriteValue", value.type);
|
|
13107
|
+
const receiverRef = receiver ? varRef(receiver.id, receiver.type, loc) : deferredSlot;
|
|
13108
|
+
const result = varRef(stored.id, stored.type, loc);
|
|
13109
|
+
const write = {
|
|
13110
|
+
kind: "fieldSet",
|
|
13111
|
+
obj: {
|
|
13112
|
+
kind: "unionNarrow",
|
|
13113
|
+
unionId,
|
|
13114
|
+
tag: presentTag,
|
|
13115
|
+
value: receiverRef,
|
|
13116
|
+
type: target.obj.type,
|
|
13117
|
+
loc,
|
|
13118
|
+
},
|
|
13119
|
+
className: target.className,
|
|
13120
|
+
field: target.field,
|
|
13121
|
+
value: result,
|
|
13122
|
+
loc,
|
|
13123
|
+
};
|
|
13124
|
+
return {
|
|
13125
|
+
kind: "exprStmt",
|
|
13126
|
+
expr: {
|
|
13127
|
+
kind: "seqExpr",
|
|
13128
|
+
stmts: [
|
|
13129
|
+
...(receiver
|
|
13130
|
+
? [{ kind: "varDecl", localId: receiver.id, init: deferredSlot, loc }]
|
|
13131
|
+
: []),
|
|
13132
|
+
{ kind: "varDecl", localId: stored.id, init: value, loc },
|
|
13133
|
+
],
|
|
13134
|
+
result: {
|
|
13135
|
+
kind: "ternary",
|
|
13136
|
+
cond: {
|
|
13137
|
+
kind: "unionIsTag",
|
|
13138
|
+
unionId,
|
|
13139
|
+
tag: undefTag,
|
|
13140
|
+
value: receiverRef,
|
|
13141
|
+
negated: false,
|
|
13142
|
+
type: BOOL,
|
|
13143
|
+
loc,
|
|
13144
|
+
},
|
|
13145
|
+
then: nodeThrowExpr(1, "", `Cannot set properties of undefined (setting '${target.field}')`, result.type, loc),
|
|
13146
|
+
else_: { kind: "seqExpr", stmts: [write], result, type: result.type, loc },
|
|
13147
|
+
type: result.type,
|
|
13148
|
+
loc,
|
|
13149
|
+
},
|
|
13150
|
+
type: result.type,
|
|
13151
|
+
loc,
|
|
13152
|
+
},
|
|
13153
|
+
loc,
|
|
13154
|
+
};
|
|
13155
|
+
}
|
|
13156
|
+
}
|
|
12834
13157
|
if (target.container === "dynamic")
|
|
12835
13158
|
return {
|
|
12836
13159
|
kind: "exprStmt",
|
|
@@ -13148,6 +13471,7 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
|
|
|
13148
13471
|
const target = targetOf();
|
|
13149
13472
|
if (!target)
|
|
13150
13473
|
lowerer.unsupported("SC1090", access, "compound assignment to unsupported field targets");
|
|
13474
|
+
checkDeferredMemberReceiver(lowerer, target, access);
|
|
13151
13475
|
target.obj = save(target.obj, "%compoundReceiver");
|
|
13152
13476
|
// Accessors observe getter, RHS side effects, then setter, all through
|
|
13153
13477
|
// the saved receiver.
|