@scriptc/compiler 0.4.1 → 0.4.3
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 +977 -113
- package/dist/backend/cycle-analysis.d.ts +5 -1
- package/dist/backend/cycle-analysis.js +6 -4
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +55 -0
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +9 -1
- package/dist/backend/cycle-mutability.js +21 -3
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +6 -1
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +7 -3
- package/dist/backend/immutability.js +33 -29
- package/dist/backend/immutability.js.map +1 -1
- package/dist/backend/library-pack.js +5 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +23 -4
- package/dist/backend/llvm/alloc.js +61 -8
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.d.ts +2 -1
- package/dist/backend/llvm/appended-array-literals.js +44 -36
- package/dist/backend/llvm/appended-array-literals.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.test.js +4 -3
- package/dist/backend/llvm/appended-array-literals.test.js.map +1 -1
- package/dist/backend/llvm/array-search.d.ts +4 -3
- package/dist/backend/llvm/array-search.js +23 -10
- package/dist/backend/llvm/array-search.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +1 -1
- package/dist/backend/llvm/blocks.js +2 -2
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/byte-windows.js +2 -0
- package/dist/backend/llvm/byte-windows.js.map +1 -1
- package/dist/backend/llvm/bytes-alias.d.ts +6 -1
- package/dist/backend/llvm/bytes-alias.js +8 -2
- package/dist/backend/llvm/bytes-alias.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.d.ts +70 -7
- package/dist/backend/llvm/bytes-loop-versions.js +567 -30
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.test.js +389 -2
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.js +2 -0
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +74 -1
- package/dist/backend/llvm/classes.js +364 -54
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +384 -17
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +10 -6
- package/dist/backend/llvm/common.js +10 -6
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +2 -1
- package/dist/backend/llvm/constant-callbacks.js +91 -56
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +4 -4
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +11 -1
- package/dist/backend/llvm/counted-loops.js +80 -23
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +39 -8
- package/dist/backend/llvm/dense-array-access.js +222 -52
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +36 -0
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.d.ts +35 -16
- package/dist/backend/llvm/dense-array-loops.js +237 -12
- package/dist/backend/llvm/dense-array-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.test.js +140 -15
- package/dist/backend/llvm/dense-array-loops.test.js.map +1 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js +6 -1
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +51 -1
- package/dist/backend/llvm/dyn.js +683 -69
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +33 -26
- package/dist/backend/llvm/emit-function.js.map +1 -1
- package/dist/backend/llvm/emit-journal.d.ts +93 -0
- package/dist/backend/llvm/emit-journal.js +170 -0
- package/dist/backend/llvm/emit-journal.js.map +1 -0
- package/dist/backend/llvm/emit-module.js +208 -34
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.d.ts +0 -27
- package/dist/backend/llvm/emit-statements.js +577 -93
- package/dist/backend/llvm/emit-statements.js.map +1 -1
- package/dist/backend/llvm/emitter-state.d.ts +7 -0
- package/dist/backend/llvm/emitter-state.js +14 -0
- package/dist/backend/llvm/emitter-state.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +314 -49
- package/dist/backend/llvm/emitter.js +1241 -129
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +54 -5
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +19 -0
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +5 -2
- package/dist/backend/llvm/expr-bytes.js +144 -52
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +47 -0
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +1 -1
- package/dist/backend/llvm/expr-calls.js +62 -36
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +14 -2
- package/dist/backend/llvm/expr-containers.js +148 -40
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +14 -0
- package/dist/backend/llvm/expr-control.js +2 -3
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +71 -16
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +126 -36
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +11 -6
- package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
- package/dist/backend/llvm/expr-records.d.ts +12 -0
- package/dist/backend/llvm/expr-records.js +106 -0
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-bridges.js +225 -64
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +200 -50
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/int32-kind-loops.d.ts +39 -0
- package/dist/backend/llvm/int32-kind-loops.js +106 -0
- package/dist/backend/llvm/int32-kind-loops.js.map +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.d.ts +1 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js +118 -0
- package/dist/backend/llvm/integer-or-nan-indexes.test.js.map +1 -0
- package/dist/backend/llvm/integer-values.d.ts +20 -1
- package/dist/backend/llvm/integer-values.js +71 -0
- package/dist/backend/llvm/integer-values.js.map +1 -1
- package/dist/backend/llvm/js-ic.d.ts +1 -1
- package/dist/backend/llvm/js-ic.js +1 -1
- package/dist/backend/llvm/js-ic.js.map +1 -1
- package/dist/backend/llvm/key-orders.d.ts +7 -0
- package/dist/backend/llvm/key-orders.js +33 -0
- package/dist/backend/llvm/key-orders.js.map +1 -0
- package/dist/backend/llvm/lib-connect.js +4 -0
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +11 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +90 -2
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +65 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.d.ts +4 -0
- package/dist/backend/llvm/lib-http2.js +24 -17
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +16 -6
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +65 -14
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +126 -3
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +97 -30
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-tls.js +23 -0
- package/dist/backend/llvm/lib-tls.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +181 -64
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +28 -0
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/loop-state.d.ts +33 -0
- package/dist/backend/llvm/loop-state.js +42 -0
- package/dist/backend/llvm/loop-state.js.map +1 -0
- package/dist/backend/llvm/map-number-lookup.d.ts +26 -8
- package/dist/backend/llvm/map-number-lookup.js +91 -31
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.js +55 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.js +4 -2
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +2 -1
- package/dist/backend/llvm/nullable-unions.js +15 -3
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +18 -1
- package/dist/backend/llvm/publish.js +76 -25
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/publish.test.js +3 -0
- package/dist/backend/llvm/publish.test.js.map +1 -1
- package/dist/backend/llvm/receivers.js +7 -2
- package/dist/backend/llvm/receivers.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +1 -9
- package/dist/backend/llvm/record-results.js +2 -11
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +7 -2
- package/dist/backend/llvm/reference-writes.js +91 -72
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.js +161 -14
- package/dist/backend/llvm/regex-matchers.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.test.js +18 -0
- package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
- package/dist/backend/llvm/running-extrema.d.ts +11 -0
- package/dist/backend/llvm/running-extrema.js +115 -0
- package/dist/backend/llvm/running-extrema.js.map +1 -0
- package/dist/backend/llvm/running-extrema.test.d.ts +1 -0
- package/dist/backend/llvm/running-extrema.test.js +89 -0
- package/dist/backend/llvm/running-extrema.test.js.map +1 -0
- package/dist/backend/llvm/shapes.d.ts +79 -21
- package/dist/backend/llvm/shapes.js +233 -42
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +53 -7
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +6 -0
- package/dist/backend/llvm/speculative-integers.js +2 -2
- package/dist/backend/llvm/speculative-integers.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +3 -2
- package/dist/backend/llvm/stack-objects.js +5 -2
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +2 -1
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.d.ts +15 -0
- package/dist/backend/llvm/string-reads.js +128 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/walk-borrows.d.ts +3 -0
- package/dist/backend/llvm/walk-borrows.js +46 -41
- package/dist/backend/llvm/walk-borrows.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +3 -0
- package/dist/backend/llvm/walkers.js +88 -65
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wasm-modules.d.ts +6 -5
- package/dist/backend/llvm/wasm-modules.js +32 -9
- package/dist/backend/llvm/wasm-modules.js.map +1 -1
- package/dist/backend/llvm/wrapping-sums.d.ts +16 -1
- package/dist/backend/llvm/wrapping-sums.js +126 -0
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/mangle.d.ts +3 -0
- package/dist/backend/mangle.js +5 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.d.ts +8 -10
- package/dist/backend/may-throw.js +14 -10
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +27 -4
- package/dist/backend/native/executable.js +31 -8
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -0
- package/dist/backend/native/library.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.d.ts +11 -6
- package/dist/backend/native-codegen.js +36 -9
- package/dist/backend/native-codegen.js.map +1 -1
- package/dist/backend/native-codegen.test.js +0 -23
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +18 -4
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/optimization.d.ts +2 -2
- package/dist/backend/publication.d.ts +12 -1
- package/dist/backend/publication.js +37 -14
- package/dist/backend/publication.js.map +1 -1
- package/dist/backend/publication.test.js +30 -0
- package/dist/backend/publication.test.js.map +1 -1
- package/dist/backend/result-slots.d.ts +16 -0
- package/dist/backend/result-slots.js +23 -0
- package/dist/backend/result-slots.js.map +1 -0
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +2 -1
- package/dist/backend/runtime-pack-core.js +2 -1
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +5 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +0 -21
- package/dist/backend/runtime-pack.js +0 -29
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +10 -69
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/stack-observations.d.ts +2 -1
- package/dist/backend/stack-observations.js +67 -42
- package/dist/backend/stack-observations.js.map +1 -1
- package/dist/backend/target-diagnostics.js +33 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/warm-cache.js +4 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +26 -6
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +5 -1
- package/dist/cli/usage.js +10 -5
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.js +1 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/contracts/check.js +5 -4
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.js +10 -2
- package/dist/contracts/int32-elements.js.map +1 -1
- package/dist/coverage/report.d.ts +7 -2
- package/dist/coverage/report.js +30 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +1 -0
- package/dist/coverage/verdict-cache.js +4 -0
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/coverage/verdict-semantic.js +4 -0
- package/dist/coverage/verdict-semantic.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/dynamic-tier.d.ts +40 -0
- package/dist/diagnostics/dynamic-tier.js +57 -0
- package/dist/diagnostics/dynamic-tier.js.map +1 -0
- package/dist/diagnostics/envelope.d.ts +5 -1
- package/dist/diagnostics/envelope.js +6 -2
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +25 -1
- package/dist/executable/executable-cache.js +60 -7
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +46 -3
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +3 -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/decl-projection.d.ts +41 -0
- package/dist/frontend/decl-projection.js +854 -0
- package/dist/frontend/decl-projection.js.map +1 -0
- package/dist/frontend/decl-projection.test.d.ts +1 -0
- package/dist/frontend/decl-projection.test.js +30 -0
- package/dist/frontend/decl-projection.test.js.map +1 -0
- package/dist/frontend/dispose-hook.d.ts +2 -0
- package/dist/frontend/dispose-hook.js +14 -0
- package/dist/frontend/dispose-hook.js.map +1 -0
- package/dist/frontend/dts-paths.d.ts +15 -0
- package/dist/frontend/dts-paths.js +25 -0
- package/dist/frontend/dts-paths.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +6 -0
- package/dist/frontend/input-tracker.js +51 -28
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/input-tracker.test.js +19 -0
- package/dist/frontend/input-tracker.test.js.map +1 -1
- package/dist/frontend/jsx-entities.d.ts +4 -0
- package/dist/frontend/jsx-entities.js +259 -0
- package/dist/frontend/jsx-entities.js.map +1 -0
- package/dist/frontend/jsx-source.d.ts +71 -0
- package/dist/frontend/jsx-source.js +781 -0
- package/dist/frontend/jsx-source.js.map +1 -0
- package/dist/frontend/jsx-source.test.d.ts +1 -0
- package/dist/frontend/jsx-source.test.js +200 -0
- package/dist/frontend/jsx-source.test.js.map +1 -0
- package/dist/frontend/literal-values.test.js +8 -9
- package/dist/frontend/literal-values.test.js.map +1 -1
- package/dist/frontend/lowering/array-indexed-mutation.js +2 -1
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -1
- package/dist/frontend/lowering/array-values.js +103 -4
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/binding-analysis.d.ts +1 -1
- package/dist/frontend/lowering/binding-analysis.js +2 -2
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtins/arguments.d.ts +3 -0
- package/dist/frontend/lowering/builtins/arguments.js +30 -15
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/atomics.js +10 -6
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-async.js +2 -1
- package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.js +46 -15
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js +2 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.js +13 -2
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +4 -2
- package/dist/frontend/lowering/builtins/crypto.js +136 -5
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/date-classes.d.ts +46 -0
- package/dist/frontend/lowering/builtins/date-classes.js +477 -0
- package/dist/frontend/lowering/builtins/date-classes.js.map +1 -0
- package/dist/frontend/lowering/builtins/dates.d.ts +11 -1
- package/dist/frontend/lowering/builtins/dates.js +55 -26
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/dh.d.ts +15 -0
- package/dist/frontend/lowering/builtins/dh.js +151 -0
- package/dist/frontend/lowering/builtins/dh.js.map +1 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js +2 -1
- package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -1
- package/dist/frontend/lowering/builtins/ecdh.d.ts +12 -1
- package/dist/frontend/lowering/builtins/ecdh.js +7 -7
- package/dist/frontend/lowering/builtins/ecdh.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.d.ts +15 -0
- package/dist/frontend/lowering/builtins/errors.js +110 -0
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js +23 -17
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.js +6 -4
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-paths.d.ts +15 -0
- package/dist/frontend/lowering/builtins/fs-paths.js +209 -0
- package/dist/frontend/lowering/builtins/fs-paths.js.map +1 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.d.ts +3 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js +122 -0
- package/dist/frontend/lowering/builtins/global-namespace-keys.js.map +1 -0
- package/dist/frontend/lowering/builtins/hash-stream.d.ts +16 -4
- package/dist/frontend/lowering/builtins/hash-stream.js +86 -23
- package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +2 -1
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/key-object.d.ts +2 -1
- package/dist/frontend/lowering/builtins/key-object.js +20 -7
- package/dist/frontend/lowering/builtins/key-object.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +11 -4
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +18 -6
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.js +4 -3
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/performance.js +3 -2
- package/dist/frontend/lowering/builtins/performance.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.js +3 -2
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +6 -0
- package/dist/frontend/lowering/builtins/promises.js +91 -4
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/promisify-callback.js +2 -1
- package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +7 -2
- package/dist/frontend/lowering/builtins/readline.js +58 -9
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/strings.js +13 -5
- package/dist/frontend/lowering/builtins/strings.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.js +2 -1
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/timers.js +1 -1
- package/dist/frontend/lowering/builtins/timers.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.js +28 -4
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/v8.js +2 -1
- package/dist/frontend/lowering/builtins/v8.js.map +1 -1
- package/dist/frontend/lowering/builtins/webassembly.js +6 -3
- package/dist/frontend/lowering/builtins/webassembly.js.map +1 -1
- package/dist/frontend/lowering/builtins/webcrypto.js +39 -20
- package/dist/frontend/lowering/builtins/webcrypto.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +2 -1
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +13 -6
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/caught-value-dispatch.d.ts +18 -1
- package/dist/frontend/lowering/caught-value-dispatch.js +201 -32
- package/dist/frontend/lowering/caught-value-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-assertions.js +3 -2
- package/dist/frontend/lowering/class-assertions.js.map +1 -1
- package/dist/frontend/lowering/class-callbacks.d.ts +5 -2
- package/dist/frontend/lowering/class-callbacks.js +82 -12
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.d.ts +6 -2
- package/dist/frontend/lowering/class-construction.js +25 -16
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.js +1 -1
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +73 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1334 -259
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +124 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-iterables.d.ts +2 -1
- package/dist/frontend/lowering/class-iterables.js +9 -1
- package/dist/frontend/lowering/class-iterables.js.map +1 -1
- package/dist/frontend/lowering/class-method-mutations.js +35 -9
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.js +1 -1
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +7 -0
- package/dist/frontend/lowering/class-protocols.js +64 -4
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +5 -0
- package/dist/frontend/lowering/class-prototypes.js +67 -5
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.d.ts +9 -3
- package/dist/frontend/lowering/class-runtime-statics.js +29 -4
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-to-primitive.js +25 -5
- package/dist/frontend/lowering/class-to-primitive.js.map +1 -1
- package/dist/frontend/lowering/class-unions.js +2 -1
- package/dist/frontend/lowering/class-unions.js.map +1 -1
- package/dist/frontend/lowering/coercions/function-adapters.js +6 -5
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +48 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +99 -8
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.js +8 -7
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.js +2 -1
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callback-call.js +2 -2
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +7 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +352 -31
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +12 -1
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +25 -4
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +21 -5
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +21 -9
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +1 -1
- package/dist/frontend/lowering/containers/bytes.js +131 -29
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +55 -2
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-grouping.js +3 -2
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +15 -9
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/filter-predicates.d.ts +6 -0
- package/dist/frontend/lowering/containers/filter-predicates.js +205 -0
- package/dist/frontend/lowering/containers/filter-predicates.js.map +1 -0
- package/dist/frontend/lowering/containers/indexed-objects.d.ts +0 -12
- package/dist/frontend/lowering/containers/indexed-objects.js +54 -14
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/iterator-helpers.d.ts +32 -1
- package/dist/frontend/lowering/containers/iterator-helpers.js +6 -5
- package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +87 -14
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +45 -20
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.js +25 -4
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.d.ts +18 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +226 -115
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.test.js +28 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
- package/dist/frontend/lowering/dispatch-sites.d.ts +59 -0
- package/dist/frontend/lowering/dispatch-sites.js +218 -0
- package/dist/frontend/lowering/dispatch-sites.js.map +1 -0
- package/dist/frontend/lowering/dispatch-sites.test.d.ts +1 -0
- package/dist/frontend/lowering/dispatch-sites.test.js +59 -0
- package/dist/frontend/lowering/dispatch-sites.test.js.map +1 -0
- package/dist/frontend/lowering/divergences.js +9 -1
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/dyn-streams.d.ts +3 -0
- package/dist/frontend/lowering/dyn-streams.js +1 -1
- package/dist/frontend/lowering/dyn-streams.js.map +1 -1
- package/dist/frontend/lowering/dynamic-tier.d.ts +25 -0
- package/dist/frontend/lowering/dynamic-tier.js +327 -0
- package/dist/frontend/lowering/dynamic-tier.js.map +1 -0
- package/dist/frontend/lowering/error-methods.js +51 -2
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.js +62 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/binary.js +81 -5
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.js +107 -14
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.js +79 -11
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/narrowing.js +130 -6
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +3 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -3
- package/dist/frontend/lowering/expressions/object-literals.js +164 -56
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +17 -5
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +0 -4
- package/dist/frontend/lowering/expressions/property-access.js +211 -17
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +267 -30
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/union-fields.js +4 -0
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.js +85 -12
- package/dist/frontend/lowering/expressions/updates.js.map +1 -1
- package/dist/frontend/lowering/frozen-records.d.ts +28 -0
- package/dist/frontend/lowering/frozen-records.js +322 -0
- package/dist/frontend/lowering/frozen-records.js.map +1 -0
- package/dist/frontend/lowering/function-returns.js +49 -0
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +6 -1
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +20 -30
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +42 -1
- package/dist/frontend/lowering/generic-functions.js +455 -20
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/intern-tables.js +2 -1
- package/dist/frontend/lowering/intern-tables.js.map +1 -1
- package/dist/frontend/lowering/iterable-values.d.ts +49 -0
- package/dist/frontend/lowering/iterable-values.js +297 -0
- package/dist/frontend/lowering/iterable-values.js.map +1 -0
- package/dist/frontend/lowering/iterator-adapters.js +195 -9
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/js-class-fields.d.ts +8 -0
- package/dist/frontend/lowering/js-class-fields.js +45 -10
- package/dist/frontend/lowering/js-class-fields.js.map +1 -1
- package/dist/frontend/lowering/js-dynamic-objects.js +3 -2
- package/dist/frontend/lowering/js-dynamic-objects.js.map +1 -1
- package/dist/frontend/lowering/json-require.js +2 -1
- package/dist/frontend/lowering/json-require.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.d.ts +24 -4
- package/dist/frontend/lowering/key-order-witness.js +790 -25
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.test.js +466 -10
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -1
- package/dist/frontend/lowering/lifetime-regions.js +2 -1
- package/dist/frontend/lowering/lifetime-regions.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +6 -5
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +7 -2
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +11 -0
- package/dist/frontend/lowering/lower-calls.js +776 -126
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +29 -2
- package/dist/frontend/lowering/lower-classes.js +581 -46
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +6 -3
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +14 -0
- package/dist/frontend/lowering/lower-event-emitter.js +267 -20
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +19 -2
- package/dist/frontend/lowering/lower-exprs.js +126 -13
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.d.ts +11 -0
- package/dist/frontend/lowering/lower-functions.js +387 -72
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +41 -31
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +6 -3
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +28 -12
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +2 -1
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.js +2 -1
- package/dist/frontend/lowering/lower-mock.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +47 -5
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.test.js +2 -2
- package/dist/frontend/lowering/lower-modules.test.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +2 -1
- package/dist/frontend/lowering/lower-namespaces.js +9 -4
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +10 -0
- package/dist/frontend/lowering/lower-server.js +239 -61
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +5 -0
- package/dist/frontend/lowering/lower-stdlib.js +42 -10
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +23 -0
- package/dist/frontend/lowering/lower-stmts.js +622 -68
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js +1 -1
- package/dist/frontend/lowering/lower-stmts.test.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +20 -2
- package/dist/frontend/lowering/lower-stream.js +2055 -318
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +4 -3
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +197 -29
- package/dist/frontend/lowering/lowerer.js +862 -84
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +21 -9
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/module-namespace-elements.d.ts +11 -1
- package/dist/frontend/lowering/module-namespace-elements.js +82 -5
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.js +5 -0
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +1 -1
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/new-target.d.ts +12 -0
- package/dist/frontend/lowering/new-target.js +280 -0
- package/dist/frontend/lowering/new-target.js.map +1 -0
- package/dist/frontend/lowering/object-enumeration-receiver.js +2 -1
- package/dist/frontend/lowering/object-enumeration-receiver.js.map +1 -1
- package/dist/frontend/lowering/pairs-snapshot.js +2 -1
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- package/dist/frontend/lowering/private-brands.d.ts +9 -0
- package/dist/frontend/lowering/private-brands.js +66 -15
- package/dist/frontend/lowering/private-brands.js.map +1 -1
- package/dist/frontend/lowering/promise-executor-adapter.js +2 -1
- package/dist/frontend/lowering/promise-executor-adapter.js.map +1 -1
- package/dist/frontend/lowering/require-initialization.js +2 -1
- package/dist/frontend/lowering/require-initialization.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-elements.d.ts +5 -0
- package/dist/frontend/lowering/runtime-optional-elements.js +17 -1
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.d.ts +2 -0
- package/dist/frontend/lowering/runtime-optional-records.js +18 -5
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -1
- package/dist/frontend/lowering/site-dependencies.d.ts +35 -0
- package/dist/frontend/lowering/site-dependencies.js +84 -0
- package/dist/frontend/lowering/site-dependencies.js.map +1 -0
- package/dist/frontend/lowering/site-dependencies.test.d.ts +1 -0
- package/dist/frontend/lowering/site-dependencies.test.js +53 -0
- package/dist/frontend/lowering/site-dependencies.test.js.map +1 -0
- package/dist/frontend/lowering/stable-names.d.ts +11 -0
- package/dist/frontend/lowering/stable-names.js +35 -0
- package/dist/frontend/lowering/stable-names.js.map +1 -0
- package/dist/frontend/lowering/static-typeof.d.ts +2 -2
- package/dist/frontend/lowering/static-typeof.js +42 -3
- package/dist/frontend/lowering/static-typeof.js.map +1 -1
- package/dist/frontend/lowering/strict-equality.js +2 -1
- package/dist/frontend/lowering/strict-equality.js.map +1 -1
- package/dist/frontend/lowering/structural-positions.d.ts +32 -0
- package/dist/frontend/lowering/structural-positions.js +108 -0
- package/dist/frontend/lowering/structural-positions.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -0
- package/dist/frontend/lowering/surfaces.js +60 -32
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/undefined-index.d.ts +27 -0
- package/dist/frontend/lowering/undefined-index.js +82 -0
- package/dist/frontend/lowering/undefined-index.js.map +1 -0
- package/dist/frontend/lowering/var-hoisting.js +66 -16
- package/dist/frontend/lowering/var-hoisting.js.map +1 -1
- package/dist/frontend/lowering/width-lift.d.ts +18 -0
- package/dist/frontend/npm-static-bundled-chunks.js +9 -11
- package/dist/frontend/npm-static-bundled-chunks.js.map +1 -1
- package/dist/frontend/npm-static-bundled-chunks.test.js +6 -5
- package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +9 -1
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static-tsc-helpers.d.ts +5 -0
- package/dist/frontend/npm-static-tsc-helpers.js +106 -0
- package/dist/frontend/npm-static-tsc-helpers.js.map +1 -0
- package/dist/frontend/npm-static-tsc-helpers.test.d.ts +1 -0
- package/dist/frontend/npm-static-tsc-helpers.test.js +58 -0
- package/dist/frontend/npm-static-tsc-helpers.test.js.map +1 -0
- package/dist/frontend/npm-static-type-exports-host.d.ts +8 -0
- package/dist/frontend/npm-static-type-exports-host.js +214 -0
- package/dist/frontend/npm-static-type-exports-host.js.map +1 -0
- package/dist/frontend/npm-static-type-exports-host.test.d.ts +1 -0
- package/dist/frontend/npm-static-type-exports-host.test.js +53 -0
- package/dist/frontend/npm-static-type-exports-host.test.js.map +1 -0
- package/dist/frontend/npm-static-type-exports.d.ts +52 -0
- package/dist/frontend/npm-static-type-exports.js +261 -0
- package/dist/frontend/npm-static-type-exports.js.map +1 -0
- package/dist/frontend/npm-static-type-exports.test.d.ts +1 -0
- package/dist/frontend/npm-static-type-exports.test.js +103 -0
- package/dist/frontend/npm-static-type-exports.test.js.map +1 -0
- package/dist/frontend/npm-static-umd.d.ts +6 -0
- package/dist/frontend/npm-static-umd.js +203 -0
- package/dist/frontend/npm-static-umd.js.map +1 -0
- package/dist/frontend/npm-static-umd.test.d.ts +1 -0
- package/dist/frontend/npm-static-umd.test.js +105 -0
- package/dist/frontend/npm-static-umd.test.js.map +1 -0
- package/dist/frontend/npm-static.d.ts +8 -0
- package/dist/frontend/npm-static.js +51 -22
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/package-shims.d.ts +3 -0
- package/dist/frontend/package-shims.js +71 -8
- package/dist/frontend/package-shims.js.map +1 -1
- package/dist/frontend/pipeline.js +18 -10
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/process-fork.d.ts +25 -0
- package/dist/frontend/process-fork.js +2 -0
- package/dist/frontend/process-fork.js.map +1 -0
- package/dist/frontend/program.d.ts +21 -1
- package/dist/frontend/program.js +586 -74
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +44 -4
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/services.d.ts +6 -0
- package/dist/frontend/services.js +18 -0
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/token-equivalence.d.ts +3 -0
- package/dist/frontend/token-equivalence.js +409 -0
- package/dist/frontend/token-equivalence.js.map +1 -0
- package/dist/frontend/token-equivalence.test.d.ts +1 -0
- package/dist/frontend/token-equivalence.test.js +67 -0
- package/dist/frontend/token-equivalence.test.js.map +1 -0
- package/dist/frontend/ts7/ast-node.d.ts +43 -7
- package/dist/frontend/ts7/ast-node.js +1176 -129
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +84 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +29 -3
- package/dist/frontend/ts7/ast-wire.js +144 -31
- package/dist/frontend/ts7/ast-wire.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.test.js +23 -0
- package/dist/frontend/ts7/ast-wire.test.js.map +1 -1
- package/dist/frontend/ts7/ast.d.ts +23 -2
- package/dist/frontend/ts7/ast.js +143 -2
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +3 -4
- package/dist/frontend/ts7/checker-backend.js +2 -2
- package/dist/frontend/ts7/checker-backend.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.test.js +5 -9
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +17 -1
- package/dist/frontend/ts7/checker.js +82 -1
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +9 -6
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/enums.d.ts +3 -3
- package/dist/frontend/ts7/enums.generated.d.ts +10 -0
- package/dist/frontend/ts7/enums.generated.js +21 -0
- package/dist/frontend/ts7/enums.generated.js.map +1 -1
- package/dist/frontend/ts7/enums.js +19 -0
- package/dist/frontend/ts7/enums.js.map +1 -1
- package/dist/frontend/ts7/lib-diagnostics.d.ts +24 -0
- package/dist/frontend/ts7/lib-diagnostics.js +307 -0
- package/dist/frontend/ts7/lib-diagnostics.js.map +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.d.ts +1 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js +199 -0
- package/dist/frontend/ts7/lib-diagnostics.test.js.map +1 -0
- package/dist/frontend/ts7/program-host.d.ts +7 -0
- package/dist/frontend/ts7/program-host.js +30 -4
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.d.ts +10 -0
- package/dist/frontend/ts7/semantic-checker.js +25 -20
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.d.ts +13 -0
- package/dist/frontend/ts7/semantic-json.js +146 -0
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/ts7/semantic-json.test.js +57 -1
- package/dist/frontend/ts7/semantic-json.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +15 -0
- package/dist/frontend/ts7/semantic-model.js +67 -19
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +3 -2
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +14 -1
- package/dist/frontend/ts7/session.js +23 -1
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/tsc-codes.d.ts +1 -1
- package/dist/frontend/tsc-codes.js +7 -0
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +51 -7
- package/dist/frontend/type-mapper.js +456 -43
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.js +1 -1
- package/dist/frontend/type-mapper.test.js.map +1 -1
- package/dist/frontend-process-args.d.ts +4 -0
- package/dist/frontend-process-args.js +52 -0
- package/dist/frontend-process-args.js.map +1 -0
- package/dist/frontend-process-args.test.d.ts +1 -0
- package/dist/frontend-process-args.test.js +47 -0
- package/dist/frontend-process-args.test.js.map +1 -0
- package/dist/frontend-process.d.ts +1 -0
- package/dist/frontend-process.js +23 -0
- package/dist/frontend-process.js.map +1 -0
- package/dist/heap-collection.d.ts +16 -0
- package/dist/heap-collection.js +42 -0
- package/dist/heap-collection.js.map +1 -0
- package/dist/heap-collection.test.d.ts +1 -0
- package/dist/heap-collection.test.js +59 -0
- package/dist/heap-collection.test.js.map +1 -0
- package/dist/heap-pressure.d.ts +2 -0
- package/dist/heap-pressure.js +12 -0
- package/dist/heap-pressure.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +435 -89
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +5 -3
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/array-length-stability.d.ts +4 -0
- package/dist/ir/array-length-stability.js +26 -6
- package/dist/ir/array-length-stability.js.map +1 -1
- package/dist/ir/array-length-stability.test.js +49 -0
- package/dist/ir/array-length-stability.test.js.map +1 -1
- package/dist/ir/builtin-effects.d.ts +7 -0
- package/dist/ir/builtin-effects.js +80 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +7 -1
- package/dist/ir/builtin-signatures.js +303 -21
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/callback-specialization.d.ts +2 -1
- package/dist/ir/callback-specialization.js +23 -18
- package/dist/ir/callback-specialization.js.map +1 -1
- package/dist/ir/char-unit-locals.d.ts +19 -0
- package/dist/ir/char-unit-locals.js +185 -0
- package/dist/ir/char-unit-locals.js.map +1 -0
- package/dist/ir/char-unit-locals.test.d.ts +1 -0
- package/dist/ir/char-unit-locals.test.js +94 -0
- package/dist/ir/char-unit-locals.test.js.map +1 -0
- package/dist/ir/final-fields.d.ts +3 -1
- package/dist/ir/final-fields.js +15 -17
- package/dist/ir/final-fields.js.map +1 -1
- package/dist/ir/function-references.d.ts +2 -0
- package/dist/ir/function-references.js +2 -0
- package/dist/ir/function-references.js.map +1 -1
- package/dist/ir/function-references.test.js +5 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/initializer-bindings.d.ts +2 -1
- package/dist/ir/initializer-bindings.js +27 -20
- package/dist/ir/initializer-bindings.js.map +1 -1
- package/dist/ir/int32-arrays.d.ts +108 -0
- package/dist/ir/int32-arrays.js +831 -0
- package/dist/ir/int32-arrays.js.map +1 -0
- package/dist/ir/int32-slots.d.ts +36 -6
- package/dist/ir/int32-slots.js +370 -171
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +3 -1
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loop-facts.d.ts +9 -4
- package/dist/ir/integer-loop-facts.js +93 -18
- package/dist/ir/integer-loop-facts.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +49 -0
- package/dist/ir/integer-loops.js +202 -40
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +211 -1
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +5 -0
- package/dist/ir/integer-ranges.js +125 -12
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +94 -0
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +87 -9
- package/dist/ir/ir.js +61 -2
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +21 -1
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/js-ic.d.ts +19 -2
- package/dist/ir/js-ic.js +95 -11
- package/dist/ir/js-ic.js.map +1 -1
- package/dist/ir/js-ic.test.js +188 -0
- package/dist/ir/js-ic.test.js.map +1 -1
- package/dist/ir/node-index.d.ts +57 -0
- package/dist/ir/node-index.js +215 -0
- package/dist/ir/node-index.js.map +1 -0
- package/dist/ir/paired-while-loops.d.ts +25 -0
- package/dist/ir/paired-while-loops.js +335 -0
- package/dist/ir/paired-while-loops.js.map +1 -0
- package/dist/ir/paired-while-loops.test.d.ts +1 -0
- package/dist/ir/paired-while-loops.test.js +163 -0
- package/dist/ir/paired-while-loops.test.js.map +1 -0
- package/dist/ir/parameter-versions.d.ts +25 -0
- package/dist/ir/parameter-versions.js +300 -0
- package/dist/ir/parameter-versions.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +60 -15
- package/dist/ir/runtime-features.js +276 -35
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/serialize.d.ts +12 -2
- package/dist/ir/serialize.js +16 -3
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/serialize.test.js +17 -0
- package/dist/ir/serialize.test.js.map +1 -1
- package/dist/ir/tiers.js +1 -0
- package/dist/ir/tiers.js.map +1 -1
- package/dist/ir/traverse.d.ts +2 -0
- package/dist/ir/traverse.js +29 -5
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +171 -45
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +12 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-cache.d.ts +2 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/prepare.js +2 -0
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/cache.d.ts +6 -1
- package/dist/native/cache.js +28 -5
- package/dist/native/cache.js.map +1 -1
- package/dist/native/cache.test.js +16 -2
- package/dist/native/cache.test.js.map +1 -1
- package/dist/native/cli.js +26 -1
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +8 -6
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/executable-cache.d.ts +1 -1
- package/dist/native/executable-cache.js +2 -2
- package/dist/native/executable-cache.js.map +1 -1
- package/dist/native/prepare.d.ts +3 -1
- package/dist/native/prepare.js +123 -31
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/prepare.test.js +78 -18
- package/dist/native/prepare.test.js.map +1 -1
- package/dist/native/sanitizer.test.js +6 -1
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/text-file.d.ts +13 -3
- package/dist/native/text-file.js +63 -9
- package/dist/native/text-file.js.map +1 -1
- package/dist/native/text-file.test.d.ts +1 -0
- package/dist/native/text-file.test.js +49 -0
- package/dist/native/text-file.test.js.map +1 -0
- package/dist/native/toolchain.js +4 -4
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +3 -3
- package/dist/native/toolchain.test.js.map +1 -1
- package/dist/startup-cache.d.ts +1 -0
- package/dist/startup-cache.js +1 -0
- package/dist/startup-cache.js.map +1 -1
- package/dist/text-parts.d.ts +7 -0
- package/dist/text-parts.js +44 -0
- package/dist/text-parts.js.map +1 -1
- package/dist/text-parts.test.d.ts +1 -0
- package/dist/text-parts.test.js +46 -0
- package/dist/text-parts.test.js.map +1 -0
- package/dist/timing.d.ts +9 -2
- package/dist/timing.js +7 -4
- package/dist/timing.js.map +1 -1
- package/dist/wasm/translate.d.ts +4 -0
- package/dist/wasm/translate.js +2 -2
- package/dist/wasm/translate.js.map +1 -1
- package/package.json +21 -21
- package/shims/chalk/v5.ts +688 -0
- package/shims/hono-node-server/v2.ts +645 -0
- package/shims/hot-shots/client.ts +1126 -0
- package/shims/hot-shots/v8-unix-dgram.ts +8 -0
- package/shims/hot-shots/v8.ts +8 -0
- package/shims/undici/core/client.ts +4 -4
- package/surface-manifest.json +44 -52
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { primitiveConstructorOr } from "./lower-exprs.js";
|
|
2
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
2
3
|
import { dynUndefinedExpr, helperLoc, nodeThrowExpr, varRef } from "../../ir/build.js";
|
|
3
4
|
import { constructedValue } from "./constructor-returns.js";
|
|
4
5
|
import { eventTargetApiMembers, eventTargetInheritedMember } from "./lower-event-target.js";
|
|
5
|
-
import {
|
|
6
|
+
import { DATE_PROTOTYPE_METHOD_NAMES, DATE_TIME_FIELD, dateInheritedMember, dateRootOf, programDeclaresDateClass, } from "./builtins/date-classes.js";
|
|
7
|
+
import { dateValueMethod } from "./builtins/dates.js";
|
|
8
|
+
import { BOOL, DATE_T, DYN, F64, DYN_CLASS_PROPERTIES as PROPERTY_BAG, STRING, VOID, canConvertToDyn, canDynCheckTo, isClassOwnEnumerableFieldName, isDynTypedRefType, isUnitType, typeEquals, typeKey, } from "../../ir/ir.js";
|
|
6
9
|
import { streamTypedRefEligible } from "../../ir/analysis.js";
|
|
7
10
|
import { everyStmtList, transformExpr, transformStmtList } from "../../ir/traverse.js";
|
|
8
11
|
import { PoisonError } from "./lowerer.js";
|
|
@@ -22,9 +25,10 @@ import { isClassCallback } from "./class-callbacks.js";
|
|
|
22
25
|
import { CaughtValueDispatch } from "./caught-value-dispatch.js";
|
|
23
26
|
import { refreshDescriptorGuards } from "./class-descriptors.js";
|
|
24
27
|
import { ClassConstructionDispatch } from "./class-construction.js";
|
|
25
|
-
import {
|
|
28
|
+
import { DispatchSites } from "./dispatch-sites.js";
|
|
29
|
+
import { emitterRooted, lowerDynamicEmitterEmit, lowerDynamicEmitterOn, } from "./lower-event-emitter.js";
|
|
26
30
|
import { protocolArm, protocolFieldArm } from "./class-protocol-dispatch.js";
|
|
27
|
-
import { STREAM_OPERATORS } from "./lower-stream.js";
|
|
31
|
+
import { STREAM_OPERATORS, operatorSignalOptions, reduceSignalSetup } from "./lower-stream.js";
|
|
28
32
|
import { deletedPropertyNames, fixedFieldFamily } from "./js-class-fields.js";
|
|
29
33
|
const STREAM_METHODS = new Set([
|
|
30
34
|
"on",
|
|
@@ -50,6 +54,25 @@ const EMITTER_METHODS = new Set([
|
|
|
50
54
|
"off",
|
|
51
55
|
"removeListener",
|
|
52
56
|
]);
|
|
57
|
+
/** The rest of EventEmitter.prototype, answered through an untyped value
|
|
58
|
+
* on emitters that are not streams (streams keep their own surface). */
|
|
59
|
+
const EMITTER_INTROSPECTION_METHODS = new Set([
|
|
60
|
+
"listenerCount",
|
|
61
|
+
"eventNames",
|
|
62
|
+
"removeAllListeners",
|
|
63
|
+
"listeners",
|
|
64
|
+
"rawListeners",
|
|
65
|
+
"setMaxListeners",
|
|
66
|
+
"getMaxListeners",
|
|
67
|
+
]);
|
|
68
|
+
/** True when the class is or extends one of the runtime stream classes. */
|
|
69
|
+
function streamRooted(info) {
|
|
70
|
+
for (let c = info; c; c = c.base) {
|
|
71
|
+
if (c.builtinStream !== undefined)
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
53
76
|
const STREAM_BOOL_PROPERTIES = new Set([
|
|
54
77
|
"readable",
|
|
55
78
|
"readableEnded",
|
|
@@ -128,7 +151,7 @@ const KEY_CALLS = new Map([
|
|
|
128
151
|
["dyn.keyDeleteComputed", "value"],
|
|
129
152
|
["dyn.keySetComputed", "value"],
|
|
130
153
|
]);
|
|
131
|
-
function toPrimitiveHint(expr) {
|
|
154
|
+
export function toPrimitiveHint(expr) {
|
|
132
155
|
if (expr.kind === "toString")
|
|
133
156
|
return expr.operand.type.kind === "dyn" ? "string" : null;
|
|
134
157
|
if (expr.kind === "dynKeyGet")
|
|
@@ -176,6 +199,7 @@ function isPrimitive(value, loc) {
|
|
|
176
199
|
}
|
|
177
200
|
export function classInstanceOf(lowerer, value, info, loc, classValue) {
|
|
178
201
|
const name = `%dyn.class.${classValue ? "valueInstanceof" : "instanceof"}:${info.def.name}`;
|
|
202
|
+
lowerer.shareHelper(name);
|
|
179
203
|
const params = [
|
|
180
204
|
{ localId: "value", name: "value", type: DYN },
|
|
181
205
|
...(classValue ? [{ localId: "class", name: "class", type: classValue.type }] : []),
|
|
@@ -185,6 +209,32 @@ export function classInstanceOf(lowerer, value, info, loc, classValue) {
|
|
|
185
209
|
const prototype = classPrototypeData(lowerer, info, loc, classValue ? varRef("class", classValue.type, loc) : undefined);
|
|
186
210
|
const body = prototype
|
|
187
211
|
? [
|
|
212
|
+
// In a program that declares a class extending Date, a Date can
|
|
213
|
+
// meet a class test (`date instanceof Moment`): its prototype
|
|
214
|
+
// chain holds no class prototype.
|
|
215
|
+
...(programDeclaresDateClass(lowerer)
|
|
216
|
+
? [
|
|
217
|
+
{
|
|
218
|
+
kind: "if",
|
|
219
|
+
cond: {
|
|
220
|
+
kind: "libCall",
|
|
221
|
+
fn: "dyn.nativeDateHandleIs",
|
|
222
|
+
args: [varRef("value", DYN, loc)],
|
|
223
|
+
type: BOOL,
|
|
224
|
+
loc,
|
|
225
|
+
},
|
|
226
|
+
then: [
|
|
227
|
+
{
|
|
228
|
+
kind: "return",
|
|
229
|
+
value: { kind: "boolLit", value: false, type: BOOL, loc },
|
|
230
|
+
loc,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
else_: null,
|
|
234
|
+
loc,
|
|
235
|
+
},
|
|
236
|
+
]
|
|
237
|
+
: []),
|
|
188
238
|
{ kind: "varDecl", localId: "candidate", init: varRef("value", DYN, loc), loc },
|
|
189
239
|
{
|
|
190
240
|
kind: "while",
|
|
@@ -202,7 +252,7 @@ export function classInstanceOf(lowerer, value, info, loc, classValue) {
|
|
|
202
252
|
localId: "candidate",
|
|
203
253
|
value: {
|
|
204
254
|
kind: "libCall",
|
|
205
|
-
fn: "dyn.
|
|
255
|
+
fn: "dyn.getPrototypeForIdentity",
|
|
206
256
|
args: [candidate],
|
|
207
257
|
type: DYN,
|
|
208
258
|
loc,
|
|
@@ -245,6 +295,37 @@ export function classInstanceOf(lowerer, value, info, loc, classValue) {
|
|
|
245
295
|
loc,
|
|
246
296
|
};
|
|
247
297
|
}
|
|
298
|
+
/** `value` is the parameter itself, possibly through js.fromDyn. */
|
|
299
|
+
function returnsParam(value, param) {
|
|
300
|
+
if (value.kind === "varRef")
|
|
301
|
+
return value.localId === param;
|
|
302
|
+
return (value.kind === "libCall" &&
|
|
303
|
+
value.fn === "js.fromDyn" &&
|
|
304
|
+
value.args.length === 1 &&
|
|
305
|
+
value.args[0].kind === "varRef" &&
|
|
306
|
+
value.args[0].localId === param);
|
|
307
|
+
}
|
|
308
|
+
/** The kind a class-table branch requires of `param`: a capsule-key test
|
|
309
|
+
* (alone or guarding a conjunction) needs a capsule, a class-key test a
|
|
310
|
+
* function value; null for any other condition. */
|
|
311
|
+
function branchKind(cond, param) {
|
|
312
|
+
if (cond.kind === "libCall" &&
|
|
313
|
+
(cond.fn === "dyn.typedRefIs" ||
|
|
314
|
+
cond.fn === "dyn.typedRefKeyIs" ||
|
|
315
|
+
cond.fn === "dyn.classIs") &&
|
|
316
|
+
cond.args[0]?.kind === "varRef" &&
|
|
317
|
+
cond.args[0].localId === param) {
|
|
318
|
+
if (cond.fn === "dyn.classIs")
|
|
319
|
+
return "funcKind";
|
|
320
|
+
const key = cond.args[1];
|
|
321
|
+
return key?.kind === "strLit" && key.value.startsWith("object:") ? "classCapsule" : null;
|
|
322
|
+
}
|
|
323
|
+
if (cond.kind === "ternary" && cond.else_.kind === "boolLit" && cond.else_.value === false)
|
|
324
|
+
return branchKind(cond.cond, param);
|
|
325
|
+
if (cond.kind === "logical" && cond.op === "&&")
|
|
326
|
+
return branchKind(cond.left, param);
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
248
329
|
const READ_PROPERTIES = "%dyn.class.readProperties";
|
|
249
330
|
const READ_PROPERTIES_OR_EMPTY = "%dyn.class.readPropertiesOrEmpty";
|
|
250
331
|
function isEmptyBag(value) {
|
|
@@ -273,9 +354,106 @@ function readOnlyBagBody(body, orEmpty = false) {
|
|
|
273
354
|
}
|
|
274
355
|
return body;
|
|
275
356
|
}
|
|
357
|
+
/** `value` with the class branch's checked receiver (`p.0` as a dynamic
|
|
358
|
+
* value, possibly cast to the branch's class) replaced by `receiver`, the
|
|
359
|
+
* typed receiver of a per-class helper. */
|
|
360
|
+
function withTypedReceiver(value, receiver) {
|
|
361
|
+
const checked = (e) => e.kind === "dynCheck" && e.value.kind === "varRef" && e.value.localId === "p.0";
|
|
362
|
+
return transformExpr(value, {
|
|
363
|
+
stmt: (stmt) => stmt,
|
|
364
|
+
expr: (expr) => (expr.kind === "downcast" &&
|
|
365
|
+
checked(expr.value) &&
|
|
366
|
+
expr.type.kind === "object" &&
|
|
367
|
+
receiver.type.kind === "object" &&
|
|
368
|
+
expr.type.className === receiver.type.className) ||
|
|
369
|
+
checked(expr)
|
|
370
|
+
? receiver
|
|
371
|
+
: expr,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
/** Re-adds the classes of `set` after the first `from` in a fixed order:
|
|
375
|
+
* the program's classes by name, then the classes the runtime implements by
|
|
376
|
+
* name. The dispatch helpers add each class's branch in front of the
|
|
377
|
+
* earlier ones, so a runtime class's branch, which answers its methods for
|
|
378
|
+
* instances of the program's subclasses too, is tested before the
|
|
379
|
+
* subclasses' own branches. */
|
|
380
|
+
function sortAdded(lowerer, set, from) {
|
|
381
|
+
const runtime = (name) => {
|
|
382
|
+
const info = lowerer.classes.get(name);
|
|
383
|
+
return !!(info &&
|
|
384
|
+
(info.def.runtime || info.builtinEmitter || info.builtinStream || info.builtinError));
|
|
385
|
+
};
|
|
386
|
+
const added = [...set]
|
|
387
|
+
.slice(from)
|
|
388
|
+
.sort((left, right) => Number(runtime(left)) - Number(runtime(right)) ||
|
|
389
|
+
(left < right ? -1 : left > right ? 1 : 0));
|
|
390
|
+
for (const name of added)
|
|
391
|
+
set.delete(name);
|
|
392
|
+
for (const name of added)
|
|
393
|
+
set.add(name);
|
|
394
|
+
}
|
|
395
|
+
function receiverIndex(lowerer, plans) {
|
|
396
|
+
const methods = new Map();
|
|
397
|
+
const members = new Map();
|
|
398
|
+
const rooted = [];
|
|
399
|
+
const add = (table, name, position) => {
|
|
400
|
+
const positions = table.get(name);
|
|
401
|
+
if (positions === undefined)
|
|
402
|
+
table.set(name, [position]);
|
|
403
|
+
else if (positions[positions.length - 1] !== position)
|
|
404
|
+
positions.push(position);
|
|
405
|
+
};
|
|
406
|
+
plans.forEach(({ info }, position) => {
|
|
407
|
+
if (emitterRooted(lowerer, info) ||
|
|
408
|
+
info.builtinStream !== undefined ||
|
|
409
|
+
eventTargetApiMembers(info) !== null ||
|
|
410
|
+
dateRootOf(info) !== null) {
|
|
411
|
+
rooted.push(position);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
for (let c = info; c; c = c.base) {
|
|
415
|
+
for (const name of c.methods.keys()) {
|
|
416
|
+
add(methods, name, position);
|
|
417
|
+
// A `get:`/`set:` key is an accessor of the property after the
|
|
418
|
+
// prefix, or a method whose quoted name has that prefix; the test
|
|
419
|
+
// looks up both.
|
|
420
|
+
add(members, name, position);
|
|
421
|
+
if (name.startsWith("get:") || name.startsWith("set:"))
|
|
422
|
+
add(members, name.slice(4), position);
|
|
423
|
+
}
|
|
424
|
+
if (c.genericMethods)
|
|
425
|
+
for (const name of c.genericMethods.keys()) {
|
|
426
|
+
add(methods, name, position);
|
|
427
|
+
add(members, name, position);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
for (const name of info.fields.keys())
|
|
431
|
+
add(members, name, position);
|
|
432
|
+
});
|
|
433
|
+
for (const table of [methods, members])
|
|
434
|
+
for (const positions of table.values())
|
|
435
|
+
positions.sort((a, b) => a - b);
|
|
436
|
+
return { plans, methods, members, rooted };
|
|
437
|
+
}
|
|
438
|
+
/** The ascending union of two ascending position lists. */
|
|
439
|
+
function mergePositions(left, right) {
|
|
440
|
+
const out = [];
|
|
441
|
+
let i = 0;
|
|
442
|
+
let j = 0;
|
|
443
|
+
while (i < left.length || j < right.length) {
|
|
444
|
+
const next = j >= right.length || (i < left.length && left[i] <= right[j]) ? left[i++] : right[j++];
|
|
445
|
+
if (out[out.length - 1] !== next)
|
|
446
|
+
out.push(next);
|
|
447
|
+
}
|
|
448
|
+
return out;
|
|
449
|
+
}
|
|
450
|
+
/** SCRIPTC_CHECK_DISPATCH_CANDIDATES=1 checks every indexed receiver selection
|
|
451
|
+
* against a test of every receiver. */
|
|
452
|
+
const CHECK_CANDIDATES = process.env["SCRIPTC_CHECK_DISPATCH_CANDIDATES"] === "1";
|
|
276
453
|
export function classPropertiesHelper(lowerer, loc, readOnly = false) {
|
|
277
454
|
const name = readOnly ? READ_PROPERTIES : "%dyn.class.properties";
|
|
278
|
-
|
|
455
|
+
lowerer.shareHelper(name);
|
|
456
|
+
const existing = lowerer.liftedFnNamed(name);
|
|
279
457
|
if (existing)
|
|
280
458
|
return existing;
|
|
281
459
|
const helper = {
|
|
@@ -309,6 +487,8 @@ export function classPropertiesHelper(lowerer, loc, readOnly = false) {
|
|
|
309
487
|
* than that table, so a miss rechecks the instance itself. */
|
|
310
488
|
export function classForInHasKey(lowerer, value, key, loc) {
|
|
311
489
|
const name = "%dyn.class.forInHasKey";
|
|
490
|
+
lowerer.shareHelper(name);
|
|
491
|
+
lowerer.shareHelper("%dyn.class.forInBagHas");
|
|
312
492
|
if (!lowerer.liftedFns.some((fn) => fn.name === name)) {
|
|
313
493
|
// The read-only table: a recheck never creates an instance's table, which
|
|
314
494
|
// is undefined while the instance has no own dynamic properties.
|
|
@@ -408,15 +588,151 @@ export function trackClassFieldCreation(lowerer, functions) {
|
|
|
408
588
|
return;
|
|
409
589
|
const loc = functions[0].loc;
|
|
410
590
|
const name = "%dyn.class.fieldCreated";
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
591
|
+
const key = varRef("key", DYN, loc);
|
|
592
|
+
// One helper per class: the instance's bag is its own hidden field, so a
|
|
593
|
+
// creation reads it directly instead of boxing the instance and testing
|
|
594
|
+
// it against every class's capsule (%dyn.class.properties), which runs
|
|
595
|
+
// only to create the bag, once per instance.
|
|
596
|
+
const perClass = new Map();
|
|
597
|
+
const helperFor = (className) => {
|
|
598
|
+
const known = perClass.get(className);
|
|
599
|
+
if (known !== undefined)
|
|
600
|
+
return known;
|
|
601
|
+
const helperName = `${name}:${className}`;
|
|
602
|
+
perClass.set(className, helperName);
|
|
603
|
+
const self = varRef("this", { kind: "object", className }, loc);
|
|
604
|
+
const bagRef = varRef("bag", DYN, loc);
|
|
605
|
+
functions.push({
|
|
606
|
+
name: helperName,
|
|
607
|
+
params: [
|
|
608
|
+
{ localId: "this", name: "this", type: { kind: "object", className } },
|
|
609
|
+
{ localId: "key", name: "key", type: DYN },
|
|
610
|
+
],
|
|
611
|
+
returnType: VOID,
|
|
612
|
+
locals: [
|
|
613
|
+
{ id: "this", name: "this", type: { kind: "object", className }, mutable: false },
|
|
614
|
+
{ id: "key", name: "key", type: DYN, mutable: false },
|
|
615
|
+
{ id: "bag", name: "bag", type: DYN, mutable: true },
|
|
616
|
+
],
|
|
617
|
+
body: [
|
|
618
|
+
{
|
|
619
|
+
kind: "varDecl",
|
|
620
|
+
localId: "bag",
|
|
621
|
+
init: { kind: "fieldGet", obj: self, className, field: PROPERTY_BAG, type: DYN, loc },
|
|
622
|
+
loc,
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
kind: "if",
|
|
626
|
+
cond: { kind: "dynTest", test: "undefined", value: bagRef, type: BOOL, loc },
|
|
627
|
+
then: initializeBag(lowerer, className, self, loc),
|
|
628
|
+
else_: null,
|
|
629
|
+
loc,
|
|
630
|
+
},
|
|
631
|
+
...defineIfAbsent(lowerer, bagRef, key, loc),
|
|
632
|
+
],
|
|
633
|
+
loc,
|
|
634
|
+
});
|
|
635
|
+
return helperName;
|
|
636
|
+
};
|
|
637
|
+
// String-keyed fields take the runtime's direct insert for an ordinary
|
|
638
|
+
// bag; the general path stays for any other bag and for symbol keys.
|
|
639
|
+
const stringHelperFor = (className) => {
|
|
640
|
+
const known = perClass.get(`str:${className}`);
|
|
641
|
+
if (known !== undefined)
|
|
642
|
+
return known;
|
|
643
|
+
const general = helperFor(className);
|
|
644
|
+
const helperName = `${name}.string:${className}`;
|
|
645
|
+
perClass.set(`str:${className}`, helperName);
|
|
646
|
+
const type = { kind: "object", className };
|
|
647
|
+
const self = varRef("this", type, loc);
|
|
648
|
+
const bagRef = varRef("bag", DYN, loc);
|
|
649
|
+
const field = varRef("field", STRING, loc);
|
|
650
|
+
functions.push({
|
|
651
|
+
name: helperName,
|
|
652
|
+
params: [
|
|
653
|
+
{ localId: "this", name: "this", type },
|
|
654
|
+
{ localId: "field", name: "field", type: STRING },
|
|
655
|
+
],
|
|
656
|
+
returnType: VOID,
|
|
657
|
+
locals: [
|
|
658
|
+
{ id: "this", name: "this", type, mutable: false },
|
|
659
|
+
{ id: "field", name: "field", type: STRING, mutable: false },
|
|
660
|
+
{ id: "bag", name: "bag", type: DYN, mutable: true },
|
|
661
|
+
],
|
|
662
|
+
body: [
|
|
663
|
+
{
|
|
664
|
+
kind: "varDecl",
|
|
665
|
+
localId: "bag",
|
|
666
|
+
init: { kind: "fieldGet", obj: self, className, field: PROPERTY_BAG, type: DYN, loc },
|
|
667
|
+
loc,
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
kind: "if",
|
|
671
|
+
cond: { kind: "dynTest", test: "undefined", value: bagRef, type: BOOL, loc },
|
|
672
|
+
then: initializeBag(lowerer, className, self, loc),
|
|
673
|
+
else_: null,
|
|
674
|
+
loc,
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
kind: "if",
|
|
678
|
+
cond: {
|
|
679
|
+
kind: "libCall",
|
|
680
|
+
fn: "dyn.bagCreateField",
|
|
681
|
+
args: [bagRef, field],
|
|
682
|
+
type: BOOL,
|
|
683
|
+
loc,
|
|
684
|
+
},
|
|
685
|
+
then: [{ kind: "return", value: null, loc }],
|
|
686
|
+
else_: null,
|
|
687
|
+
loc,
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
kind: "exprStmt",
|
|
691
|
+
expr: {
|
|
692
|
+
kind: "call",
|
|
693
|
+
callee: general,
|
|
694
|
+
args: [self, lowerer.coerceToExpected(field, DYN)],
|
|
695
|
+
type: VOID,
|
|
696
|
+
loc,
|
|
697
|
+
},
|
|
698
|
+
loc,
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
loc,
|
|
702
|
+
});
|
|
703
|
+
return helperName;
|
|
704
|
+
};
|
|
705
|
+
const created = (receiver, className, field, loc) => {
|
|
706
|
+
const symbolKey = symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc);
|
|
707
|
+
if (symbolKey === null) {
|
|
708
|
+
return {
|
|
709
|
+
kind: "exprStmt",
|
|
710
|
+
expr: {
|
|
711
|
+
kind: "call",
|
|
712
|
+
callee: stringHelperFor(className),
|
|
713
|
+
args: [
|
|
714
|
+
receiver.type.kind === "object" && receiver.type.className !== className
|
|
715
|
+
? { kind: "upcast", value: receiver, type: { kind: "object", className }, loc }
|
|
716
|
+
: receiver,
|
|
717
|
+
{ kind: "strLit", value: field, type: STRING, loc },
|
|
718
|
+
],
|
|
719
|
+
type: VOID,
|
|
720
|
+
loc,
|
|
721
|
+
},
|
|
722
|
+
loc,
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
return createdGeneral(receiver, className, field, loc);
|
|
726
|
+
};
|
|
727
|
+
const createdGeneral = (receiver, className, field, loc) => ({
|
|
414
728
|
kind: "exprStmt",
|
|
415
729
|
expr: {
|
|
416
730
|
kind: "call",
|
|
417
|
-
callee:
|
|
731
|
+
callee: helperFor(className),
|
|
418
732
|
args: [
|
|
419
|
-
|
|
733
|
+
receiver.type.kind === "object" && receiver.type.className !== className
|
|
734
|
+
? { kind: "upcast", value: receiver, type: { kind: "object", className }, loc }
|
|
735
|
+
: receiver,
|
|
420
736
|
symbolMemberKey(lowerer, lowerer.classes.get(className), field, loc) ??
|
|
421
737
|
lowerer.coerceToExpected({ kind: "strLit", value: field, type: STRING, loc }, DYN),
|
|
422
738
|
],
|
|
@@ -484,77 +800,101 @@ export function trackClassFieldCreation(lowerer, functions) {
|
|
|
484
800
|
},
|
|
485
801
|
});
|
|
486
802
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
{ id: "value", name: "value", type: DYN, mutable: false },
|
|
496
|
-
{ id: "key", name: "key", type: DYN, mutable: false },
|
|
497
|
-
{ id: "bag", name: "bag", type: DYN, mutable: false },
|
|
498
|
-
],
|
|
499
|
-
body: [
|
|
803
|
+
}
|
|
804
|
+
/** `bag = <the class's new bag>`, stored in the instance's hidden field:
|
|
805
|
+
* the class's own initializer when recorded, else the class-table
|
|
806
|
+
* dispatch, which creates it. */
|
|
807
|
+
function initializeBag(lowerer, className, self, loc) {
|
|
808
|
+
const init = lowerer.classBagInitializers?.get(className);
|
|
809
|
+
if (init === undefined) {
|
|
810
|
+
return [
|
|
500
811
|
{
|
|
501
|
-
kind: "
|
|
812
|
+
kind: "assign",
|
|
502
813
|
localId: "bag",
|
|
503
|
-
|
|
814
|
+
value: {
|
|
504
815
|
kind: "call",
|
|
505
816
|
callee: classPropertiesHelper(lowerer, loc).name,
|
|
506
|
-
args: [
|
|
817
|
+
args: [lowerer.coerceToExpected(self, DYN)],
|
|
507
818
|
type: DYN,
|
|
508
819
|
loc,
|
|
509
820
|
},
|
|
510
821
|
loc,
|
|
511
822
|
},
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
},
|
|
551
|
-
],
|
|
552
|
-
else_: null,
|
|
823
|
+
];
|
|
824
|
+
}
|
|
825
|
+
return [
|
|
826
|
+
{
|
|
827
|
+
kind: "fieldSet",
|
|
828
|
+
obj: self,
|
|
829
|
+
className,
|
|
830
|
+
field: PROPERTY_BAG,
|
|
831
|
+
value: structuredClone(init),
|
|
832
|
+
loc,
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
kind: "assign",
|
|
836
|
+
localId: "bag",
|
|
837
|
+
value: { kind: "fieldGet", obj: self, className, field: PROPERTY_BAG, type: DYN, loc },
|
|
838
|
+
loc,
|
|
839
|
+
},
|
|
840
|
+
];
|
|
841
|
+
}
|
|
842
|
+
/** `value` as JSON without its source locations. */
|
|
843
|
+
function withoutLocations(value) {
|
|
844
|
+
return JSON.stringify(value, (key, field) => (key === "loc" ? undefined : field));
|
|
845
|
+
}
|
|
846
|
+
/** Whether `value` reads local `id`. */
|
|
847
|
+
function mentionsLocal(value, id) {
|
|
848
|
+
return JSON.stringify(value).includes(`"localId":${JSON.stringify(id)}`);
|
|
849
|
+
}
|
|
850
|
+
/** `if (!hasOwn(bag, key)) defineProperty(bag, key, <undefined data field>)`:
|
|
851
|
+
* a field's creation in its instance's property bag. */
|
|
852
|
+
function defineIfAbsent(lowerer, bag, key, loc) {
|
|
853
|
+
return [
|
|
854
|
+
{
|
|
855
|
+
kind: "if",
|
|
856
|
+
cond: {
|
|
857
|
+
kind: "unary",
|
|
858
|
+
op: "!",
|
|
859
|
+
operand: { kind: "libCall", fn: "dyn.hasOwnComputed", args: [bag, key], type: BOOL, loc },
|
|
860
|
+
type: BOOL,
|
|
553
861
|
loc,
|
|
554
862
|
},
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
863
|
+
then: [
|
|
864
|
+
{
|
|
865
|
+
kind: "exprStmt",
|
|
866
|
+
expr: {
|
|
867
|
+
kind: "libCall",
|
|
868
|
+
fn: "dyn.defineProperty",
|
|
869
|
+
args: [
|
|
870
|
+
bag,
|
|
871
|
+
lowerer.coerceToExpected(key, DYN),
|
|
872
|
+
{
|
|
873
|
+
kind: "dynObjLit",
|
|
874
|
+
fields: [
|
|
875
|
+
{
|
|
876
|
+
key: { kind: "strLit", value: "value", type: STRING, loc },
|
|
877
|
+
value: dynUndefinedExpr(loc),
|
|
878
|
+
},
|
|
879
|
+
...["writable", "enumerable", "configurable"].map((key) => ({
|
|
880
|
+
key: { kind: "strLit", value: key, type: STRING, loc },
|
|
881
|
+
value: lowerer.coerceToExpected({ kind: "boolLit", value: true, type: BOOL, loc }, DYN),
|
|
882
|
+
})),
|
|
883
|
+
],
|
|
884
|
+
type: DYN,
|
|
885
|
+
loc,
|
|
886
|
+
},
|
|
887
|
+
],
|
|
888
|
+
type: DYN,
|
|
889
|
+
loc,
|
|
890
|
+
},
|
|
891
|
+
loc,
|
|
892
|
+
},
|
|
893
|
+
],
|
|
894
|
+
else_: null,
|
|
895
|
+
loc,
|
|
896
|
+
},
|
|
897
|
+
];
|
|
558
898
|
}
|
|
559
899
|
/** Calls on native class capsules keep the instance's compiled methods. The
|
|
560
900
|
* reachable-body fixed point discovers both the boxed classes and method
|
|
@@ -568,11 +908,16 @@ export class ClassDynamicDispatch {
|
|
|
568
908
|
generatorDispatch = new GeneratorDynamicDispatch();
|
|
569
909
|
caughtDispatch = new CaughtValueDispatch();
|
|
570
910
|
constructionDispatch = new ClassConstructionDispatch();
|
|
911
|
+
/** What each function's body holds for this pass and its sub-passes. */
|
|
912
|
+
sites = new DispatchSites();
|
|
571
913
|
/** Property names a delete can remove (null: any name), for the field
|
|
572
914
|
* creation tracking decision. */
|
|
573
915
|
deletedNames;
|
|
574
916
|
boxed = new Set();
|
|
575
917
|
boxedConstructors = new Set();
|
|
918
|
+
/** Every class a boxed value was statically typed as, runtime error
|
|
919
|
+
* classes included: the value's capsule can be any of its subclasses. */
|
|
920
|
+
boxedStatic = new Set();
|
|
576
921
|
dispatches = new Map();
|
|
577
922
|
properties = new Map();
|
|
578
923
|
computed = new Map();
|
|
@@ -589,6 +934,9 @@ export class ClassDynamicDispatch {
|
|
|
589
934
|
/** Per-class prototype selection for new property bags (bagPrototypeHelper). */
|
|
590
935
|
bagPrototypeHelpers = new Map();
|
|
591
936
|
readPropertyBags = [];
|
|
937
|
+
/** Read-only bags of exactly one class (exactPropertyBag), by class and
|
|
938
|
+
* whether an absent bag reads as a fresh empty object. */
|
|
939
|
+
exactPropertyBags = new Map();
|
|
592
940
|
generated = new Set();
|
|
593
941
|
/** Protocol dispatch helpers and callee reads whose receivers normalize. */
|
|
594
942
|
protocols = [];
|
|
@@ -601,8 +949,17 @@ export class ClassDynamicDispatch {
|
|
|
601
949
|
descriptorHelper = null;
|
|
602
950
|
prototypeHelper = null;
|
|
603
951
|
prototypeClasses = new Set();
|
|
604
|
-
|
|
605
|
-
|
|
952
|
+
/** The stand-in prototype object of each class without prototype data
|
|
953
|
+
* (prototypeStandIn), by class name. */
|
|
954
|
+
prototypeStandIns = new Set();
|
|
955
|
+
/** The prototype reads of identity walks, by libCall, and the classes
|
|
956
|
+
* each one answers for boxed instances. */
|
|
957
|
+
prototypeIdentityHelpers = new Map();
|
|
958
|
+
/** `value instanceof Error` through Error.prototype: boxed instances of
|
|
959
|
+
* classes with a heritage evaluated at run time test their prototype
|
|
960
|
+
* data's chain. */
|
|
961
|
+
errorPrototypeHelper = null;
|
|
962
|
+
errorPrototypeClasses = new Set();
|
|
606
963
|
instancePrototypes = new Map();
|
|
607
964
|
checkedCasts = new Map();
|
|
608
965
|
/** The for-in key helpers, by libCall (dyn and native string[] keys). */
|
|
@@ -625,22 +982,25 @@ export class ClassDynamicDispatch {
|
|
|
625
982
|
first.value.callee === this.normalization?.name)
|
|
626
983
|
fn.body.shift();
|
|
627
984
|
}
|
|
628
|
-
let changed = this.caughtDispatch.process(lowerer, functions);
|
|
985
|
+
let changed = this.caughtDispatch.process(lowerer, functions, this.sites);
|
|
629
986
|
changed = refreshErrorMethodDispatch(lowerer, functions) || changed;
|
|
630
987
|
changed = refreshClassMethodValueSelections(lowerer) || changed;
|
|
631
988
|
changed = refreshErrorPropertyDispatch(lowerer, functions) || changed;
|
|
632
|
-
changed =
|
|
633
|
-
|
|
989
|
+
changed =
|
|
990
|
+
this.generatorDispatch.process(lowerer, functions, this.generated, this.sites) || changed;
|
|
991
|
+
changed = this.constructionDispatch.process(lowerer, functions, this.sites) || changed;
|
|
634
992
|
const seenTypes = new Set();
|
|
635
993
|
const rewrite = new Set();
|
|
636
994
|
const toPrimitiveSites = new Set();
|
|
637
995
|
const hasKeySites = new Set();
|
|
996
|
+
const caughtSites = new Set();
|
|
638
997
|
const discover = (type) => {
|
|
639
998
|
const key = typeKey(type);
|
|
640
999
|
if (seenTypes.has(key))
|
|
641
1000
|
return;
|
|
642
1001
|
seenTypes.add(key);
|
|
643
1002
|
if (type.kind === "object") {
|
|
1003
|
+
this.boxedStatic.add(type.className);
|
|
644
1004
|
if (isDynTypedRefType(type))
|
|
645
1005
|
this.boxed.add(type.className);
|
|
646
1006
|
}
|
|
@@ -661,83 +1021,30 @@ export class ClassDynamicDispatch {
|
|
|
661
1021
|
else if (type.kind === "promise")
|
|
662
1022
|
discover(type.inner);
|
|
663
1023
|
};
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
case "fieldIncDec":
|
|
689
|
-
if (lowerer.classes.get(expr.className)?.def.tracksOwnFields &&
|
|
690
|
-
isClassOwnEnumerableFieldName(expr.field))
|
|
691
|
-
discover(expr.obj.type);
|
|
692
|
-
break;
|
|
693
|
-
case "call":
|
|
694
|
-
if ((expr.callee === "%dyn.class.properties" ||
|
|
695
|
-
expr.callee === "%dyn.class.readProperties") &&
|
|
696
|
-
expr.args[0]?.kind === "dynFrom" &&
|
|
697
|
-
isDynTypedRefType(expr.args[0].value.type))
|
|
698
|
-
rewrite.add(fn);
|
|
699
|
-
break;
|
|
700
|
-
case "dynHasKey":
|
|
701
|
-
hasKeySites.add(fn);
|
|
702
|
-
break;
|
|
703
|
-
case "dynKeyGet":
|
|
704
|
-
case "dynInvoke":
|
|
705
|
-
rewrite.add(fn);
|
|
706
|
-
break;
|
|
707
|
-
case "dynCheck":
|
|
708
|
-
if (isDynTypedRefType(expr.type))
|
|
709
|
-
rewrite.add(fn);
|
|
710
|
-
// A dynamic function checked into a native function type
|
|
711
|
-
// receives its arguments as dynamic values: class instances
|
|
712
|
-
// passed to it cross the boundary when it is called (a JS
|
|
713
|
-
// `list.map((rec) => rec.match(x))` callback with an untyped
|
|
714
|
-
// parameter).
|
|
715
|
-
if (expr.type.kind === "func")
|
|
716
|
-
expr.type.params.forEach(discover);
|
|
717
|
-
break;
|
|
718
|
-
case "libCall":
|
|
719
|
-
if (expr.fn === "bytes.construct" ||
|
|
720
|
-
expr.fn === "dyn.keySet" ||
|
|
721
|
-
expr.fn === "dyn.keySetComputed" ||
|
|
722
|
-
expr.fn === "dyn.iterator" ||
|
|
723
|
-
expr.fn === "dyn.arrayFromIterator" ||
|
|
724
|
-
expr.fn === "dyn.toString" ||
|
|
725
|
-
expr.fn === "dyn.stringConstructor" ||
|
|
726
|
-
expr.fn === "dyn.forInKeys" ||
|
|
727
|
-
expr.fn === "dyn.forInKeyStrings" ||
|
|
728
|
-
expr.fn === "dyn.hasKeyComputed" ||
|
|
729
|
-
expr.fn === "dyn.hasOwnComputed" ||
|
|
730
|
-
expr.fn === "dyn.propertyIsEnumerableComputed" ||
|
|
731
|
-
expr.fn === "dyn.defineProperty" ||
|
|
732
|
-
expr.fn === "dyn.getPrototype" ||
|
|
733
|
-
expr.fn === "dyn.reflectGet" ||
|
|
734
|
-
expr.fn === "dyn.reflectSet")
|
|
735
|
-
rewrite.add(fn);
|
|
736
|
-
break;
|
|
737
|
-
}
|
|
738
|
-
return true;
|
|
739
|
-
},
|
|
740
|
-
});
|
|
1024
|
+
const boxedBefore = this.boxed.size;
|
|
1025
|
+
const boxedConstructorsBefore = this.boxedConstructors.size;
|
|
1026
|
+
for (const fn of functions) {
|
|
1027
|
+
const found = this.sites.of(fn);
|
|
1028
|
+
// A class starts tracking its own fields during this pass.
|
|
1029
|
+
for (const { type, fieldClass } of found.boxing)
|
|
1030
|
+
if (fieldClass === undefined || lowerer.classes.get(fieldClass)?.def.tracksOwnFields)
|
|
1031
|
+
discover(type);
|
|
1032
|
+
if (found.serializes)
|
|
1033
|
+
this.serializesClasses = true;
|
|
1034
|
+
if (found.conversions)
|
|
1035
|
+
toPrimitiveSites.add(fn);
|
|
1036
|
+
if (found.dispatches)
|
|
1037
|
+
rewrite.add(fn);
|
|
1038
|
+
if (found.keyTests)
|
|
1039
|
+
hasKeySites.add(fn);
|
|
1040
|
+
if (found.caughtClassTests)
|
|
1041
|
+
caughtSites.add(fn);
|
|
1042
|
+
}
|
|
1043
|
+
// The classes this pass found join the tables in a fixed order, not in
|
|
1044
|
+
// the order the scan met them.
|
|
1045
|
+
sortAdded(lowerer, this.boxed, boxedBefore);
|
|
1046
|
+
sortAdded(lowerer, this.boxedConstructors, boxedConstructorsBefore);
|
|
1047
|
+
changed = this.caughtDispatch.dynamicPayloads(lowerer, caughtSites, this.boxed) || changed;
|
|
741
1048
|
if (this.boxed.size === 0 && rewrite.size === 0)
|
|
742
1049
|
return changed;
|
|
743
1050
|
const converting = this.convertingHints(lowerer);
|
|
@@ -844,9 +1151,11 @@ export class ClassDynamicDispatch {
|
|
|
844
1151
|
});
|
|
845
1152
|
changed = true;
|
|
846
1153
|
}
|
|
847
|
-
if (this.
|
|
848
|
-
this.
|
|
849
|
-
|
|
1154
|
+
if (this.errorPrototypeHelper &&
|
|
1155
|
+
!this.errorPrototypeClasses.has(className) &&
|
|
1156
|
+
hasRuntimeHeritage(info)) {
|
|
1157
|
+
this.errorPrototypeClasses.add(className);
|
|
1158
|
+
const loc = this.errorPrototypeHelper.loc;
|
|
850
1159
|
const type = { kind: "object", className };
|
|
851
1160
|
const value = varRef("value", DYN, loc);
|
|
852
1161
|
const prototype = classPrototypeData(lowerer, info, loc, {
|
|
@@ -856,7 +1165,7 @@ export class ClassDynamicDispatch {
|
|
|
856
1165
|
loc,
|
|
857
1166
|
});
|
|
858
1167
|
if (prototype)
|
|
859
|
-
this.
|
|
1168
|
+
this.errorPrototypeHelper.body.unshift({
|
|
860
1169
|
kind: "if",
|
|
861
1170
|
cond: {
|
|
862
1171
|
kind: "libCall",
|
|
@@ -865,7 +1174,19 @@ export class ClassDynamicDispatch {
|
|
|
865
1174
|
type: BOOL,
|
|
866
1175
|
loc,
|
|
867
1176
|
},
|
|
868
|
-
then: [
|
|
1177
|
+
then: [
|
|
1178
|
+
{
|
|
1179
|
+
kind: "return",
|
|
1180
|
+
value: {
|
|
1181
|
+
kind: "libCall",
|
|
1182
|
+
fn: "dyn.inheritsErrorPrototype",
|
|
1183
|
+
args: [prototype],
|
|
1184
|
+
type: BOOL,
|
|
1185
|
+
loc,
|
|
1186
|
+
},
|
|
1187
|
+
loc,
|
|
1188
|
+
},
|
|
1189
|
+
],
|
|
869
1190
|
else_: null,
|
|
870
1191
|
loc,
|
|
871
1192
|
});
|
|
@@ -879,7 +1200,7 @@ export class ClassDynamicDispatch {
|
|
|
879
1200
|
const loc = this.propertyBag.loc;
|
|
880
1201
|
const method = classMethodValue(lowerer, info.decl, info, "toJSON", loc);
|
|
881
1202
|
const prototype = method ? classPrototypeData(lowerer, info, loc) : null;
|
|
882
|
-
const helper = lowerer.
|
|
1203
|
+
const helper = lowerer.liftedFnNamed(info.def.prototypeDataHelper);
|
|
883
1204
|
const init = helper?.body[0];
|
|
884
1205
|
if (!info.prototypeReflectionReady &&
|
|
885
1206
|
method &&
|
|
@@ -930,6 +1251,101 @@ export class ClassDynamicDispatch {
|
|
|
930
1251
|
}
|
|
931
1252
|
}
|
|
932
1253
|
}
|
|
1254
|
+
// The runtime boxes a class instance as its exact class, so a value
|
|
1255
|
+
// boxed at a base (or Error) static type reaches the identity views as
|
|
1256
|
+
// any subclass's capsule.
|
|
1257
|
+
for (const helper of this.prototypeIdentityHelpers.values())
|
|
1258
|
+
for (const [className, info] of lowerer.classes) {
|
|
1259
|
+
if (helper.classes.has(className))
|
|
1260
|
+
continue;
|
|
1261
|
+
if (info.builtinEmitter || info.builtinStream || info.builtinError)
|
|
1262
|
+
continue;
|
|
1263
|
+
if (!isDynTypedRefType({ kind: "object", className }))
|
|
1264
|
+
continue;
|
|
1265
|
+
if (!this.boxed.has(className) &&
|
|
1266
|
+
![...this.boxedStatic].some((base) => lowerer.isSubclassOf(className, base)))
|
|
1267
|
+
continue;
|
|
1268
|
+
helper.classes.add(className);
|
|
1269
|
+
const loc = helper.fn.loc;
|
|
1270
|
+
const type = { kind: "object", className };
|
|
1271
|
+
const value = varRef("value", DYN, loc);
|
|
1272
|
+
// A class with no prototype data in its chain (one extending
|
|
1273
|
+
// Error, or with no methods) has no prototype a program can name:
|
|
1274
|
+
// an object of the class's own stands in, so instances of one class
|
|
1275
|
+
// share it (`Object.getPrototypeOf(a) === Object.getPrototypeOf(b)`),
|
|
1276
|
+
// other prototypes differ from it, and an instanceof walk (through
|
|
1277
|
+
// Object.prototype to null) answers false instead of reaching the
|
|
1278
|
+
// reflection refusal. A function-local class is a new class at
|
|
1279
|
+
// each evaluation of its declaration, so its instances answer with
|
|
1280
|
+
// the prototype of their own class value instead.
|
|
1281
|
+
const answer = (name) => {
|
|
1282
|
+
const of = lowerer.classes.get(name);
|
|
1283
|
+
const prototype = hasClassPrototypeData(of) || of.localClass
|
|
1284
|
+
? classPrototypeData(lowerer, of, loc, {
|
|
1285
|
+
kind: "dynCheck",
|
|
1286
|
+
value,
|
|
1287
|
+
type: { kind: "object", className: name },
|
|
1288
|
+
loc,
|
|
1289
|
+
})
|
|
1290
|
+
: null;
|
|
1291
|
+
if (prototype)
|
|
1292
|
+
return [{ kind: "return", value: prototype, loc }];
|
|
1293
|
+
return hasClassPrototypeData(of) ? null : this.prototypeStandIn(lowerer, name, loc);
|
|
1294
|
+
};
|
|
1295
|
+
const own = answer(className);
|
|
1296
|
+
if (!own) {
|
|
1297
|
+
changed = true;
|
|
1298
|
+
continue;
|
|
1299
|
+
}
|
|
1300
|
+
// A capsule boxed at this class can hold a subclass instance: the
|
|
1301
|
+
// most derived subclass the instance belongs to answers.
|
|
1302
|
+
const depth = (name) => {
|
|
1303
|
+
let n = 0;
|
|
1304
|
+
for (let at = lowerer.classes.get(name)?.base; at; at = at.base)
|
|
1305
|
+
n++;
|
|
1306
|
+
return n;
|
|
1307
|
+
};
|
|
1308
|
+
const subclasses = [...lowerer.classes.keys()]
|
|
1309
|
+
.filter((name) => name !== className &&
|
|
1310
|
+
lowerer.isSubclassOf(name, className) &&
|
|
1311
|
+
isDynTypedRefType({ kind: "object", className: name }))
|
|
1312
|
+
.sort((a, b) => depth(b) - depth(a));
|
|
1313
|
+
const then = [];
|
|
1314
|
+
for (const name of subclasses) {
|
|
1315
|
+
const sub = answer(name);
|
|
1316
|
+
if (!sub)
|
|
1317
|
+
continue;
|
|
1318
|
+
then.push({
|
|
1319
|
+
kind: "if",
|
|
1320
|
+
cond: {
|
|
1321
|
+
kind: "instanceOf",
|
|
1322
|
+
value: { kind: "dynCheck", value, type, loc },
|
|
1323
|
+
className: name,
|
|
1324
|
+
type: BOOL,
|
|
1325
|
+
loc,
|
|
1326
|
+
},
|
|
1327
|
+
then: sub,
|
|
1328
|
+
else_: null,
|
|
1329
|
+
loc,
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
then.push(...own);
|
|
1333
|
+
helper.fn.body.unshift({
|
|
1334
|
+
kind: "if",
|
|
1335
|
+
cond: {
|
|
1336
|
+
kind: "libCall",
|
|
1337
|
+
fn: "dyn.typedRefIs",
|
|
1338
|
+
args: [value, { kind: "strLit", value: typeKey(type), type: STRING, loc }],
|
|
1339
|
+
type: BOOL,
|
|
1340
|
+
loc,
|
|
1341
|
+
},
|
|
1342
|
+
then,
|
|
1343
|
+
else_: null,
|
|
1344
|
+
loc,
|
|
1345
|
+
});
|
|
1346
|
+
changed = true;
|
|
1347
|
+
}
|
|
1348
|
+
let live = null;
|
|
933
1349
|
for (const plan of this.propertyReceivers(lowerer, false, false)) {
|
|
934
1350
|
const info = plan.info;
|
|
935
1351
|
const className = info.def.name;
|
|
@@ -999,7 +1415,11 @@ export class ClassDynamicDispatch {
|
|
|
999
1415
|
const needsPrototype = (current) => hasClassPrototypeData(current) ||
|
|
1000
1416
|
current.subclasses.some((child) => lowerer.classCanBeConstructed(child) && needsPrototype(child));
|
|
1001
1417
|
const prototypeFor = (current, receiver, loc) => this.bagPrototype(lowerer, current, receiver, loc);
|
|
1002
|
-
|
|
1418
|
+
live ??= this.liveBagInitializers();
|
|
1419
|
+
for (const existingInit of [
|
|
1420
|
+
...(this.bagInitializers.get(className) ?? []),
|
|
1421
|
+
...(live.get(className) ?? []),
|
|
1422
|
+
]) {
|
|
1003
1423
|
if (existingInit.value.kind === "dynObjLit" && needsPrototype(info)) {
|
|
1004
1424
|
const prototype = prototypeFor(info, existingInit.obj, existingInit.loc);
|
|
1005
1425
|
if (prototype) {
|
|
@@ -1010,6 +1430,14 @@ export class ClassDynamicDispatch {
|
|
|
1010
1430
|
type: DYN,
|
|
1011
1431
|
loc: existingInit.loc,
|
|
1012
1432
|
};
|
|
1433
|
+
// The initializer is a statement of the property bag helpers;
|
|
1434
|
+
// their reused site summaries do not see an edit inside it.
|
|
1435
|
+
if (this.propertyBag)
|
|
1436
|
+
this.sites.forget(this.propertyBag);
|
|
1437
|
+
for (const fn of this.typedPropertyBags.values())
|
|
1438
|
+
this.sites.forget(fn);
|
|
1439
|
+
for (const fn of this.exactPropertyBags.values())
|
|
1440
|
+
this.sites.forget(fn);
|
|
1013
1441
|
changed = true;
|
|
1014
1442
|
}
|
|
1015
1443
|
}
|
|
@@ -1079,15 +1507,36 @@ export class ClassDynamicDispatch {
|
|
|
1079
1507
|
}
|
|
1080
1508
|
refreshDescriptorGuards(lowerer);
|
|
1081
1509
|
const byMethod = new Map();
|
|
1510
|
+
// A query asks every receiver about one name, and the program's dispatch
|
|
1511
|
+
// sites ask about thousands: index the receivers by name once per list.
|
|
1512
|
+
let index = null;
|
|
1513
|
+
const indexOf = (plans) => index?.plans === plans ? index : (index = receiverIndex(lowerer, plans));
|
|
1514
|
+
/** The receivers of `plans` that can answer `name`, in list order: those
|
|
1515
|
+
* `table` lists under it and the rooted ones. Emit-override
|
|
1516
|
+
* specializations (`emit:<event>`) join a class's methods while bodies
|
|
1517
|
+
* lower, so they keep every receiver. */
|
|
1518
|
+
const receiversFor = (plans, name, table) => {
|
|
1519
|
+
if (name.startsWith("emit:"))
|
|
1520
|
+
return plans;
|
|
1521
|
+
const found = indexOf(plans);
|
|
1522
|
+
const positions = (table === "methods" ? found.methods : found.members).get(name);
|
|
1523
|
+
return mergePositions(positions ?? [], found.rooted).map((position) => plans[position]);
|
|
1524
|
+
};
|
|
1082
1525
|
const candidates = (method) => {
|
|
1083
1526
|
const found = byMethod.get(method);
|
|
1084
1527
|
if (found)
|
|
1085
1528
|
return found;
|
|
1086
|
-
const
|
|
1529
|
+
const plans = this.propertyReceivers(lowerer, true);
|
|
1530
|
+
const test = ({ info }) => {
|
|
1087
1531
|
if (!info || info.fields.has(method) || info.builtinError)
|
|
1088
1532
|
return [];
|
|
1089
1533
|
if (emitterRooted(lowerer, info) && EMITTER_METHODS.has(method))
|
|
1090
1534
|
return [info];
|
|
1535
|
+
if (emitterRooted(lowerer, info) &&
|
|
1536
|
+
!streamRooted(info) &&
|
|
1537
|
+
EMITTER_INTROSPECTION_METHODS.has(method) &&
|
|
1538
|
+
!findMethodOn(lowerer, info, method))
|
|
1539
|
+
return [info];
|
|
1091
1540
|
if (info.builtinStream) {
|
|
1092
1541
|
return STREAM_METHODS.has(method) ||
|
|
1093
1542
|
(STREAM_OPERATORS.has(method) && info.builtinStream !== "w")
|
|
@@ -1097,10 +1546,25 @@ export class ClassDynamicDispatch {
|
|
|
1097
1546
|
return findMethodOn(lowerer, info, method) || findGenericMethodOn(lowerer, info, method)
|
|
1098
1547
|
? [info]
|
|
1099
1548
|
: [];
|
|
1100
|
-
}
|
|
1549
|
+
};
|
|
1550
|
+
const matching = receiversFor(plans, method, "methods").flatMap(test);
|
|
1551
|
+
if (CHECK_CANDIDATES) {
|
|
1552
|
+
const every = plans.flatMap(test);
|
|
1553
|
+
if (every.length !== matching.length || every.some((info, i) => info !== matching[i]))
|
|
1554
|
+
throw new InternalCompilerError(`indexed candidates for ${method} differ`);
|
|
1555
|
+
}
|
|
1101
1556
|
byMethod.set(method, matching);
|
|
1102
1557
|
return matching;
|
|
1103
1558
|
};
|
|
1559
|
+
const candidateSets = new Map();
|
|
1560
|
+
const candidateSet = (method) => {
|
|
1561
|
+
let set = candidateSets.get(method);
|
|
1562
|
+
if (!set) {
|
|
1563
|
+
set = new Set(candidates(method));
|
|
1564
|
+
candidateSets.set(method, set);
|
|
1565
|
+
}
|
|
1566
|
+
return set;
|
|
1567
|
+
};
|
|
1104
1568
|
for (const fn of functions) {
|
|
1105
1569
|
// Discovery already visits every expression. Preserve bodies without
|
|
1106
1570
|
// dispatch sites instead of rebuilding their entire typed IR tree on
|
|
@@ -1219,29 +1683,65 @@ export class ClassDynamicDispatch {
|
|
|
1219
1683
|
}
|
|
1220
1684
|
return { kind: "call", callee: cast.fn.name, args: [expr.value], type, loc: expr.loc };
|
|
1221
1685
|
}
|
|
1686
|
+
if (expr.kind === "libCall" && expr.fn === "dyn.inheritsErrorPrototype") {
|
|
1687
|
+
if (!this.errorPrototypeHelper) {
|
|
1688
|
+
const loc = expr.loc;
|
|
1689
|
+
this.errorPrototypeHelper = {
|
|
1690
|
+
name: "%dyn.class.inheritsErrorPrototype",
|
|
1691
|
+
params: [{ localId: "value", name: "value", type: DYN }],
|
|
1692
|
+
locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
|
|
1693
|
+
returnType: BOOL,
|
|
1694
|
+
loc,
|
|
1695
|
+
body: [
|
|
1696
|
+
{ kind: "return", value: { ...expr, args: [varRef("value", DYN, loc)] }, loc },
|
|
1697
|
+
],
|
|
1698
|
+
};
|
|
1699
|
+
lowerer.liftedFns.push(this.errorPrototypeHelper);
|
|
1700
|
+
this.generated.add(this.errorPrototypeHelper);
|
|
1701
|
+
changed = true;
|
|
1702
|
+
}
|
|
1703
|
+
return {
|
|
1704
|
+
kind: "call",
|
|
1705
|
+
callee: this.errorPrototypeHelper.name,
|
|
1706
|
+
args: expr.args,
|
|
1707
|
+
type: BOOL,
|
|
1708
|
+
loc: expr.loc,
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1222
1711
|
if (expr.kind === "libCall" &&
|
|
1223
|
-
expr.fn === "dyn.getPrototype" &&
|
|
1712
|
+
(expr.fn === "dyn.getPrototype" || expr.fn === "dyn.getPrototypeForIdentity") &&
|
|
1224
1713
|
expr.args[0]?.kind !== "dynObjLit") {
|
|
1225
1714
|
if (expr.prototypeIdentityOnly) {
|
|
1226
|
-
|
|
1715
|
+
let helper = this.prototypeIdentityHelpers.get(expr.fn);
|
|
1716
|
+
if (!helper) {
|
|
1227
1717
|
const loc = expr.loc;
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1718
|
+
helper = {
|
|
1719
|
+
fn: {
|
|
1720
|
+
name: expr.fn === "dyn.getPrototype"
|
|
1721
|
+
? "%dyn.class.prototypeIdentity"
|
|
1722
|
+
: "%dyn.class.prototypeChainIdentity",
|
|
1723
|
+
params: [{ localId: "value", name: "value", type: DYN }],
|
|
1724
|
+
locals: [{ id: "value", name: "value", type: DYN, mutable: false }],
|
|
1725
|
+
returnType: DYN,
|
|
1726
|
+
loc,
|
|
1727
|
+
body: [
|
|
1728
|
+
{
|
|
1729
|
+
kind: "return",
|
|
1730
|
+
value: { ...expr, args: [varRef("value", DYN, loc)] },
|
|
1731
|
+
loc,
|
|
1732
|
+
},
|
|
1733
|
+
],
|
|
1734
|
+
},
|
|
1735
|
+
classes: new Set(),
|
|
1237
1736
|
};
|
|
1238
|
-
|
|
1239
|
-
|
|
1737
|
+
this.prototypeIdentityHelpers.set(expr.fn, helper);
|
|
1738
|
+
lowerer.liftedFns.push(helper.fn);
|
|
1739
|
+
this.generated.add(helper.fn);
|
|
1240
1740
|
changed = true;
|
|
1241
1741
|
}
|
|
1242
1742
|
return {
|
|
1243
1743
|
kind: "call",
|
|
1244
|
-
callee:
|
|
1744
|
+
callee: helper.fn.name,
|
|
1245
1745
|
args: expr.args,
|
|
1246
1746
|
type: DYN,
|
|
1247
1747
|
loc: expr.loc,
|
|
@@ -2013,7 +2513,28 @@ export class ClassDynamicDispatch {
|
|
|
2013
2513
|
loc,
|
|
2014
2514
|
});
|
|
2015
2515
|
}
|
|
2016
|
-
|
|
2516
|
+
const receiverAccess = read
|
|
2517
|
+
? [{ kind: "return", value: { ...read, value: varRef("p.0", DYN, loc) }, loc }]
|
|
2518
|
+
: [
|
|
2519
|
+
{
|
|
2520
|
+
kind: "exprStmt",
|
|
2521
|
+
expr: {
|
|
2522
|
+
...write,
|
|
2523
|
+
args: [varRef("p.0", DYN, loc), write.args[1], varRef("p.1", DYN, loc)],
|
|
2524
|
+
},
|
|
2525
|
+
loc,
|
|
2526
|
+
},
|
|
2527
|
+
{ kind: "return", value: null, loc },
|
|
2528
|
+
];
|
|
2529
|
+
dispatch = {
|
|
2530
|
+
name,
|
|
2531
|
+
write: !!write,
|
|
2532
|
+
fn: helper,
|
|
2533
|
+
classes: new Set(),
|
|
2534
|
+
...(name !== "constructor" && name !== "toString"
|
|
2535
|
+
? { plain: { tail: [...helper.body], access: receiverAccess } }
|
|
2536
|
+
: {}),
|
|
2537
|
+
};
|
|
2017
2538
|
this.properties.set(key, dispatch);
|
|
2018
2539
|
this.generated.add(helper);
|
|
2019
2540
|
lowerer.liftedFns.push(helper);
|
|
@@ -2044,14 +2565,14 @@ export class ClassDynamicDispatch {
|
|
|
2044
2565
|
: expr.kind === "dynInvoke"
|
|
2045
2566
|
? expr
|
|
2046
2567
|
: null;
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2568
|
+
// Static methods matter only for methods no instance answers.
|
|
2569
|
+
const staticCandidates = (method) => [...this.boxedConstructors].some((name) => {
|
|
2570
|
+
const info = lowerer.classes.get(name);
|
|
2571
|
+
return info && findStaticOn(lowerer, info, method)?.method;
|
|
2572
|
+
});
|
|
2052
2573
|
if (!invoke ||
|
|
2053
2574
|
(candidates(invoke.method).length === 0 &&
|
|
2054
|
-
!staticCandidates &&
|
|
2575
|
+
!staticCandidates(invoke.method) &&
|
|
2055
2576
|
!(invoke.method === "toString" && lowerer.classes.has("%Error"))))
|
|
2056
2577
|
return expr;
|
|
2057
2578
|
const key = JSON.stringify([
|
|
@@ -2316,17 +2837,41 @@ export class ClassDynamicDispatch {
|
|
|
2316
2837
|
});
|
|
2317
2838
|
changed = true;
|
|
2318
2839
|
}
|
|
2319
|
-
|
|
2840
|
+
// Compute the candidates where the first plan would have, so the
|
|
2841
|
+
// memoized set is the same whichever plans are already answered.
|
|
2842
|
+
const plans = this.propertyReceivers(lowerer, true);
|
|
2843
|
+
const matching = plans.length ? candidateSet(dispatch.source.method) : null;
|
|
2844
|
+
for (const plan of plans) {
|
|
2320
2845
|
const { info } = plan;
|
|
2321
|
-
if (
|
|
2846
|
+
if (dispatch.classes.has(plan.key) || !matching.has(info))
|
|
2322
2847
|
continue;
|
|
2323
2848
|
dispatch.classes.add(plan.key);
|
|
2324
2849
|
const loc = dispatch.source.loc;
|
|
2325
|
-
const value = varRef("p.0", DYN, loc);
|
|
2326
2850
|
const { receiver, condition } = this.propertyReceiver(plan, loc);
|
|
2327
2851
|
if (isClassCallback(lowerer, info, dispatch.source.method)) {
|
|
2328
2852
|
const prototypeMethod = observedPrototypeMethod(lowerer, info, dispatch.source.method, loc, receiver);
|
|
2329
|
-
const bag = this.
|
|
2853
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
2854
|
+
const methodKey = {
|
|
2855
|
+
kind: "strLit",
|
|
2856
|
+
value: dispatch.source.method,
|
|
2857
|
+
type: STRING,
|
|
2858
|
+
loc,
|
|
2859
|
+
};
|
|
2860
|
+
const bagHas = {
|
|
2861
|
+
kind: "libCall",
|
|
2862
|
+
fn: "dyn.hasKey",
|
|
2863
|
+
args: [bag, methodKey],
|
|
2864
|
+
type: BOOL,
|
|
2865
|
+
loc,
|
|
2866
|
+
};
|
|
2867
|
+
// An observed prototype slot answers through the bag when the bag
|
|
2868
|
+
// holds the name (own or through its prototype). A bag read as a
|
|
2869
|
+
// fresh empty object (an instance with no own dynamic properties
|
|
2870
|
+
// whose bag initializer predates the class's prototype data) does
|
|
2871
|
+
// not, so the method then comes from the class's prototype data.
|
|
2872
|
+
const prototype = prototypeMethod
|
|
2873
|
+
? classPrototypeData(lowerer, info, loc, receiver)
|
|
2874
|
+
: null;
|
|
2330
2875
|
dispatch.callback.body.unshift({
|
|
2331
2876
|
kind: "if",
|
|
2332
2877
|
cond: condition,
|
|
@@ -2335,18 +2880,7 @@ export class ClassDynamicDispatch {
|
|
|
2335
2880
|
kind: "return",
|
|
2336
2881
|
value: {
|
|
2337
2882
|
kind: "ternary",
|
|
2338
|
-
cond:
|
|
2339
|
-
? { kind: "boolLit", value: true, type: BOOL, loc }
|
|
2340
|
-
: {
|
|
2341
|
-
kind: "libCall",
|
|
2342
|
-
fn: "dyn.hasKey",
|
|
2343
|
-
args: [
|
|
2344
|
-
bag,
|
|
2345
|
-
{ kind: "strLit", value: dispatch.source.method, type: STRING, loc },
|
|
2346
|
-
],
|
|
2347
|
-
type: BOOL,
|
|
2348
|
-
loc,
|
|
2349
|
-
},
|
|
2883
|
+
cond: prototype ? { kind: "boolLit", value: true, type: BOOL, loc } : bagHas,
|
|
2350
2884
|
then: {
|
|
2351
2885
|
kind: "dynObjLit",
|
|
2352
2886
|
fields: [
|
|
@@ -2354,8 +2888,17 @@ export class ClassDynamicDispatch {
|
|
|
2354
2888
|
key: { kind: "strLit", value: "value", type: STRING, loc },
|
|
2355
2889
|
value: {
|
|
2356
2890
|
kind: "dynKeyGet",
|
|
2357
|
-
value:
|
|
2358
|
-
|
|
2891
|
+
value: prototype
|
|
2892
|
+
? {
|
|
2893
|
+
kind: "ternary",
|
|
2894
|
+
cond: bagHas,
|
|
2895
|
+
then: bag,
|
|
2896
|
+
else_: prototype,
|
|
2897
|
+
type: DYN,
|
|
2898
|
+
loc,
|
|
2899
|
+
}
|
|
2900
|
+
: bag,
|
|
2901
|
+
key: methodKey,
|
|
2359
2902
|
type: DYN,
|
|
2360
2903
|
loc,
|
|
2361
2904
|
},
|
|
@@ -2462,7 +3005,7 @@ export class ClassDynamicDispatch {
|
|
|
2462
3005
|
for (const plan of this.propertyReceivers(lowerer)) {
|
|
2463
3006
|
if (plan.info !== plan.capsule ||
|
|
2464
3007
|
dispatch.classes.has(plan.key) ||
|
|
2465
|
-
(!dispatch.field && !
|
|
3008
|
+
(!dispatch.field && !candidateSet(dispatch.method).has(plan.info)))
|
|
2466
3009
|
continue;
|
|
2467
3010
|
dispatch.classes.add(plan.key);
|
|
2468
3011
|
const loc = dispatch.fn.loc;
|
|
@@ -2545,28 +3088,52 @@ export class ClassDynamicDispatch {
|
|
|
2545
3088
|
});
|
|
2546
3089
|
changed = true;
|
|
2547
3090
|
}
|
|
2548
|
-
|
|
3091
|
+
// Only the receivers that declare or hold the name, and the rooted
|
|
3092
|
+
// ones, can pass the test, except for names it decides on every
|
|
3093
|
+
// receiver. Fields added while bodies lower (the property bag and the
|
|
3094
|
+
// attribute words) have compiler names, which take every receiver.
|
|
3095
|
+
const plans = this.propertyReceivers(lowerer, true);
|
|
3096
|
+
const anyReceiver = !isClassOwnEnumerableFieldName(dispatch.name) ||
|
|
3097
|
+
dispatch.name === "constructor" ||
|
|
3098
|
+
dispatch.name === "stack";
|
|
3099
|
+
const skips = (plan) => !isClassOwnEnumerableFieldName(dispatch.name) ||
|
|
3100
|
+
(!(plan.info.builtinStream !== undefined && streamProperty(dispatch.name)) &&
|
|
3101
|
+
!eventTargetInheritedMember(plan.info, dispatch.name) &&
|
|
3102
|
+
!dateInheritedMember(lowerer, plan.info, dispatch.name) &&
|
|
3103
|
+
!findMethodOn(lowerer, plan.info, dispatch.name) &&
|
|
3104
|
+
!findGenericMethodOn(lowerer, plan.info, dispatch.name) &&
|
|
3105
|
+
dispatch.name !== "constructor" &&
|
|
3106
|
+
!plan.info.fields.has(dispatch.name) &&
|
|
3107
|
+
!(dispatch.name === "stack" && lowerer.isSubclassOf(plan.info.def.name, "%Error")) &&
|
|
3108
|
+
!findMethodOn(lowerer, plan.info, `get:${dispatch.name}`) &&
|
|
3109
|
+
!findMethodOn(lowerer, plan.info, `set:${dispatch.name}`));
|
|
3110
|
+
const selected = anyReceiver ? plans : receiversFor(plans, dispatch.name, "members");
|
|
3111
|
+
if (CHECK_CANDIDATES &&
|
|
3112
|
+
plans.some((plan) => !dispatch.classes.has(plan.key) && !skips(plan) && !selected.includes(plan)))
|
|
3113
|
+
throw new InternalCompilerError(`indexed receivers for ${dispatch.name} differ`);
|
|
3114
|
+
for (const plan of selected) {
|
|
2549
3115
|
const { info } = plan;
|
|
2550
|
-
|
|
2551
|
-
(!(info.builtinStream !== undefined && streamProperty(dispatch.name)) &&
|
|
2552
|
-
!eventTargetInheritedMember(info, dispatch.name) &&
|
|
2553
|
-
!findMethodOn(lowerer, info, dispatch.name) &&
|
|
2554
|
-
!findGenericMethodOn(lowerer, info, dispatch.name) &&
|
|
2555
|
-
dispatch.name !== "constructor" &&
|
|
2556
|
-
!info.fields.has(dispatch.name) &&
|
|
2557
|
-
!(dispatch.name === "stack" && lowerer.isSubclassOf(info.def.name, "%Error")) &&
|
|
2558
|
-
!findMethodOn(lowerer, info, `get:${dispatch.name}`) &&
|
|
2559
|
-
!findMethodOn(lowerer, info, `set:${dispatch.name}`)))
|
|
2560
|
-
continue;
|
|
3116
|
+
// Classes answered in an earlier pass skip the member lookups.
|
|
2561
3117
|
if (dispatch.classes.has(plan.key))
|
|
2562
3118
|
continue;
|
|
3119
|
+
if (skips(plan))
|
|
3120
|
+
continue;
|
|
2563
3121
|
dispatch.classes.add(plan.key);
|
|
2564
3122
|
const loc = dispatch.fn.loc;
|
|
2565
3123
|
const { receiver, condition } = this.propertyReceiver(plan, loc);
|
|
3124
|
+
// The branch checks its receiver once: each use of the checked
|
|
3125
|
+
// receiver would repeat the check.
|
|
3126
|
+
const local = `receiver.${dispatch.fn.locals.length}`;
|
|
3127
|
+
dispatch.fn.locals.push({
|
|
3128
|
+
id: local,
|
|
3129
|
+
name: "receiver",
|
|
3130
|
+
type: receiver.type,
|
|
3131
|
+
mutable: false,
|
|
3132
|
+
});
|
|
2566
3133
|
const before = lowerer.diags.length;
|
|
2567
3134
|
let branch;
|
|
2568
3135
|
try {
|
|
2569
|
-
branch = this.propertyBody(lowerer, dispatch, info, receiver);
|
|
3136
|
+
branch = this.propertyBody(lowerer, dispatch, info, varRef(local, receiver.type, loc));
|
|
2570
3137
|
}
|
|
2571
3138
|
catch (error) {
|
|
2572
3139
|
if (!(error instanceof PoisonError) || !info.decl)
|
|
@@ -2579,7 +3146,7 @@ export class ClassDynamicDispatch {
|
|
|
2579
3146
|
dispatch.fn.body.unshift({
|
|
2580
3147
|
kind: "if",
|
|
2581
3148
|
cond: condition,
|
|
2582
|
-
then: branch,
|
|
3149
|
+
then: [{ kind: "varDecl", localId: local, init: receiver, loc }, ...branch],
|
|
2583
3150
|
else_: null,
|
|
2584
3151
|
loc,
|
|
2585
3152
|
});
|
|
@@ -2655,7 +3222,8 @@ export class ClassDynamicDispatch {
|
|
|
2655
3222
|
},
|
|
2656
3223
|
];
|
|
2657
3224
|
if (((info.builtinStream !== undefined && streamProperty(name)) ||
|
|
2658
|
-
eventTargetInheritedMember(info, name)
|
|
3225
|
+
eventTargetInheritedMember(info, name) ||
|
|
3226
|
+
dateInheritedMember(lowerer, info, name)) &&
|
|
2659
3227
|
dispatch.probe)
|
|
2660
3228
|
return [
|
|
2661
3229
|
{
|
|
@@ -2671,7 +3239,7 @@ export class ClassDynamicDispatch {
|
|
|
2671
3239
|
const prototypeMethod = !info.fields.has(name) && observedPrototypeMethod(lowerer, info, name, loc, receiver);
|
|
2672
3240
|
if (info.fields.has(name) || (dispatch.probe === "in" && !prototypeMethod)) {
|
|
2673
3241
|
if (info.fields.has(name) && info.def.tracksOwnFields) {
|
|
2674
|
-
const bag = this.
|
|
3242
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
2675
3243
|
const symbol = symbolMemberKey(lowerer, info, name, loc);
|
|
2676
3244
|
const fn = dispatch.probe === "in"
|
|
2677
3245
|
? "dyn.hasKey"
|
|
@@ -2696,7 +3264,7 @@ export class ClassDynamicDispatch {
|
|
|
2696
3264
|
{ kind: "return", value: { kind: "boolLit", value: true, type: BOOL, loc }, loc },
|
|
2697
3265
|
];
|
|
2698
3266
|
}
|
|
2699
|
-
const bag = this.
|
|
3267
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
2700
3268
|
const symbol = name.startsWith("sym:") || name.startsWith("%symbol:");
|
|
2701
3269
|
const fn = dispatch.probe === "in"
|
|
2702
3270
|
? "dyn.hasKey"
|
|
@@ -2762,9 +3330,8 @@ export class ClassDynamicDispatch {
|
|
|
2762
3330
|
}
|
|
2763
3331
|
const branches = [];
|
|
2764
3332
|
if (!dispatch.write && !dispatch.reflect && !info.def.tracksOwnFields) {
|
|
2765
|
-
const value = varRef("p.0", DYN, loc);
|
|
2766
3333
|
const key = varRef("p.key", DYN, loc);
|
|
2767
|
-
const bag = this.
|
|
3334
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
2768
3335
|
branches.push({
|
|
2769
3336
|
kind: "if",
|
|
2770
3337
|
cond: {
|
|
@@ -2866,6 +3433,10 @@ export class ClassDynamicDispatch {
|
|
|
2866
3433
|
if (inherited)
|
|
2867
3434
|
for (const name of inherited)
|
|
2868
3435
|
names.add(name);
|
|
3436
|
+
if (dateRootOf(info))
|
|
3437
|
+
for (const name of DATE_PROTOTYPE_METHOD_NAMES)
|
|
3438
|
+
if (dateInheritedMember(lowerer, info, name))
|
|
3439
|
+
names.add(name);
|
|
2869
3440
|
for (let owner = info; owner; owner = owner.base) {
|
|
2870
3441
|
const methodNames = [...owner.methods.keys()];
|
|
2871
3442
|
if (owner.genericMethods)
|
|
@@ -3084,6 +3655,39 @@ export class ClassDynamicDispatch {
|
|
|
3084
3655
|
}
|
|
3085
3656
|
/** The receiver's own dynamic properties for a read: undefined while it has
|
|
3086
3657
|
* none, and never stored, so reads stay valid on published objects. */
|
|
3658
|
+
/** Statements that return `className`'s stand-in prototype: one empty
|
|
3659
|
+
* object per class, created on first use and kept in a module global. */
|
|
3660
|
+
prototypeStandIn(lowerer, className, loc) {
|
|
3661
|
+
const globalId = `%g.%prototype.standIn.${className}`;
|
|
3662
|
+
const readyId = `${globalId}.ready`;
|
|
3663
|
+
if (!this.prototypeStandIns.has(className)) {
|
|
3664
|
+
this.prototypeStandIns.add(className);
|
|
3665
|
+
lowerer.globalsList.push({ id: globalId, name: `${className}.prototype`, type: DYN, mutable: true }, { id: readyId, name: `${className}.prototype.ready`, type: BOOL, mutable: true });
|
|
3666
|
+
}
|
|
3667
|
+
return [
|
|
3668
|
+
{
|
|
3669
|
+
kind: "if",
|
|
3670
|
+
cond: { kind: "unary", op: "!", operand: varRef(readyId, BOOL, loc), type: BOOL, loc },
|
|
3671
|
+
then: [
|
|
3672
|
+
{
|
|
3673
|
+
kind: "assign",
|
|
3674
|
+
localId: globalId,
|
|
3675
|
+
value: { kind: "dynObjLit", fields: [], type: DYN, loc },
|
|
3676
|
+
loc,
|
|
3677
|
+
},
|
|
3678
|
+
{
|
|
3679
|
+
kind: "assign",
|
|
3680
|
+
localId: readyId,
|
|
3681
|
+
value: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
3682
|
+
loc,
|
|
3683
|
+
},
|
|
3684
|
+
],
|
|
3685
|
+
else_: null,
|
|
3686
|
+
loc,
|
|
3687
|
+
},
|
|
3688
|
+
{ kind: "return", value: varRef(globalId, DYN, loc), loc },
|
|
3689
|
+
];
|
|
3690
|
+
}
|
|
3087
3691
|
readPropertyBag(lowerer, receiver, loc) {
|
|
3088
3692
|
const helper = classPropertiesHelper(lowerer, loc, true);
|
|
3089
3693
|
this.generated.add(helper);
|
|
@@ -3105,7 +3709,7 @@ export class ClassDynamicDispatch {
|
|
|
3105
3709
|
* each class branch as small as the storing form. */
|
|
3106
3710
|
readBagHas(lowerer, fn, bag, key, loc) {
|
|
3107
3711
|
const name = fn === "dyn.hasKey" ? "%dyn.class.bagHas" : "%dyn.class.bagHasComputed";
|
|
3108
|
-
let helper = lowerer.
|
|
3712
|
+
let helper = lowerer.liftedFnNamed(name);
|
|
3109
3713
|
if (!helper) {
|
|
3110
3714
|
const keyType = fn === "dyn.hasKey" ? STRING : DYN;
|
|
3111
3715
|
const value = varRef("p.0", DYN, loc);
|
|
@@ -3498,6 +4102,66 @@ export class ClassDynamicDispatch {
|
|
|
3498
4102
|
];
|
|
3499
4103
|
return { kind: "if", cond: condition, then: body, else_: null, loc };
|
|
3500
4104
|
}
|
|
4105
|
+
// Date.prototype[Symbol.toPrimitive] takes "default" as "string", and a
|
|
4106
|
+
// class declared `extends Date` inherits Date's toString and valueOf,
|
|
4107
|
+
// which answer primitives from the time value.
|
|
4108
|
+
const dateRoot = dateRootOf(info);
|
|
4109
|
+
if (dateRoot) {
|
|
4110
|
+
const dateOrder = hint === "number" ? ["valueOf", "toString"] : ["toString", "valueOf"];
|
|
4111
|
+
const { receiver } = this.propertyReceiver(plan, loc);
|
|
4112
|
+
const body = [];
|
|
4113
|
+
for (const method of dateOrder) {
|
|
4114
|
+
if (!conversionMethod(lowerer, info, method)) {
|
|
4115
|
+
const time = {
|
|
4116
|
+
kind: "fieldGet",
|
|
4117
|
+
obj: upcastTo(lowerer, receiver, dateRoot.def.name),
|
|
4118
|
+
className: dateRoot.def.name,
|
|
4119
|
+
field: DATE_TIME_FIELD,
|
|
4120
|
+
type: DATE_T,
|
|
4121
|
+
loc,
|
|
4122
|
+
};
|
|
4123
|
+
body.push({
|
|
4124
|
+
kind: "return",
|
|
4125
|
+
value: lowerer.coerceToExpected(dateValueMethod(method, time, loc), DYN),
|
|
4126
|
+
loc,
|
|
4127
|
+
});
|
|
4128
|
+
break;
|
|
4129
|
+
}
|
|
4130
|
+
const result = `%toPrimitive.${method}.${helper.locals.length}`;
|
|
4131
|
+
helper.locals.push({ id: result, name: method, type: DYN, mutable: false });
|
|
4132
|
+
body.push({
|
|
4133
|
+
kind: "varDecl",
|
|
4134
|
+
localId: result,
|
|
4135
|
+
init: {
|
|
4136
|
+
kind: "call",
|
|
4137
|
+
callee: this.toPrimitiveCall(lowerer, plan, method, 0, loc),
|
|
4138
|
+
args: [varRef("p.0", DYN, loc)],
|
|
4139
|
+
type: DYN,
|
|
4140
|
+
loc,
|
|
4141
|
+
},
|
|
4142
|
+
loc,
|
|
4143
|
+
}, {
|
|
4144
|
+
kind: "if",
|
|
4145
|
+
cond: isPrimitive(varRef(result, DYN, loc), loc),
|
|
4146
|
+
then: [{ kind: "return", value: varRef(result, DYN, loc), loc }],
|
|
4147
|
+
else_: null,
|
|
4148
|
+
loc,
|
|
4149
|
+
});
|
|
4150
|
+
}
|
|
4151
|
+
if (body.at(-1)?.kind !== "return")
|
|
4152
|
+
body.push({
|
|
4153
|
+
kind: "return",
|
|
4154
|
+
value: nodeThrowExpr(1, "", "Cannot convert object to primitive value", DYN, loc),
|
|
4155
|
+
loc,
|
|
4156
|
+
});
|
|
4157
|
+
return {
|
|
4158
|
+
kind: "if",
|
|
4159
|
+
cond: this.propertyReceiver(plan, loc).condition,
|
|
4160
|
+
then: body,
|
|
4161
|
+
else_: null,
|
|
4162
|
+
loc,
|
|
4163
|
+
};
|
|
4164
|
+
}
|
|
3501
4165
|
const order = hint === "string" ? ["toString", "valueOf"] : ["valueOf", "toString"];
|
|
3502
4166
|
if (!order.some((method) => conversionMethod(lowerer, info, method)))
|
|
3503
4167
|
return null;
|
|
@@ -3665,7 +4329,7 @@ export class ClassDynamicDispatch {
|
|
|
3665
4329
|
readPropertyBagOrEmpty(lowerer, receiver, loc) {
|
|
3666
4330
|
// One call per read site: large JS programs have a branch per class and
|
|
3667
4331
|
// property, so the absent-bag handling lives in the shared helper.
|
|
3668
|
-
let helper = lowerer.
|
|
4332
|
+
let helper = lowerer.liftedFnNamed(READ_PROPERTIES_OR_EMPTY);
|
|
3669
4333
|
if (!helper) {
|
|
3670
4334
|
// Settled by finalize; until then, the read-only bag's own dispatch.
|
|
3671
4335
|
helper = {
|
|
@@ -3752,11 +4416,119 @@ export class ClassDynamicDispatch {
|
|
|
3752
4416
|
lowerer.liftedFns.push(helper);
|
|
3753
4417
|
return helper;
|
|
3754
4418
|
}
|
|
4419
|
+
/** The read-only bag a class branch reads for its receiver: the
|
|
4420
|
+
* receiver's own field when the branch selected the receiver's exact
|
|
4421
|
+
* class, otherwise the dispatch over every class (readPropertyBag, or
|
|
4422
|
+
* readPropertyBagOrEmpty with `orEmpty`). */
|
|
4423
|
+
branchPropertyBag(lowerer, info, receiver, orEmpty, loc) {
|
|
4424
|
+
const helper = this.exactPropertyBag(lowerer, info, receiver, orEmpty, loc);
|
|
4425
|
+
if (helper)
|
|
4426
|
+
return { kind: "call", callee: helper.name, args: [receiver], type: DYN, loc };
|
|
4427
|
+
return orEmpty
|
|
4428
|
+
? this.readPropertyBagOrEmpty(lowerer, lowerer.coerceToExpected(receiver, DYN), loc)
|
|
4429
|
+
: this.readPropertyBag(lowerer, receiver, loc);
|
|
4430
|
+
}
|
|
4431
|
+
/** `%class.branchProperties[OrEmpty]:<class>(receiver)`: the read-only bag of
|
|
4432
|
+
* an instance of exactly `info`. A class branch of the dispatch helpers
|
|
4433
|
+
* selects a canonical receiver (normalizeDispatches gives an instance its
|
|
4434
|
+
* actual class's capsule), so its branch for `info` sees only instances
|
|
4435
|
+
* of `info`; instances of its subclasses take their own branches. Such a
|
|
4436
|
+
* receiver needs neither the dispatch over every class nor a boxed copy of
|
|
4437
|
+
* itself. Null
|
|
4438
|
+
* when `receiver` is not typed as `info`, when a runtime or builtin class
|
|
4439
|
+
* in the family keeps its own property contract, or before the class has
|
|
4440
|
+
* a bag. */
|
|
4441
|
+
exactPropertyBag(lowerer, info, receiver, orEmpty, loc) {
|
|
4442
|
+
const type = receiver.type;
|
|
4443
|
+
if (type.kind !== "object" || type.className !== info.def.name)
|
|
4444
|
+
return null;
|
|
4445
|
+
for (let current = info; current; current = current.base)
|
|
4446
|
+
if (current.def.runtime ||
|
|
4447
|
+
current.builtinEmitter ||
|
|
4448
|
+
current.builtinStream ||
|
|
4449
|
+
current.builtinError)
|
|
4450
|
+
return null;
|
|
4451
|
+
const key = `${type.className}:${orEmpty}`;
|
|
4452
|
+
const existing = this.exactPropertyBags.get(key);
|
|
4453
|
+
if (existing)
|
|
4454
|
+
return existing;
|
|
4455
|
+
const initializers = this.bagInitializers.get(type.className);
|
|
4456
|
+
if (!initializers)
|
|
4457
|
+
return null;
|
|
4458
|
+
const self = varRef("p.0", type, loc);
|
|
4459
|
+
const bag = {
|
|
4460
|
+
kind: "fieldGet",
|
|
4461
|
+
obj: self,
|
|
4462
|
+
className: type.className,
|
|
4463
|
+
field: PROPERTY_BAG,
|
|
4464
|
+
type: DYN,
|
|
4465
|
+
loc,
|
|
4466
|
+
};
|
|
4467
|
+
const initialize = {
|
|
4468
|
+
...initializers[0],
|
|
4469
|
+
obj: self,
|
|
4470
|
+
value: withTypedReceiver(initializers[0].value, self),
|
|
4471
|
+
loc,
|
|
4472
|
+
};
|
|
4473
|
+
const helper = {
|
|
4474
|
+
name: `%class.branchProperties${orEmpty ? "OrEmpty" : ""}:${type.className}`,
|
|
4475
|
+
params: [{ localId: "p.0", name: "value", type }],
|
|
4476
|
+
returnType: DYN,
|
|
4477
|
+
locals: [{ id: "p.0", name: "value", type, mutable: false }],
|
|
4478
|
+
loc,
|
|
4479
|
+
body: [
|
|
4480
|
+
{
|
|
4481
|
+
kind: "if",
|
|
4482
|
+
cond: { kind: "dynTest", test: "undefined", value: bag, type: BOOL, loc },
|
|
4483
|
+
then: [initialize],
|
|
4484
|
+
else_: null,
|
|
4485
|
+
loc,
|
|
4486
|
+
},
|
|
4487
|
+
{ kind: "return", value: bag, loc },
|
|
4488
|
+
],
|
|
4489
|
+
};
|
|
4490
|
+
// Initializers gain their prototype as subclasses become constructible;
|
|
4491
|
+
// finalize then turns the lazy store into the read's result.
|
|
4492
|
+
initializers.push(initialize);
|
|
4493
|
+
this.exactPropertyBags.set(key, helper);
|
|
4494
|
+
this.readPropertyBags.push({ helper, initialize, orEmpty });
|
|
4495
|
+
this.generated.add(helper);
|
|
4496
|
+
lowerer.liftedFns.push(helper);
|
|
4497
|
+
return helper;
|
|
4498
|
+
}
|
|
3755
4499
|
/** The prototype a new property bag of `current` (or of the subclass the
|
|
3756
4500
|
* receiver is) starts from, or null when `current` has no prototype data.
|
|
3757
4501
|
* A class with constructible subclasses that have prototype data selects
|
|
3758
4502
|
* it through its `%class.bagPrototype` helper; any other class reads its
|
|
3759
4503
|
* own prototype data. */
|
|
4504
|
+
/** The lazy bag stores as they stand in the generated bodies, by class.
|
|
4505
|
+
* Worklist passes that transform every function rebuild statement
|
|
4506
|
+
* objects, so a recorded initializer can be a detached copy; a store that
|
|
4507
|
+
* gains its prototype must be updated where it runs. */
|
|
4508
|
+
liveBagInitializers() {
|
|
4509
|
+
const live = new Map();
|
|
4510
|
+
const add = (stmt) => {
|
|
4511
|
+
if (stmt?.kind !== "if")
|
|
4512
|
+
return;
|
|
4513
|
+
const store = stmt.then[0];
|
|
4514
|
+
if (store?.kind !== "fieldSet" || store.field !== PROPERTY_BAG)
|
|
4515
|
+
return;
|
|
4516
|
+
const list = live.get(store.className);
|
|
4517
|
+
if (list)
|
|
4518
|
+
list.push(store);
|
|
4519
|
+
else
|
|
4520
|
+
live.set(store.className, [store]);
|
|
4521
|
+
};
|
|
4522
|
+
// The complete dispatch guards each class's lazy store by its receiver.
|
|
4523
|
+
for (const stmt of this.propertyBag?.body ?? [])
|
|
4524
|
+
if (stmt.kind === "if")
|
|
4525
|
+
add(stmt.then[0]);
|
|
4526
|
+
for (const helper of this.typedPropertyBags.values())
|
|
4527
|
+
add(helper.body[0]);
|
|
4528
|
+
for (const helper of this.exactPropertyBags.values())
|
|
4529
|
+
add(helper.body[0]);
|
|
4530
|
+
return live;
|
|
4531
|
+
}
|
|
3760
4532
|
bagPrototype(lowerer, current, receiver, loc) {
|
|
3761
4533
|
const arg = receiver.type.kind === "object" && receiver.type.className !== current.def.name
|
|
3762
4534
|
? {
|
|
@@ -3826,9 +4598,15 @@ export class ClassDynamicDispatch {
|
|
|
3826
4598
|
* prototype-backed bag is produced for this read only. A published object
|
|
3827
4599
|
* cannot take the store, and Node's reads never write. */
|
|
3828
4600
|
finalize(lowerer) {
|
|
3829
|
-
|
|
4601
|
+
// Each table serves every site that reaches it.
|
|
4602
|
+
if (lowerer)
|
|
4603
|
+
for (const fn of this.generated)
|
|
4604
|
+
lowerer.shareHelper(fn);
|
|
4605
|
+
if (lowerer)
|
|
4606
|
+
this.recordBagInitializers(lowerer);
|
|
4607
|
+
for (const { helper, initialize, orEmpty } of this.readPropertyBags) {
|
|
3830
4608
|
const absent = helper.body[0];
|
|
3831
|
-
if (isEmptyBag(initialize.value))
|
|
4609
|
+
if (isEmptyBag(initialize.value) && !orEmpty)
|
|
3832
4610
|
helper.body.shift();
|
|
3833
4611
|
else if (absent?.kind === "if")
|
|
3834
4612
|
absent.then = [{ kind: "return", value: initialize.value, loc: initialize.loc }];
|
|
@@ -3842,6 +4620,170 @@ export class ClassDynamicDispatch {
|
|
|
3842
4620
|
fn.locals = structuredClone(this.propertyBag.locals);
|
|
3843
4621
|
fn.body = readOnlyBagBody(structuredClone(this.propertyBag.body), fn.name === READ_PROPERTIES_OR_EMPTY);
|
|
3844
4622
|
}
|
|
4623
|
+
if (lowerer)
|
|
4624
|
+
this.guardClassTables(lowerer);
|
|
4625
|
+
if (lowerer)
|
|
4626
|
+
this.guardPropertyHelpers(lowerer);
|
|
4627
|
+
}
|
|
4628
|
+
/** Each tracked class's bag initializer over a typed receiver (`this`),
|
|
4629
|
+
* for the per-class field-creation helpers (trackClassFieldCreation),
|
|
4630
|
+
* which create an instance's bag without the class-table dispatch. */
|
|
4631
|
+
recordBagInitializers(lowerer) {
|
|
4632
|
+
for (const [className, initializers] of this.bagInitializers) {
|
|
4633
|
+
const init = initializers[0];
|
|
4634
|
+
if (!init || !lowerer.classes.get(className)?.def.tracksOwnFields)
|
|
4635
|
+
continue;
|
|
4636
|
+
const self = varRef("this", { kind: "object", className }, init.loc);
|
|
4637
|
+
const value = withTypedReceiver(structuredClone(init.value), self);
|
|
4638
|
+
if (mentionsLocal(value, "p.0"))
|
|
4639
|
+
continue;
|
|
4640
|
+
// The class-table branches can give the class's instances different
|
|
4641
|
+
// bags (a base class's own prototype for its instances, the
|
|
4642
|
+
// instance's class prototype for subclass instances); only a class
|
|
4643
|
+
// whose branches all agree has one initializer for every instance.
|
|
4644
|
+
const shape = withoutLocations(value);
|
|
4645
|
+
if (initializers.some((other) => withoutLocations(withTypedReceiver(structuredClone(other.value), self)) !== shape))
|
|
4646
|
+
continue;
|
|
4647
|
+
// Lowerer stand-ins in unit tests may not carry the table.
|
|
4648
|
+
lowerer.classBagInitializers?.set(className, value);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
/** Fast exits for the generated class tables: every class branch of
|
|
4652
|
+
* the property-bag, normalization and static-bag helpers tests the
|
|
4653
|
+
* value's capsule key (or class key), so a value of another kind (a
|
|
4654
|
+
* plain object, the common case in untyped code) skips straight to the
|
|
4655
|
+
* table's fallthrough instead of testing every class in the program. */
|
|
4656
|
+
guardClassTables(lowerer) {
|
|
4657
|
+
const names = new Set([
|
|
4658
|
+
"%dyn.class.properties",
|
|
4659
|
+
READ_PROPERTIES,
|
|
4660
|
+
READ_PROPERTIES_OR_EMPTY,
|
|
4661
|
+
"%dyn.class.normalize",
|
|
4662
|
+
"%dyn.class.staticProperties",
|
|
4663
|
+
]);
|
|
4664
|
+
for (const fn of lowerer.liftedFns) {
|
|
4665
|
+
if (!names.has(fn.name) || fn.body.length < 2)
|
|
4666
|
+
continue;
|
|
4667
|
+
const param = fn.params[0]?.localId;
|
|
4668
|
+
if (param === undefined)
|
|
4669
|
+
continue;
|
|
4670
|
+
const last = fn.body[fn.body.length - 1];
|
|
4671
|
+
if (last.kind !== "return" || last.value === null || !returnsParam(last.value, param))
|
|
4672
|
+
continue;
|
|
4673
|
+
let test = null;
|
|
4674
|
+
let ok = true;
|
|
4675
|
+
for (const stmt of fn.body.slice(0, -1)) {
|
|
4676
|
+
if (stmt.kind === "assign" &&
|
|
4677
|
+
stmt.localId === param &&
|
|
4678
|
+
stmt.value.kind === "call" &&
|
|
4679
|
+
stmt.value.callee === "%dyn.class.normalize")
|
|
4680
|
+
continue;
|
|
4681
|
+
const kind = stmt.kind === "if" && stmt.else_ === null ? branchKind(stmt.cond, param) : null;
|
|
4682
|
+
if (kind === null || (test !== null && kind !== test)) {
|
|
4683
|
+
ok = false;
|
|
4684
|
+
break;
|
|
4685
|
+
}
|
|
4686
|
+
test = kind;
|
|
4687
|
+
}
|
|
4688
|
+
if (!ok || test === null)
|
|
4689
|
+
continue;
|
|
4690
|
+
const first = fn.body[0];
|
|
4691
|
+
if (first.kind === "if" && first.cond.kind === "dynTest" && first.cond.test === test)
|
|
4692
|
+
continue;
|
|
4693
|
+
const loc = fn.loc;
|
|
4694
|
+
fn.body.unshift({
|
|
4695
|
+
kind: "if",
|
|
4696
|
+
cond: {
|
|
4697
|
+
kind: "dynTest",
|
|
4698
|
+
test,
|
|
4699
|
+
negated: true,
|
|
4700
|
+
value: varRef(param, DYN, loc),
|
|
4701
|
+
type: BOOL,
|
|
4702
|
+
loc,
|
|
4703
|
+
},
|
|
4704
|
+
then: [structuredClone(last)],
|
|
4705
|
+
else_: null,
|
|
4706
|
+
loc,
|
|
4707
|
+
});
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4710
|
+
/** Fast exits for the generated property helpers: when every class
|
|
4711
|
+
* branch tests a capsule key or a class key and the fallthrough is still
|
|
4712
|
+
* the bag access the helper was created with, a value of another kind
|
|
4713
|
+
* (a plain object, array or primitive) normalizes to itself, has itself
|
|
4714
|
+
* as its bag, and so gets the plain access directly, without the
|
|
4715
|
+
* normalization, bag and static-bag calls. */
|
|
4716
|
+
guardPropertyHelpers(lowerer) {
|
|
4717
|
+
// Every class table the fallthrough or normalization calls must answer
|
|
4718
|
+
// a plain value with the value itself: its kind exit is in place.
|
|
4719
|
+
const exits = (name) => {
|
|
4720
|
+
const helper = lowerer.liftedFnNamed(name);
|
|
4721
|
+
const first = helper?.body[0];
|
|
4722
|
+
const param = helper?.params[0]?.localId;
|
|
4723
|
+
return (param !== undefined &&
|
|
4724
|
+
first?.kind === "if" &&
|
|
4725
|
+
first.cond.kind === "dynTest" &&
|
|
4726
|
+
first.cond.negated === true &&
|
|
4727
|
+
first.then.length === 1 &&
|
|
4728
|
+
first.then[0].kind === "return" &&
|
|
4729
|
+
first.then[0].value !== null &&
|
|
4730
|
+
returnsParam(first.then[0].value, param));
|
|
4731
|
+
};
|
|
4732
|
+
const tables = new Set([
|
|
4733
|
+
"%dyn.class.properties",
|
|
4734
|
+
READ_PROPERTIES,
|
|
4735
|
+
READ_PROPERTIES_OR_EMPTY,
|
|
4736
|
+
"%dyn.class.normalize",
|
|
4737
|
+
"%dyn.class.staticProperties",
|
|
4738
|
+
]);
|
|
4739
|
+
const callsOnlyGuardedTables = (statements) => everyStmtList(statements, {
|
|
4740
|
+
stmt: () => true,
|
|
4741
|
+
expr: (expression) => expression.kind !== "call" || (tables.has(expression.callee) && exits(expression.callee)),
|
|
4742
|
+
});
|
|
4743
|
+
for (const dispatch of this.properties.values()) {
|
|
4744
|
+
const plain = dispatch.plain;
|
|
4745
|
+
if (!plain)
|
|
4746
|
+
continue;
|
|
4747
|
+
const fn = dispatch.fn;
|
|
4748
|
+
const param = fn.params[0]?.localId;
|
|
4749
|
+
if (param === undefined)
|
|
4750
|
+
continue;
|
|
4751
|
+
const head = fn.body.length - plain.tail.length;
|
|
4752
|
+
if (head < 0 || plain.tail.some((stmt, i) => fn.body[head + i] !== stmt))
|
|
4753
|
+
continue;
|
|
4754
|
+
let ok = true;
|
|
4755
|
+
for (const stmt of fn.body.slice(0, head)) {
|
|
4756
|
+
if (stmt.kind === "assign" &&
|
|
4757
|
+
stmt.localId === param &&
|
|
4758
|
+
stmt.value.kind === "call" &&
|
|
4759
|
+
stmt.value.callee === "%dyn.class.normalize")
|
|
4760
|
+
continue;
|
|
4761
|
+
if (stmt.kind === "if" && stmt.else_ === null && branchKind(stmt.cond, param) !== null)
|
|
4762
|
+
continue;
|
|
4763
|
+
ok = false;
|
|
4764
|
+
break;
|
|
4765
|
+
}
|
|
4766
|
+
// Class branches never run for a plain value; the rest always does.
|
|
4767
|
+
if (!ok || !callsOnlyGuardedTables(fn.body.filter((stmt) => stmt.kind !== "if")))
|
|
4768
|
+
continue;
|
|
4769
|
+
const loc = fn.loc;
|
|
4770
|
+
const not = (test) => ({
|
|
4771
|
+
kind: "dynTest",
|
|
4772
|
+
test,
|
|
4773
|
+
negated: true,
|
|
4774
|
+
value: varRef(param, DYN, loc),
|
|
4775
|
+
type: BOOL,
|
|
4776
|
+
loc,
|
|
4777
|
+
});
|
|
4778
|
+
fn.body.unshift({
|
|
4779
|
+
kind: "if",
|
|
4780
|
+
cond: not("classCapsule"),
|
|
4781
|
+
then: [{ kind: "if", cond: not("funcKind"), then: plain.access, else_: null, loc }],
|
|
4782
|
+
else_: null,
|
|
4783
|
+
loc,
|
|
4784
|
+
});
|
|
4785
|
+
delete dispatch.plain;
|
|
4786
|
+
}
|
|
3845
4787
|
}
|
|
3846
4788
|
normalizedDispatches() {
|
|
3847
4789
|
return [
|
|
@@ -3913,10 +4855,15 @@ export class ClassDynamicDispatch {
|
|
|
3913
4855
|
this.normalizationKey = key;
|
|
3914
4856
|
const loc = this.normalization.loc;
|
|
3915
4857
|
const value = varRef("value", DYN, loc);
|
|
3916
|
-
|
|
4858
|
+
// The checked receiver is unboxed once per capsule branch, not once
|
|
4859
|
+
// per subclass test.
|
|
4860
|
+
this.normalization.locals = this.normalization.locals.filter((local) => !local.id.startsWith("%normalized."));
|
|
4861
|
+
this.normalization.body = entries.map(({ capsule, children }, index) => {
|
|
3917
4862
|
const type = { kind: "object", className: capsule.def.name };
|
|
3918
|
-
const
|
|
3919
|
-
|
|
4863
|
+
const id = `%normalized.${index}`;
|
|
4864
|
+
this.normalization.locals.push({ id, name: id, type, mutable: false });
|
|
4865
|
+
const receiver = varRef(id, type, loc);
|
|
4866
|
+
const branch = {
|
|
3920
4867
|
kind: "if",
|
|
3921
4868
|
cond: {
|
|
3922
4869
|
kind: "libCall",
|
|
@@ -3957,6 +4904,15 @@ export class ClassDynamicDispatch {
|
|
|
3957
4904
|
else_: null,
|
|
3958
4905
|
loc,
|
|
3959
4906
|
};
|
|
4907
|
+
// The capsule test stays the branch condition; its body unboxes.
|
|
4908
|
+
if (branch.kind === "if")
|
|
4909
|
+
branch.then.unshift({
|
|
4910
|
+
kind: "varDecl",
|
|
4911
|
+
localId: id,
|
|
4912
|
+
init: { kind: "dynCheck", value, type, loc },
|
|
4913
|
+
loc,
|
|
4914
|
+
});
|
|
4915
|
+
return branch;
|
|
3960
4916
|
});
|
|
3961
4917
|
this.normalization.body.push({ kind: "return", value, loc });
|
|
3962
4918
|
}
|
|
@@ -3997,21 +4953,43 @@ export class ClassDynamicDispatch {
|
|
|
3997
4953
|
};
|
|
3998
4954
|
add(root);
|
|
3999
4955
|
}
|
|
4956
|
+
/** propertyReceivers results by mode, with the class graph they were
|
|
4957
|
+
* computed from: the boxed classes, the registered classes, the subclass
|
|
4958
|
+
* links and the constructed classes only grow, so equal counts and the
|
|
4959
|
+
* same capsules give the same plans. */
|
|
4960
|
+
receiverPlans = new Map();
|
|
4000
4961
|
/** A capsule retains its static type, while its object may be a subclass.
|
|
4001
4962
|
* Preorder insertion lets later branches test the most derived layout first. */
|
|
4002
4963
|
propertyReceivers(lowerer, streams = false, normalize = true) {
|
|
4964
|
+
const mode = `${streams}:${normalize}`;
|
|
4965
|
+
const revision = `${this.boxed.size}:${lowerer.classes.size}:${lowerer.subclassLinks}:${lowerer.constructedClassCount()}`;
|
|
4966
|
+
const cached = this.receiverPlans.get(mode);
|
|
4967
|
+
if (cached?.revision === revision) {
|
|
4968
|
+
let i = 0;
|
|
4969
|
+
let same = true;
|
|
4970
|
+
for (const name of this.boxed)
|
|
4971
|
+
if (lowerer.classes.get(name) !== cached.capsules[i++])
|
|
4972
|
+
same = false;
|
|
4973
|
+
if (same)
|
|
4974
|
+
return cached.plans;
|
|
4975
|
+
}
|
|
4976
|
+
const capsules = [];
|
|
4003
4977
|
const plans = [];
|
|
4004
4978
|
const seen = new Set();
|
|
4005
4979
|
for (const name of this.boxed) {
|
|
4006
4980
|
const capsule = lowerer.classes.get(name);
|
|
4981
|
+
capsules.push(capsule);
|
|
4007
4982
|
if (!capsule ||
|
|
4008
4983
|
((capsule.builtinEmitter || capsule.builtinStream) && !streams) ||
|
|
4009
4984
|
capsule.builtinError)
|
|
4010
4985
|
continue;
|
|
4011
4986
|
const canonical = normalize && !capsule.builtinStream && !capsule.builtinEmitter;
|
|
4012
4987
|
const visit = (info) => {
|
|
4013
|
-
|
|
4014
|
-
|
|
4988
|
+
// A seen class was visited with its whole subtree, and a canonical
|
|
4989
|
+
// visit adds no plan for a seen class.
|
|
4990
|
+
if (canonical && seen.has(info.def.name))
|
|
4991
|
+
return;
|
|
4992
|
+
if (info === capsule || lowerer.classCanBeConstructed(info)) {
|
|
4015
4993
|
seen.add(info.def.name);
|
|
4016
4994
|
plans.push({
|
|
4017
4995
|
info,
|
|
@@ -4024,6 +5002,7 @@ export class ClassDynamicDispatch {
|
|
|
4024
5002
|
};
|
|
4025
5003
|
visit(capsule);
|
|
4026
5004
|
}
|
|
5005
|
+
this.receiverPlans.set(mode, { revision, capsules, plans });
|
|
4027
5006
|
return plans;
|
|
4028
5007
|
}
|
|
4029
5008
|
propertyReceiver(plan, loc) {
|
|
@@ -4204,9 +5183,11 @@ export class ClassDynamicDispatch {
|
|
|
4204
5183
|
propertyBody(lowerer, dispatch, info, receiver) {
|
|
4205
5184
|
const { name, write } = dispatch;
|
|
4206
5185
|
const loc = dispatch.fn.loc;
|
|
4207
|
-
// The inherited EventTarget/Event members of a subclass instance
|
|
4208
|
-
//
|
|
4209
|
-
|
|
5186
|
+
// The inherited EventTarget/Event members of a subclass instance, and
|
|
5187
|
+
// the inherited Date methods of an instance of a class declared
|
|
5188
|
+
// `extends Date`: the runtime's capsule view answers the accessors and
|
|
5189
|
+
// method values.
|
|
5190
|
+
if (eventTargetInheritedMember(info, name) || dateInheritedMember(lowerer, info, name)) {
|
|
4210
5191
|
const key = { kind: "strLit", value: name, type: STRING, loc };
|
|
4211
5192
|
if (!write)
|
|
4212
5193
|
return [
|
|
@@ -4348,7 +5329,7 @@ export class ClassDynamicDispatch {
|
|
|
4348
5329
|
},
|
|
4349
5330
|
{
|
|
4350
5331
|
kind: "if",
|
|
4351
|
-
cond: this.readBagHas(lowerer, "dyn.hasKey", this.
|
|
5332
|
+
cond: this.readBagHas(lowerer, "dyn.hasKey", this.branchPropertyBag(lowerer, info, receiver, false, loc), key, loc),
|
|
4352
5333
|
then: [store],
|
|
4353
5334
|
else_: null,
|
|
4354
5335
|
loc,
|
|
@@ -4360,7 +5341,7 @@ export class ClassDynamicDispatch {
|
|
|
4360
5341
|
{ kind: "return", value: null, loc },
|
|
4361
5342
|
];
|
|
4362
5343
|
}
|
|
4363
|
-
const bag = this.
|
|
5344
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, false, loc);
|
|
4364
5345
|
return [
|
|
4365
5346
|
{
|
|
4366
5347
|
kind: "return",
|
|
@@ -4418,7 +5399,7 @@ export class ClassDynamicDispatch {
|
|
|
4418
5399
|
!info.classDecorators) {
|
|
4419
5400
|
this.constructors.set(info.def.name, info);
|
|
4420
5401
|
const cls = lowerer.coerceToExpected(classValueRef(lowerer, info, info.decl), DYN);
|
|
4421
|
-
const bag = this.
|
|
5402
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, false, loc);
|
|
4422
5403
|
const key = { kind: "strLit", value: name, type: STRING, loc };
|
|
4423
5404
|
return [
|
|
4424
5405
|
{
|
|
@@ -4489,7 +5470,7 @@ export class ClassDynamicDispatch {
|
|
|
4489
5470
|
if (symbol || (isClassOwnEnumerableFieldName(name) && !name.startsWith("sym:"))) {
|
|
4490
5471
|
const prototypeMethod = observedPrototypeMethod(lowerer, info, name, loc, receiver);
|
|
4491
5472
|
// Selecting the method must not give the object own storage.
|
|
4492
|
-
const bag = this.
|
|
5473
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, false, loc);
|
|
4493
5474
|
const key = symbol ?? { kind: "strLit", value: name, type: STRING, loc };
|
|
4494
5475
|
body.push({
|
|
4495
5476
|
kind: "if",
|
|
@@ -4550,7 +5531,7 @@ export class ClassDynamicDispatch {
|
|
|
4550
5531
|
}
|
|
4551
5532
|
if (!field && !accessor) {
|
|
4552
5533
|
const instance = lowerer.coerceToExpected(receiver, DYN);
|
|
4553
|
-
const bag = this.
|
|
5534
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
4554
5535
|
const key = { kind: "strLit", value: name, type: STRING, loc };
|
|
4555
5536
|
const own = {
|
|
4556
5537
|
kind: "libCall",
|
|
@@ -4598,7 +5579,7 @@ export class ClassDynamicDispatch {
|
|
|
4598
5579
|
if (boxed.kind === "dynFrom" && mutable(boxed.value.type))
|
|
4599
5580
|
boxed.liveRef = true;
|
|
4600
5581
|
if (accessor) {
|
|
4601
|
-
const bag = this.
|
|
5582
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
4602
5583
|
const key = { kind: "strLit", value: name, type: STRING, loc };
|
|
4603
5584
|
return [
|
|
4604
5585
|
{
|
|
@@ -4625,7 +5606,7 @@ export class ClassDynamicDispatch {
|
|
|
4625
5606
|
}
|
|
4626
5607
|
if (field && info.def.tracksOwnFields) {
|
|
4627
5608
|
const instance = lowerer.coerceToExpected(receiver, DYN);
|
|
4628
|
-
const bag = this.
|
|
5609
|
+
const bag = this.branchPropertyBag(lowerer, info, receiver, true, loc);
|
|
4629
5610
|
const symbol = symbolMemberKey(lowerer, info, name, loc);
|
|
4630
5611
|
const key = symbol ?? { kind: "strLit", value: name, type: STRING, loc };
|
|
4631
5612
|
return [
|
|
@@ -4730,6 +5711,50 @@ export class ClassDynamicDispatch {
|
|
|
4730
5711
|
};
|
|
4731
5712
|
return [store, { kind: "return", value: null, loc }];
|
|
4732
5713
|
}
|
|
5714
|
+
/** EventEmitter.prototype's introspection and bookkeeping members on an
|
|
5715
|
+
* emitter seen through an untyped value: Node's results over the native
|
|
5716
|
+
* listener registry. */
|
|
5717
|
+
emitterIntrospection(lowerer, dispatch, receiver) {
|
|
5718
|
+
const { method, loc } = dispatch.source;
|
|
5719
|
+
const incoming = dispatch.source.args.map((_, i) => varRef(`p.${i + 1}`, DYN, loc));
|
|
5720
|
+
const ret = (value) => [
|
|
5721
|
+
{ kind: "return", value: lowerer.coerceToExpected(value, DYN), loc },
|
|
5722
|
+
];
|
|
5723
|
+
const call = (fn, args, type) => ({
|
|
5724
|
+
kind: "libCall",
|
|
5725
|
+
fn,
|
|
5726
|
+
args: [receiver, ...args],
|
|
5727
|
+
type,
|
|
5728
|
+
loc,
|
|
5729
|
+
});
|
|
5730
|
+
// Node indexes _events with the argument itself: an omitted name is
|
|
5731
|
+
// the key "undefined".
|
|
5732
|
+
const eventName = () => incoming.length
|
|
5733
|
+
? lowerer.coerceToExpected(incoming[0], STRING)
|
|
5734
|
+
: { kind: "strLit", value: "undefined", type: STRING, loc };
|
|
5735
|
+
switch (method) {
|
|
5736
|
+
case "listenerCount":
|
|
5737
|
+
return ret(incoming.length >= 2
|
|
5738
|
+
? call("emitter.countDyn", [eventName(), incoming[1]], F64)
|
|
5739
|
+
: call("emitter.count", [eventName()], F64));
|
|
5740
|
+
case "eventNames":
|
|
5741
|
+
return ret(call("emitter.names", [], { kind: "array", elem: STRING }));
|
|
5742
|
+
case "removeAllListeners":
|
|
5743
|
+
return ret(incoming.length
|
|
5744
|
+
? call("emitter.removeAll", [eventName(), { kind: "boolLit", value: false, type: BOOL, loc }], receiver.type)
|
|
5745
|
+
: call("emitter.removeAll", [
|
|
5746
|
+
{ kind: "strLit", value: "", type: STRING, loc },
|
|
5747
|
+
{ kind: "boolLit", value: true, type: BOOL, loc },
|
|
5748
|
+
], receiver.type));
|
|
5749
|
+
case "listeners":
|
|
5750
|
+
case "rawListeners":
|
|
5751
|
+
return ret(call("emitter.listenersDyn", [eventName()], DYN));
|
|
5752
|
+
case "setMaxListeners":
|
|
5753
|
+
return ret(call("emitter.setMaxChk", [incoming[0] ?? dynUndefinedExpr(loc)], receiver.type));
|
|
5754
|
+
default:
|
|
5755
|
+
return ret(call("emitter.getMax", [], F64));
|
|
5756
|
+
}
|
|
5757
|
+
}
|
|
4733
5758
|
methodBody(lowerer, dispatch, info, receiver) {
|
|
4734
5759
|
const { method, loc } = dispatch.source;
|
|
4735
5760
|
const fence = () => [
|
|
@@ -4740,6 +5765,12 @@ export class ClassDynamicDispatch {
|
|
|
4740
5765
|
loc,
|
|
4741
5766
|
},
|
|
4742
5767
|
];
|
|
5768
|
+
if (emitterRooted(lowerer, info) &&
|
|
5769
|
+
!streamRooted(info) &&
|
|
5770
|
+
EMITTER_INTROSPECTION_METHODS.has(method) &&
|
|
5771
|
+
!findMethodOn(lowerer, info, method)) {
|
|
5772
|
+
return this.emitterIntrospection(lowerer, dispatch, receiver);
|
|
5773
|
+
}
|
|
4743
5774
|
if (info.builtinStream ||
|
|
4744
5775
|
(emitterRooted(lowerer, info) &&
|
|
4745
5776
|
EMITTER_METHODS.has(method) &&
|
|
@@ -4759,10 +5790,14 @@ export class ClassDynamicDispatch {
|
|
|
4759
5790
|
if (method === "emit") {
|
|
4760
5791
|
if (!incoming.length)
|
|
4761
5792
|
return fence();
|
|
4762
|
-
|
|
5793
|
+
const event = lowerer.coerceToExpected(incoming[0], STRING);
|
|
5794
|
+
const bridged = streamRooted(info)
|
|
5795
|
+
? null
|
|
5796
|
+
: lowerDynamicEmitterEmit(lowerer, receiver, event, incoming.slice(1), loc);
|
|
5797
|
+
return ret(bridged ?? {
|
|
4763
5798
|
kind: "libCall",
|
|
4764
|
-
fn: "emitter.
|
|
4765
|
-
args: [receiver,
|
|
5799
|
+
fn: "emitter.emitAny",
|
|
5800
|
+
args: [receiver, event, ...incoming.slice(1)],
|
|
4766
5801
|
type: BOOL,
|
|
4767
5802
|
loc,
|
|
4768
5803
|
});
|
|
@@ -4772,6 +5807,11 @@ export class ClassDynamicDispatch {
|
|
|
4772
5807
|
return fence();
|
|
4773
5808
|
const event = lowerer.coerceToExpected(incoming[0], STRING);
|
|
4774
5809
|
const cb = incoming[1];
|
|
5810
|
+
const bridged = registering && !streamRooted(info)
|
|
5811
|
+
? lowerDynamicEmitterOn(lowerer, receiver, event, cb, method === "once" || method === "prependOnceListener", method.startsWith("prepend"), loc)
|
|
5812
|
+
: null;
|
|
5813
|
+
if (bridged)
|
|
5814
|
+
return ret(bridged);
|
|
4775
5815
|
return [
|
|
4776
5816
|
{
|
|
4777
5817
|
kind: "exprStmt",
|
|
@@ -4783,7 +5823,7 @@ export class ClassDynamicDispatch {
|
|
|
4783
5823
|
fn: registering
|
|
4784
5824
|
? info.builtinStream
|
|
4785
5825
|
? "stream.onDyn"
|
|
4786
|
-
: "emitter.
|
|
5826
|
+
: "emitter.onAny"
|
|
4787
5827
|
: "emitter.offDyn",
|
|
4788
5828
|
args: [
|
|
4789
5829
|
receiver,
|
|
@@ -4837,13 +5877,16 @@ export class ClassDynamicDispatch {
|
|
|
4837
5877
|
const arg = (i) => incoming[i] ?? dynUndefinedExpr(loc);
|
|
4838
5878
|
const readableT = { kind: "object", className: "%Readable" };
|
|
4839
5879
|
const op = (fn, args, type) => ret({ kind: "libCall", fn: fn, args: [receiver, ...args], type, loc });
|
|
5880
|
+
// Node passes every callback its { signal }; the callback's
|
|
5881
|
+
// declared parameters are not known here.
|
|
5882
|
+
const sig = () => operatorSignalOptions(lowerer, arg(1), loc);
|
|
4840
5883
|
switch (method) {
|
|
4841
5884
|
case "map":
|
|
4842
|
-
return op("readable.opMap", [arg(0), arg(1)], readableT);
|
|
5885
|
+
return op("readable.opMap", [arg(0), arg(1), sig()], readableT);
|
|
4843
5886
|
case "filter":
|
|
4844
|
-
return op("readable.opFilter", [arg(0), arg(1)], readableT);
|
|
5887
|
+
return op("readable.opFilter", [arg(0), arg(1), sig()], readableT);
|
|
4845
5888
|
case "flatMap":
|
|
4846
|
-
return op("readable.opFlatMap", [arg(0), arg(1)], readableT);
|
|
5889
|
+
return op("readable.opFlatMap", [arg(0), arg(1), sig()], readableT);
|
|
4847
5890
|
case "drop":
|
|
4848
5891
|
return op("readable.opDrop", [arg(0), arg(1)], readableT);
|
|
4849
5892
|
case "take":
|
|
@@ -4851,21 +5894,45 @@ export class ClassDynamicDispatch {
|
|
|
4851
5894
|
case "toArray":
|
|
4852
5895
|
return op("readable.opToArray", [arg(0)], { kind: "promise", inner: DYN });
|
|
4853
5896
|
case "forEach":
|
|
4854
|
-
return op("readable.opForEach", [arg(0), arg(1)], {
|
|
5897
|
+
return op("readable.opForEach", [arg(0), arg(1), sig()], {
|
|
5898
|
+
kind: "promise",
|
|
5899
|
+
inner: VOID,
|
|
5900
|
+
});
|
|
4855
5901
|
case "some":
|
|
4856
|
-
return op("readable.opSome", [arg(0), arg(1)], { kind: "promise", inner: BOOL });
|
|
5902
|
+
return op("readable.opSome", [arg(0), arg(1), sig()], { kind: "promise", inner: BOOL });
|
|
4857
5903
|
case "every":
|
|
4858
|
-
return op("readable.opEvery", [arg(0), arg(1)], {
|
|
5904
|
+
return op("readable.opEvery", [arg(0), arg(1), sig()], {
|
|
5905
|
+
kind: "promise",
|
|
5906
|
+
inner: BOOL,
|
|
5907
|
+
});
|
|
4859
5908
|
case "find":
|
|
4860
|
-
return op("readable.opFind", [arg(0), arg(1)], { kind: "promise", inner: DYN });
|
|
4861
|
-
case "reduce":
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
5909
|
+
return op("readable.opFind", [arg(0), arg(1), sig()], { kind: "promise", inner: DYN });
|
|
5910
|
+
case "reduce": {
|
|
5911
|
+
// the dispatch function's locals: there is no function
|
|
5912
|
+
// context while dispatch bodies are built
|
|
5913
|
+
const setup = reduceSignalSetup(lowerer, arg(2), loc, (name, type) => {
|
|
5914
|
+
const local = {
|
|
5915
|
+
id: `${name}.${dispatch.fn.locals.length}`,
|
|
5916
|
+
name,
|
|
5917
|
+
type,
|
|
5918
|
+
mutable: false,
|
|
5919
|
+
};
|
|
5920
|
+
dispatch.fn.locals.push(local);
|
|
5921
|
+
return local;
|
|
5922
|
+
});
|
|
5923
|
+
return [
|
|
5924
|
+
...setup.stmts,
|
|
5925
|
+
...op("readable.opReduceSignal", [
|
|
5926
|
+
arg(0),
|
|
5927
|
+
arg(1),
|
|
5928
|
+
{ kind: "boolLit", value: dispatch.source.args.length >= 2, type: BOOL, loc },
|
|
5929
|
+
arg(2),
|
|
5930
|
+
{ kind: "numLit", value: 0, type: F64, loc },
|
|
5931
|
+
setup.abort,
|
|
5932
|
+
setup.cbOpts,
|
|
5933
|
+
], { kind: "promise", inner: DYN }),
|
|
5934
|
+
];
|
|
5935
|
+
}
|
|
4869
5936
|
}
|
|
4870
5937
|
}
|
|
4871
5938
|
if (method === "destroy" && (!incoming.length || incoming[0]?.kind === "unitLit"))
|
|
@@ -5113,4 +6180,12 @@ const INHERITED_OBJECT_METHODS = new Set([
|
|
|
5113
6180
|
"hasOwnProperty",
|
|
5114
6181
|
"propertyIsEnumerable",
|
|
5115
6182
|
]);
|
|
6183
|
+
/** Whether a class or one of its bases has a heritage evaluated at run
|
|
6184
|
+
* time, whose prototype chain may reach Error.prototype. */
|
|
6185
|
+
function hasRuntimeHeritage(info) {
|
|
6186
|
+
for (let current = info; current; current = current.base)
|
|
6187
|
+
if (current.callableBase)
|
|
6188
|
+
return true;
|
|
6189
|
+
return false;
|
|
6190
|
+
}
|
|
5116
6191
|
//# sourceMappingURL=class-dynamic-dispatch.js.map
|