@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
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
import * as ts from "../ts7/adapter.js";
|
|
2
|
+
import { indexStoreInBounds } from "./runtime-optional-bounds.js";
|
|
3
|
+
const NOTHING = { undefined: false, holes: false };
|
|
4
|
+
/** Methods whose callbacks also visit holes, as `undefined`. */
|
|
5
|
+
const HOLE_VISITING = new Set(["find", "findIndex", "findLast", "findLastIndex"]);
|
|
6
|
+
/** Array methods returning a new array, by what happens to the receiver's
|
|
7
|
+
* holes in it, and methods returning the receiver itself. */
|
|
8
|
+
const HOLES_KEPT = new Set(["slice", "splice", "concat"]);
|
|
9
|
+
const HOLES_SKIPPED = new Set(["filter", "flat"]);
|
|
10
|
+
const HOLES_FILLED = new Set(["toSorted", "toReversed", "toSpliced", "with"]);
|
|
11
|
+
const IN_PLACE = new Set(["sort", "reverse", "fill", "copyWithin"]);
|
|
12
|
+
/** Whole-program facts about which native array element ABIs can hold an
|
|
13
|
+
* explicit `undefined` value or a hole, refined per expression for arrays
|
|
14
|
+
* an expression creates itself. An element parameter of an array callback
|
|
15
|
+
* is present whenever its receiver can hold neither: the callback methods
|
|
16
|
+
* skip holes (except the find family), and every explicit `undefined`
|
|
17
|
+
* enters a native array through a store, a copy, or a builtin scanned
|
|
18
|
+
* here. Facts only grow, so the enclosing fixed point stays monotone. */
|
|
19
|
+
export class ArrayElementStates {
|
|
20
|
+
host;
|
|
21
|
+
undefinedKeys = new Set();
|
|
22
|
+
holeyKeys = new Set();
|
|
23
|
+
/** A store wrote a possibly undefined value or a hole into an array
|
|
24
|
+
* whose element ABI is decided per generic instantiation. */
|
|
25
|
+
anyUndefined = false;
|
|
26
|
+
anyHoley = false;
|
|
27
|
+
/** Facts of arrays owned by one storage slot. */
|
|
28
|
+
undefinedOwners = new Set();
|
|
29
|
+
holeyOwners = new Set();
|
|
30
|
+
/** The node being scanned, for provenance notes. */
|
|
31
|
+
site;
|
|
32
|
+
/** While set, arrays judged only by their element ABI count as present. */
|
|
33
|
+
ownFactsOnly = false;
|
|
34
|
+
constructor(host) {
|
|
35
|
+
this.host = host;
|
|
36
|
+
}
|
|
37
|
+
/** Every element a callback of `method` receives from `receiver` is a
|
|
38
|
+
* present value. */
|
|
39
|
+
elementsPresent(receiver, method) {
|
|
40
|
+
const contents = this.contents(receiver);
|
|
41
|
+
return (contents !== null && !contents.undefined && !(HOLE_VISITING.has(method) && contents.holes));
|
|
42
|
+
}
|
|
43
|
+
/** Scans one syntax node; true when a fact was added. */
|
|
44
|
+
scan(node) {
|
|
45
|
+
this.site = node;
|
|
46
|
+
if (ts.isBinaryExpression(node))
|
|
47
|
+
return this.scanAssignment(node);
|
|
48
|
+
if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) &&
|
|
49
|
+
(node.operator === ts.SyntaxKind.PlusPlusToken ||
|
|
50
|
+
node.operator === ts.SyntaxKind.MinusMinusToken)) {
|
|
51
|
+
// `xs[i]++` writes index i, and `xs.length++` grows the array.
|
|
52
|
+
const target = peel(node.operand);
|
|
53
|
+
if (ts.isElementAccessExpression(target))
|
|
54
|
+
return this.addHolesTo(target.expression);
|
|
55
|
+
if (ts.isPropertyAccessExpression(target) &&
|
|
56
|
+
target.name.text === "length" &&
|
|
57
|
+
node.operator === ts.SyntaxKind.PlusPlusToken)
|
|
58
|
+
return this.addHolesTo(target.expression);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (ts.isDeleteExpression(node)) {
|
|
62
|
+
const target = peel(node.expression);
|
|
63
|
+
return ts.isElementAccessExpression(target) ? this.addHolesTo(target.expression) : false;
|
|
64
|
+
}
|
|
65
|
+
if (ts.isArrayLiteralExpression(node))
|
|
66
|
+
return this.record(node);
|
|
67
|
+
if (ts.isCallExpression(node) || ts.isNewExpression(node))
|
|
68
|
+
return this.scanCall(node);
|
|
69
|
+
if (ts.isForOfStatement(node))
|
|
70
|
+
return this.scanForOf(node);
|
|
71
|
+
if (ts.isArrayBindingPattern(node))
|
|
72
|
+
return this.scanRestPattern(node);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/** `[a, ...rest] = source` copies the remaining indices into a new
|
|
76
|
+
* array: holes become undefined. */
|
|
77
|
+
scanRestPattern(pattern) {
|
|
78
|
+
const last = pattern.elements[pattern.elements.length - 1];
|
|
79
|
+
if (!last || ts.isOmittedExpression(last) || !last.dotDotDotToken)
|
|
80
|
+
return false;
|
|
81
|
+
// A parameter or nested pattern has no source expression to judge.
|
|
82
|
+
const owner = pattern.parent;
|
|
83
|
+
const source = ts.isVariableDeclaration(owner) && owner.name === pattern && owner.initializer
|
|
84
|
+
? this.contents(owner.initializer)
|
|
85
|
+
: null;
|
|
86
|
+
if (source !== null && !source.undefined && !source.holes)
|
|
87
|
+
return false;
|
|
88
|
+
const target = last.name;
|
|
89
|
+
if (!ts.isIdentifier(target))
|
|
90
|
+
return false;
|
|
91
|
+
return this.addUndefined(this.host.arrayKeys(target));
|
|
92
|
+
}
|
|
93
|
+
/** `[a, ...rest] = source` as an assignment. */
|
|
94
|
+
scanRestAssignment(node) {
|
|
95
|
+
const pattern = peel(node.left);
|
|
96
|
+
if (!ts.isArrayLiteralExpression(pattern))
|
|
97
|
+
return false;
|
|
98
|
+
const last = pattern.elements[pattern.elements.length - 1];
|
|
99
|
+
if (!last || !ts.isSpreadElement(last))
|
|
100
|
+
return false;
|
|
101
|
+
if (!this.mayYieldUndefined(node.right))
|
|
102
|
+
return false;
|
|
103
|
+
return this.addUndefinedTo(last.expression);
|
|
104
|
+
}
|
|
105
|
+
/** Contents of the array `node` evaluates to; null when its element ABI
|
|
106
|
+
* is generic. Arrays the expression creates are judged by how they are
|
|
107
|
+
* built; any other array by the facts of its element ABI. */
|
|
108
|
+
contents(node) {
|
|
109
|
+
const e = peel(node);
|
|
110
|
+
if (ts.isArrayLiteralExpression(e)) {
|
|
111
|
+
let undefinedValue = false;
|
|
112
|
+
let holes = false;
|
|
113
|
+
for (const element of e.elements) {
|
|
114
|
+
if (ts.isOmittedExpression(element))
|
|
115
|
+
holes = true;
|
|
116
|
+
else if (this.valueMayBeUndefined(element))
|
|
117
|
+
undefinedValue = true;
|
|
118
|
+
}
|
|
119
|
+
return { undefined: undefinedValue, holes };
|
|
120
|
+
}
|
|
121
|
+
if (ts.isConditionalExpression(e))
|
|
122
|
+
return merge(this.contents(e.whenTrue), this.contents(e.whenFalse));
|
|
123
|
+
if (ts.isBinaryExpression(e)) {
|
|
124
|
+
const op = e.operatorToken.kind;
|
|
125
|
+
if (op === ts.SyntaxKind.QuestionQuestionToken || op === ts.SyntaxKind.BarBarToken)
|
|
126
|
+
return merge(this.contents(e.left), this.contents(e.right));
|
|
127
|
+
if (op === ts.SyntaxKind.AmpersandAmpersandToken || op === ts.SyntaxKind.CommaToken)
|
|
128
|
+
return this.contents(e.right);
|
|
129
|
+
}
|
|
130
|
+
if (ts.isCallExpression(e) || ts.isNewExpression(e)) {
|
|
131
|
+
const built = this.builtContents(e);
|
|
132
|
+
if (built !== undefined)
|
|
133
|
+
return built;
|
|
134
|
+
}
|
|
135
|
+
const owner = this.host.ownerOf(e);
|
|
136
|
+
if (owner !== null)
|
|
137
|
+
return { undefined: this.undefinedOwners.has(owner), holes: this.holeyOwners.has(owner) };
|
|
138
|
+
return this.stored(this.host.arrayKeys(e));
|
|
139
|
+
}
|
|
140
|
+
/** Contents of an array a call creates; undefined when the call is not a
|
|
141
|
+
* known array constructor or method. */
|
|
142
|
+
builtContents(node) {
|
|
143
|
+
const args = node.arguments ?? [];
|
|
144
|
+
const callee = peel(node.expression);
|
|
145
|
+
if (ts.isIdentifier(callee)) {
|
|
146
|
+
if (!this.host.isGlobal(callee, "Array"))
|
|
147
|
+
return undefined;
|
|
148
|
+
// `new Array(n)` allocates holes; more arguments are the elements.
|
|
149
|
+
if (args.length === 1 && !ts.isSpreadElement(args[0]) && isNumberLike(args[0]))
|
|
150
|
+
return { undefined: false, holes: true };
|
|
151
|
+
return { undefined: args.some((arg) => this.valueMayBeUndefined(arg)), holes: false };
|
|
152
|
+
}
|
|
153
|
+
if (!ts.isPropertyAccessExpression(callee))
|
|
154
|
+
return undefined;
|
|
155
|
+
const method = callee.name.text;
|
|
156
|
+
const owner = callee.expression;
|
|
157
|
+
if (this.host.isGlobal(owner, "Array")) {
|
|
158
|
+
if (method === "of")
|
|
159
|
+
return { undefined: args.some((arg) => this.valueMayBeUndefined(arg)), holes: false };
|
|
160
|
+
if (method === "from" || method === "fromAsync") {
|
|
161
|
+
const source = args[0];
|
|
162
|
+
const mapper = args[1];
|
|
163
|
+
// Without a mapper an array-like's missing indices become undefined.
|
|
164
|
+
const fromSource = source !== undefined &&
|
|
165
|
+
!ts.isSpreadElement(source) &&
|
|
166
|
+
(this.mayYieldUndefined(source) ||
|
|
167
|
+
(mapper === undefined && this.host.isArrayLikeObject(source)));
|
|
168
|
+
const fromMapper = mapper !== undefined && this.host.callbackReturnsUndefined(mapper);
|
|
169
|
+
return { undefined: fromSource || fromMapper, holes: false };
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
if (this.host.isGlobal(owner, "Object")) {
|
|
174
|
+
// Present-undefined properties are listed as values.
|
|
175
|
+
return method === "values" || method === "entries"
|
|
176
|
+
? { undefined: true, holes: false }
|
|
177
|
+
: undefined;
|
|
178
|
+
}
|
|
179
|
+
if (this.host.isGlobal(owner, "Promise")) {
|
|
180
|
+
// A settled value can be a runtime-absent result.
|
|
181
|
+
return method === "all" || method === "allSettled"
|
|
182
|
+
? { undefined: true, holes: false }
|
|
183
|
+
: undefined;
|
|
184
|
+
}
|
|
185
|
+
if (method === "match" || method === "matchAll" || method === "exec" || method === "split") {
|
|
186
|
+
const separator = args[0];
|
|
187
|
+
if (method === "split" &&
|
|
188
|
+
separator !== undefined &&
|
|
189
|
+
!ts.isSpreadElement(separator) &&
|
|
190
|
+
this.host.isString(separator))
|
|
191
|
+
return NOTHING;
|
|
192
|
+
// Non-participating capture groups produce undefined entries.
|
|
193
|
+
return { undefined: true, holes: false };
|
|
194
|
+
}
|
|
195
|
+
const receiverKeys = this.host.arrayKeys(owner);
|
|
196
|
+
if (receiverKeys !== null && receiverKeys.length === 0)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (method === "map") {
|
|
199
|
+
const callback = args[0];
|
|
200
|
+
const receiver = this.contents(owner);
|
|
201
|
+
// map keeps the receiver's holes; its values are the callback's.
|
|
202
|
+
if (receiver === null)
|
|
203
|
+
return null;
|
|
204
|
+
return {
|
|
205
|
+
undefined: callback !== undefined && this.host.callbackReturnsUndefined(callback),
|
|
206
|
+
holes: receiver.holes,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
if (method === "flatMap") {
|
|
210
|
+
const callback = args[0];
|
|
211
|
+
if (callback !== undefined && this.host.callbackReturnsUndefined(callback))
|
|
212
|
+
return { undefined: true, holes: false };
|
|
213
|
+
// Returned arrays are flattened, keeping their explicit undefined.
|
|
214
|
+
const flattened = this.stored(this.host.arrayKeys(node));
|
|
215
|
+
return flattened === null ? null : { undefined: flattened.undefined, holes: false };
|
|
216
|
+
}
|
|
217
|
+
if (!IN_PLACE.has(method) &&
|
|
218
|
+
!HOLES_KEPT.has(method) &&
|
|
219
|
+
!HOLES_SKIPPED.has(method) &&
|
|
220
|
+
!HOLES_FILLED.has(method))
|
|
221
|
+
return undefined;
|
|
222
|
+
const receiver = this.contents(owner);
|
|
223
|
+
// A whole-array fill writes every slot.
|
|
224
|
+
if (method === "fill" && args.length === 1 && !ts.isSpreadElement(args[0]))
|
|
225
|
+
return receiver === null
|
|
226
|
+
? null
|
|
227
|
+
: { undefined: this.host.mayBeUndefined(args[0]), holes: false };
|
|
228
|
+
if (IN_PLACE.has(method) || receiver === null)
|
|
229
|
+
return receiver;
|
|
230
|
+
if (HOLES_KEPT.has(method)) {
|
|
231
|
+
let undefinedValue = receiver.undefined;
|
|
232
|
+
let holes = receiver.holes;
|
|
233
|
+
// concat appends its arguments; the slices splice returns keep holes.
|
|
234
|
+
if (method === "concat") {
|
|
235
|
+
for (const arg of args) {
|
|
236
|
+
if (ts.isSpreadElement(arg)) {
|
|
237
|
+
if (this.mayYieldUndefined(arg.expression))
|
|
238
|
+
undefinedValue = true;
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const keys = this.host.arrayKeys(arg);
|
|
242
|
+
if (keys !== null && keys.length === 0) {
|
|
243
|
+
if (this.host.mayBeUndefined(arg))
|
|
244
|
+
undefinedValue = true;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
const other = this.contents(arg);
|
|
248
|
+
if (other === null)
|
|
249
|
+
return null;
|
|
250
|
+
undefinedValue ||= other.undefined;
|
|
251
|
+
holes ||= other.holes;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return { undefined: undefinedValue, holes };
|
|
255
|
+
}
|
|
256
|
+
if (HOLES_SKIPPED.has(method)) {
|
|
257
|
+
if (method === "flat") {
|
|
258
|
+
// Nested arrays are flattened, keeping their explicit undefined.
|
|
259
|
+
const flattened = this.stored(this.host.arrayKeys(node));
|
|
260
|
+
if (flattened === null)
|
|
261
|
+
return null;
|
|
262
|
+
return { undefined: receiver.undefined || flattened.undefined, holes: false };
|
|
263
|
+
}
|
|
264
|
+
return { undefined: receiver.undefined, holes: false };
|
|
265
|
+
}
|
|
266
|
+
let undefinedValue = receiver.undefined || receiver.holes;
|
|
267
|
+
if (method === "with" && args[1] !== undefined && this.valueMayBeUndefined(args[1]))
|
|
268
|
+
undefinedValue = true;
|
|
269
|
+
if (method === "toSpliced")
|
|
270
|
+
for (const arg of args.slice(2))
|
|
271
|
+
if (this.valueMayBeUndefined(arg))
|
|
272
|
+
undefinedValue = true;
|
|
273
|
+
return { undefined: undefinedValue, holes: false };
|
|
274
|
+
}
|
|
275
|
+
/** The facts recorded for arrays with these element ABIs. */
|
|
276
|
+
stored(keys) {
|
|
277
|
+
if (this.ownFactsOnly)
|
|
278
|
+
return NOTHING;
|
|
279
|
+
if (keys === null)
|
|
280
|
+
return null;
|
|
281
|
+
return {
|
|
282
|
+
undefined: this.anyUndefined ||
|
|
283
|
+
keys.some((key) => this.undefinedKeys.has(key) || this.host.elementAdmitsUndefined(key)),
|
|
284
|
+
holes: this.anyHoley || keys.some((key) => this.holeyKeys.has(key)),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
/** Reading every index of `node` (a spread, an iteration, `Array.from`)
|
|
288
|
+
* can produce `undefined`. Only native arrays can: other iterables reject
|
|
289
|
+
* an undefined value when it is stored. */
|
|
290
|
+
mayYieldUndefined(node) {
|
|
291
|
+
const keys = this.host.arrayKeys(node);
|
|
292
|
+
if (keys !== null && keys.length === 0)
|
|
293
|
+
return false;
|
|
294
|
+
const contents = this.contents(node);
|
|
295
|
+
return contents === null
|
|
296
|
+
? this.anyUndefined || this.anyHoley
|
|
297
|
+
: contents.undefined || contents.holes;
|
|
298
|
+
}
|
|
299
|
+
/** One stored value, or the elements a spread copies. */
|
|
300
|
+
valueMayBeUndefined(value) {
|
|
301
|
+
if (ts.isSpreadElement(value))
|
|
302
|
+
return this.mayYieldUndefined(value.expression);
|
|
303
|
+
return this.host.mayBeUndefined(value);
|
|
304
|
+
}
|
|
305
|
+
/** Records an array the expression creates, for the slot that owns it
|
|
306
|
+
* or else under its element ABI. */
|
|
307
|
+
record(node) {
|
|
308
|
+
// Only array constructors and methods build an array whose contents
|
|
309
|
+
// can differ from what its element ABI already records.
|
|
310
|
+
if ((ts.isCallExpression(node) || ts.isNewExpression(node)) && !buildsArray(node))
|
|
311
|
+
return false;
|
|
312
|
+
if (consumedWhereBuilt(node))
|
|
313
|
+
return false;
|
|
314
|
+
// An empty literal holds nothing.
|
|
315
|
+
if (ts.isArrayLiteralExpression(node) && node.elements.length === 0)
|
|
316
|
+
return false;
|
|
317
|
+
const contents = this.contents(node);
|
|
318
|
+
if (contents === null || (!contents.undefined && !contents.holes))
|
|
319
|
+
return false;
|
|
320
|
+
const keys = this.keysAsUsed(node);
|
|
321
|
+
if (keys !== null && keys.length === 0)
|
|
322
|
+
return false;
|
|
323
|
+
const owner = this.host.allocationOwner(node);
|
|
324
|
+
if (owner !== null) {
|
|
325
|
+
let changed = false;
|
|
326
|
+
if (contents.undefined && !this.undefinedOwners.has(owner)) {
|
|
327
|
+
this.undefinedOwners.add(owner);
|
|
328
|
+
changed = true;
|
|
329
|
+
}
|
|
330
|
+
if (contents.holes && !this.holeyOwners.has(owner)) {
|
|
331
|
+
this.holeyOwners.add(owner);
|
|
332
|
+
changed = true;
|
|
333
|
+
}
|
|
334
|
+
return changed;
|
|
335
|
+
}
|
|
336
|
+
let changed = false;
|
|
337
|
+
if (contents.undefined && this.addUndefined(keys))
|
|
338
|
+
changed = true;
|
|
339
|
+
if (contents.holes && this.addHoles(keys))
|
|
340
|
+
changed = true;
|
|
341
|
+
return changed;
|
|
342
|
+
}
|
|
343
|
+
/** Element ABIs of a built array, including those an enclosing type
|
|
344
|
+
* assertion gives it (`[a, , b] as T[]`). */
|
|
345
|
+
keysAsUsed(node) {
|
|
346
|
+
const keys = new Set();
|
|
347
|
+
for (let e = node;; e = e.parent) {
|
|
348
|
+
const own = this.host.arrayKeys(e);
|
|
349
|
+
if (own === null)
|
|
350
|
+
return null;
|
|
351
|
+
for (const key of own)
|
|
352
|
+
keys.add(key);
|
|
353
|
+
const parent = e.parent;
|
|
354
|
+
if (!parent ||
|
|
355
|
+
!(ts.isParenthesizedExpression(parent) ||
|
|
356
|
+
ts.isAsExpression(parent) ||
|
|
357
|
+
ts.isTypeAssertion(parent) ||
|
|
358
|
+
ts.isSatisfiesExpression(parent) ||
|
|
359
|
+
ts.isNonNullExpression(parent)))
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
return [...keys];
|
|
363
|
+
}
|
|
364
|
+
/** A store through `receiver` can add an undefined value. */
|
|
365
|
+
addUndefinedTo(receiver) {
|
|
366
|
+
const owner = this.host.ownerOf(receiver);
|
|
367
|
+
if (owner === null)
|
|
368
|
+
return this.addUndefined(this.host.arrayKeys(receiver));
|
|
369
|
+
if (this.undefinedOwners.has(owner))
|
|
370
|
+
return false;
|
|
371
|
+
this.undefinedOwners.add(owner);
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
/** A store through `receiver` can leave holes. */
|
|
375
|
+
addHolesTo(receiver) {
|
|
376
|
+
const owner = this.host.ownerOf(receiver);
|
|
377
|
+
if (owner === null)
|
|
378
|
+
return this.addHoles(this.host.arrayKeys(receiver));
|
|
379
|
+
if (this.holeyOwners.has(owner))
|
|
380
|
+
return false;
|
|
381
|
+
this.holeyOwners.add(owner);
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
addUndefined(keys) {
|
|
385
|
+
if (keys === null) {
|
|
386
|
+
if (this.anyUndefined)
|
|
387
|
+
return false;
|
|
388
|
+
this.anyUndefined = true;
|
|
389
|
+
this.host.note?.("undefined", "*", this.site);
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
let changed = false;
|
|
393
|
+
for (const key of keys) {
|
|
394
|
+
if (this.undefinedKeys.has(key))
|
|
395
|
+
continue;
|
|
396
|
+
this.undefinedKeys.add(key);
|
|
397
|
+
this.host.note?.("undefined", key, this.site);
|
|
398
|
+
changed = true;
|
|
399
|
+
}
|
|
400
|
+
return changed;
|
|
401
|
+
}
|
|
402
|
+
addHoles(keys) {
|
|
403
|
+
if (keys === null) {
|
|
404
|
+
if (this.anyHoley)
|
|
405
|
+
return false;
|
|
406
|
+
this.anyHoley = true;
|
|
407
|
+
this.host.note?.("holes", "*", this.site);
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
let changed = false;
|
|
411
|
+
for (const key of keys) {
|
|
412
|
+
if (this.holeyKeys.has(key))
|
|
413
|
+
continue;
|
|
414
|
+
this.holeyKeys.add(key);
|
|
415
|
+
this.host.note?.("holes", key, this.site);
|
|
416
|
+
changed = true;
|
|
417
|
+
}
|
|
418
|
+
return changed;
|
|
419
|
+
}
|
|
420
|
+
scanAssignment(node) {
|
|
421
|
+
const op = node.operatorToken.kind;
|
|
422
|
+
if (op < ts.SyntaxKind.FirstAssignment || op > ts.SyntaxKind.LastAssignment)
|
|
423
|
+
return false;
|
|
424
|
+
const target = peel(node.left);
|
|
425
|
+
if (op === ts.SyntaxKind.EqualsToken && ts.isArrayLiteralExpression(target))
|
|
426
|
+
return this.scanRestAssignment(node);
|
|
427
|
+
if (ts.isElementAccessExpression(target)) {
|
|
428
|
+
// A write past the end leaves holes before it; appending at the
|
|
429
|
+
// receiver's own length does not.
|
|
430
|
+
const holes = !isAppendIndex(target) && !indexStoreInBounds(node);
|
|
431
|
+
const storesValue = op === ts.SyntaxKind.EqualsToken ||
|
|
432
|
+
op === ts.SyntaxKind.QuestionQuestionEqualsToken ||
|
|
433
|
+
op === ts.SyntaxKind.BarBarEqualsToken ||
|
|
434
|
+
op === ts.SyntaxKind.AmpersandAmpersandEqualsToken;
|
|
435
|
+
const undefinedValue = storesValue && this.host.mayBeUndefined(node.right);
|
|
436
|
+
if (!holes && !undefinedValue)
|
|
437
|
+
return false;
|
|
438
|
+
const keys = this.host.arrayKeys(target.expression);
|
|
439
|
+
if (keys !== null && keys.length === 0)
|
|
440
|
+
return false;
|
|
441
|
+
let changed = false;
|
|
442
|
+
if (holes && this.addHolesTo(target.expression))
|
|
443
|
+
changed = true;
|
|
444
|
+
if (undefinedValue && this.addUndefinedTo(target.expression))
|
|
445
|
+
changed = true;
|
|
446
|
+
return changed;
|
|
447
|
+
}
|
|
448
|
+
if (ts.isPropertyAccessExpression(target) &&
|
|
449
|
+
target.name.text === "length" &&
|
|
450
|
+
!isShrinkingLength(node, target)) {
|
|
451
|
+
const keys = this.host.arrayKeys(target.expression);
|
|
452
|
+
if (keys !== null && keys.length === 0)
|
|
453
|
+
return false;
|
|
454
|
+
return this.addHolesTo(target.expression);
|
|
455
|
+
}
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
scanCall(node) {
|
|
459
|
+
let changed = false;
|
|
460
|
+
const args = node.arguments ?? [];
|
|
461
|
+
// Spreading a sparse array into a rest parameter fills the holes.
|
|
462
|
+
if (args.some((arg) => ts.isSpreadElement(arg))) {
|
|
463
|
+
for (const arg of args) {
|
|
464
|
+
if (!ts.isSpreadElement(arg) || !this.mayYieldUndefined(arg.expression))
|
|
465
|
+
continue;
|
|
466
|
+
const rest = this.host.restKeys(node) ?? this.host.arrayKeys(arg.expression);
|
|
467
|
+
if (this.addUndefined(rest))
|
|
468
|
+
changed = true;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (this.record(node))
|
|
472
|
+
changed = true;
|
|
473
|
+
const callee = peel(node.expression);
|
|
474
|
+
if (!ts.isPropertyAccessExpression(callee))
|
|
475
|
+
return changed;
|
|
476
|
+
if (this.scanReflectiveWrite(callee, args))
|
|
477
|
+
changed = true;
|
|
478
|
+
// In-place stores into the receiver.
|
|
479
|
+
let stored;
|
|
480
|
+
switch (callee.name.text) {
|
|
481
|
+
case "push":
|
|
482
|
+
case "unshift":
|
|
483
|
+
stored = args;
|
|
484
|
+
break;
|
|
485
|
+
case "splice":
|
|
486
|
+
stored = args.slice(2);
|
|
487
|
+
break;
|
|
488
|
+
case "fill":
|
|
489
|
+
if (args.length === 0 && this.addUndefinedTo(callee.expression))
|
|
490
|
+
changed = true;
|
|
491
|
+
stored = args.slice(0, 1);
|
|
492
|
+
break;
|
|
493
|
+
default:
|
|
494
|
+
return changed;
|
|
495
|
+
}
|
|
496
|
+
const receiver = this.host.arrayKeys(callee.expression);
|
|
497
|
+
if (receiver !== null && receiver.length === 0)
|
|
498
|
+
return changed;
|
|
499
|
+
for (const value of stored)
|
|
500
|
+
if (this.valueMayBeUndefined(value) && this.addUndefinedTo(callee.expression))
|
|
501
|
+
changed = true;
|
|
502
|
+
return changed;
|
|
503
|
+
}
|
|
504
|
+
/** Writes that bypass the array methods: `Object.assign(xs, ...)`,
|
|
505
|
+
* `Reflect.set(xs, ...)`, `Array.prototype.push.call(xs, ...)` and the
|
|
506
|
+
* like may store any value at any index of an array argument. */
|
|
507
|
+
scanReflectiveWrite(callee, args) {
|
|
508
|
+
const method = callee.name.text;
|
|
509
|
+
const owner = peel(callee.expression);
|
|
510
|
+
const reflective = (this.host.isGlobal(owner, "Object") &&
|
|
511
|
+
(method === "assign" ||
|
|
512
|
+
method === "defineProperty" ||
|
|
513
|
+
method === "defineProperties" ||
|
|
514
|
+
method === "setPrototypeOf")) ||
|
|
515
|
+
(this.host.isGlobal(owner, "Reflect") &&
|
|
516
|
+
(method === "set" || method === "defineProperty" || method === "apply")) ||
|
|
517
|
+
((method === "call" || method === "apply") &&
|
|
518
|
+
ts.isPropertyAccessExpression(owner) &&
|
|
519
|
+
ts.isPropertyAccessExpression(peel(owner.expression)) &&
|
|
520
|
+
peel(owner.expression).name.text === "prototype" &&
|
|
521
|
+
this.host.isGlobal(peel(owner.expression).expression, "Array"));
|
|
522
|
+
if (!reflective)
|
|
523
|
+
return false;
|
|
524
|
+
let changed = false;
|
|
525
|
+
for (const arg of args) {
|
|
526
|
+
const target = ts.isSpreadElement(arg) ? arg.expression : arg;
|
|
527
|
+
const keys = this.host.arrayKeys(target);
|
|
528
|
+
if (keys !== null && keys.length === 0)
|
|
529
|
+
continue;
|
|
530
|
+
if (this.addUndefinedTo(target))
|
|
531
|
+
changed = true;
|
|
532
|
+
if (this.addHolesTo(target))
|
|
533
|
+
changed = true;
|
|
534
|
+
}
|
|
535
|
+
return changed;
|
|
536
|
+
}
|
|
537
|
+
/** A for-of loop over `node`'s iterable can bind `undefined`: a hole
|
|
538
|
+
* or a stored undefined in the array it walks. When it cannot, every
|
|
539
|
+
* element the loop reads is a present value. */
|
|
540
|
+
loopMayYieldUndefined(node) {
|
|
541
|
+
return this.mayYieldUndefined(this.loopSource(node));
|
|
542
|
+
}
|
|
543
|
+
/** The loop's array itself, as built or as owned by one slot, can hold
|
|
544
|
+
* a hole or undefined. Facts shared by every array with the same element
|
|
545
|
+
* ABI are coarser: a loop judged only by them keeps checked reads. */
|
|
546
|
+
loopHolesKnown(node) {
|
|
547
|
+
const source = this.loopSource(node);
|
|
548
|
+
const keys = this.host.arrayKeys(source);
|
|
549
|
+
if (keys !== null && keys.length === 0)
|
|
550
|
+
return false;
|
|
551
|
+
this.ownFactsOnly = true;
|
|
552
|
+
try {
|
|
553
|
+
const contents = this.contents(source);
|
|
554
|
+
return contents !== null && (contents.undefined || contents.holes);
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
this.ownFactsOnly = false;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
loopSource(node) {
|
|
561
|
+
let source = peel(node.expression);
|
|
562
|
+
if (ts.isCallExpression(source) &&
|
|
563
|
+
ts.isPropertyAccessExpression(source.expression) &&
|
|
564
|
+
(source.expression.name.text === "values" || source.expression.name.text === "entries") &&
|
|
565
|
+
source.arguments.length === 0) {
|
|
566
|
+
const receiver = this.host.arrayKeys(source.expression.expression);
|
|
567
|
+
if (receiver === null || receiver.length > 0)
|
|
568
|
+
source = source.expression.expression;
|
|
569
|
+
}
|
|
570
|
+
return source;
|
|
571
|
+
}
|
|
572
|
+
scanForOf(node) {
|
|
573
|
+
if (!this.loopMayYieldUndefined(node))
|
|
574
|
+
return false;
|
|
575
|
+
const known = this.loopHolesKnown(node);
|
|
576
|
+
const initializer = node.initializer;
|
|
577
|
+
let changed = false;
|
|
578
|
+
const mark = (name) => {
|
|
579
|
+
if (ts.isIdentifier(name)) {
|
|
580
|
+
if (this.host.markIterationBinding(name, known))
|
|
581
|
+
changed = true;
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
name.forEachChild(mark);
|
|
585
|
+
};
|
|
586
|
+
if (ts.isVariableDeclarationList(initializer)) {
|
|
587
|
+
for (const declaration of initializer.declarations)
|
|
588
|
+
mark(declaration.name);
|
|
589
|
+
}
|
|
590
|
+
else
|
|
591
|
+
mark(initializer);
|
|
592
|
+
return changed;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/** Names of the constructors, methods and builtins that return a new
|
|
596
|
+
* array or their receiver. */
|
|
597
|
+
const ARRAY_BUILDERS = new Set([
|
|
598
|
+
"Array",
|
|
599
|
+
"of",
|
|
600
|
+
"from",
|
|
601
|
+
"fromAsync",
|
|
602
|
+
"values",
|
|
603
|
+
"entries",
|
|
604
|
+
"all",
|
|
605
|
+
"allSettled",
|
|
606
|
+
"match",
|
|
607
|
+
"matchAll",
|
|
608
|
+
"exec",
|
|
609
|
+
"split",
|
|
610
|
+
"map",
|
|
611
|
+
"flatMap",
|
|
612
|
+
...HOLES_KEPT,
|
|
613
|
+
...HOLES_SKIPPED,
|
|
614
|
+
...HOLES_FILLED,
|
|
615
|
+
...IN_PLACE,
|
|
616
|
+
]);
|
|
617
|
+
function buildsArray(node) {
|
|
618
|
+
const callee = peel(node.expression);
|
|
619
|
+
if (ts.isIdentifier(callee))
|
|
620
|
+
return callee.text === "Array";
|
|
621
|
+
return ts.isPropertyAccessExpression(callee) && ARRAY_BUILDERS.has(callee.name.text);
|
|
622
|
+
}
|
|
623
|
+
/** Callback methods, by the position of the parameter receiving the
|
|
624
|
+
* array itself. */
|
|
625
|
+
const ARRAY_ARGUMENT_AT = new Map([
|
|
626
|
+
["map", 2],
|
|
627
|
+
["filter", 2],
|
|
628
|
+
["forEach", 2],
|
|
629
|
+
["some", 2],
|
|
630
|
+
["every", 2],
|
|
631
|
+
["find", 2],
|
|
632
|
+
["findIndex", 2],
|
|
633
|
+
["findLast", 2],
|
|
634
|
+
["findLastIndex", 2],
|
|
635
|
+
["flatMap", 2],
|
|
636
|
+
["reduce", 3],
|
|
637
|
+
["reduceRight", 3],
|
|
638
|
+
]);
|
|
639
|
+
/** A newly built array that is used up where it is built: discarded, or
|
|
640
|
+
* read by a spread, an iteration, or a method call whose callback cannot
|
|
641
|
+
* see it. Nothing else ever references it, so only the value derived from
|
|
642
|
+
* it (judged by its own contents) can carry its holes or undefined. */
|
|
643
|
+
function consumedWhereBuilt(node) {
|
|
644
|
+
let child = node;
|
|
645
|
+
let parent = node.parent;
|
|
646
|
+
while (parent && ts.isParenthesizedExpression(parent)) {
|
|
647
|
+
child = parent;
|
|
648
|
+
parent = parent.parent;
|
|
649
|
+
}
|
|
650
|
+
if (!parent)
|
|
651
|
+
return false;
|
|
652
|
+
if (ts.isExpressionStatement(parent))
|
|
653
|
+
return true;
|
|
654
|
+
if (ts.isSpreadElement(parent))
|
|
655
|
+
return true;
|
|
656
|
+
if (ts.isForOfStatement(parent))
|
|
657
|
+
return parent.expression === child;
|
|
658
|
+
if (ts.isPropertyAccessExpression(parent) &&
|
|
659
|
+
parent.expression === child &&
|
|
660
|
+
parent.parent &&
|
|
661
|
+
ts.isCallExpression(parent.parent) &&
|
|
662
|
+
parent.parent.expression === parent) {
|
|
663
|
+
const arrayAt = ARRAY_ARGUMENT_AT.get(parent.name.text);
|
|
664
|
+
if (arrayAt === undefined)
|
|
665
|
+
return true;
|
|
666
|
+
const callback = parent.parent.arguments[0];
|
|
667
|
+
return (callback !== undefined &&
|
|
668
|
+
(ts.isArrowFunction(callback) || ts.isFunctionExpression(callback)) &&
|
|
669
|
+
callback.parameters.length <= arrayAt &&
|
|
670
|
+
!callback.parameters.some((parameter) => parameter.dotDotDotToken) &&
|
|
671
|
+
ts.isArrowFunction(callback));
|
|
672
|
+
}
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
function merge(a, b) {
|
|
676
|
+
if (a === null || b === null)
|
|
677
|
+
return null;
|
|
678
|
+
return { undefined: a.undefined || b.undefined, holes: a.holes || b.holes };
|
|
679
|
+
}
|
|
680
|
+
function peel(node) {
|
|
681
|
+
let e = node;
|
|
682
|
+
while (ts.isParenthesizedExpression(e) ||
|
|
683
|
+
ts.isAsExpression(e) ||
|
|
684
|
+
ts.isTypeAssertion(e) ||
|
|
685
|
+
ts.isSatisfiesExpression(e) ||
|
|
686
|
+
ts.isNonNullExpression(e))
|
|
687
|
+
e = e.expression;
|
|
688
|
+
return e;
|
|
689
|
+
}
|
|
690
|
+
function sameReference(a, b) {
|
|
691
|
+
const left = peel(a);
|
|
692
|
+
const right = peel(b);
|
|
693
|
+
if (ts.isIdentifier(left) && ts.isIdentifier(right))
|
|
694
|
+
return left.text === right.text;
|
|
695
|
+
if (left.kind === ts.SyntaxKind.ThisKeyword && right.kind === ts.SyntaxKind.ThisKeyword)
|
|
696
|
+
return true;
|
|
697
|
+
if (ts.isPropertyAccessExpression(left) && ts.isPropertyAccessExpression(right))
|
|
698
|
+
return left.name.text === right.name.text && sameReference(left.expression, right.expression);
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
/** `xs[xs.length] = v` appends without leaving a hole. */
|
|
702
|
+
function isAppendIndex(target) {
|
|
703
|
+
const index = peel(target.argumentExpression);
|
|
704
|
+
return (ts.isPropertyAccessExpression(index) &&
|
|
705
|
+
index.name.text === "length" &&
|
|
706
|
+
sameReference(index.expression, target.expression));
|
|
707
|
+
}
|
|
708
|
+
/** `xs.length = 0`, `xs.length = xs.length - k` and `xs.length -= k`
|
|
709
|
+
* truncate; truncation never leaves holes. */
|
|
710
|
+
function isShrinkingLength(node, target) {
|
|
711
|
+
const op = node.operatorToken.kind;
|
|
712
|
+
const right = peel(node.right);
|
|
713
|
+
if (op === ts.SyntaxKind.MinusEqualsToken)
|
|
714
|
+
return ts.isNumericLiteral(right);
|
|
715
|
+
if (op !== ts.SyntaxKind.EqualsToken)
|
|
716
|
+
return false;
|
|
717
|
+
if (ts.isNumericLiteral(right))
|
|
718
|
+
return Number(right.text) === 0;
|
|
719
|
+
if (!ts.isBinaryExpression(right) || right.operatorToken.kind !== ts.SyntaxKind.MinusToken)
|
|
720
|
+
return false;
|
|
721
|
+
const length = peel(right.left);
|
|
722
|
+
return (ts.isNumericLiteral(peel(right.right)) &&
|
|
723
|
+
ts.isPropertyAccessExpression(length) &&
|
|
724
|
+
length.name.text === "length" &&
|
|
725
|
+
sameReference(length.expression, target.expression));
|
|
726
|
+
}
|
|
727
|
+
function isNumberLike(node) {
|
|
728
|
+
const e = peel(node);
|
|
729
|
+
return !(ts.isStringLiteral(e) ||
|
|
730
|
+
ts.isNoSubstitutionTemplateLiteral(e) ||
|
|
731
|
+
ts.isObjectLiteralExpression(e) ||
|
|
732
|
+
ts.isArrayLiteralExpression(e) ||
|
|
733
|
+
ts.isArrowFunction(e) ||
|
|
734
|
+
ts.isFunctionExpression(e) ||
|
|
735
|
+
e.kind === ts.SyntaxKind.TrueKeyword ||
|
|
736
|
+
e.kind === ts.SyntaxKind.FalseKeyword);
|
|
737
|
+
}
|
|
738
|
+
//# sourceMappingURL=runtime-optional-elements.js.map
|