@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,5 +1,6 @@
|
|
|
1
|
+
import { keyedHelperName } from "./stable-names.js";
|
|
1
2
|
import { nodeThrowExpr, boolLit, numLit, strLit } from "../../ir/build.js";
|
|
2
|
-
import {
|
|
3
|
+
import { isValueStream, valueStreamOf } from "./builtins/hash-stream.js";
|
|
3
4
|
import { InternalCompilerError } from "../../errors.js";
|
|
4
5
|
/* The node:stream lowering (the spoke-module pattern, like
|
|
5
6
|
* lower-event-emitter.ts): construction of the five runtime stream classes
|
|
@@ -43,8 +44,12 @@ import { dynUndefinedExpr, varRef } from "../../ir/build.js";
|
|
|
43
44
|
import { genResultRecord } from "../type-mapper.js";
|
|
44
45
|
import { noteUntypedStreamFlow, requestGeneralStreamSurface } from "./general-streams.js";
|
|
45
46
|
import { dynNativeBranch } from "./dyn-streams.js";
|
|
47
|
+
import { bindingNeverReassigned } from "./binding-analysis.js";
|
|
46
48
|
import { extractIteratorValue, genStep, genValue, stepDrivable } from "./lower-generators.js";
|
|
47
|
-
import {
|
|
49
|
+
import { LiftedFrame, driveGenerator } from "./containers/iterator-helpers.js";
|
|
50
|
+
import { lowerArrayIteratorValue, lowerStringIteratorValue } from "./iterator-adapters.js";
|
|
51
|
+
import { staticReadableStreamElementType } from "./lower-stdlib.js";
|
|
52
|
+
import { BOOL, DYN, F64, RUNTIME_STREAM_CLASSES, STRING, VOID, arrayOf, BYTES_U8, canBoxFuncIntoDyn, canConvertToDyn, funcOf, typeEquals, typeKey, UNDEFINED_T, } from "../../ir/ir.js";
|
|
48
53
|
const BYTES = BYTES_U8;
|
|
49
54
|
/** An expression that only reads bindings and properties (no calls,
|
|
50
55
|
* assignments or construction): reading it a step later observes the
|
|
@@ -66,6 +71,55 @@ function pureRead(node) {
|
|
|
66
71
|
}
|
|
67
72
|
return false;
|
|
68
73
|
}
|
|
74
|
+
/** A literal, `undefined`, or a function expression: a value that reads
|
|
75
|
+
* no binding or property. */
|
|
76
|
+
function constantOptionValue(node) {
|
|
77
|
+
let e = node;
|
|
78
|
+
while (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isTypeAssertion(e))
|
|
79
|
+
e = e.expression;
|
|
80
|
+
if (ts.isIdentifier(e))
|
|
81
|
+
return e.text === "undefined";
|
|
82
|
+
if (ts.isPrefixUnaryExpression(e) &&
|
|
83
|
+
(e.operator === ts.SyntaxKind.MinusToken ||
|
|
84
|
+
e.operator === ts.SyntaxKind.PlusToken ||
|
|
85
|
+
e.operator === ts.SyntaxKind.ExclamationToken))
|
|
86
|
+
return constantOptionValue(e.operand);
|
|
87
|
+
return (ts.isStringLiteralLike(e) ||
|
|
88
|
+
ts.isNumericLiteral(e) ||
|
|
89
|
+
ts.isBigIntLiteral(e) ||
|
|
90
|
+
e.kind === ts.SyntaxKind.TrueKeyword ||
|
|
91
|
+
e.kind === ts.SyntaxKind.FalseKeyword ||
|
|
92
|
+
e.kind === ts.SyntaxKind.NullKeyword ||
|
|
93
|
+
ts.isArrowFunction(e) ||
|
|
94
|
+
ts.isFunctionExpression(e));
|
|
95
|
+
}
|
|
96
|
+
/** Whether a runtime decodeStrings or defaultEncoding value (`prop`'s
|
|
97
|
+
* `value`) may be read before the other option members. Those values are
|
|
98
|
+
* read into locals before the constructor evaluates the other members,
|
|
99
|
+
* while Node evaluates the members in order, so every earlier member must
|
|
100
|
+
* evaluate without effects, and when the value itself has effects, every
|
|
101
|
+
* earlier member must also read nothing those effects could change. */
|
|
102
|
+
function earlierOptionsPure(options, prop, value) {
|
|
103
|
+
const valueHasEffects = !sideEffectFreeOptionValue(value) && !pureRead(value);
|
|
104
|
+
for (const member of options.properties.nodes) {
|
|
105
|
+
if (member === prop)
|
|
106
|
+
return true;
|
|
107
|
+
if (ts.isPropertyAssignment(member)) {
|
|
108
|
+
const init = member.initializer;
|
|
109
|
+
if (valueHasEffects
|
|
110
|
+
? !constantOptionValue(init)
|
|
111
|
+
: !sideEffectFreeOptionValue(init) && !pureRead(init))
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
else if (ts.isShorthandPropertyAssignment(member)) {
|
|
115
|
+
if (valueHasEffects)
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
else if (ts.isSpreadAssignment(member))
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
69
123
|
/** The stream sides of a receiver class: the nearest stream-class
|
|
70
124
|
* ancestor's, or null off the stream hierarchy. */
|
|
71
125
|
export function streamSidesOf(lowerer, info) {
|
|
@@ -131,10 +185,23 @@ export const UNDERSCORE_METHODS = new Map([
|
|
|
131
185
|
["transform", "_transform"],
|
|
132
186
|
["flush", "_flush"],
|
|
133
187
|
]);
|
|
188
|
+
/** The option callbacks applied after construction rather than through
|
|
189
|
+
* the constructor's callback slots (option name → method name): construct
|
|
190
|
+
* on every stream class, and writev on every class with a writable side
|
|
191
|
+
* (a Transform's batches reach writev, not the transform, as in Node). */
|
|
192
|
+
export const STREAM_EXTRA_CALLBACKS = new Map([
|
|
193
|
+
["construct", "_construct"],
|
|
194
|
+
["writev", "_writev"],
|
|
195
|
+
]);
|
|
196
|
+
export function streamExtraCallbacks(cls) {
|
|
197
|
+
return cls === "%Readable" ? ["construct"] : ["construct", "writev"];
|
|
198
|
+
}
|
|
134
199
|
/** The completion callback's parameter position in each underscore
|
|
135
200
|
* method that takes one (cbTuples' "fn" positions). */
|
|
136
201
|
export const STREAM_COMPLETION_CALLBACK_INDEX = new Map([
|
|
137
202
|
["_write", 2],
|
|
203
|
+
["_writev", 1],
|
|
204
|
+
["_construct", 0],
|
|
138
205
|
["_final", 0],
|
|
139
206
|
["_destroy", 1],
|
|
140
207
|
["_transform", 2],
|
|
@@ -229,7 +296,7 @@ export function streamForcedTuple(lowerer, info, name) {
|
|
|
229
296
|
* (Node calls them stream-bound); arrows keep lexical `this` (the hidden
|
|
230
297
|
* leading param is ABI-only). The declared parameters must be a
|
|
231
298
|
* typeEquals PREFIX of the callback's Node signature. */
|
|
232
|
-
function lowerStreamCallback(lowerer, which, node, thisType, fullTuple) {
|
|
299
|
+
function lowerStreamCallback(lowerer, which, node, thisType, fullTuple, chunkValues = true) {
|
|
233
300
|
const loc = locOf(node);
|
|
234
301
|
const { shapes, funcType } = lowerer.lambdaSignature(node);
|
|
235
302
|
if (node.modifiers?.nodes.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) {
|
|
@@ -245,11 +312,26 @@ function lowerStreamCallback(lowerer, which, node, thisType, fullTuple) {
|
|
|
245
312
|
// callable dyn whose glue dispatches to the runtime's *_done).
|
|
246
313
|
if (funcType.params[i].kind === "dyn")
|
|
247
314
|
continue;
|
|
315
|
+
// A write or transform chunk of another type converts from the
|
|
316
|
+
// chunk's value when the callback runs (an object-mode side's value),
|
|
317
|
+
// or throws a TypeError there — on a side known to be byte mode the
|
|
318
|
+
// chunk is a Buffer, so the declared type must be Node's or a
|
|
319
|
+
// supertype of it (`Buffer | string`); an encoding of another type
|
|
320
|
+
// (`string | null | undefined`) converts from the encoding argument's
|
|
321
|
+
// value.
|
|
322
|
+
if (((((i === 0 &&
|
|
323
|
+
(chunkValues || widensInto(lowerer, fullTuple[0], funcType.params[0], loc))) ||
|
|
324
|
+
i === 1) &&
|
|
325
|
+
(which === "write" || which === "transform")) ||
|
|
326
|
+
(i === 0 && which === "writev")) &&
|
|
327
|
+
funcType.params[i].kind !== "func" &&
|
|
328
|
+
canConvertToDyn(funcType.params[i], (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
329
|
+
continue;
|
|
248
330
|
if (!typeEquals(funcType.params[i], fullTuple[i])) {
|
|
249
331
|
lowerer.noLowering(`a '${which}' callback whose parameter ${i} is '${lowerer.fmt(funcType.params[i])}' where Node passes '${lowerer.fmt(fullTuple[i])}'`, node, "annotate the parameter with the Node signature's type (chunks are Buffers here)");
|
|
250
332
|
}
|
|
251
333
|
}
|
|
252
|
-
const fnName =
|
|
334
|
+
const fnName = lowerer.closureName(loc, `_${which}cb`);
|
|
253
335
|
const fnCtx = newFnCtx(true, null, funcType, funcType.ret);
|
|
254
336
|
lowerer.fnStack.push(fnCtx);
|
|
255
337
|
try {
|
|
@@ -311,6 +393,58 @@ function lowerStreamCallback(lowerer, which, node, thisType, fullTuple) {
|
|
|
311
393
|
lowerer.fnStack.pop();
|
|
312
394
|
}
|
|
313
395
|
}
|
|
396
|
+
/** The objectMode, readableObjectMode and writableObjectMode members of a
|
|
397
|
+
* stream options literal (boolean literals; the sided keys count only on
|
|
398
|
+
* a Duplex, Transform or PassThrough, as in Node). */
|
|
399
|
+
function streamObjectModes(lowerer, ctorName, optsLit) {
|
|
400
|
+
const out = { readable: false, writable: false };
|
|
401
|
+
const duplexish = ctorName !== "Readable" && ctorName !== "Writable";
|
|
402
|
+
for (const prop of optsLit?.properties?.nodes ?? []) {
|
|
403
|
+
if (!ts.isPropertyAssignment(prop))
|
|
404
|
+
continue;
|
|
405
|
+
const name = ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
406
|
+
if (name !== "objectMode" && name !== "readableObjectMode" && name !== "writableObjectMode")
|
|
407
|
+
continue;
|
|
408
|
+
const value = prop.initializer;
|
|
409
|
+
if (value.kind === ts.SyntaxKind.FalseKeyword)
|
|
410
|
+
continue;
|
|
411
|
+
if (value.kind !== ts.SyntaxKind.TrueKeyword) {
|
|
412
|
+
lowerer.noLowering(`${ctorName} with a runtime '${name}' value`, prop, `write '${name}: true' or '${name}: false'`);
|
|
413
|
+
}
|
|
414
|
+
if (name === "objectMode") {
|
|
415
|
+
out.readable = true;
|
|
416
|
+
out.writable = true;
|
|
417
|
+
}
|
|
418
|
+
else if (duplexish) {
|
|
419
|
+
if (name === "readableObjectMode")
|
|
420
|
+
out.readable = true;
|
|
421
|
+
else
|
|
422
|
+
out.writable = true;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return out;
|
|
426
|
+
}
|
|
427
|
+
/** Whether an options literal makes the writable side hold values: its
|
|
428
|
+
* object mode set with a `true` literal (objectMode, or writableObjectMode
|
|
429
|
+
* on a duplex stream), or decodeStrings: false (strings stay strings).
|
|
430
|
+
* Reports nothing: the options parse fences the other value forms. */
|
|
431
|
+
function literalWritesValues(opts, duplexish) {
|
|
432
|
+
for (const prop of opts.properties?.nodes ?? []) {
|
|
433
|
+
if (!ts.isPropertyAssignment(prop))
|
|
434
|
+
continue;
|
|
435
|
+
const name = ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name) ? prop.name.text : null;
|
|
436
|
+
if (name === "decodeStrings") {
|
|
437
|
+
if (prop.initializer.kind !== ts.SyntaxKind.TrueKeyword)
|
|
438
|
+
return true;
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (name !== "objectMode" && !(duplexish && name === "writableObjectMode"))
|
|
442
|
+
continue;
|
|
443
|
+
if (prop.initializer.kind !== ts.SyntaxKind.FalseKeyword)
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
314
448
|
/** The full Node parameter tuples of the option callbacks, given the
|
|
315
449
|
* concrete stream's `this` type. The trailing completion callbacks keep
|
|
316
450
|
* whatever func type the checker contextually gave the user's parameter
|
|
@@ -321,6 +455,8 @@ function cbTuples(lowerer) {
|
|
|
321
455
|
read: [F64],
|
|
322
456
|
write: [BYTES, STRING, "fn"],
|
|
323
457
|
final: ["fn"],
|
|
458
|
+
construct: ["fn"],
|
|
459
|
+
writev: [DYN, "fn"],
|
|
324
460
|
destroy: [errorOrNull(lowerer), "fn"],
|
|
325
461
|
transform: [BYTES, STRING, "fn"],
|
|
326
462
|
flush: ["fn"],
|
|
@@ -514,10 +650,57 @@ function pinAnyDataCompletion(lowerer, which, fnNode) {
|
|
|
514
650
|
const declared = lowerer.paramShape(param).type;
|
|
515
651
|
if (declared.kind !== "func" || declared.rest || declared.params[1]?.kind !== "dyn")
|
|
516
652
|
return null;
|
|
653
|
+
// Only when every use calls the callback with a Buffer, a string or
|
|
654
|
+
// nothing as `data`: another value (or a callback that escapes) keeps
|
|
655
|
+
// `data` checked-dynamic, so the runtime pushes it as push(data) does
|
|
656
|
+
// and reports ERR_INVALID_ARG_TYPE through 'error', as Node does.
|
|
657
|
+
if (fnNode.body === undefined || !completionDataIsChunk(lowerer, fnNode.body, symbol, param.name))
|
|
658
|
+
return null;
|
|
517
659
|
const data = unionOf(lowerer, [BYTES, STRING, { kind: "undefinedT" }]);
|
|
518
660
|
lowerer.stageSourceTypes.set(symbol, funcOf([declared.params[0], data, ...declared.params.slice(2)], declared.ret));
|
|
519
661
|
return symbol;
|
|
520
662
|
}
|
|
663
|
+
/** Whether every reference to the completion callback `symbol` in `body`
|
|
664
|
+
* calls it with a `data` argument that is a Buffer, a string, null or
|
|
665
|
+
* undefined (or with no data). */
|
|
666
|
+
function completionDataIsChunk(lowerer, body, symbol, declaration) {
|
|
667
|
+
let ok = true;
|
|
668
|
+
const visit = (node) => {
|
|
669
|
+
if (!ok)
|
|
670
|
+
return;
|
|
671
|
+
if (ts.isIdentifier(node) &&
|
|
672
|
+
node !== declaration &&
|
|
673
|
+
lowerer.checker.getSymbolAtLocation(node) === symbol) {
|
|
674
|
+
const call = node.parent;
|
|
675
|
+
if (!call || !ts.isCallExpression(call) || call.expression !== node) {
|
|
676
|
+
ok = false;
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const data = call.arguments.nodes[1];
|
|
680
|
+
if (data !== undefined) {
|
|
681
|
+
let t;
|
|
682
|
+
try {
|
|
683
|
+
t = lowerer.mapTypeOf(lowerer.typeOf(data));
|
|
684
|
+
}
|
|
685
|
+
catch {
|
|
686
|
+
t = null;
|
|
687
|
+
}
|
|
688
|
+
const arms = t?.kind === "union" ? (lowerer.unions.get(t.unionId)?.arms ?? null) : t ? [t] : null;
|
|
689
|
+
if (arms === null ||
|
|
690
|
+
!arms.every((a) => (a.kind === "bytes" && a.elem === "u8") ||
|
|
691
|
+
a.kind === "string" ||
|
|
692
|
+
a.kind === "undefinedT" ||
|
|
693
|
+
a.kind === "nullT")) {
|
|
694
|
+
ok = false;
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
ts.forEachChild(node, visit);
|
|
700
|
+
};
|
|
701
|
+
visit(body);
|
|
702
|
+
return ok;
|
|
703
|
+
}
|
|
521
704
|
/** Parses the options object literal of a stream constructor. `which`
|
|
522
705
|
* names the callbacks this class accepts, in canonical flag order. */
|
|
523
706
|
function parseStreamOptions(lowerer, ctorName, arg, thisType, accepted, loc,
|
|
@@ -538,14 +721,50 @@ fallbackCb) {
|
|
|
538
721
|
badEncoding: null,
|
|
539
722
|
pushEncoding: null,
|
|
540
723
|
signal: null,
|
|
724
|
+
valueDecls: [],
|
|
725
|
+
decodeStringsValue: null,
|
|
726
|
+
defaultEncodingValue: null,
|
|
727
|
+
readableObject: false,
|
|
728
|
+
writableObject: false,
|
|
729
|
+
decodeStringsOff: false,
|
|
730
|
+
writeEncoding: null,
|
|
731
|
+
extras: [],
|
|
541
732
|
flags: 0,
|
|
542
733
|
cbs: [],
|
|
543
734
|
};
|
|
735
|
+
const extraNames = streamExtraCallbacks(`%${ctorName}`);
|
|
736
|
+
const writableClass = ctorName !== "Readable";
|
|
544
737
|
const followed = followOptionsArg(lowerer, arg);
|
|
545
738
|
const optsLit = followed === null ? undefined : followed;
|
|
546
739
|
if (optsLit !== undefined && !ts.isObjectLiteralExpression(optsLit)) {
|
|
547
740
|
lowerer.noLowering(`new ${ctorName} with a non-literal options argument`, optsLit, "the options must be an object literal, inline or through const-initialized bindings (the callbacks lower as compile-time closures)");
|
|
548
741
|
}
|
|
742
|
+
// Read before the callbacks lower: an object-mode readable side keeps a
|
|
743
|
+
// completion callback's `data: any` (its values are not only strings and
|
|
744
|
+
// Buffers). An object-mode side's high-water mark defaults to 16.
|
|
745
|
+
const objectModes = streamObjectModes(lowerer, ctorName, optsLit !== undefined && ts.isObjectLiteralExpression(optsLit) ? optsLit : undefined);
|
|
746
|
+
out.readableObject = objectModes.readable;
|
|
747
|
+
out.writableObject = objectModes.writable;
|
|
748
|
+
// the chunk an option callback receives can be another value than a
|
|
749
|
+
// Buffer (literalWritesValues), read before any callback lowers
|
|
750
|
+
const writesValues = optsLit !== undefined &&
|
|
751
|
+
ts.isObjectLiteralExpression(optsLit) &&
|
|
752
|
+
literalWritesValues(optsLit, ctorName !== "Readable" && ctorName !== "Writable");
|
|
753
|
+
// In JavaScript a decodeStrings value known only at run time may let
|
|
754
|
+
// string writes through, so the write and transform callbacks' chunk
|
|
755
|
+
// parameters read as any (the declarations type it Buffer).
|
|
756
|
+
const runtimeDecodeStrings = optsLit !== undefined &&
|
|
757
|
+
isJsSourceFile(ts.getSourceFileOfNode(optsLit)) &&
|
|
758
|
+
ts.isObjectLiteralExpression(optsLit) &&
|
|
759
|
+
(optsLit.properties?.nodes ?? []).some((p) => ts.isPropertyAssignment(p) &&
|
|
760
|
+
(ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) &&
|
|
761
|
+
p.name.text === "decodeStrings" &&
|
|
762
|
+
p.initializer.kind !== ts.SyntaxKind.TrueKeyword &&
|
|
763
|
+
p.initializer.kind !== ts.SyntaxKind.FalseKeyword);
|
|
764
|
+
if (out.readableObject)
|
|
765
|
+
out.hwmR = numLit(16, loc);
|
|
766
|
+
if (out.writableObject)
|
|
767
|
+
out.hwmW = numLit(16, loc);
|
|
549
768
|
const tuples = cbTuples(lowerer);
|
|
550
769
|
const present = new Map();
|
|
551
770
|
for (const prop of optsLit?.properties?.nodes ?? []) {
|
|
@@ -559,7 +778,7 @@ fallbackCb) {
|
|
|
559
778
|
lowerer.unsupported("SC1090", prop, `computed or spread members in ${ctorName} options`);
|
|
560
779
|
}
|
|
561
780
|
// Callback members: shorthand methods and function-valued properties.
|
|
562
|
-
if (accepted.includes(name)) {
|
|
781
|
+
if (accepted.includes(name) || extraNames.includes(name)) {
|
|
563
782
|
let fnNode = null;
|
|
564
783
|
if (ts.isMethodDeclaration(prop))
|
|
565
784
|
fnNode = prop;
|
|
@@ -583,7 +802,8 @@ fallbackCb) {
|
|
|
583
802
|
continue;
|
|
584
803
|
}
|
|
585
804
|
const full = tuples[name].map((t) => (t === "fn" ? null : t));
|
|
586
|
-
const pinned = pinAnyDataCompletion(lowerer, name, fnNode);
|
|
805
|
+
const pinned = out.readableObject ? null : pinAnyDataCompletion(lowerer, name, fnNode);
|
|
806
|
+
let anyChunk;
|
|
587
807
|
try {
|
|
588
808
|
// The completion-callback tail: typed by the checker contextually;
|
|
589
809
|
// accept the user's declared func type as the tuple's entry so the
|
|
@@ -598,11 +818,22 @@ fallbackCb) {
|
|
|
598
818
|
}
|
|
599
819
|
return declared ?? funcOf([], VOID);
|
|
600
820
|
});
|
|
601
|
-
|
|
821
|
+
const chunkParam = runtimeDecodeStrings && (name === "write" || name === "transform")
|
|
822
|
+
? fnNode.parameters.nodes[0]
|
|
823
|
+
: undefined;
|
|
824
|
+
anyChunk =
|
|
825
|
+
chunkParam !== undefined && ts.isIdentifier(chunkParam.name) && !chunkParam.type
|
|
826
|
+
? lowerer.checker.getSymbolAtLocation(chunkParam.name)
|
|
827
|
+
: undefined;
|
|
828
|
+
if (anyChunk)
|
|
829
|
+
lowerer.anySymbols.add(anyChunk);
|
|
830
|
+
present.set(name, lowerStreamCallback(lowerer, name, fnNode, thisType, tuple, writesValues));
|
|
602
831
|
}
|
|
603
832
|
finally {
|
|
604
833
|
if (pinned)
|
|
605
834
|
lowerer.stageSourceTypes.delete(pinned);
|
|
835
|
+
if (anyChunk)
|
|
836
|
+
lowerer.anySymbols.delete(anyChunk);
|
|
606
837
|
}
|
|
607
838
|
continue;
|
|
608
839
|
}
|
|
@@ -641,17 +872,33 @@ fallbackCb) {
|
|
|
641
872
|
break;
|
|
642
873
|
case "objectMode":
|
|
643
874
|
case "readableObjectMode":
|
|
644
|
-
case "writableObjectMode":
|
|
645
|
-
//
|
|
646
|
-
if (value.kind === ts.SyntaxKind.FalseKeyword)
|
|
647
|
-
break;
|
|
648
|
-
lowerer.noLowering(`${ctorName} in objectMode`, prop, "object-mode streams have no static chunk type yet — chunks are Buffers (utf8 strings convert at push/write)");
|
|
875
|
+
case "writableObjectMode":
|
|
876
|
+
// read up front (streamObjectModes)
|
|
649
877
|
break;
|
|
650
|
-
}
|
|
651
878
|
case "decodeStrings": {
|
|
879
|
+
// WritableState's `options.decodeStrings === false`; a Readable
|
|
880
|
+
// ignores the option
|
|
652
881
|
if (value.kind === ts.SyntaxKind.TrueKeyword)
|
|
653
882
|
break; // Node's default
|
|
654
|
-
|
|
883
|
+
if (value.kind === ts.SyntaxKind.FalseKeyword) {
|
|
884
|
+
if (writableClass)
|
|
885
|
+
out.decodeStringsOff = true;
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
// a runtime value: WritableState's `options.decodeStrings !== false`
|
|
889
|
+
if (optsLit !== undefined &&
|
|
890
|
+
ts.isObjectLiteralExpression(optsLit) &&
|
|
891
|
+
!earlierOptionsPure(optsLit, prop, value))
|
|
892
|
+
lowerer.noLowering(`the ${ctorName} option 'decodeStrings' with a runtime value that an earlier option value could observe or change`, prop, "compute the option values into consts before the options object (the runtime value is read before the other options run)");
|
|
893
|
+
const local = lowerer.declareHiddenLocal("%decodeStrings", DYN);
|
|
894
|
+
out.valueDecls.push({
|
|
895
|
+
kind: "varDecl",
|
|
896
|
+
localId: local.id,
|
|
897
|
+
init: lowerer.lowerExprExpecting(value, DYN),
|
|
898
|
+
loc,
|
|
899
|
+
});
|
|
900
|
+
if (writableClass)
|
|
901
|
+
out.decodeStringsValue = varRef(local.id, DYN, loc);
|
|
655
902
|
break;
|
|
656
903
|
}
|
|
657
904
|
case "encoding": {
|
|
@@ -687,12 +934,45 @@ fallbackCb) {
|
|
|
687
934
|
out.badEncoding = t.value;
|
|
688
935
|
break;
|
|
689
936
|
}
|
|
690
|
-
if (t.isStringLiteralType()
|
|
691
|
-
|
|
937
|
+
if (t.isStringLiteralType()) {
|
|
938
|
+
// the readable side decodes push(string) with it, and the
|
|
939
|
+
// writable side encodes write(string) with it (the name as
|
|
940
|
+
// written reaches _write when decodeStrings is false)
|
|
941
|
+
if (ctorName !== "Writable" && !out.readableObject)
|
|
942
|
+
out.pushEncoding = knownBufEncoding(t.value);
|
|
943
|
+
if (writableClass)
|
|
944
|
+
out.writeEncoding = t.value;
|
|
692
945
|
break;
|
|
693
946
|
}
|
|
694
947
|
}
|
|
695
|
-
|
|
948
|
+
{
|
|
949
|
+
// a runtime value: null, undefined and utf8 are the default,
|
|
950
|
+
// another name Buffer.isEncoding knows is kept as given, and any
|
|
951
|
+
// other value throws ERR_UNKNOWN_ENCODING before construction
|
|
952
|
+
if (optsLit !== undefined &&
|
|
953
|
+
ts.isObjectLiteralExpression(optsLit) &&
|
|
954
|
+
!earlierOptionsPure(optsLit, prop, value))
|
|
955
|
+
lowerer.noLowering(`the ${ctorName} option 'defaultEncoding' with a runtime value that an earlier option value could observe or change`, prop, "compute the option values into consts before the options object (the runtime value is read before the other options run)");
|
|
956
|
+
const local = lowerer.declareHiddenLocal("%defaultEncoding", DYN);
|
|
957
|
+
const ref = varRef(local.id, DYN, loc);
|
|
958
|
+
out.valueDecls.push({
|
|
959
|
+
kind: "varDecl",
|
|
960
|
+
localId: local.id,
|
|
961
|
+
init: lowerer.lowerExprExpecting(value, DYN),
|
|
962
|
+
loc,
|
|
963
|
+
}, {
|
|
964
|
+
kind: "exprStmt",
|
|
965
|
+
expr: {
|
|
966
|
+
kind: "libCall",
|
|
967
|
+
fn: "stream.checkEncodingOption",
|
|
968
|
+
args: [ref],
|
|
969
|
+
type: VOID,
|
|
970
|
+
loc,
|
|
971
|
+
},
|
|
972
|
+
loc,
|
|
973
|
+
});
|
|
974
|
+
out.defaultEncodingValue = ref;
|
|
975
|
+
}
|
|
696
976
|
break;
|
|
697
977
|
case "signal": {
|
|
698
978
|
// `if (options.signal) addAbortSignal(options.signal, this)`:
|
|
@@ -742,11 +1022,8 @@ fallbackCb) {
|
|
|
742
1022
|
: "the final callback is supported on Writable and Duplex");
|
|
743
1023
|
break;
|
|
744
1024
|
}
|
|
745
|
-
case "construct":
|
|
746
|
-
lowerer.noLowering(`the ${ctorName} option 'construct'`, prop, "deferred construction (_construct) is not lowered yet");
|
|
747
|
-
break;
|
|
748
1025
|
case "writev":
|
|
749
|
-
lowerer.noLowering(`the ${ctorName} option 'writev'`, prop, "
|
|
1026
|
+
lowerer.noLowering(`the ${ctorName} option 'writev'`, prop, "a Readable has no writable side");
|
|
750
1027
|
break;
|
|
751
1028
|
default:
|
|
752
1029
|
lowerer.noLowering(`the ${ctorName} option '${name}'`, prop);
|
|
@@ -762,6 +1039,11 @@ fallbackCb) {
|
|
|
762
1039
|
out.cbs.push(cb);
|
|
763
1040
|
}
|
|
764
1041
|
}
|
|
1042
|
+
for (const name of extraNames) {
|
|
1043
|
+
const cb = present.get(name) ?? fallbackCb?.(name) ?? null;
|
|
1044
|
+
if (cb)
|
|
1045
|
+
out.extras.push({ name, cb });
|
|
1046
|
+
}
|
|
765
1047
|
return out;
|
|
766
1048
|
}
|
|
767
1049
|
/** The head + flags argument list of a stream construction/initialization
|
|
@@ -788,8 +1070,66 @@ function streamCtorArgs(lowerer, cls, arg, thisType, loc, fallbackCb) {
|
|
|
788
1070
|
badEncoding: o.badEncoding,
|
|
789
1071
|
pushEncoding: o.pushEncoding,
|
|
790
1072
|
signal: o.signal,
|
|
1073
|
+
valueDecls: o.valueDecls,
|
|
1074
|
+
decodeStringsValue: o.decodeStringsValue,
|
|
1075
|
+
defaultEncodingValue: o.defaultEncodingValue,
|
|
1076
|
+
readableObject: o.readableObject,
|
|
1077
|
+
writableObject: o.writableObject,
|
|
1078
|
+
decodeStringsOff: o.decodeStringsOff,
|
|
1079
|
+
writeEncoding: o.writeEncoding,
|
|
1080
|
+
extras: o.extras,
|
|
791
1081
|
};
|
|
792
1082
|
}
|
|
1083
|
+
/** The follow-ups a stream's options apply over the fresh stream `recv`
|
|
1084
|
+
* after the chained ones: decodeStrings, the writable defaultEncoding,
|
|
1085
|
+
* then writev and construct (Node's constructors schedule construct
|
|
1086
|
+
* last). */
|
|
1087
|
+
function streamOptionFollowUps(parsed, recv, thisType, loc, writevFn = "stream.setWritev") {
|
|
1088
|
+
const out = [];
|
|
1089
|
+
if (parsed.decodeStringsOff) {
|
|
1090
|
+
out.push({
|
|
1091
|
+
kind: "exprStmt",
|
|
1092
|
+
expr: {
|
|
1093
|
+
kind: "libCall",
|
|
1094
|
+
fn: "stream.decodeStrings",
|
|
1095
|
+
args: [recv(), boolLit(false, loc)],
|
|
1096
|
+
type: thisType,
|
|
1097
|
+
loc,
|
|
1098
|
+
},
|
|
1099
|
+
loc,
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
if (parsed.writeEncoding !== null) {
|
|
1103
|
+
out.push({
|
|
1104
|
+
kind: "exprStmt",
|
|
1105
|
+
expr: {
|
|
1106
|
+
kind: "libCall",
|
|
1107
|
+
fn: "writable.writeEncoding",
|
|
1108
|
+
args: [recv(), strLit(parsed.writeEncoding, loc)],
|
|
1109
|
+
type: thisType,
|
|
1110
|
+
loc,
|
|
1111
|
+
},
|
|
1112
|
+
loc,
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
for (const name of ["writev", "construct"]) {
|
|
1116
|
+
const extra = parsed.extras.find((x) => x.name === name);
|
|
1117
|
+
if (!extra)
|
|
1118
|
+
continue;
|
|
1119
|
+
out.push({
|
|
1120
|
+
kind: "exprStmt",
|
|
1121
|
+
expr: {
|
|
1122
|
+
kind: "libCall",
|
|
1123
|
+
fn: name === "writev" ? writevFn : "stream.setConstruct",
|
|
1124
|
+
args: [recv(), extra.cb],
|
|
1125
|
+
type: VOID,
|
|
1126
|
+
loc,
|
|
1127
|
+
},
|
|
1128
|
+
loc,
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
return out;
|
|
1132
|
+
}
|
|
793
1133
|
/** `new Readable(opts?)` and friends — called from lowerNew once the
|
|
794
1134
|
* callee resolved to a builtin stream class. */
|
|
795
1135
|
export function lowerStreamNew(lowerer, expr, info) {
|
|
@@ -822,6 +1162,29 @@ export function lowerStreamNew(lowerer, expr, info) {
|
|
|
822
1162
|
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${parsed.badEncoding}`, thisType, loc);
|
|
823
1163
|
}
|
|
824
1164
|
let built = { kind: "libCall", fn, args: parsed.args, type: thisType, loc };
|
|
1165
|
+
if (parsed.readableObject || parsed.writableObject) {
|
|
1166
|
+
// { objectMode }: applied before any other follow-up (answers the
|
|
1167
|
+
// receiver +1).
|
|
1168
|
+
built = {
|
|
1169
|
+
kind: "libCall",
|
|
1170
|
+
fn: "stream.objectMode",
|
|
1171
|
+
args: [built, boolLit(parsed.readableObject, loc), boolLit(parsed.writableObject, loc)],
|
|
1172
|
+
type: thisType,
|
|
1173
|
+
loc,
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
const values = optionValuesArgs(parsed, loc);
|
|
1177
|
+
if (values) {
|
|
1178
|
+
// runtime decodeStrings and defaultEncoding values (answers the
|
|
1179
|
+
// receiver +1)
|
|
1180
|
+
built = {
|
|
1181
|
+
kind: "libCall",
|
|
1182
|
+
fn: "stream.optionValues",
|
|
1183
|
+
args: [built, ...values],
|
|
1184
|
+
type: thisType,
|
|
1185
|
+
loc,
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
825
1188
|
if (parsed.pushEncoding !== null) {
|
|
826
1189
|
// { defaultEncoding }: chain the push-side decode default (the
|
|
827
1190
|
// setEncoding chaining shape — answers the receiver +1).
|
|
@@ -844,17 +1207,45 @@ export function lowerStreamNew(lowerer, expr, info) {
|
|
|
844
1207
|
loc,
|
|
845
1208
|
};
|
|
846
1209
|
}
|
|
847
|
-
if (parsed.signal
|
|
848
|
-
|
|
849
|
-
|
|
1210
|
+
if (parsed.signal !== null) {
|
|
1211
|
+
// { signal }: addAbortSignal over the fresh stream (answers it +1).
|
|
1212
|
+
built = {
|
|
1213
|
+
kind: "libCall",
|
|
1214
|
+
fn: "stream.addAbortSignal",
|
|
1215
|
+
args: [built, parsed.signal],
|
|
1216
|
+
type: thisType,
|
|
1217
|
+
loc,
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
if (!parsed.decodeStringsOff && parsed.writeEncoding === null && parsed.extras.length === 0) {
|
|
1221
|
+
return parsed.valueDecls.length > 0
|
|
1222
|
+
? { kind: "seqExpr", stmts: parsed.valueDecls, result: built, type: thisType, loc }
|
|
1223
|
+
: built;
|
|
1224
|
+
}
|
|
1225
|
+
const fresh = lowerer.declareHiddenLocal("%stream", thisType);
|
|
1226
|
+
const followUps = streamOptionFollowUps(parsed, () => varRef(fresh.id, thisType, loc), thisType, loc);
|
|
850
1227
|
return {
|
|
851
|
-
kind: "
|
|
852
|
-
|
|
853
|
-
|
|
1228
|
+
kind: "seqExpr",
|
|
1229
|
+
stmts: [
|
|
1230
|
+
...parsed.valueDecls,
|
|
1231
|
+
{ kind: "varDecl", localId: fresh.id, init: built, loc },
|
|
1232
|
+
...followUps,
|
|
1233
|
+
],
|
|
1234
|
+
result: varRef(fresh.id, thisType, loc),
|
|
854
1235
|
type: thisType,
|
|
855
1236
|
loc,
|
|
856
1237
|
};
|
|
857
1238
|
}
|
|
1239
|
+
/** stream.optionValues' (decodeStrings, defaultEncoding) arguments, or
|
|
1240
|
+
* null when both options are literals or absent. */
|
|
1241
|
+
function optionValuesArgs(parsed, loc) {
|
|
1242
|
+
if (parsed.decodeStringsValue === null && parsed.defaultEncodingValue === null)
|
|
1243
|
+
return null;
|
|
1244
|
+
return [
|
|
1245
|
+
parsed.decodeStringsValue ?? dynUndefinedExpr(loc),
|
|
1246
|
+
parsed.defaultEncodingValue ?? dynUndefinedExpr(loc),
|
|
1247
|
+
];
|
|
1248
|
+
}
|
|
858
1249
|
/** True when a value of Node's argument type `passed` widens implicitly
|
|
859
1250
|
* into the declared parameter type `declared` (one of its union arms, or a
|
|
860
1251
|
* sub-union of it). */
|
|
@@ -871,7 +1262,7 @@ function widensInto(lowerer, passed, declared, loc) {
|
|
|
871
1262
|
* overrides it (the ordinary devirtualization rule), so an inherited
|
|
872
1263
|
* constructor still binds the DYNAMIC class's override. The method may
|
|
873
1264
|
* declare any PREFIX of its Node signature (the option-callback rule). */
|
|
874
|
-
function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, blame) {
|
|
1265
|
+
function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, blame, chunkValues = true) {
|
|
875
1266
|
const found = lowerer.findMethodOn(info, methodName);
|
|
876
1267
|
if (!found) {
|
|
877
1268
|
// A DESCENDANT-only declaration (the base chain never declares it):
|
|
@@ -914,6 +1305,18 @@ function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, bl
|
|
|
914
1305
|
}
|
|
915
1306
|
}
|
|
916
1307
|
else if (!typeEquals(got.type, want)) {
|
|
1308
|
+
// A write or transform encoding of another type (`string | null |
|
|
1309
|
+
// undefined`) converts from the encoding argument's value: an
|
|
1310
|
+
// object-mode write passes undefined, null or the name. A chunk of
|
|
1311
|
+
// another type (`string | Buffer` under decodeStrings: false)
|
|
1312
|
+
// converts from the chunk's value.
|
|
1313
|
+
if ((i === 1 || (i === 0 && (chunkValues || which === "writev"))) &&
|
|
1314
|
+
(which === "write" || which === "transform" || which === "writev") &&
|
|
1315
|
+
got.type.kind !== "func" &&
|
|
1316
|
+
canConvertToDyn(got.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
1317
|
+
paramTypes.push(got.type);
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
917
1320
|
// A declared supertype of what Node passes (`chunk: Buffer | string`)
|
|
918
1321
|
// is sound: the wrapper takes Node's value and widens it into the
|
|
919
1322
|
// declared parameter.
|
|
@@ -921,12 +1324,22 @@ function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, bl
|
|
|
921
1324
|
paramTypes.push(want);
|
|
922
1325
|
continue;
|
|
923
1326
|
}
|
|
1327
|
+
// A write or transform chunk of another type converts from the
|
|
1328
|
+
// chunk's value when the method runs (an object-mode side's value),
|
|
1329
|
+
// or throws a TypeError there; a byte-mode side's chunk is a Buffer.
|
|
1330
|
+
if (i === 0 &&
|
|
1331
|
+
(which === "writev" || (chunkValues && (which === "write" || which === "transform"))) &&
|
|
1332
|
+
got.type.kind !== "func" &&
|
|
1333
|
+
canConvertToDyn(got.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
1334
|
+
paramTypes.push(got.type);
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
924
1337
|
lowerer.noLowering(`a '${methodName}' method whose parameter ${i} is '${lowerer.fmt(got.type)}' where Node passes '${lowerer.fmt(want)}'`, blame, "annotate the parameter with the Node signature's type or a supertype of it (chunks are Buffers here)");
|
|
925
1338
|
}
|
|
926
1339
|
paramTypes.push(got.type);
|
|
927
1340
|
}
|
|
928
1341
|
const ret = found.sig.ret;
|
|
929
|
-
const fnName =
|
|
1342
|
+
const fnName = lowerer.closureName(loc, `_${which}vt`);
|
|
930
1343
|
const funcType = funcOf([thisType, ...paramTypes], ret);
|
|
931
1344
|
lowerer.fnStack.push(newFnCtx(true, null, funcType, ret));
|
|
932
1345
|
try {
|
|
@@ -996,10 +1409,21 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
996
1409
|
lowerer.noLowering(`super(...) with ${argNodes.length} arguments in a ${cls.slice(1)} subclass`, blame, "the supported form takes one inline options object (or none)");
|
|
997
1410
|
}
|
|
998
1411
|
const shape = streamCtorShape(cls);
|
|
1412
|
+
// Whether the writable side holds values: options read at run time may
|
|
1413
|
+
// set objectMode, and a literal says so with objectMode (or a Duplex's
|
|
1414
|
+
// writableObjectMode) true; otherwise _write and _transform receive
|
|
1415
|
+
// Buffers.
|
|
1416
|
+
// super(undefined) and super(null) pass no options (followOptionsArg
|
|
1417
|
+
// answers null), so their sides are byte mode too.
|
|
1418
|
+
const optsNode = argNodes[0] !== undefined ? followOptionsArg(lowerer, argNodes[0]) : null;
|
|
1419
|
+
const chunkValues = optsNode !== null &&
|
|
1420
|
+
optsNode !== undefined &&
|
|
1421
|
+
(!ts.isObjectLiteralExpression(optsNode) ||
|
|
1422
|
+
literalWritesValues(optsNode, cls !== "%Readable" && cls !== "%Writable"));
|
|
999
1423
|
const fallback = (name) => {
|
|
1000
|
-
const methodName = UNDERSCORE_METHODS.get(name);
|
|
1424
|
+
const methodName = UNDERSCORE_METHODS.get(name) ?? STREAM_EXTRA_CALLBACKS.get(name);
|
|
1001
1425
|
return methodName
|
|
1002
|
-
? streamMethodWrapper(lowerer, info, name, methodName, thisType, loc, blame)
|
|
1426
|
+
? streamMethodWrapper(lowerer, info, name, methodName, thisType, loc, blame, chunkValues)
|
|
1003
1427
|
: null;
|
|
1004
1428
|
};
|
|
1005
1429
|
const thisRef = () => ({ kind: "varRef", localId: thisLocal.id, type: thisType, loc });
|
|
@@ -1018,6 +1442,14 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1018
1442
|
cbs.push(cb);
|
|
1019
1443
|
}
|
|
1020
1444
|
}
|
|
1445
|
+
// The class's _writev and _construct ride the same way: an options
|
|
1446
|
+
// writev or construct (applied by initDyn) wins.
|
|
1447
|
+
const extras = [];
|
|
1448
|
+
for (const name of streamExtraCallbacks(cls)) {
|
|
1449
|
+
const cb = fallback(name);
|
|
1450
|
+
if (cb)
|
|
1451
|
+
extras.push({ name, cb });
|
|
1452
|
+
}
|
|
1021
1453
|
return [
|
|
1022
1454
|
{
|
|
1023
1455
|
kind: "exprStmt",
|
|
@@ -1030,6 +1462,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1030
1462
|
},
|
|
1031
1463
|
loc,
|
|
1032
1464
|
},
|
|
1465
|
+
...streamOptionFollowUps({ decodeStringsOff: false, writeEncoding: null, extras }, thisRef, thisType, loc, "stream.setWritevDefault"),
|
|
1033
1466
|
];
|
|
1034
1467
|
}
|
|
1035
1468
|
}
|
|
@@ -1046,6 +1479,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1046
1479
|
];
|
|
1047
1480
|
}
|
|
1048
1481
|
const out = [
|
|
1482
|
+
...parsed.valueDecls,
|
|
1049
1483
|
{
|
|
1050
1484
|
kind: "exprStmt",
|
|
1051
1485
|
expr: {
|
|
@@ -1058,6 +1492,33 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1058
1492
|
loc,
|
|
1059
1493
|
},
|
|
1060
1494
|
];
|
|
1495
|
+
if (parsed.readableObject || parsed.writableObject) {
|
|
1496
|
+
out.push({
|
|
1497
|
+
kind: "exprStmt",
|
|
1498
|
+
expr: {
|
|
1499
|
+
kind: "libCall",
|
|
1500
|
+
fn: "stream.objectMode",
|
|
1501
|
+
args: [thisRef(), boolLit(parsed.readableObject, loc), boolLit(parsed.writableObject, loc)],
|
|
1502
|
+
type: thisType,
|
|
1503
|
+
loc,
|
|
1504
|
+
},
|
|
1505
|
+
loc,
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
const values = optionValuesArgs(parsed, loc);
|
|
1509
|
+
if (values) {
|
|
1510
|
+
out.push({
|
|
1511
|
+
kind: "exprStmt",
|
|
1512
|
+
expr: {
|
|
1513
|
+
kind: "libCall",
|
|
1514
|
+
fn: "stream.optionValues",
|
|
1515
|
+
args: [thisRef(), ...values],
|
|
1516
|
+
type: thisType,
|
|
1517
|
+
loc,
|
|
1518
|
+
},
|
|
1519
|
+
loc,
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1061
1522
|
if (parsed.pushEncoding !== null) {
|
|
1062
1523
|
out.push({
|
|
1063
1524
|
kind: "exprStmt",
|
|
@@ -1097,6 +1558,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1097
1558
|
loc,
|
|
1098
1559
|
});
|
|
1099
1560
|
}
|
|
1561
|
+
out.push(...streamOptionFollowUps(parsed, thisRef, thisType, loc));
|
|
1100
1562
|
return out;
|
|
1101
1563
|
}
|
|
1102
1564
|
/* ── the underscore-method assignment surface ─────────────────────────── */
|
|
@@ -1140,14 +1602,16 @@ export function lowerStreamUnderscoreAssign(lowerer, expr) {
|
|
|
1140
1602
|
const loc = locOf(expr);
|
|
1141
1603
|
const cls = base.def.name;
|
|
1142
1604
|
const clsName = cls.slice(1);
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1605
|
+
// `_construct`: Node's constructNT reads it on the construction tick, so
|
|
1606
|
+
// an assignment before that tick replaces a scheduled hook
|
|
1607
|
+
// (stream.replaceConstruct) and has no effect after it or without one.
|
|
1608
|
+
const which = methodName === "_writev"
|
|
1609
|
+
? "writev"
|
|
1610
|
+
: methodName === "_construct"
|
|
1611
|
+
? "construct"
|
|
1612
|
+
: optionByMethod.get(methodName);
|
|
1149
1613
|
const { accepted } = streamCtorShape(cls);
|
|
1150
|
-
if (!accepted.includes(which)) {
|
|
1614
|
+
if (!accepted.includes(which) && !streamExtraCallbacks(cls).includes(which)) {
|
|
1151
1615
|
lowerer.noLowering(`assigning '${methodName}' on a ${clsName}`, expr.left, `a ${clsName}'s machinery consumes ${accepted.map((a) => `'${UNDERSCORE_METHODS.get(a)}'`).join("/")} — '${methodName}' would ride machinery with no lowering here`);
|
|
1152
1616
|
}
|
|
1153
1617
|
const thisType = recv.type;
|
|
@@ -1178,6 +1642,8 @@ export function lowerStreamUnderscoreAssign(lowerer, expr) {
|
|
|
1178
1642
|
destroy: "stream.setDestroy",
|
|
1179
1643
|
transform: "stream.setTransform",
|
|
1180
1644
|
flush: "stream.setFlush",
|
|
1645
|
+
writev: "stream.setWritev",
|
|
1646
|
+
construct: "stream.replaceConstruct",
|
|
1181
1647
|
};
|
|
1182
1648
|
return {
|
|
1183
1649
|
kind: "exprStmt",
|
|
@@ -1235,25 +1701,165 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1235
1701
|
}
|
|
1236
1702
|
}
|
|
1237
1703
|
}
|
|
1704
|
+
if (member === "fromWeb" && cls === "%Readable")
|
|
1705
|
+
return lowerReadableFromWeb(lowerer, call, loc);
|
|
1238
1706
|
if (member !== "from") {
|
|
1239
1707
|
lowerer.noLowering(`${cls.slice(1)}.${member}`, call);
|
|
1240
1708
|
}
|
|
1709
|
+
if (cls === "%Duplex") {
|
|
1710
|
+
const fromArgs = call.arguments.nodes;
|
|
1711
|
+
if (fromArgs.length !== 1) {
|
|
1712
|
+
lowerer.noLowering(`Duplex.from with ${fromArgs.length} arguments`, call, "Duplex.from takes one body");
|
|
1713
|
+
}
|
|
1714
|
+
return duplexFromBody(lowerer, fromArgs[0], locOf(call));
|
|
1715
|
+
}
|
|
1241
1716
|
if (cls !== "%Readable") {
|
|
1242
|
-
lowerer.noLowering(`${cls.slice(1)}.from`, call, "Readable.from
|
|
1717
|
+
lowerer.noLowering(`${cls.slice(1)}.from`, call, "Readable.from and Duplex.from are the lowered forms");
|
|
1243
1718
|
}
|
|
1244
1719
|
const args = call.arguments.nodes;
|
|
1245
1720
|
if (args.length > 2) {
|
|
1246
1721
|
lowerer.noLowering(`Readable.from with ${args.length} arguments`, call, "Readable.from(iterable, options) is the supported form");
|
|
1247
1722
|
}
|
|
1248
|
-
|
|
1723
|
+
return lowerFromSource(lowerer, call, args[0], args[1], false);
|
|
1724
|
+
}
|
|
1725
|
+
/** Readable.fromWeb(readableStream, options): Node's adapter over the web
|
|
1726
|
+
* stream's reader (scr_stream_from_web.c). The options are an object
|
|
1727
|
+
* literal: objectMode a boolean literal, highWaterMark a number, encoding
|
|
1728
|
+
* a literal name, and signal a variable or property read, applied with
|
|
1729
|
+
* addAbortSignal as the constructors do. */
|
|
1730
|
+
function lowerReadableFromWeb(lowerer, call, loc) {
|
|
1731
|
+
const args = call.arguments.nodes;
|
|
1732
|
+
const readable = { kind: "object", className: "%Readable" };
|
|
1733
|
+
if (args.length === 0 || args.length > 2 || args.some((a) => ts.isSpreadElement(a))) {
|
|
1734
|
+
lowerer.noLowering(`Readable.fromWeb with ${args.length} arguments`, call, "the supported form is Readable.fromWeb(readableStream, options)");
|
|
1735
|
+
}
|
|
1736
|
+
const web = lowerer.lowerExprExpecting(args[0], DYN);
|
|
1737
|
+
let objectMode = false;
|
|
1738
|
+
let hwm = numLit(-1, loc);
|
|
1739
|
+
let encoding = "";
|
|
1740
|
+
let signal = null;
|
|
1741
|
+
const options = args[1];
|
|
1742
|
+
if (options !== undefined) {
|
|
1743
|
+
if (!ts.isObjectLiteralExpression(options)) {
|
|
1744
|
+
lowerer.noLowering("Readable.fromWeb options that are not an object literal", options, "pass { objectMode, highWaterMark, encoding, signal } as an object literal");
|
|
1745
|
+
}
|
|
1746
|
+
for (const p of options.properties.nodes) {
|
|
1747
|
+
const key = (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) &&
|
|
1748
|
+
ts.isIdentifier(p.name)
|
|
1749
|
+
? p.name.text
|
|
1750
|
+
: null;
|
|
1751
|
+
const value = key === null
|
|
1752
|
+
? null
|
|
1753
|
+
: ts.isShorthandPropertyAssignment(p)
|
|
1754
|
+
? p.name
|
|
1755
|
+
: p.initializer;
|
|
1756
|
+
if (key === "objectMode" && value) {
|
|
1757
|
+
if (value.kind === ts.SyntaxKind.TrueKeyword)
|
|
1758
|
+
objectMode = true;
|
|
1759
|
+
else if (value.kind !== ts.SyntaxKind.FalseKeyword)
|
|
1760
|
+
lowerer.noLowering("the Readable.fromWeb option 'objectMode' with this value", p, "write true or false");
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
if (key === "highWaterMark" && value) {
|
|
1764
|
+
hwm = lowerer.lowerExprExpecting(value, F64);
|
|
1765
|
+
continue;
|
|
1766
|
+
}
|
|
1767
|
+
if (key === "encoding" && value) {
|
|
1768
|
+
const t = lowerer.typeOf(value);
|
|
1769
|
+
if (t.isStringLiteralType() && knownBufEncoding(t.value) === undefined) {
|
|
1770
|
+
return nodeThrowExpr(1, "ERR_INVALID_ARG_VALUE", `The property 'options.encoding' is invalid. Received '${t.value}'`, readable, loc);
|
|
1771
|
+
}
|
|
1772
|
+
encoding = bufEncoding(lowerer, "the Readable.fromWeb option 'encoding'", value);
|
|
1773
|
+
continue;
|
|
1774
|
+
}
|
|
1775
|
+
if (key === "signal" && value) {
|
|
1776
|
+
if (!sideEffectFreeOptionValue(value) && !pureRead(value)) {
|
|
1777
|
+
lowerer.noLowering("the Readable.fromWeb option 'signal' with this value", p, "pass a variable or property read (const signal = controller.signal)");
|
|
1778
|
+
}
|
|
1779
|
+
signal = lowerer.lowerExprExpecting(value, DYN);
|
|
1780
|
+
continue;
|
|
1781
|
+
}
|
|
1782
|
+
lowerer.noLowering(key === null
|
|
1783
|
+
? "Readable.fromWeb options with this member"
|
|
1784
|
+
: `the Readable.fromWeb option '${key}'`, p, "objectMode, highWaterMark, encoding and signal are the Readable.fromWeb options");
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
const built = {
|
|
1788
|
+
kind: "libCall",
|
|
1789
|
+
fn: "fetch.readableFromWeb",
|
|
1790
|
+
args: [web, boolLit(objectMode, loc), hwm, strLit(encoding, loc)],
|
|
1791
|
+
type: readable,
|
|
1792
|
+
loc,
|
|
1793
|
+
};
|
|
1794
|
+
if (signal === null)
|
|
1795
|
+
return built;
|
|
1796
|
+
return {
|
|
1797
|
+
kind: "libCall",
|
|
1798
|
+
fn: "stream.addAbortSignal",
|
|
1799
|
+
args: [built, signal],
|
|
1800
|
+
type: readable,
|
|
1801
|
+
loc,
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
/** Readable.from(source, options), and for Duplex.from over an iterable
|
|
1805
|
+
* (duplex) duplexify.js's from(Duplexify, body, { objectMode: true,
|
|
1806
|
+
* writable: false }): the same builders with SCR_FROM_DUPLEX, answering a
|
|
1807
|
+
* Duplexify without a writable side. */
|
|
1808
|
+
function lowerFromSource(lowerer, at, srcNode, optsNode, duplex) {
|
|
1809
|
+
const loc = locOf(at);
|
|
1810
|
+
const call = at;
|
|
1811
|
+
const type = { kind: "object", className: duplex ? "%Duplex" : "%Readable" };
|
|
1812
|
+
const what = duplex ? "Duplex.from" : "Readable.from";
|
|
1813
|
+
// SCR_FROM_DUPLEX
|
|
1814
|
+
const duplexFlag = duplex ? 32 : 0;
|
|
1249
1815
|
const js = isJsSourceFile(ts.getSourceFileOfNode(call));
|
|
1250
|
-
|
|
1251
|
-
|
|
1816
|
+
// A web ReadableStream is async iterable: from.js reads its iterator.
|
|
1817
|
+
// Duplex.from takes _duplexify({ readable: Readable.fromWeb(body) }).
|
|
1818
|
+
const webElem = srcNode ? staticReadableStreamElementType(lowerer, srcNode) : null;
|
|
1819
|
+
if (srcNode && webElem !== null && duplex) {
|
|
1820
|
+
const fromWeb = {
|
|
1821
|
+
kind: "libCall",
|
|
1822
|
+
fn: "fetch.readableFromWeb",
|
|
1823
|
+
args: [
|
|
1824
|
+
lowerer.lowerExprExpecting(srcNode, DYN),
|
|
1825
|
+
boolLit(false, loc),
|
|
1826
|
+
numLit(-1, loc),
|
|
1827
|
+
strLit("", loc),
|
|
1828
|
+
],
|
|
1829
|
+
type: { kind: "object", className: "%Readable" },
|
|
1830
|
+
loc,
|
|
1831
|
+
};
|
|
1832
|
+
return { kind: "libCall", fn: "stream.duplexifyReadable", args: [fromWeb], type, loc };
|
|
1833
|
+
}
|
|
1834
|
+
if (srcNode && webElem !== null) {
|
|
1835
|
+
const source = lowerWebStreamSource(lowerer, srcNode, webElem, loc);
|
|
1836
|
+
const helpers = source ? fromGenHelpers(lowerer, source.out, loc) : null;
|
|
1837
|
+
const opts = optsNode ? fromOptions(lowerer, optsNode) : { flags: 0, hwm: null };
|
|
1838
|
+
if (!source || !helpers || !opts || !fromGenChunk(lowerer, webElem)) {
|
|
1839
|
+
lowerer.noLowering(`Readable.from over a web ReadableStream of '${lowerer.fmt(webElem)}'`, srcNode);
|
|
1840
|
+
}
|
|
1841
|
+
const hwm = opts.hwm ? lowerer.lowerExprExpecting(opts.hwm, F64) : numLit(0, loc);
|
|
1842
|
+
const gen = {
|
|
1843
|
+
kind: "callValue",
|
|
1844
|
+
callee: source.closure,
|
|
1845
|
+
args: [],
|
|
1846
|
+
type: source.out,
|
|
1847
|
+
loc,
|
|
1848
|
+
};
|
|
1849
|
+
return {
|
|
1850
|
+
kind: "libCall",
|
|
1851
|
+
fn: "readable.fromAsyncGen",
|
|
1852
|
+
args: [gen, ...helpers, numLit(opts.flags, loc), hwm],
|
|
1853
|
+
type,
|
|
1854
|
+
loc,
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1252
1857
|
const srcT = srcNode ? lowerer.mapTypeOf(lowerer.typeOf(srcNode)) : null;
|
|
1253
1858
|
const typedElem = (t) => t?.kind === "string" ? "string" : t?.kind === "bytes" && t.elem === "u8" ? "bytes" : null;
|
|
1254
1859
|
const single = typedElem(srcT);
|
|
1255
1860
|
const elem = srcT?.kind === "array" ? typedElem(srcT.elem) : null;
|
|
1256
|
-
const
|
|
1861
|
+
const opts0 = optsNode ? fromOptions(lowerer, optsNode) : { flags: 0, hwm: null };
|
|
1862
|
+
const opts = opts0 ? { ...opts0, flags: opts0.flags | duplexFlag } : opts0;
|
|
1257
1863
|
// A class whose [Symbol.iterator]() or [Symbol.asyncIterator]() is a
|
|
1258
1864
|
// generator method: from.js calls the method when the stream is built,
|
|
1259
1865
|
// then reads the generator like any other.
|
|
@@ -1330,7 +1936,13 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1330
1936
|
};
|
|
1331
1937
|
}
|
|
1332
1938
|
const anySrc = srcT?.kind === "dyn" ||
|
|
1333
|
-
|
|
1939
|
+
// a Set or Map (entry arrays) of other values: the checked-dynamic
|
|
1940
|
+
// view iterates the collection itself
|
|
1941
|
+
((srcT?.kind === "set" || srcT?.kind === "map") &&
|
|
1942
|
+
canConvertToDyn(srcT, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) ||
|
|
1943
|
+
// an array of other values: the object-mode entries come from its
|
|
1944
|
+
// checked-dynamic copy
|
|
1945
|
+
(srcT?.kind === "array" && fromGenChunk(lowerer, srcT.elem) && typedElem(srcT.elem) === null) ||
|
|
1334
1946
|
(srcNode !== undefined &&
|
|
1335
1947
|
srcT === null &&
|
|
1336
1948
|
(lowerer.typeOf(srcNode).flags & ts.TypeFlags.Any) !== 0);
|
|
@@ -1338,25 +1950,25 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1338
1950
|
// The checked-dynamic form: the runtime takes from.js's ladder
|
|
1339
1951
|
// (ERR_INVALID_ARG_TYPE for a non-iterable, the options, null values).
|
|
1340
1952
|
const src = srcNode ? lowerer.lowerExprExpecting(srcNode, DYN) : dynUndefinedExpr(loc);
|
|
1953
|
+
if (duplex)
|
|
1954
|
+
return { kind: "libCall", fn: "stream.duplexFromDyn", args: [src], type, loc };
|
|
1341
1955
|
const o = lowerOperatorValue(lowerer, optsNode, "Readable.from options", loc, true);
|
|
1342
1956
|
return { kind: "libCall", fn: "readable.fromDyn", args: [src, o], type, loc };
|
|
1343
1957
|
}
|
|
1344
1958
|
if (srcNode && (single || elem)) {
|
|
1345
1959
|
lowerer.noLowering("Readable.from with these options", optsNode, "an object literal with 'objectMode' (true or false) and a number 'highWaterMark' is supported");
|
|
1346
1960
|
}
|
|
1347
|
-
lowerer.noLowering(
|
|
1961
|
+
lowerer.noLowering(`${what} over a '${srcT ? lowerer.fmt(srcT) : "?"}' source`, srcNode ?? call, "the supported sources are a string or Buffer, and arrays, Sets, Maps, generators and class iterables of values that convert to checked-dynamic values");
|
|
1348
1962
|
}
|
|
1349
|
-
/** Whether a generator's yields
|
|
1350
|
-
*
|
|
1351
|
-
* ERR_STREAM_NULL_VALUES)
|
|
1352
|
-
* pushed
|
|
1963
|
+
/** Whether a generator's yields can be stream chunks: values that box
|
|
1964
|
+
* into checked-dynamic values (null included: the runtime destroys the
|
|
1965
|
+
* stream with ERR_STREAM_NULL_VALUES). An object-mode stream takes any of
|
|
1966
|
+
* them; a byte-mode one checks them when they are pushed or written. */
|
|
1353
1967
|
function fromGenChunk(lowerer, t) {
|
|
1354
|
-
|
|
1355
|
-
if (t.kind === "dyn" || (chunk(t) && t.kind !== "nullT"))
|
|
1356
|
-
return true;
|
|
1357
|
-
if (t.kind !== "union")
|
|
1968
|
+
if (t.kind === "nullT" || t.kind === "void" || t.kind === "func")
|
|
1358
1969
|
return false;
|
|
1359
|
-
return
|
|
1970
|
+
return (t.kind === "dyn" ||
|
|
1971
|
+
canConvertToDyn(t, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)));
|
|
1360
1972
|
}
|
|
1361
1973
|
/** The helpers Readable.from pulls a compiled generator through, as
|
|
1362
1974
|
* closures in libcall order: a sync generator's next/return/throw answer
|
|
@@ -1399,7 +2011,7 @@ function fromGenHelpers(lowerer, gen, loc) {
|
|
|
1399
2011
|
const key = `streamFromGen:${role}:${typeKey(gen)}`;
|
|
1400
2012
|
let name = lowerer.valueHelpers.get(key);
|
|
1401
2013
|
if (!name) {
|
|
1402
|
-
name = `%stream.fromGen.${role}
|
|
2014
|
+
name = keyedHelperName(lowerer, `%stream.fromGen.${role}`, key);
|
|
1403
2015
|
lowerer.valueHelpers.set(key, name);
|
|
1404
2016
|
lowerer.liftedFns.push({
|
|
1405
2017
|
name,
|
|
@@ -1480,7 +2092,7 @@ function classIteratorObject(lowerer, cit, iter, loc) {
|
|
|
1480
2092
|
const key = `streamFromIter:${cit.iterT.className}`;
|
|
1481
2093
|
let name = lowerer.valueHelpers.get(key);
|
|
1482
2094
|
if (!name) {
|
|
1483
|
-
name =
|
|
2095
|
+
name = keyedHelperName(lowerer, "%stream.fromIter", key);
|
|
1484
2096
|
lowerer.valueHelpers.set(key, name);
|
|
1485
2097
|
const nextName = `${name}.next`;
|
|
1486
2098
|
const nextT = funcOf([], DYN);
|
|
@@ -1624,7 +2236,7 @@ function classAsyncIteratorObject(lowerer, cit, recv, loc) {
|
|
|
1624
2236
|
const key = `streamFromAsyncIter:${cit.className}`;
|
|
1625
2237
|
let name = lowerer.valueHelpers.get(key);
|
|
1626
2238
|
if (!name) {
|
|
1627
|
-
name =
|
|
2239
|
+
name = keyedHelperName(lowerer, "%stream.fromAsyncIter", key);
|
|
1628
2240
|
lowerer.valueHelpers.set(key, name);
|
|
1629
2241
|
const it = { id: "it.0", name: "it", type: cit.iterT, mutable: false, boxed: true };
|
|
1630
2242
|
const src = {
|
|
@@ -1743,10 +2355,10 @@ const PIPELINE_STAGE_EXPECTED = "of type function or an instance of Blob, Readab
|
|
|
1743
2355
|
* a ladder Node never throws. */
|
|
1744
2356
|
function lowerStreamArg(lowerer, node, what) {
|
|
1745
2357
|
const lowered = lowerer.lowerExpr(node);
|
|
1746
|
-
// A Hash or
|
|
1747
|
-
// keep the value alive until the stream settles.
|
|
1748
|
-
const v =
|
|
1749
|
-
?
|
|
2358
|
+
// A Hash, Hmac, Cipheriv or Decipheriv stage is its Transform; pipeline
|
|
2359
|
+
// and compose stages keep the value alive until the stream settles.
|
|
2360
|
+
const v = isValueStream(lowerer, node)
|
|
2361
|
+
? valueStreamOf(lowered, what === "pipeline" || what === "compose")
|
|
1750
2362
|
: lowered;
|
|
1751
2363
|
// A checked-dynamic pipeline stage (an untyped source or destination):
|
|
1752
2364
|
// a boxed native stream unwraps at run time; other values (iterables,
|
|
@@ -1827,6 +2439,24 @@ class StreamArgTypeThrow extends Error {
|
|
|
1827
2439
|
this.expr = expr;
|
|
1828
2440
|
}
|
|
1829
2441
|
}
|
|
2442
|
+
/** Whether a checked-dynamic pipeline callback can take undefined as its
|
|
2443
|
+
* error: a callback that is already checked-dynamic, one without
|
|
2444
|
+
* parameters, and one whose first parameter (or rest element) type holds
|
|
2445
|
+
* undefined. */
|
|
2446
|
+
function callbackErrorAdmitsUndefined(lowerer, cb) {
|
|
2447
|
+
if (cb.kind !== "dynFrom" || cb.value.type.kind !== "func")
|
|
2448
|
+
return true;
|
|
2449
|
+
const fnT = cb.value.type;
|
|
2450
|
+
const first = fnT.params[0];
|
|
2451
|
+
if (first === undefined)
|
|
2452
|
+
return true;
|
|
2453
|
+
const p0 = fnT.rest === true && fnT.params.length === 1 && first.kind === "array" ? first.elem : first;
|
|
2454
|
+
if (p0.kind === "dyn" || p0.kind === "jsval" || p0.kind === "undefinedT")
|
|
2455
|
+
return true;
|
|
2456
|
+
if (p0.kind !== "union")
|
|
2457
|
+
return false;
|
|
2458
|
+
return lowerer.unions.get(p0.unionId)?.arms.some((a) => a.kind === "undefinedT") ?? false;
|
|
2459
|
+
}
|
|
1830
2460
|
/** The finished/pipeline completion callback: an inline function lowers
|
|
1831
2461
|
* through the option-callback machinery (leading `this`, an `Error |
|
|
1832
2462
|
* null` prefix — Node binds the stream and passes the error); any other
|
|
@@ -2025,19 +2655,29 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2025
2655
|
? pipelineOptions(lowerer, lastArg)
|
|
2026
2656
|
: null;
|
|
2027
2657
|
const stageArgs = opts ? args.slice(0, -1) : args;
|
|
2028
|
-
if (stageArgs
|
|
2029
|
-
if (opts) {
|
|
2030
|
-
lowerer.noLowering("pipeline with function stages and options", lastArg, "pipeline(source, async function* (source) { ... }, destination) without options is supported");
|
|
2031
|
-
}
|
|
2658
|
+
if (hasPipelineFunctionStage(lowerer, stageArgs)) {
|
|
2032
2659
|
const staged = lowerPipelineStages(lowerer, stageArgs, loc);
|
|
2660
|
+
const type = staged.destPromise ?? { kind: "promise", inner: VOID };
|
|
2033
2661
|
// A promise destination's value settles the result (same type).
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2662
|
+
if (!opts) {
|
|
2663
|
+
return staged.wrap({
|
|
2664
|
+
kind: "libCall",
|
|
2665
|
+
fn: "sp.pipelineStages",
|
|
2666
|
+
args: staged.args,
|
|
2667
|
+
type,
|
|
2668
|
+
loc,
|
|
2669
|
+
});
|
|
2670
|
+
}
|
|
2671
|
+
// the options: end, and the signal (flags bit 6)
|
|
2672
|
+
const flagsArg = staged.args[3];
|
|
2673
|
+
if (flagsArg.kind !== "numLit")
|
|
2674
|
+
throw new InternalCompilerError("pipeline flags not a literal");
|
|
2675
|
+
const args = [...staged.args, boolLit(opts.end, loc)];
|
|
2676
|
+
if (opts.signal) {
|
|
2677
|
+
args[3] = numLit(flagsArg.value | 64, loc);
|
|
2678
|
+
args.push(opts.signal);
|
|
2679
|
+
}
|
|
2680
|
+
return staged.wrap({ kind: "libCall", fn: "sp.pipelineStagesOpts", args, type, loc });
|
|
2041
2681
|
}
|
|
2042
2682
|
let streams;
|
|
2043
2683
|
try {
|
|
@@ -2091,7 +2731,10 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2091
2731
|
// (finished/pipeline throw synchronously; consumers do not). A
|
|
2092
2732
|
// sync throw here would be observably wrong timing, so the
|
|
2093
2733
|
// provable case takes the named fence instead.
|
|
2094
|
-
|
|
2734
|
+
// A Hash, Hmac, Cipheriv or Decipheriv is read through its Transform.
|
|
2735
|
+
const argV = isValueStream(lowerer, args[0])
|
|
2736
|
+
? valueStreamOf(lowerer.lowerExpr(args[0]))
|
|
2737
|
+
: lowerer.lowerExpr(args[0]);
|
|
2095
2738
|
const argInfo = argV.type.kind === "object" ? lowerer.classes.get(argV.type.className) : undefined;
|
|
2096
2739
|
if (argV.type.kind !== "dyn" && !streamSidesOf(lowerer, argInfo)) {
|
|
2097
2740
|
lowerer.noLowering(`stream/consumers.${bi.member} over a value that is not a stream`, call, "Node rejects the promise with 'stream is not async iterable' — pass a readable stream");
|
|
@@ -2190,20 +2833,30 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2190
2833
|
if (args.length < 3) {
|
|
2191
2834
|
lowerer.noLowering(`pipeline with ${args.length} arguments`, call, "the supported form is pipeline(source, ...streams, callback)");
|
|
2192
2835
|
}
|
|
2193
|
-
if (args.slice(0, -1)
|
|
2836
|
+
if (hasPipelineFunctionStage(lowerer, args.slice(0, -1))) {
|
|
2194
2837
|
const staged = lowerPipelineStages(lowerer, args.slice(0, -1), loc);
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2838
|
+
const cbNode = args[args.length - 1];
|
|
2839
|
+
const cbParams = ts.isArrowFunction(cbNode) || ts.isFunctionExpression(cbNode)
|
|
2840
|
+
? cbNode.parameters.nodes.length
|
|
2841
|
+
: 0;
|
|
2842
|
+
if (staged.dest === 2 || (staged.dest === 1 && cbParams > 1)) {
|
|
2843
|
+
// callback(err, value): the destination's value (undefined for
|
|
2844
|
+
// an async generator) reaches the callback through the
|
|
2845
|
+
// checked-dynamic path.
|
|
2202
2846
|
const cb = lowerer.lowerExprExpecting(args[args.length - 1], DYN);
|
|
2847
|
+
// SCR_PIPE_TYPED_CB: a typed callback whose error parameter cannot
|
|
2848
|
+
// hold undefined takes null for no error; others take undefined.
|
|
2849
|
+
const stagedArgs = [...staged.args];
|
|
2850
|
+
const flagsArg = stagedArgs[3];
|
|
2851
|
+
if (flagsArg.kind !== "numLit")
|
|
2852
|
+
throw new InternalCompilerError("pipeline flags not a literal");
|
|
2853
|
+
if (!isJsSourceFile(ts.getSourceFileOfNode(call)) &&
|
|
2854
|
+
!callbackErrorAdmitsUndefined(lowerer, cb))
|
|
2855
|
+
stagedArgs[3] = numLit(flagsArg.value | 128, loc);
|
|
2203
2856
|
return staged.wrap({
|
|
2204
2857
|
kind: "libCall",
|
|
2205
2858
|
fn: "stream.pipelineStagesDyn",
|
|
2206
|
-
args: [...
|
|
2859
|
+
args: [...stagedArgs, cb],
|
|
2207
2860
|
type: staged.last,
|
|
2208
2861
|
loc,
|
|
2209
2862
|
});
|
|
@@ -2236,136 +2889,578 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2236
2889
|
loc,
|
|
2237
2890
|
};
|
|
2238
2891
|
}
|
|
2239
|
-
if (bi.member === "compose")
|
|
2240
|
-
|
|
2892
|
+
if (bi.member === "compose") {
|
|
2893
|
+
if (call.arguments.nodes.some((a) => ts.isSpreadElement(a))) {
|
|
2894
|
+
lowerer.noLowering("compose with spread arguments", call, "pass the streams directly");
|
|
2895
|
+
}
|
|
2896
|
+
return lowerStreamCompose(lowerer, call.arguments.nodes, loc);
|
|
2897
|
+
}
|
|
2241
2898
|
return null;
|
|
2242
2899
|
}
|
|
2243
|
-
/**
|
|
2244
|
-
* function stage. */
|
|
2245
|
-
function
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
const
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2900
|
+
/** The function a pipeline() argument writes or names, or null when the
|
|
2901
|
+
* argument is not a function stage. */
|
|
2902
|
+
function pipelineStageFunction(lowerer, node) {
|
|
2903
|
+
if (ts.isFunctionExpression(node) || ts.isArrowFunction(node))
|
|
2904
|
+
return node;
|
|
2905
|
+
if (!ts.isIdentifier(node))
|
|
2906
|
+
return null;
|
|
2907
|
+
// The stage lowers the declaration's body again with its source typed
|
|
2908
|
+
// by the pipeline, so resolving it here must not report what collecting
|
|
2909
|
+
// the declaration's own signature deferred (resolveValueSymbol would).
|
|
2910
|
+
const resolve = (ident) => {
|
|
2911
|
+
const found = lowerer.checker.getSymbolAtLocation(ident);
|
|
2912
|
+
return found && found.flags & ts.SymbolFlags.Alias
|
|
2913
|
+
? lowerer.checker.getAliasedSymbol(found)
|
|
2914
|
+
: found;
|
|
2915
|
+
};
|
|
2916
|
+
const symbol = resolve(node);
|
|
2917
|
+
const declarations = symbol?.declarations ?? [];
|
|
2918
|
+
const bodies = declarations.filter((d) => !ts.isFunctionDeclaration(d) || d.body !== undefined);
|
|
2919
|
+
if (!symbol || bodies.length !== 1)
|
|
2920
|
+
return null;
|
|
2921
|
+
const decl = bodies[0];
|
|
2922
|
+
if (lowerer.isStdlibFile(ts.getSourceFileOfNode(decl)))
|
|
2923
|
+
return null;
|
|
2924
|
+
if (ts.isFunctionDeclaration(decl)) {
|
|
2925
|
+
return bindingNeverReassigned(lowerer, symbol, decl, resolve) ? decl : null;
|
|
2926
|
+
}
|
|
2927
|
+
if (ts.isVariableDeclaration(decl) &&
|
|
2928
|
+
decl.initializer &&
|
|
2929
|
+
ts.isVariableDeclarationList(decl.parent) &&
|
|
2930
|
+
(decl.parent.flags & ts.NodeFlags.Const) !== 0) {
|
|
2931
|
+
let init = decl.initializer;
|
|
2932
|
+
while (ts.isParenthesizedExpression(init))
|
|
2933
|
+
init = init.expression;
|
|
2934
|
+
if (ts.isFunctionExpression(init) || ts.isArrowFunction(init))
|
|
2935
|
+
return init;
|
|
2936
|
+
}
|
|
2937
|
+
return null;
|
|
2938
|
+
}
|
|
2939
|
+
function hasPipelineFunctionStage(lowerer, args) {
|
|
2940
|
+
return (args.some((a) => pipelineStageFunction(lowerer, a) !== null) ||
|
|
2941
|
+
(args.length > 0 && iterableSourceType(lowerer, args[0]) !== null));
|
|
2942
|
+
}
|
|
2943
|
+
/** The element type of a pipeline source that is an iterable value (an
|
|
2944
|
+
* array, a string or a synchronous generator object), or null. */
|
|
2945
|
+
function iterableSourceType(lowerer, node) {
|
|
2946
|
+
if (pipelineStageFunction(lowerer, node) !== null)
|
|
2947
|
+
return null;
|
|
2948
|
+
const webElem = staticReadableStreamElementType(lowerer, node);
|
|
2949
|
+
if (webElem !== null)
|
|
2950
|
+
return webElem;
|
|
2951
|
+
let t;
|
|
2268
2952
|
try {
|
|
2269
|
-
|
|
2270
|
-
before.push(lowerStreamArg(lowerer, a, "pipeline"));
|
|
2953
|
+
t = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
2271
2954
|
}
|
|
2272
|
-
catch
|
|
2273
|
-
|
|
2274
|
-
lowerer.noLowering("pipeline over this value", stageArgs[0]);
|
|
2275
|
-
throw e;
|
|
2955
|
+
catch {
|
|
2956
|
+
return null;
|
|
2276
2957
|
}
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2958
|
+
if (t?.kind === "array")
|
|
2959
|
+
return t.elem;
|
|
2960
|
+
if (t?.kind === "string")
|
|
2961
|
+
return STRING;
|
|
2962
|
+
if (t?.kind === "generator" && t.async !== true && stepDrivable(t))
|
|
2963
|
+
return t.yieldT;
|
|
2964
|
+
return null;
|
|
2965
|
+
}
|
|
2966
|
+
/** A pipeline source that is an iterable value or a synchronous generator
|
|
2967
|
+
* function without parameters, as an async generator closure that steps
|
|
2968
|
+
* the value's iterator (or the generator the function returns) and yields
|
|
2969
|
+
* each element. Node's pipeline iterates such a source with `for await`,
|
|
2970
|
+
* through an async-from-sync iterator, and an async generator that
|
|
2971
|
+
* yields the same elements resumes its consumer on the same ticks. Null
|
|
2972
|
+
* when the source has no such lowering. */
|
|
2973
|
+
/** A web ReadableStream source, as an async generator closure over its
|
|
2974
|
+
* reader: each pass awaits reader.read() and yields the chunk, as the
|
|
2975
|
+
* stream's async iterator does; leaving early cancels the stream (its
|
|
2976
|
+
* iterator's return()), and the reader's lock is released either way. */
|
|
2977
|
+
function lowerWebStreamSource(lowerer, node, elemT, loc) {
|
|
2978
|
+
const resultT = genResultRecord(elemT, VOID, lowerer.shapes, lowerer.unions);
|
|
2979
|
+
if (!resultT)
|
|
2980
|
+
return null;
|
|
2981
|
+
const valueField = lowerer.shapes.get(resultT.shapeId)?.fields.find((f) => f.name === "value");
|
|
2982
|
+
if (!valueField)
|
|
2983
|
+
return null;
|
|
2984
|
+
const out = {
|
|
2985
|
+
kind: "generator",
|
|
2986
|
+
async: true,
|
|
2987
|
+
yieldT: elemT,
|
|
2988
|
+
retT: VOID,
|
|
2989
|
+
nextT: UNDEFINED_T,
|
|
2990
|
+
};
|
|
2991
|
+
const genResultT = genResultRecord(elemT, VOID, lowerer.shapes, lowerer.unions);
|
|
2992
|
+
if (!genResultT)
|
|
2993
|
+
return null;
|
|
2994
|
+
const value = lowerer.lowerExprExpecting(node, DYN);
|
|
2995
|
+
const key = `webStreamSource:${typeKey(elemT)}`;
|
|
2996
|
+
let maker = lowerer.valueHelpers.get(key);
|
|
2997
|
+
if (!maker) {
|
|
2998
|
+
maker = `%stream.webStreamSource.${lowerer.valueHelpers.size}`;
|
|
2999
|
+
const genName = `${maker}.gen`;
|
|
3000
|
+
const frame = new LiftedFrame(loc);
|
|
3001
|
+
const srcId = frame.local("src", DYN, false);
|
|
3002
|
+
const readerId = frame.local("reader", DYN, false);
|
|
3003
|
+
const activeId = frame.local("active", BOOL, true);
|
|
3004
|
+
const promiseT = { kind: "promise", inner: resultT };
|
|
3005
|
+
const pId = frame.local("p", promiseT, false);
|
|
3006
|
+
const rId = frame.local("r", resultT, false);
|
|
3007
|
+
const reader = () => varRef(readerId, DYN, loc);
|
|
3008
|
+
const r = () => varRef(rId, resultT, loc);
|
|
3009
|
+
const setActive = (on) => ({
|
|
3010
|
+
kind: "assign",
|
|
3011
|
+
localId: activeId,
|
|
3012
|
+
value: { kind: "boolLit", value: on, type: BOOL, loc },
|
|
3013
|
+
loc,
|
|
3014
|
+
});
|
|
3015
|
+
const extracted = extractIteratorValue(lowerer, elemT, valueField.type, {
|
|
3016
|
+
kind: "recordGet",
|
|
3017
|
+
obj: r(),
|
|
3018
|
+
shapeId: resultT.shapeId,
|
|
3019
|
+
field: "value",
|
|
3020
|
+
type: valueField.type,
|
|
3021
|
+
loc,
|
|
3022
|
+
}, loc);
|
|
3023
|
+
if (!extracted)
|
|
3024
|
+
return null;
|
|
3025
|
+
const invoke = (method, args, calleeName) => ({
|
|
3026
|
+
kind: "dynInvoke",
|
|
3027
|
+
recv: reader(),
|
|
3028
|
+
method,
|
|
3029
|
+
calleeName,
|
|
3030
|
+
args,
|
|
3031
|
+
type: DYN,
|
|
3032
|
+
loc,
|
|
3033
|
+
});
|
|
3034
|
+
const body = [
|
|
3035
|
+
{
|
|
3036
|
+
kind: "varDecl",
|
|
3037
|
+
localId: readerId,
|
|
3038
|
+
init: {
|
|
3039
|
+
kind: "dynInvoke",
|
|
3040
|
+
recv: varRef(srcId, DYN, loc),
|
|
3041
|
+
method: "getReader",
|
|
3042
|
+
calleeName: "ReadableStream async iterator",
|
|
3043
|
+
args: [],
|
|
3044
|
+
type: DYN,
|
|
3045
|
+
loc,
|
|
3046
|
+
},
|
|
3047
|
+
loc,
|
|
3048
|
+
},
|
|
3049
|
+
{
|
|
3050
|
+
kind: "varDecl",
|
|
3051
|
+
localId: activeId,
|
|
3052
|
+
init: { kind: "boolLit", value: false, type: BOOL, loc },
|
|
3053
|
+
loc,
|
|
3054
|
+
},
|
|
3055
|
+
{
|
|
3056
|
+
kind: "tryCatch",
|
|
3057
|
+
tryBody: [
|
|
3058
|
+
{
|
|
3059
|
+
kind: "while",
|
|
3060
|
+
cond: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
3061
|
+
body: [
|
|
3062
|
+
setActive(false),
|
|
3063
|
+
{
|
|
3064
|
+
kind: "varDecl",
|
|
3065
|
+
localId: pId,
|
|
3066
|
+
init: {
|
|
3067
|
+
kind: "libCall",
|
|
3068
|
+
fn: "fetch.readerRead",
|
|
3069
|
+
args: [reader()],
|
|
3070
|
+
type: promiseT,
|
|
3071
|
+
loc,
|
|
3072
|
+
},
|
|
3073
|
+
loc,
|
|
3074
|
+
},
|
|
3075
|
+
{
|
|
3076
|
+
kind: "varDecl",
|
|
3077
|
+
localId: rId,
|
|
3078
|
+
init: { kind: "awaitExpr", value: varRef(pId, promiseT, loc), type: resultT, loc },
|
|
3079
|
+
loc,
|
|
3080
|
+
},
|
|
3081
|
+
{
|
|
3082
|
+
kind: "if",
|
|
3083
|
+
cond: {
|
|
3084
|
+
kind: "recordGet",
|
|
3085
|
+
obj: r(),
|
|
3086
|
+
shapeId: resultT.shapeId,
|
|
3087
|
+
field: "done",
|
|
3088
|
+
type: BOOL,
|
|
3089
|
+
loc,
|
|
3090
|
+
},
|
|
3091
|
+
then: [{ kind: "break", loc }],
|
|
3092
|
+
else_: null,
|
|
3093
|
+
loc,
|
|
3094
|
+
},
|
|
3095
|
+
setActive(true),
|
|
3096
|
+
{
|
|
3097
|
+
kind: "exprStmt",
|
|
3098
|
+
expr: { kind: "yieldExpr", value: extracted, type: VOID, loc },
|
|
3099
|
+
loc,
|
|
3100
|
+
},
|
|
3101
|
+
],
|
|
3102
|
+
loc,
|
|
3103
|
+
},
|
|
3104
|
+
],
|
|
3105
|
+
catchBody: null,
|
|
3106
|
+
catchLocalId: null,
|
|
3107
|
+
finallyBody: [
|
|
3108
|
+
{
|
|
3109
|
+
kind: "tryCatch",
|
|
3110
|
+
tryBody: [
|
|
3111
|
+
{
|
|
3112
|
+
kind: "if",
|
|
3113
|
+
cond: varRef(activeId, BOOL, loc),
|
|
3114
|
+
then: [
|
|
3115
|
+
{
|
|
3116
|
+
kind: "exprStmt",
|
|
3117
|
+
expr: {
|
|
3118
|
+
kind: "libCall",
|
|
3119
|
+
fn: "async.awaitDyn",
|
|
3120
|
+
args: [
|
|
3121
|
+
invoke("cancel", [dynUndefinedExpr(loc)], "ReadableStream async iterator return"),
|
|
3122
|
+
],
|
|
3123
|
+
type: DYN,
|
|
3124
|
+
loc,
|
|
3125
|
+
},
|
|
3126
|
+
loc,
|
|
3127
|
+
},
|
|
3128
|
+
],
|
|
3129
|
+
else_: null,
|
|
3130
|
+
loc,
|
|
3131
|
+
},
|
|
3132
|
+
],
|
|
3133
|
+
catchBody: null,
|
|
3134
|
+
catchLocalId: null,
|
|
3135
|
+
finallyBody: [
|
|
3136
|
+
{
|
|
3137
|
+
kind: "exprStmt",
|
|
3138
|
+
expr: invoke("releaseLock", [], "ReadableStream async iterator releaseLock"),
|
|
3139
|
+
loc,
|
|
3140
|
+
},
|
|
3141
|
+
],
|
|
3142
|
+
loc,
|
|
3143
|
+
},
|
|
3144
|
+
],
|
|
3145
|
+
loc,
|
|
3146
|
+
},
|
|
3147
|
+
{ kind: "return", value: null, loc },
|
|
3148
|
+
];
|
|
3149
|
+
const srcLocal = frame.locals.find((l) => l.id === srcId);
|
|
3150
|
+
srcLocal.boxed = true;
|
|
3151
|
+
lowerer.valueHelpers.set(key, maker);
|
|
3152
|
+
lowerer.liftedFns.push({
|
|
3153
|
+
name: genName,
|
|
3154
|
+
params: [],
|
|
3155
|
+
returnType: VOID,
|
|
3156
|
+
async: true,
|
|
3157
|
+
captures: [{ localId: srcId, name: "src", type: DYN }],
|
|
3158
|
+
locals: frame.locals,
|
|
3159
|
+
body,
|
|
3160
|
+
generator: { yieldT: elemT, nextT: UNDEFINED_T, resultType: genResultT },
|
|
3161
|
+
loc,
|
|
3162
|
+
});
|
|
3163
|
+
const makerSrc = { id: "src.0", name: "src", type: DYN, mutable: false, boxed: true };
|
|
3164
|
+
lowerer.liftedFns.push({
|
|
3165
|
+
name: maker,
|
|
3166
|
+
params: [{ localId: makerSrc.id, name: makerSrc.name, type: DYN }],
|
|
3167
|
+
returnType: funcOf([], out),
|
|
3168
|
+
locals: [makerSrc],
|
|
3169
|
+
body: [
|
|
3170
|
+
{
|
|
3171
|
+
kind: "return",
|
|
3172
|
+
value: {
|
|
3173
|
+
kind: "closure",
|
|
3174
|
+
fnName: genName,
|
|
3175
|
+
captures: [makerSrc.id],
|
|
3176
|
+
type: funcOf([], out),
|
|
3177
|
+
loc,
|
|
3178
|
+
},
|
|
3179
|
+
loc,
|
|
3180
|
+
},
|
|
3181
|
+
],
|
|
3182
|
+
loc,
|
|
3183
|
+
});
|
|
3184
|
+
}
|
|
3185
|
+
return {
|
|
3186
|
+
closure: { kind: "call", callee: maker, args: [value], type: funcOf([], out), loc },
|
|
3187
|
+
out,
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
function lowerIterableSource(lowerer, node, fn, loc) {
|
|
3191
|
+
if (fn === null) {
|
|
3192
|
+
const webElem = staticReadableStreamElementType(lowerer, node);
|
|
3193
|
+
if (webElem !== null)
|
|
3194
|
+
return lowerWebStreamSource(lowerer, node, webElem, loc);
|
|
3195
|
+
}
|
|
3196
|
+
let value;
|
|
3197
|
+
if (fn !== null) {
|
|
3198
|
+
if (fn.parameters.nodes.length > 0) {
|
|
3199
|
+
lowerer.noLowering("a synchronous generator function pipeline source with parameters", fn.parameters.nodes[0], "declare the source without parameters, or make it an async generator function");
|
|
2310
3200
|
}
|
|
3201
|
+
value = lowerer.lowerLambda(fn);
|
|
3202
|
+
if (value.type.kind !== "func" || value.type.ret.kind !== "generator")
|
|
3203
|
+
return null;
|
|
3204
|
+
}
|
|
3205
|
+
else {
|
|
3206
|
+
value = lowerer.lowerExpr(node);
|
|
3207
|
+
}
|
|
3208
|
+
const srcT = value.type;
|
|
3209
|
+
const elemT = srcT.kind === "func" && srcT.ret.kind === "generator"
|
|
3210
|
+
? srcT.ret.yieldT
|
|
3211
|
+
: srcT.kind === "array"
|
|
3212
|
+
? srcT.elem
|
|
3213
|
+
: srcT.kind === "string"
|
|
3214
|
+
? STRING
|
|
3215
|
+
: srcT.kind === "generator" && srcT.async !== true
|
|
3216
|
+
? srcT.yieldT
|
|
3217
|
+
: null;
|
|
3218
|
+
if (elemT === null)
|
|
3219
|
+
return null;
|
|
3220
|
+
const out = {
|
|
3221
|
+
kind: "generator",
|
|
3222
|
+
async: true,
|
|
3223
|
+
yieldT: elemT,
|
|
3224
|
+
retT: VOID,
|
|
3225
|
+
nextT: UNDEFINED_T,
|
|
3226
|
+
};
|
|
3227
|
+
const resultType = genResultRecord(elemT, VOID, lowerer.shapes, lowerer.unions);
|
|
3228
|
+
if (!resultType)
|
|
3229
|
+
return null;
|
|
3230
|
+
const key = `pipelineSource:${typeKey(srcT)}`;
|
|
3231
|
+
let maker = lowerer.valueHelpers.get(key);
|
|
3232
|
+
if (!maker) {
|
|
3233
|
+
maker = `%stream.pipelineSource.${lowerer.valueHelpers.size}`;
|
|
3234
|
+
const genName = `${maker}.gen`;
|
|
3235
|
+
// The generator: g = the source's iterator; for (v of g) yield v.
|
|
3236
|
+
const frame = new LiftedFrame(loc);
|
|
3237
|
+
const srcId = frame.local("src", srcT, false);
|
|
3238
|
+
const src = varRef(srcId, srcT, loc);
|
|
3239
|
+
const syncT = {
|
|
3240
|
+
kind: "generator",
|
|
3241
|
+
yieldT: elemT,
|
|
3242
|
+
retT: VOID,
|
|
3243
|
+
nextT: UNDEFINED_T,
|
|
3244
|
+
};
|
|
3245
|
+
let iterator;
|
|
3246
|
+
if (srcT.kind === "func") {
|
|
3247
|
+
iterator = { kind: "callValue", callee: src, args: [], type: srcT.ret, loc };
|
|
3248
|
+
}
|
|
3249
|
+
else if (srcT.kind === "array") {
|
|
3250
|
+
iterator = lowerArrayIteratorValue(lowerer, src, "values", syncT, loc);
|
|
3251
|
+
}
|
|
3252
|
+
else if (srcT.kind === "string") {
|
|
3253
|
+
iterator = lowerStringIteratorValue(lowerer, src, syncT, loc);
|
|
3254
|
+
}
|
|
3255
|
+
else {
|
|
3256
|
+
iterator = src;
|
|
3257
|
+
}
|
|
3258
|
+
if (iterator === null || iterator.type.kind !== "generator" || !stepDrivable(iterator.type))
|
|
3259
|
+
return null;
|
|
3260
|
+
const iterT = iterator.type;
|
|
3261
|
+
const gId = frame.local("g", iterT, false);
|
|
3262
|
+
const body = [
|
|
3263
|
+
{ kind: "varDecl", localId: gId, init: iterator, loc },
|
|
3264
|
+
...driveGenerator(lowerer, frame, gId, iterT, elemT, [], (v) => [{ kind: "exprStmt", expr: { kind: "yieldExpr", value: v, type: VOID, loc }, loc }], loc),
|
|
3265
|
+
{ kind: "return", value: null, loc },
|
|
3266
|
+
];
|
|
3267
|
+
const srcLocal = frame.locals.find((l) => l.id === srcId);
|
|
3268
|
+
srcLocal.boxed = true;
|
|
3269
|
+
lowerer.valueHelpers.set(key, maker);
|
|
3270
|
+
lowerer.liftedFns.push({
|
|
3271
|
+
name: genName,
|
|
3272
|
+
params: [],
|
|
3273
|
+
returnType: VOID,
|
|
3274
|
+
async: true,
|
|
3275
|
+
captures: [{ localId: srcId, name: "src", type: srcT }],
|
|
3276
|
+
locals: frame.locals,
|
|
3277
|
+
body,
|
|
3278
|
+
generator: { yieldT: elemT, nextT: UNDEFINED_T, resultType },
|
|
3279
|
+
loc,
|
|
3280
|
+
});
|
|
3281
|
+
// The maker: (src) => the generator function closed over src.
|
|
3282
|
+
const makerSrc = { id: "src.0", name: "src", type: srcT, mutable: false, boxed: true };
|
|
3283
|
+
lowerer.liftedFns.push({
|
|
3284
|
+
name: maker,
|
|
3285
|
+
params: [{ localId: makerSrc.id, name: makerSrc.name, type: srcT }],
|
|
3286
|
+
returnType: funcOf([], out),
|
|
3287
|
+
locals: [makerSrc],
|
|
3288
|
+
body: [
|
|
3289
|
+
{
|
|
3290
|
+
kind: "return",
|
|
3291
|
+
value: {
|
|
3292
|
+
kind: "closure",
|
|
3293
|
+
fnName: genName,
|
|
3294
|
+
captures: [makerSrc.id],
|
|
3295
|
+
type: funcOf([], out),
|
|
3296
|
+
loc,
|
|
3297
|
+
},
|
|
3298
|
+
loc,
|
|
3299
|
+
},
|
|
3300
|
+
],
|
|
3301
|
+
loc,
|
|
3302
|
+
});
|
|
3303
|
+
}
|
|
3304
|
+
return {
|
|
3305
|
+
closure: { kind: "call", callee: maker, args: [value], type: funcOf([], out), loc },
|
|
3306
|
+
out,
|
|
3307
|
+
};
|
|
3308
|
+
}
|
|
3309
|
+
/** pipeline(...) with function stages (pipeline.js). A function may
|
|
3310
|
+
* start the pipeline (a source function, called with `{ signal }`), may
|
|
3311
|
+
* end it (an async function whose promise's value reaches the callback or
|
|
3312
|
+
* the promise, or an async generator function), and runs of async
|
|
3313
|
+
* generator functions may sit between streams; the last generator of a
|
|
3314
|
+
* run that a stream follows is pumped into that stream. A function
|
|
3315
|
+
* destination feeds the object-mode PassThrough that pipeline() answers. Each stage's `source` parameter is typed as what the
|
|
3316
|
+
* pipeline passes it: makeAsyncIterable answers the previous stream
|
|
3317
|
+
* itself (a Readable is async iterable) or the previous stage's
|
|
3318
|
+
* generator. */
|
|
3319
|
+
function lowerPipelineStages(lowerer, stageArgs, loc, preLowered) {
|
|
3320
|
+
if (stageArgs.length > 52) {
|
|
3321
|
+
lowerer.noLowering("pipeline with function stages and more than 52 stages", stageArgs[52], "split the pipeline");
|
|
3322
|
+
}
|
|
3323
|
+
const streams = [];
|
|
3324
|
+
const stages = [];
|
|
3325
|
+
const helperArgs = [];
|
|
3326
|
+
let positions = 0;
|
|
3327
|
+
let mask = 0;
|
|
3328
|
+
let dest = 0;
|
|
3329
|
+
let destPromise = null;
|
|
3330
|
+
// What the next function stage receives: null before the first stage,
|
|
3331
|
+
// else the previous stream's type or the previous stage's generator.
|
|
3332
|
+
let srcT = null;
|
|
3333
|
+
// The streams and stages in argument order: the head lists all streams
|
|
3334
|
+
// before all stages, so when a stage precedes a stream the arguments
|
|
3335
|
+
// are bound to locals first, keeping JavaScript's evaluation order.
|
|
3336
|
+
const argOrder = [];
|
|
3337
|
+
for (let j = 0; j < stageArgs.length; j++) {
|
|
3338
|
+
const arg = stageArgs[j];
|
|
3339
|
+
// compose's head and tail functions arrive as Duplex.from streams
|
|
3340
|
+
const fn = preLowered?.has(j) ? null : pipelineStageFunction(lowerer, arg);
|
|
3341
|
+
const syncSourceFn = j === 0 &&
|
|
3342
|
+
fn !== null &&
|
|
3343
|
+
!ts.isArrowFunction(fn) &&
|
|
3344
|
+
fn.asteriskToken !== undefined &&
|
|
3345
|
+
!(fn.modifiers?.nodes ?? []).some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
|
|
3346
|
+
if (j === 0 &&
|
|
3347
|
+
!preLowered?.has(j) &&
|
|
3348
|
+
(syncSourceFn || (fn === null && iterableSourceType(lowerer, arg) !== null))) {
|
|
3349
|
+
const source = lowerIterableSource(lowerer, arg, syncSourceFn ? fn : null, loc);
|
|
3350
|
+
if (source === null)
|
|
3351
|
+
lowerer.noLowering("pipeline over this source", arg);
|
|
3352
|
+
positions += 1;
|
|
3353
|
+
argOrder.push({ list: stages, index: stages.length });
|
|
3354
|
+
stages.push(source.closure);
|
|
3355
|
+
srcT = source.out;
|
|
3356
|
+
continue;
|
|
3357
|
+
}
|
|
3358
|
+
if (fn === null) {
|
|
3359
|
+
if (srcT?.kind === "generator") {
|
|
3360
|
+
// the generator before this stream, pumped into it
|
|
3361
|
+
if (!fromGenChunk(lowerer, srcT.yieldT)) {
|
|
3362
|
+
lowerer.noLowering(`a pipeline stage yielding '${lowerer.fmt(srcT.yieldT)}'`, stageArgs[j - 1], "stage values written to a stream are strings or Buffers");
|
|
3363
|
+
}
|
|
3364
|
+
const helpers = fromGenHelpers(lowerer, srcT, loc);
|
|
3365
|
+
if (!helpers)
|
|
3366
|
+
lowerer.noLowering("a pipeline stage with this generator type", stageArgs[j - 1]);
|
|
3367
|
+
helperArgs.push(helpers[0], helpers[1], helpers[2]);
|
|
3368
|
+
}
|
|
3369
|
+
let stream;
|
|
3370
|
+
try {
|
|
3371
|
+
stream = preLowered?.get(j) ?? lowerStreamArg(lowerer, arg, "pipeline");
|
|
3372
|
+
}
|
|
3373
|
+
catch (e) {
|
|
3374
|
+
if (e instanceof StreamArgTypeThrow)
|
|
3375
|
+
lowerer.noLowering("pipeline over this value", arg);
|
|
3376
|
+
throw e;
|
|
3377
|
+
}
|
|
3378
|
+
argOrder.push({ list: streams, index: streams.length });
|
|
3379
|
+
streams.push(stream);
|
|
3380
|
+
srcT = stream.type;
|
|
3381
|
+
continue;
|
|
3382
|
+
}
|
|
3383
|
+
const isLast = j === stageArgs.length - 1;
|
|
3384
|
+
const isAsync = (fn.modifiers?.nodes ?? []).some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
|
|
3385
|
+
const isGen = !ts.isArrowFunction(fn) && fn.asteriskToken !== undefined;
|
|
3386
|
+
if (!isAsync || (!isGen && !isLast)) {
|
|
3387
|
+
lowerer.noLowering(isLast
|
|
3388
|
+
? "a pipeline destination that is not an async function"
|
|
3389
|
+
: srcT === null
|
|
3390
|
+
? "a pipeline source function that is not an async generator function"
|
|
3391
|
+
: "pipeline stages that are not async generator functions", arg, "write the stage as async function* (source) { for await (const chunk of source) ... }");
|
|
3392
|
+
}
|
|
3393
|
+
const optionsAt = srcT === null ? 0 : 1;
|
|
3394
|
+
if (fn.parameters.nodes.length > optionsAt + 1) {
|
|
3395
|
+
lowerer.noLowering("pipeline stages with parameters after the options argument", fn.parameters.nodes[optionsAt + 1], "a stage takes the source and { signal }");
|
|
3396
|
+
}
|
|
3397
|
+
const lowered = lowerStageFunction(lowerer, fn, srcT);
|
|
3398
|
+
const params = lowered.closure.type.kind === "func" ? lowered.closure.type.params : [];
|
|
3399
|
+
if (params.length > optionsAt) {
|
|
3400
|
+
if (params[optionsAt].kind !== "dyn") {
|
|
3401
|
+
lowerer.noLowering("a pipeline stage's options argument with this type", fn.parameters.nodes[optionsAt], "type it as { signal: AbortSignal }");
|
|
3402
|
+
}
|
|
3403
|
+
mask |= 1 << stages.length;
|
|
3404
|
+
}
|
|
3405
|
+
positions += 2 ** j;
|
|
3406
|
+
argOrder.push({ list: stages, index: stages.length });
|
|
2311
3407
|
stages.push(lowered.closure);
|
|
2312
3408
|
if (lowered.out.kind === "promise") {
|
|
2313
3409
|
dest = 2;
|
|
2314
3410
|
destPromise = lowered.out;
|
|
2315
3411
|
srcT = null;
|
|
2316
3412
|
}
|
|
3413
|
+
else if (isLast) {
|
|
3414
|
+
// an async generator destination: pumped into the object-mode
|
|
3415
|
+
// PassThrough that pipeline() answers
|
|
3416
|
+
const helpers = fromGenHelpers(lowerer, lowered.out, loc);
|
|
3417
|
+
if (!helpers)
|
|
3418
|
+
lowerer.noLowering("a pipeline destination with this generator type", arg);
|
|
3419
|
+
helperArgs.push(helpers[0], helpers[1], helpers[2]);
|
|
3420
|
+
dest = 1;
|
|
3421
|
+
srcT = null;
|
|
3422
|
+
}
|
|
2317
3423
|
else {
|
|
2318
3424
|
srcT = lowered.out;
|
|
2319
3425
|
}
|
|
2320
3426
|
}
|
|
2321
|
-
|
|
2322
|
-
for (const a of stageArgs.slice(end))
|
|
2323
|
-
after.push(lowerStreamArg(lowerer, a, "pipeline"));
|
|
2324
|
-
}
|
|
2325
|
-
catch (e) {
|
|
2326
|
-
if (e instanceof StreamArgTypeThrow)
|
|
2327
|
-
lowerer.noLowering("pipeline over this value", stageArgs[end]);
|
|
2328
|
-
throw e;
|
|
2329
|
-
}
|
|
2330
|
-
const helperArgs = [];
|
|
2331
|
-
if (dest !== 2) {
|
|
2332
|
-
// the generator pumped into the next stream or the PassThrough
|
|
2333
|
-
const lastGen = srcT;
|
|
2334
|
-
if (!fromGenChunk(lowerer, lastGen.yieldT)) {
|
|
2335
|
-
lowerer.noLowering(`a pipeline stage yielding '${lowerer.fmt(lastGen.yieldT)}'`, stageArgs[end - 1], "stage values written to a stream are strings or Buffers");
|
|
2336
|
-
}
|
|
2337
|
-
const helpers = fromGenHelpers(lowerer, lastGen, loc);
|
|
2338
|
-
if (!helpers)
|
|
2339
|
-
lowerer.noLowering("a pipeline stage with this generator type", stageArgs[end - 1]);
|
|
2340
|
-
helperArgs.push(helpers[0], helpers[1], helpers[2]);
|
|
2341
|
-
}
|
|
2342
|
-
else {
|
|
3427
|
+
if (dest === 2) {
|
|
2343
3428
|
const valueT = destPromise.inner;
|
|
2344
3429
|
if (valueT.kind !== "void" &&
|
|
2345
3430
|
!canConvertToDyn(valueT, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
2346
|
-
lowerer.noLowering(`a pipeline destination resolving to '${lowerer.fmt(valueT)}'`, stageArgs[
|
|
3431
|
+
lowerer.noLowering(`a pipeline destination resolving to '${lowerer.fmt(valueT)}'`, stageArgs[stageArgs.length - 1]);
|
|
2347
3432
|
}
|
|
2348
3433
|
helperArgs.push(pipelineBoxHelper(lowerer, destPromise, loc));
|
|
2349
3434
|
}
|
|
2350
|
-
const
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
3435
|
+
const argDecls = [];
|
|
3436
|
+
const firstStage = argOrder.findIndex((a) => a.list === stages);
|
|
3437
|
+
if (firstStage >= 0 && argOrder.slice(firstStage).some((a) => a.list === streams)) {
|
|
3438
|
+
for (const a of argOrder) {
|
|
3439
|
+
const init = a.list[a.index];
|
|
3440
|
+
const local = lowerer.declareHiddenLocal("%pipelineArg", init.type);
|
|
3441
|
+
argDecls.push({ kind: "varDecl", localId: local.id, init, loc: init.loc });
|
|
3442
|
+
a.list[a.index] = varRef(local.id, init.type, init.loc);
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
const bindArgs = (call) => argDecls.length === 0
|
|
3446
|
+
? call
|
|
3447
|
+
: { kind: "seqExpr", stmts: argDecls, result: call, type: call.type, loc };
|
|
3448
|
+
// SCR_PIPE_* flags: bits 1-2 the destination, bit 5 the signal and
|
|
3449
|
+
// abort (bit 6, the promise form's options signal, is set by its caller).
|
|
3450
|
+
const flags = (dest << 1) | (mask !== 0 ? 32 : 0);
|
|
2354
3451
|
const head = [
|
|
2355
3452
|
numLit(streams.length, loc),
|
|
2356
|
-
numLit(before.length, loc),
|
|
2357
3453
|
numLit(stages.length, loc),
|
|
3454
|
+
numLit(positions, loc),
|
|
2358
3455
|
numLit(flags, loc),
|
|
2359
3456
|
numLit(mask, loc),
|
|
2360
3457
|
...streams,
|
|
2361
3458
|
...stages,
|
|
2362
3459
|
...helperArgs,
|
|
2363
3460
|
];
|
|
2364
|
-
const last =
|
|
2365
|
-
? { kind: "object", className: "%PassThrough" }
|
|
2366
|
-
: streams[streams.length - 1].type;
|
|
3461
|
+
const last = dest !== 0 ? { kind: "object", className: "%PassThrough" } : streams[streams.length - 1].type;
|
|
2367
3462
|
if (mask === 0)
|
|
2368
|
-
return { args: head, last, dest, destPromise, wrap:
|
|
3463
|
+
return { args: head, last, dest, destPromise, wrap: bindArgs };
|
|
2369
3464
|
// const ac = new AbortController(): its signal goes to the stages, and
|
|
2370
3465
|
// finishImpl's ac.abort() runs through the abort closure.
|
|
2371
3466
|
const ac = lowerer.declareHiddenLocal("%pipelineAbort", DYN);
|
|
@@ -2382,7 +3477,7 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2382
3477
|
last,
|
|
2383
3478
|
dest,
|
|
2384
3479
|
destPromise,
|
|
2385
|
-
wrap: (call) => ({
|
|
3480
|
+
wrap: (call) => bindArgs({
|
|
2386
3481
|
kind: "seqExpr",
|
|
2387
3482
|
stmts: [
|
|
2388
3483
|
{
|
|
@@ -2405,7 +3500,7 @@ function pipelineBoxHelper(lowerer, promiseT, loc) {
|
|
|
2405
3500
|
const key = `pipelineBox:${typeKey(promiseT)}`;
|
|
2406
3501
|
let name = lowerer.valueHelpers.get(key);
|
|
2407
3502
|
if (!name) {
|
|
2408
|
-
name =
|
|
3503
|
+
name = keyedHelperName(lowerer, "%stream.pipelineBox", key);
|
|
2409
3504
|
lowerer.valueHelpers.set(key, name);
|
|
2410
3505
|
lowerer.liftedFns.push({
|
|
2411
3506
|
name,
|
|
@@ -2426,21 +3521,22 @@ function pipelineBoxHelper(lowerer, promiseT, loc) {
|
|
|
2426
3521
|
}
|
|
2427
3522
|
/** `() => ac.abort()` over the pipeline's AbortController: an interned
|
|
2428
3523
|
* lifted function takes the controller and answers the closure. */
|
|
2429
|
-
function pipelineAbortHelper(lowerer, ac, loc) {
|
|
2430
|
-
const key = "pipelineAbort";
|
|
3524
|
+
function pipelineAbortHelper(lowerer, ac, loc, withReason = false) {
|
|
3525
|
+
const key = withReason ? "pipelineAbortReason" : "pipelineAbort";
|
|
2431
3526
|
let name = lowerer.valueHelpers.get(key);
|
|
2432
|
-
const abortT = funcOf([], VOID);
|
|
3527
|
+
const abortT = funcOf(withReason ? [DYN] : [], VOID);
|
|
2433
3528
|
if (!name) {
|
|
2434
|
-
name =
|
|
3529
|
+
name = keyedHelperName(lowerer, "%stream.pipelineAbort", key);
|
|
2435
3530
|
lowerer.valueHelpers.set(key, name);
|
|
2436
3531
|
const acLocal = { id: "ac.0", name: "ac", type: DYN, mutable: false, boxed: true };
|
|
2437
3532
|
const acRef = varRef(acLocal.id, DYN, loc);
|
|
3533
|
+
const reasonLocal = { id: "reason.0", name: "reason", type: DYN, mutable: false };
|
|
2438
3534
|
lowerer.liftedFns.push({
|
|
2439
3535
|
name: `${name}.abort`,
|
|
2440
|
-
params: [],
|
|
3536
|
+
params: withReason ? [{ localId: reasonLocal.id, name: reasonLocal.name, type: DYN }] : [],
|
|
2441
3537
|
returnType: VOID,
|
|
2442
3538
|
captures: [{ localId: acLocal.id, name: acLocal.name, type: DYN }],
|
|
2443
|
-
locals: [acLocal],
|
|
3539
|
+
locals: withReason ? [acLocal, reasonLocal] : [acLocal],
|
|
2444
3540
|
body: [
|
|
2445
3541
|
{
|
|
2446
3542
|
kind: "exprStmt",
|
|
@@ -2449,7 +3545,7 @@ function pipelineAbortHelper(lowerer, ac, loc) {
|
|
|
2449
3545
|
recv: acRef,
|
|
2450
3546
|
method: "abort",
|
|
2451
3547
|
calleeName: "ac.abort",
|
|
2452
|
-
args: [],
|
|
3548
|
+
args: withReason ? [varRef(reasonLocal.id, DYN, loc)] : [],
|
|
2453
3549
|
type: DYN,
|
|
2454
3550
|
loc,
|
|
2455
3551
|
},
|
|
@@ -2494,6 +3590,8 @@ function lowerStageFunction(lowerer, fn, srcT) {
|
|
|
2494
3590
|
if (param && !symbol) {
|
|
2495
3591
|
lowerer.noLowering("pipeline stage parameters that are patterns", param, "name the source parameter");
|
|
2496
3592
|
}
|
|
3593
|
+
// The loop variables of the `for await` loops over the source.
|
|
3594
|
+
const chunkSymbols = [];
|
|
2497
3595
|
if (symbol && fn.body) {
|
|
2498
3596
|
const visit = (node) => {
|
|
2499
3597
|
if (ts.isIdentifier(node) &&
|
|
@@ -2506,6 +3604,14 @@ function lowerStageFunction(lowerer, fn, srcT) {
|
|
|
2506
3604
|
parent.expression === node)) {
|
|
2507
3605
|
lowerer.noLowering("a pipeline stage's source used outside a for await loop head", node, "iterate the source with for await (const chunk of source)");
|
|
2508
3606
|
}
|
|
3607
|
+
const binding = ts.isVariableDeclarationList(parent.initializer)
|
|
3608
|
+
? parent.initializer.declarations.nodes[0]?.name
|
|
3609
|
+
: undefined;
|
|
3610
|
+
const chunk = binding && ts.isIdentifier(binding)
|
|
3611
|
+
? lowerer.checker.getSymbolAtLocation(binding)
|
|
3612
|
+
: undefined;
|
|
3613
|
+
if (chunk)
|
|
3614
|
+
chunkSymbols.push(chunk);
|
|
2509
3615
|
}
|
|
2510
3616
|
ts.forEachChild(node, visit);
|
|
2511
3617
|
};
|
|
@@ -2513,8 +3619,22 @@ function lowerStageFunction(lowerer, fn, srcT) {
|
|
|
2513
3619
|
}
|
|
2514
3620
|
if (symbol)
|
|
2515
3621
|
lowerer.stageSourceTypes.set(symbol, srcT);
|
|
3622
|
+
// In JavaScript the checker types the chunks of a source that is the
|
|
3623
|
+
// previous stage's generator `any`; they read as the strings or Buffers
|
|
3624
|
+
// the generator yields, so their members take the string and Buffer
|
|
3625
|
+
// lowerings.
|
|
3626
|
+
const previousImplicit = lowerer.implicitParamTypes;
|
|
3627
|
+
const chunkType = srcT?.kind === "generator" && isJsSourceFile(ts.getSourceFileOfNode(fn))
|
|
3628
|
+
? stageChunkCheckerType(lowerer, srcT.yieldT, fn)
|
|
3629
|
+
: null;
|
|
3630
|
+
if (chunkType && chunkSymbols.length > 0) {
|
|
3631
|
+
const implicit = new Map(previousImplicit ?? []);
|
|
3632
|
+
for (const chunk of chunkSymbols)
|
|
3633
|
+
implicit.set(chunk, chunkType);
|
|
3634
|
+
lowerer.implicitParamTypes = implicit;
|
|
3635
|
+
}
|
|
2516
3636
|
try {
|
|
2517
|
-
const closure = lowerer.
|
|
3637
|
+
const closure = lowerer.lowerLambda(fn);
|
|
2518
3638
|
const out = closure.type.kind === "func" ? closure.type.ret : null;
|
|
2519
3639
|
if (!(out?.kind === "generator" && out.async) && out?.kind !== "promise") {
|
|
2520
3640
|
lowerer.noLowering("a pipeline stage that does not return an async generator", fn);
|
|
@@ -2524,25 +3644,391 @@ function lowerStageFunction(lowerer, fn, srcT) {
|
|
|
2524
3644
|
finally {
|
|
2525
3645
|
if (symbol)
|
|
2526
3646
|
lowerer.stageSourceTypes.delete(symbol);
|
|
3647
|
+
lowerer.implicitParamTypes = previousImplicit;
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
/** The async generator a Duplex.from body iterates (duplexify.js's
|
|
3651
|
+
* fromAsyncGen source), as a closure the runtime calls with next() and
|
|
3652
|
+
* ack(): each pass awaits next() (the deferred a write or the final
|
|
3653
|
+
* settles), calls ack() (process.nextTick(cb) and a fresh deferred),
|
|
3654
|
+
* returns at the done marker, and yields the chunk. */
|
|
3655
|
+
function duplexSourceHelper(lowerer, genT, loc) {
|
|
3656
|
+
const nextT = funcOf([], { kind: "promise", inner: DYN });
|
|
3657
|
+
const ackT = funcOf([], VOID);
|
|
3658
|
+
const type = funcOf([nextT, ackT], genT);
|
|
3659
|
+
const key = "duplexSource";
|
|
3660
|
+
let name = lowerer.valueHelpers.get(key);
|
|
3661
|
+
if (!name) {
|
|
3662
|
+
const resultType = genResultRecord(DYN, VOID, lowerer.shapes, lowerer.unions);
|
|
3663
|
+
if (!resultType)
|
|
3664
|
+
return null;
|
|
3665
|
+
name = `%stream.duplexSource.${lowerer.valueHelpers.size}`;
|
|
3666
|
+
const frame = new LiftedFrame(loc);
|
|
3667
|
+
const nextId = frame.param("next", nextT);
|
|
3668
|
+
const ackId = frame.param("ack", ackT);
|
|
3669
|
+
const valueId = frame.local("value", DYN, false);
|
|
3670
|
+
const value = varRef(valueId, DYN, loc);
|
|
3671
|
+
const body = [
|
|
3672
|
+
{
|
|
3673
|
+
kind: "while",
|
|
3674
|
+
cond: { kind: "boolLit", value: true, type: BOOL, loc },
|
|
3675
|
+
body: [
|
|
3676
|
+
{
|
|
3677
|
+
kind: "varDecl",
|
|
3678
|
+
localId: valueId,
|
|
3679
|
+
init: {
|
|
3680
|
+
kind: "awaitExpr",
|
|
3681
|
+
value: {
|
|
3682
|
+
kind: "callValue",
|
|
3683
|
+
callee: varRef(nextId, nextT, loc),
|
|
3684
|
+
args: [],
|
|
3685
|
+
type: { kind: "promise", inner: DYN },
|
|
3686
|
+
loc,
|
|
3687
|
+
},
|
|
3688
|
+
type: DYN,
|
|
3689
|
+
loc,
|
|
3690
|
+
},
|
|
3691
|
+
loc,
|
|
3692
|
+
},
|
|
3693
|
+
{
|
|
3694
|
+
kind: "exprStmt",
|
|
3695
|
+
expr: {
|
|
3696
|
+
kind: "callValue",
|
|
3697
|
+
callee: varRef(ackId, ackT, loc),
|
|
3698
|
+
args: [],
|
|
3699
|
+
type: VOID,
|
|
3700
|
+
loc,
|
|
3701
|
+
},
|
|
3702
|
+
loc,
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
kind: "if",
|
|
3706
|
+
cond: { kind: "libCall", fn: "stream.chunkDone", args: [value], type: BOOL, loc },
|
|
3707
|
+
then: [{ kind: "return", value: null, loc }],
|
|
3708
|
+
else_: null,
|
|
3709
|
+
loc,
|
|
3710
|
+
},
|
|
3711
|
+
{ kind: "exprStmt", expr: { kind: "yieldExpr", value, type: VOID, loc }, loc },
|
|
3712
|
+
],
|
|
3713
|
+
loc,
|
|
3714
|
+
},
|
|
3715
|
+
{ kind: "return", value: null, loc },
|
|
3716
|
+
];
|
|
3717
|
+
lowerer.valueHelpers.set(key, name);
|
|
3718
|
+
lowerer.liftedFns.push({
|
|
3719
|
+
name,
|
|
3720
|
+
params: frame.params,
|
|
3721
|
+
returnType: VOID,
|
|
3722
|
+
async: true,
|
|
3723
|
+
locals: frame.locals,
|
|
3724
|
+
body,
|
|
3725
|
+
generator: { yieldT: DYN, nextT: UNDEFINED_T, resultType },
|
|
3726
|
+
loc,
|
|
3727
|
+
});
|
|
2527
3728
|
}
|
|
3729
|
+
return { kind: "closure", fnName: name, captures: [], type, loc };
|
|
3730
|
+
}
|
|
3731
|
+
/** Duplex.from(body) (duplexify.js) for the bodies with a lowering: an
|
|
3732
|
+
* async generator function, whose source generator the Duplex's writes
|
|
3733
|
+
* feed (stream.duplexFromGen); a duplex stream, which answers itself; and
|
|
3734
|
+
* the bodies Readable.from reads (iterables, strings, generators), as a
|
|
3735
|
+
* Duplexify that is not writable. */
|
|
3736
|
+
function duplexFromBody(lowerer, node, loc) {
|
|
3737
|
+
const duplex = { kind: "object", className: "%Duplex" };
|
|
3738
|
+
const fn = pipelineStageFunction(lowerer, node);
|
|
3739
|
+
if (fn !== null) {
|
|
3740
|
+
const isAsync = (fn.modifiers?.nodes ?? []).some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
|
|
3741
|
+
const isGen = !ts.isArrowFunction(fn) && fn.asteriskToken !== undefined;
|
|
3742
|
+
if (!isAsync) {
|
|
3743
|
+
lowerer.noLowering("Duplex.from over a function that is not async", node, "write the body as async function* (source) { ... } or async function (source) { ... }");
|
|
3744
|
+
}
|
|
3745
|
+
if (fn.parameters.nodes.length > 2) {
|
|
3746
|
+
lowerer.noLowering("a Duplex.from body with parameters after the options argument", fn.parameters.nodes[2], "the body takes the source and { signal }");
|
|
3747
|
+
}
|
|
3748
|
+
const sourceT = {
|
|
3749
|
+
kind: "generator",
|
|
3750
|
+
async: true,
|
|
3751
|
+
yieldT: DYN,
|
|
3752
|
+
retT: VOID,
|
|
3753
|
+
nextT: UNDEFINED_T,
|
|
3754
|
+
};
|
|
3755
|
+
const lowered = lowerStageFunction(lowerer, fn, sourceT);
|
|
3756
|
+
const params = lowered.closure.type.kind === "func" ? lowered.closure.type.params : [];
|
|
3757
|
+
// fromAsyncGen calls the body with { signal } of an AbortController
|
|
3758
|
+
// that destroy aborts with its error.
|
|
3759
|
+
let signalArgs = [];
|
|
3760
|
+
let signalDecls = [];
|
|
3761
|
+
if (params.length > 1) {
|
|
3762
|
+
if (params[1].kind !== "dyn") {
|
|
3763
|
+
lowerer.noLowering("a Duplex.from body's options argument with this type", fn.parameters.nodes[1], "type it as { signal: AbortSignal }");
|
|
3764
|
+
}
|
|
3765
|
+
const acLocal = lowerer.declareHiddenLocal("%duplexAbort", DYN);
|
|
3766
|
+
const ac = varRef(acLocal.id, DYN, loc);
|
|
3767
|
+
signalDecls = [
|
|
3768
|
+
{
|
|
3769
|
+
kind: "varDecl",
|
|
3770
|
+
localId: acLocal.id,
|
|
3771
|
+
init: { kind: "libCall", fn: "fetch.abortControllerNew", args: [], type: DYN, loc },
|
|
3772
|
+
loc,
|
|
3773
|
+
},
|
|
3774
|
+
];
|
|
3775
|
+
signalArgs = [
|
|
3776
|
+
pipelineAbortHelper(lowerer, ac, loc, true),
|
|
3777
|
+
{ kind: "dynKeyGet", value: ac, key: strLit("signal", loc), type: DYN, loc },
|
|
3778
|
+
];
|
|
3779
|
+
}
|
|
3780
|
+
const withSignal = (fnName, args) => {
|
|
3781
|
+
const call = {
|
|
3782
|
+
kind: "libCall",
|
|
3783
|
+
fn: signalArgs.length > 0 ? `${fnName}Signal` : fnName,
|
|
3784
|
+
args: [...args, ...signalArgs],
|
|
3785
|
+
type: duplex,
|
|
3786
|
+
loc,
|
|
3787
|
+
};
|
|
3788
|
+
return signalDecls.length > 0
|
|
3789
|
+
? { kind: "seqExpr", stmts: signalDecls, result: call, type: duplex, loc }
|
|
3790
|
+
: call;
|
|
3791
|
+
};
|
|
3792
|
+
if (!isGen) {
|
|
3793
|
+
// an async function: a writable Duplexify whose final waits for
|
|
3794
|
+
// the function's promise
|
|
3795
|
+
const asyncSource = duplexSourceHelper(lowerer, sourceT, loc);
|
|
3796
|
+
const out = lowered.out;
|
|
3797
|
+
if (out.kind !== "promise" || !asyncSource)
|
|
3798
|
+
return lowerer.noLowering("Duplex.from over a function with this return type", node);
|
|
3799
|
+
if (out.inner.kind !== "void" &&
|
|
3800
|
+
!canConvertToDyn(out.inner, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
3801
|
+
lowerer.noLowering(`Duplex.from over a function resolving to '${lowerer.fmt(out.inner)}'`, node);
|
|
3802
|
+
}
|
|
3803
|
+
return withSignal("stream.duplexFromAsyncFn", [
|
|
3804
|
+
lowered.closure,
|
|
3805
|
+
asyncSource,
|
|
3806
|
+
pipelineBoxHelper(lowerer, out, loc),
|
|
3807
|
+
]);
|
|
3808
|
+
}
|
|
3809
|
+
const helpers = lowered.out.kind === "generator" ? fromGenHelpers(lowerer, lowered.out, loc) : null;
|
|
3810
|
+
const source = duplexSourceHelper(lowerer, sourceT, loc);
|
|
3811
|
+
if (!helpers || !source)
|
|
3812
|
+
lowerer.noLowering("Duplex.from over a function with this generator type", node);
|
|
3813
|
+
return withSignal("stream.duplexFromGen", [lowered.closure, source, ...helpers]);
|
|
3814
|
+
}
|
|
3815
|
+
// duplexify.js: a stream answers itself (a Duplex) or is wrapped; any
|
|
3816
|
+
// other body reads as from(Duplexify, body, { objectMode: true,
|
|
3817
|
+
// writable: false })
|
|
3818
|
+
let bodyT;
|
|
3819
|
+
try {
|
|
3820
|
+
bodyT = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
3821
|
+
}
|
|
3822
|
+
catch {
|
|
3823
|
+
bodyT = null;
|
|
3824
|
+
}
|
|
3825
|
+
const bodySides = bodyT?.kind === "object" ? streamSidesOf(lowerer, lowerer.classes.get(bodyT.className)) : null;
|
|
3826
|
+
let literal = node;
|
|
3827
|
+
while (ts.isParenthesizedExpression(literal))
|
|
3828
|
+
literal = literal.expression;
|
|
3829
|
+
if (bodySides === null && ts.isObjectLiteralExpression(literal))
|
|
3830
|
+
return duplexFromPair(lowerer, literal, loc);
|
|
3831
|
+
if (bodyT?.kind === "promise") {
|
|
3832
|
+
// a Duplexify that reads the promise's value
|
|
3833
|
+
const valueT = bodyT.inner;
|
|
3834
|
+
if (valueT.kind !== "void" &&
|
|
3835
|
+
!canConvertToDyn(valueT, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
3836
|
+
lowerer.noLowering(`Duplex.from over a promise of '${lowerer.fmt(valueT)}'`, node);
|
|
3837
|
+
}
|
|
3838
|
+
const promise = lowerer.lowerExpr(node);
|
|
3839
|
+
if (promise.type.kind !== "promise") {
|
|
3840
|
+
// a checked-dynamic promise (an untyped function's result)
|
|
3841
|
+
return {
|
|
3842
|
+
kind: "libCall",
|
|
3843
|
+
fn: "stream.duplexFromDyn",
|
|
3844
|
+
args: [lowerer.coerceToExpected(promise, DYN)],
|
|
3845
|
+
type: { kind: "object", className: "%Duplex" },
|
|
3846
|
+
loc,
|
|
3847
|
+
};
|
|
3848
|
+
}
|
|
3849
|
+
return {
|
|
3850
|
+
kind: "libCall",
|
|
3851
|
+
fn: "stream.duplexFromPromise",
|
|
3852
|
+
args: [
|
|
3853
|
+
promise,
|
|
3854
|
+
pipelineBoxHelper(lowerer, promise.type, loc),
|
|
3855
|
+
],
|
|
3856
|
+
type: { kind: "object", className: "%Duplex" },
|
|
3857
|
+
loc,
|
|
3858
|
+
};
|
|
3859
|
+
}
|
|
3860
|
+
if (bodySides === null)
|
|
3861
|
+
return lowerFromSource(lowerer, node, node, undefined, true);
|
|
3862
|
+
let stream;
|
|
3863
|
+
try {
|
|
3864
|
+
stream = lowerStreamArg(lowerer, node, "compose");
|
|
3865
|
+
}
|
|
3866
|
+
catch (e) {
|
|
3867
|
+
if (e instanceof StreamArgTypeThrow)
|
|
3868
|
+
return e.expr;
|
|
3869
|
+
throw e;
|
|
3870
|
+
}
|
|
3871
|
+
const sides = stream.type.kind === "object"
|
|
3872
|
+
? streamSidesOf(lowerer, lowerer.classes.get(stream.type.className))
|
|
3873
|
+
: null;
|
|
3874
|
+
// _duplexify({ readable }) / _duplexify({ writable })
|
|
3875
|
+
if (sides === "r" || sides === "w") {
|
|
3876
|
+
return {
|
|
3877
|
+
kind: "libCall",
|
|
3878
|
+
fn: sides === "r" ? "stream.duplexifyReadable" : "stream.duplexifyWritable",
|
|
3879
|
+
args: [stream],
|
|
3880
|
+
type: duplex,
|
|
3881
|
+
loc,
|
|
3882
|
+
};
|
|
3883
|
+
}
|
|
3884
|
+
if (sides !== "rw") {
|
|
3885
|
+
lowerer.noLowering("Duplex.from over a value of this type", node, "an async generator function, an iterable, a stream, or a { readable, writable } pair is the lowered body");
|
|
3886
|
+
}
|
|
3887
|
+
return stream;
|
|
3888
|
+
}
|
|
3889
|
+
/** Duplex.from({ readable, writable }): each member that is a stream with
|
|
3890
|
+
* that side is used as it is, any other member is Duplex.from of it, and
|
|
3891
|
+
* the pair reads and writes through _duplexify (duplexify.js). The
|
|
3892
|
+
* members evaluate in source order. */
|
|
3893
|
+
function duplexFromPair(lowerer, literal, loc) {
|
|
3894
|
+
const duplex = { kind: "object", className: "%Duplex" };
|
|
3895
|
+
const sides = {};
|
|
3896
|
+
// The members in source order; when that is not (readable, writable),
|
|
3897
|
+
// each value is bound to a local first, keeping the literal's
|
|
3898
|
+
// evaluation order.
|
|
3899
|
+
const members = [];
|
|
3900
|
+
for (const p of literal.properties.nodes) {
|
|
3901
|
+
const key = (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) && ts.isIdentifier(p.name)
|
|
3902
|
+
? p.name.text
|
|
3903
|
+
: null;
|
|
3904
|
+
if (key !== "readable" && key !== "writable") {
|
|
3905
|
+
lowerer.noLowering("Duplex.from over an object with members other than readable and writable", p, "pass { readable, writable } with streams or Duplex.from bodies");
|
|
3906
|
+
}
|
|
3907
|
+
const value = ts.isShorthandPropertyAssignment(p)
|
|
3908
|
+
? p.name
|
|
3909
|
+
: p.initializer;
|
|
3910
|
+
let valueT;
|
|
3911
|
+
try {
|
|
3912
|
+
valueT = lowerer.mapTypeOf(lowerer.typeOf(value));
|
|
3913
|
+
}
|
|
3914
|
+
catch {
|
|
3915
|
+
valueT = null;
|
|
3916
|
+
}
|
|
3917
|
+
const valueSides = valueT?.kind === "object"
|
|
3918
|
+
? streamSidesOf(lowerer, lowerer.classes.get(valueT.className))
|
|
3919
|
+
: null;
|
|
3920
|
+
const wanted = key === "readable" ? "r" : "w";
|
|
3921
|
+
const direct = valueSides === "rw" || valueSides === wanted;
|
|
3922
|
+
members.push({
|
|
3923
|
+
key: key,
|
|
3924
|
+
value: direct
|
|
3925
|
+
? lowerStreamArg(lowerer, value, "compose")
|
|
3926
|
+
: duplexFromBody(lowerer, value, loc),
|
|
3927
|
+
});
|
|
3928
|
+
}
|
|
3929
|
+
const decls = [];
|
|
3930
|
+
const inOrder = members.length <= 1 ||
|
|
3931
|
+
(members.length === 2 && members[0].key === "readable" && members[1].key === "writable");
|
|
3932
|
+
for (const m of members) {
|
|
3933
|
+
if (inOrder) {
|
|
3934
|
+
sides[m.key] = m.value;
|
|
3935
|
+
continue;
|
|
3936
|
+
}
|
|
3937
|
+
const local = lowerer.declareHiddenLocal(`%duplex${m.key}`, m.value.type);
|
|
3938
|
+
decls.push({ kind: "varDecl", localId: local.id, init: m.value, loc });
|
|
3939
|
+
sides[m.key] = varRef(local.id, m.value.type, loc);
|
|
3940
|
+
}
|
|
3941
|
+
const { readable, writable } = sides;
|
|
3942
|
+
if (readable && writable) {
|
|
3943
|
+
const call = {
|
|
3944
|
+
kind: "libCall",
|
|
3945
|
+
fn: "stream.duplexifyPair",
|
|
3946
|
+
args: [readable, writable],
|
|
3947
|
+
type: duplex,
|
|
3948
|
+
loc,
|
|
3949
|
+
};
|
|
3950
|
+
return decls.length > 0
|
|
3951
|
+
? { kind: "seqExpr", stmts: decls, result: call, type: duplex, loc }
|
|
3952
|
+
: call;
|
|
3953
|
+
}
|
|
3954
|
+
if (decls.length > 0) {
|
|
3955
|
+
// a repeated member: every value is evaluated, the last one is used
|
|
3956
|
+
const one = readable ?? writable;
|
|
3957
|
+
const call = {
|
|
3958
|
+
kind: "libCall",
|
|
3959
|
+
fn: readable ? "stream.duplexifyReadable" : "stream.duplexifyWritable",
|
|
3960
|
+
args: [one],
|
|
3961
|
+
type: duplex,
|
|
3962
|
+
loc,
|
|
3963
|
+
};
|
|
3964
|
+
return { kind: "seqExpr", stmts: decls, result: call, type: duplex, loc };
|
|
3965
|
+
}
|
|
3966
|
+
if (readable)
|
|
3967
|
+
return { kind: "libCall", fn: "stream.duplexifyReadable", args: [readable], type: duplex, loc };
|
|
3968
|
+
if (writable)
|
|
3969
|
+
return { kind: "libCall", fn: "stream.duplexifyWritable", args: [writable], type: duplex, loc };
|
|
3970
|
+
return lowerer.noLowering("Duplex.from over an object with neither readable nor writable", literal, "pass { readable, writable } with streams or Duplex.from bodies");
|
|
3971
|
+
}
|
|
3972
|
+
/** The checker type of a stage's string or Buffer chunks, or null for
|
|
3973
|
+
* other chunk types. */
|
|
3974
|
+
function stageChunkCheckerType(lowerer, chunk, at) {
|
|
3975
|
+
if (chunk.kind === "string")
|
|
3976
|
+
return lowerer.checker.getStringType();
|
|
3977
|
+
if (chunk.kind !== "bytes")
|
|
3978
|
+
return null;
|
|
3979
|
+
const buffer = lowerer.checker.resolveName("Buffer", ts.SymbolFlags.Type, at, false);
|
|
3980
|
+
return buffer ? lowerer.checker.getDeclaredTypeOfSymbol(buffer) : null;
|
|
2528
3981
|
}
|
|
2529
3982
|
/** `stream.compose(...streams)` over stream instances: a Duplex writing
|
|
2530
3983
|
* to the first stream and reading from the last (scr_stream_compose). The
|
|
2531
3984
|
* classes fix which positions can be readable and writable; a stream in
|
|
2532
3985
|
* the wrong position, a single Readable or Writable (Duplex.from wraps
|
|
2533
3986
|
* those), and functions, iterables or web streams have no lowering. */
|
|
2534
|
-
function lowerStreamCompose(lowerer,
|
|
2535
|
-
const args = call.arguments.nodes;
|
|
3987
|
+
function lowerStreamCompose(lowerer, args, loc) {
|
|
2536
3988
|
const duplex = { kind: "object", className: "%Duplex" };
|
|
2537
|
-
if (args.some((a) => ts.isSpreadElement(a))) {
|
|
2538
|
-
lowerer.noLowering("compose with spread arguments", call, "pass the streams directly");
|
|
2539
|
-
}
|
|
2540
3989
|
if (args.length === 0) {
|
|
2541
3990
|
return nodeThrowExpr(1, "ERR_MISSING_ARGS", 'The "streams" argument must be specified', duplex, loc);
|
|
2542
3991
|
}
|
|
3992
|
+
// A web ReadableStream first stage reads as an async iterable (the
|
|
3993
|
+
// pipeline's source), and alone it is Duplex.from of it; a later stage
|
|
3994
|
+
// would be Duplex.fromWeb of it.
|
|
3995
|
+
for (let i = 1; i < args.length; i++) {
|
|
3996
|
+
const a = args[i];
|
|
3997
|
+
// (typeOf on a stage function's name would report what collecting its
|
|
3998
|
+
// declared signature deferred)
|
|
3999
|
+
if (pipelineStageFunction(lowerer, a) !== null)
|
|
4000
|
+
continue;
|
|
4001
|
+
if (staticReadableStreamElementType(lowerer, a) !== null) {
|
|
4002
|
+
lowerer.noLowering("compose with a web ReadableStream after the first stage", a, "a web ReadableStream is supported as the first stage of compose or pipeline, and in Readable.from");
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
// Duplex.from(stage) for one stage (duplexify.js), and for a function at
|
|
4006
|
+
// either end; functions between, an iterable first stage or a source
|
|
4007
|
+
// function run as the pipeline's function stages (compose.js)
|
|
4008
|
+
if (args.length === 1)
|
|
4009
|
+
return duplexFromBody(lowerer, args[0], loc);
|
|
4010
|
+
const last = args.length - 1;
|
|
4011
|
+
const isFn = (i) => pipelineStageFunction(lowerer, args[i]) !== null;
|
|
4012
|
+
const pre = new Map();
|
|
4013
|
+
if (isFn(0))
|
|
4014
|
+
pre.set(0, duplexFromBody(lowerer, args[0], loc));
|
|
4015
|
+
if (isFn(last))
|
|
4016
|
+
pre.set(last, duplexFromBody(lowerer, args[last], loc));
|
|
4017
|
+
const staged = args.some((_, i) => !pre.has(i) && isFn(i)) ||
|
|
4018
|
+
(!pre.has(0) && iterableSourceType(lowerer, args[0]) !== null);
|
|
4019
|
+
if (staged) {
|
|
4020
|
+
const lowered = lowerPipelineStages(lowerer, args, loc, pre);
|
|
4021
|
+
return lowered.wrap({
|
|
4022
|
+
kind: "libCall",
|
|
4023
|
+
fn: "stream.composeStages",
|
|
4024
|
+
args: lowered.args,
|
|
4025
|
+
type: duplex,
|
|
4026
|
+
loc,
|
|
4027
|
+
});
|
|
4028
|
+
}
|
|
2543
4029
|
let streams;
|
|
2544
4030
|
try {
|
|
2545
|
-
streams = args.map((a) => lowerStreamArg(lowerer, a, "compose"));
|
|
4031
|
+
streams = args.map((a, i) => pre.get(i) ?? lowerStreamArg(lowerer, a, "compose"));
|
|
2546
4032
|
}
|
|
2547
4033
|
catch (e) {
|
|
2548
4034
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -2574,6 +4060,28 @@ function lowerStreamCompose(lowerer, call, loc) {
|
|
|
2574
4060
|
/* ── the method surface ───────────────────────────────────────────────── */
|
|
2575
4061
|
/* ── the Readable operators ──────────────────────────────────────────── */
|
|
2576
4062
|
/** The Readable operators (scr_stream_ops.c — Node's operators.js). */
|
|
4063
|
+
/** A stream member's receiver, lowered: a value the checker types as a
|
|
4064
|
+
* stream class whose lowering is checked-dynamic (a JavaScript binding
|
|
4065
|
+
* that holds an untyped call's result) or a union (an element read)
|
|
4066
|
+
* converts to that class, checked where the member runs. */
|
|
4067
|
+
function streamReceiverExpr(lowerer, node) {
|
|
4068
|
+
const value = lowerer.lowerExpr(node);
|
|
4069
|
+
if (value.type.kind !== "dyn" && value.type.kind !== "union")
|
|
4070
|
+
return value;
|
|
4071
|
+
let classT;
|
|
4072
|
+
try {
|
|
4073
|
+
classT = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
4074
|
+
}
|
|
4075
|
+
catch {
|
|
4076
|
+
return value;
|
|
4077
|
+
}
|
|
4078
|
+
if (classT?.kind !== "object" ||
|
|
4079
|
+
streamSidesOf(lowerer, lowerer.classes.get(classT.className)) === null)
|
|
4080
|
+
return value;
|
|
4081
|
+
return value.type.kind === "dyn"
|
|
4082
|
+
? { kind: "dynCheck", value, type: classT, loc: value.loc }
|
|
4083
|
+
: lowerer.coerceToExpected(value, classT);
|
|
4084
|
+
}
|
|
2577
4085
|
export const STREAM_OPERATORS = new Set([
|
|
2578
4086
|
"map",
|
|
2579
4087
|
"filter",
|
|
@@ -2587,50 +4095,125 @@ export const STREAM_OPERATORS = new Set([
|
|
|
2587
4095
|
"find",
|
|
2588
4096
|
"reduce",
|
|
2589
4097
|
]);
|
|
2590
|
-
/** An operator callback as a checked-dynamic function value
|
|
2591
|
-
*
|
|
2592
|
-
*
|
|
2593
|
-
*
|
|
2594
|
-
* strings) — or checked-dynamic values, which the runtime checks. */
|
|
4098
|
+
/** An operator callback as a checked-dynamic function value, and whether
|
|
4099
|
+
* it declares the options argument ({ signal }), which the runtime then
|
|
4100
|
+
* passes. Its results convert to checked-dynamic values (flatMap's are
|
|
4101
|
+
* iterated with yield*). */
|
|
2595
4102
|
function lowerOperatorCallback(lowerer, node, member, maxParams) {
|
|
2596
4103
|
const loc = locOf(node);
|
|
2597
|
-
const optionsParam = (at) => lowerer.noLowering(`${member} callbacks
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
4104
|
+
const optionsParam = (at) => lowerer.noLowering(`${member} callbacks with parameters after the options argument`, at, "the callback takes the chunk and { signal }");
|
|
4105
|
+
let takesOptions = false;
|
|
4106
|
+
if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) {
|
|
4107
|
+
if (node.parameters.nodes.length > maxParams + 1)
|
|
4108
|
+
optionsParam(node.parameters.nodes[maxParams + 1]);
|
|
4109
|
+
takesOptions = node.parameters.nodes.length > maxParams;
|
|
2601
4110
|
}
|
|
2602
4111
|
const v = lowerer.lowerExpr(node);
|
|
4112
|
+
// A checked-dynamic function's parameters are not known here: it gets
|
|
4113
|
+
// the { signal } argument, as Node passes it to every callback.
|
|
2603
4114
|
if (v.type.kind === "dyn")
|
|
2604
|
-
return v;
|
|
4115
|
+
return { fn: v, takesOptions: true };
|
|
2605
4116
|
if (v.type.kind !== "func" &&
|
|
2606
4117
|
isJsSourceFile(ts.getSourceFileOfNode(node)) &&
|
|
2607
4118
|
lowerer.dynConvertible(v.type)) {
|
|
2608
4119
|
// JavaScript passes any value; Node's validateFunction throws.
|
|
2609
|
-
return { kind: "dynFrom", value: v, type: DYN, loc };
|
|
4120
|
+
return { fn: { kind: "dynFrom", value: v, type: DYN, loc }, takesOptions: false };
|
|
2610
4121
|
}
|
|
2611
4122
|
if (v.type.kind !== "func") {
|
|
2612
4123
|
lowerer.noLowering(`${member} with a '${lowerer.fmt(v.type)}' callback`, node, "pass a function");
|
|
2613
4124
|
}
|
|
2614
|
-
if (v.type.params.length > maxParams)
|
|
4125
|
+
if (v.type.params.length > maxParams + 1)
|
|
2615
4126
|
optionsParam(node);
|
|
2616
|
-
if (
|
|
2617
|
-
|
|
2618
|
-
const chunk = (t) => t.kind === "string" || t.kind === "dyn" || (t.kind === "bytes" && t.elem === "u8");
|
|
2619
|
-
const ok = member === "map"
|
|
2620
|
-
? chunk(ret)
|
|
2621
|
-
: ret.kind === "dyn" || ret.kind === "string" || (ret.kind === "array" && chunk(ret.elem));
|
|
2622
|
-
if (!ok) {
|
|
2623
|
-
lowerer.noLowering(`${member} callbacks that return '${lowerer.fmt(ret)}'`, node, member === "map"
|
|
2624
|
-
? "map results are stream chunks: strings or Buffers (object-mode streams of other values are not lowered)"
|
|
2625
|
-
: "flatMap results are arrays of strings or Buffers, or strings");
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
4127
|
+
if (v.type.params.length > maxParams)
|
|
4128
|
+
takesOptions = true;
|
|
2628
4129
|
const getRecord = (id) => lowerer.shapes.get(id);
|
|
2629
4130
|
const getUnion = (id) => lowerer.unions.get(id);
|
|
2630
4131
|
if (!canBoxFuncIntoDyn(v.type, getRecord, getUnion)) {
|
|
2631
4132
|
lowerer.noLowering(`${member} with this callback`, node, "the callback's parameter and result types must cross the checked-dynamic boundary");
|
|
2632
4133
|
}
|
|
2633
|
-
|
|
4134
|
+
const fn = { kind: "dynFrom", value: v, type: DYN, loc };
|
|
4135
|
+
// flatMap over a compiled generator: the runtime steps it through the
|
|
4136
|
+
// helpers over its type
|
|
4137
|
+
if (member === "flatMap" && v.type.ret.kind === "generator")
|
|
4138
|
+
return { fn, takesOptions, gen: v.type.ret };
|
|
4139
|
+
return { fn, takesOptions };
|
|
4140
|
+
}
|
|
4141
|
+
/** The operator callbacks' `{ signal }` (operators.js): map and the
|
|
4142
|
+
* operators over it pass `{ signal: AbortSignal.any([options?.signal]
|
|
4143
|
+
* .filter(Boolean)) }`. options is the operator's options value. */
|
|
4144
|
+
export function operatorSignalOptions(lowerer, options, loc) {
|
|
4145
|
+
void lowerer;
|
|
4146
|
+
const list = {
|
|
4147
|
+
kind: "libCall",
|
|
4148
|
+
fn: "readable.opSignalList",
|
|
4149
|
+
args: [options],
|
|
4150
|
+
type: DYN,
|
|
4151
|
+
loc,
|
|
4152
|
+
};
|
|
4153
|
+
const signal = { kind: "libCall", fn: "fetch.abortAny", args: [list], type: DYN, loc };
|
|
4154
|
+
return { kind: "libCall", fn: "readable.opSignalOpts", args: [signal], type: DYN, loc };
|
|
4155
|
+
}
|
|
4156
|
+
/** reduce's signal for a reducer that reads it (operators.js): `const ac
|
|
4157
|
+
* = new AbortController()`, `options.signal.addEventListener('abort', ()
|
|
4158
|
+
* => ac.abort(), { once: true })`, then reduceSignal's ac.abort() closure
|
|
4159
|
+
* and `{ signal: ac.signal }`. options is the bound options value. */
|
|
4160
|
+
export function reduceSignalSetup(lowerer, options, loc, declare = (name, type) => lowerer.declareHiddenLocal(name, type)) {
|
|
4161
|
+
const acLocal = declare("%opAbort", DYN);
|
|
4162
|
+
const ac = varRef(acLocal.id, DYN, loc);
|
|
4163
|
+
const sigLocal = declare("%opUserSignal", DYN);
|
|
4164
|
+
const sig = varRef(sigLocal.id, DYN, loc);
|
|
4165
|
+
const abort = pipelineAbortHelper(lowerer, ac, loc);
|
|
4166
|
+
const stmts = [
|
|
4167
|
+
{
|
|
4168
|
+
kind: "varDecl",
|
|
4169
|
+
localId: acLocal.id,
|
|
4170
|
+
init: { kind: "libCall", fn: "fetch.abortControllerNew", args: [], type: DYN, loc },
|
|
4171
|
+
loc,
|
|
4172
|
+
},
|
|
4173
|
+
{
|
|
4174
|
+
kind: "varDecl",
|
|
4175
|
+
localId: sigLocal.id,
|
|
4176
|
+
init: { kind: "libCall", fn: "readable.opSignalOf", args: [options], type: DYN, loc },
|
|
4177
|
+
loc,
|
|
4178
|
+
},
|
|
4179
|
+
{
|
|
4180
|
+
kind: "if",
|
|
4181
|
+
cond: { kind: "dynTest", test: "truthy", value: sig, type: BOOL, loc },
|
|
4182
|
+
then: [
|
|
4183
|
+
{
|
|
4184
|
+
kind: "exprStmt",
|
|
4185
|
+
expr: {
|
|
4186
|
+
kind: "dynInvoke",
|
|
4187
|
+
recv: sig,
|
|
4188
|
+
method: "addEventListener",
|
|
4189
|
+
calleeName: "options.signal.addEventListener",
|
|
4190
|
+
args: [
|
|
4191
|
+
{ kind: "dynFrom", value: strLit("abort", loc), type: DYN, loc },
|
|
4192
|
+
{ kind: "dynFrom", value: pipelineAbortHelper(lowerer, ac, loc), type: DYN, loc },
|
|
4193
|
+
{ kind: "libCall", fn: "readable.opOnceOptions", args: [], type: DYN, loc },
|
|
4194
|
+
],
|
|
4195
|
+
type: DYN,
|
|
4196
|
+
loc,
|
|
4197
|
+
},
|
|
4198
|
+
loc,
|
|
4199
|
+
},
|
|
4200
|
+
],
|
|
4201
|
+
else_: null,
|
|
4202
|
+
loc,
|
|
4203
|
+
},
|
|
4204
|
+
];
|
|
4205
|
+
const signal = {
|
|
4206
|
+
kind: "dynKeyGet",
|
|
4207
|
+
value: ac,
|
|
4208
|
+
key: strLit("signal", loc),
|
|
4209
|
+
type: DYN,
|
|
4210
|
+
loc,
|
|
4211
|
+
};
|
|
4212
|
+
return {
|
|
4213
|
+
stmts,
|
|
4214
|
+
abort,
|
|
4215
|
+
cbOpts: { kind: "libCall", fn: "readable.opSignalOpts", args: [signal], type: DYN, loc },
|
|
4216
|
+
};
|
|
2634
4217
|
}
|
|
2635
4218
|
/** An operator's options (or reduce's initial value): an object literal
|
|
2636
4219
|
* becomes a checked-dynamic object, checked-dynamic values pass through,
|
|
@@ -2654,21 +4237,37 @@ function lowerOperatorValue(lowerer, node, what, loc, literalObject) {
|
|
|
2654
4237
|
function lowerStreamOperator(lowerer, call, access, member) {
|
|
2655
4238
|
const loc = locOf(call);
|
|
2656
4239
|
const args = call.arguments.nodes;
|
|
2657
|
-
|
|
4240
|
+
// JS order: the receiver, the callback, then the options; the
|
|
4241
|
+
// callback's { signal } is built over the options value afterwards.
|
|
4242
|
+
const decls = [];
|
|
4243
|
+
const bind = (value, name) => {
|
|
4244
|
+
const local = lowerer.declareHiddenLocal(name, value.type);
|
|
4245
|
+
decls.push({ kind: "varDecl", localId: local.id, init: value, loc });
|
|
4246
|
+
return varRef(local.id, value.type, loc);
|
|
4247
|
+
};
|
|
4248
|
+
const recv = bind(streamReceiverExpr(lowerer, access.expression), "%opRecv");
|
|
2658
4249
|
const readable = { kind: "object", className: "%Readable" };
|
|
2659
4250
|
const opts = (i) => lowerOperatorValue(lowerer, args[i], `${member} options`, loc, true);
|
|
4251
|
+
let takesOptions = false;
|
|
4252
|
+
let callbackGen;
|
|
2660
4253
|
const fnArg = (maxParams) => {
|
|
2661
4254
|
if (args[0] === undefined)
|
|
2662
4255
|
return dynUndefinedExpr(loc);
|
|
2663
|
-
|
|
4256
|
+
const lowered = lowerOperatorCallback(lowerer, args[0], member, maxParams);
|
|
4257
|
+
takesOptions = lowered.takesOptions;
|
|
4258
|
+
callbackGen = lowered.gen;
|
|
4259
|
+
return bind(lowered.fn, "%opFn");
|
|
4260
|
+
};
|
|
4261
|
+
const lib = (fn, a, type) => {
|
|
4262
|
+
const call = { kind: "libCall", fn: fn, args: a, type, loc };
|
|
4263
|
+
return { kind: "seqExpr", stmts: decls, result: call, type, loc };
|
|
4264
|
+
};
|
|
4265
|
+
// the options argument (bound), and the callback's { signal } when it
|
|
4266
|
+
// declares one
|
|
4267
|
+
const withSignal = (optsValue) => {
|
|
4268
|
+
const o = bind(optsValue, "%opOptions");
|
|
4269
|
+
return [o, takesOptions ? operatorSignalOptions(lowerer, o, loc) : dynUndefinedExpr(loc)];
|
|
2664
4270
|
};
|
|
2665
|
-
const lib = (fn, a, type) => ({
|
|
2666
|
-
kind: "libCall",
|
|
2667
|
-
fn: fn,
|
|
2668
|
-
args: a,
|
|
2669
|
-
type,
|
|
2670
|
-
loc,
|
|
2671
|
-
});
|
|
2672
4271
|
switch (member) {
|
|
2673
4272
|
case "map":
|
|
2674
4273
|
case "filter":
|
|
@@ -2679,7 +4278,12 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
2679
4278
|
: member === "filter"
|
|
2680
4279
|
? "readable.opFilter"
|
|
2681
4280
|
: "readable.opFlatMap";
|
|
2682
|
-
|
|
4281
|
+
const rest = withSignal(opts(1));
|
|
4282
|
+
const genHelpers = callbackGen ? fromGenHelpers(lowerer, callbackGen, loc) : null;
|
|
4283
|
+
if (callbackGen && genHelpers) {
|
|
4284
|
+
return lib(callbackGen.async ? "readable.opFlatMapAsyncGen" : "readable.opFlatMapSyncGen", [recv, fn, ...rest, ...genHelpers], readable);
|
|
4285
|
+
}
|
|
4286
|
+
return lib(fnName, [recv, fn, ...rest], readable);
|
|
2683
4287
|
}
|
|
2684
4288
|
case "drop":
|
|
2685
4289
|
case "take": {
|
|
@@ -2688,12 +4292,17 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
2688
4292
|
}
|
|
2689
4293
|
case "toArray":
|
|
2690
4294
|
return lib("readable.opToArray", [recv, opts(0)], { kind: "promise", inner: DYN });
|
|
2691
|
-
case "forEach":
|
|
2692
|
-
|
|
4295
|
+
case "forEach": {
|
|
4296
|
+
const fn = fnArg(1);
|
|
4297
|
+
return lib("readable.opForEach", [recv, fn, ...withSignal(opts(1))], {
|
|
4298
|
+
kind: "promise",
|
|
4299
|
+
inner: VOID,
|
|
4300
|
+
});
|
|
4301
|
+
}
|
|
2693
4302
|
case "some":
|
|
2694
4303
|
case "every": {
|
|
2695
4304
|
const fn = fnArg(1);
|
|
2696
|
-
return lib(member === "some" ? "readable.opSome" : "readable.opEvery", [recv, fn, opts(1)], {
|
|
4305
|
+
return lib(member === "some" ? "readable.opSome" : "readable.opEvery", [recv, fn, ...withSignal(opts(1))], {
|
|
2697
4306
|
kind: "promise",
|
|
2698
4307
|
inner: BOOL,
|
|
2699
4308
|
});
|
|
@@ -2704,7 +4313,11 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
2704
4313
|
if (inner && !(inner.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown))) {
|
|
2705
4314
|
lowerer.noLowering("find with a type-guard callback", call, "the result is a checked-dynamic value — use a boolean predicate and narrow the result");
|
|
2706
4315
|
}
|
|
2707
|
-
|
|
4316
|
+
const fn = fnArg(1);
|
|
4317
|
+
return lib("readable.opFind", [recv, fn, ...withSignal(opts(1))], {
|
|
4318
|
+
kind: "promise",
|
|
4319
|
+
inner: DYN,
|
|
4320
|
+
});
|
|
2708
4321
|
}
|
|
2709
4322
|
case "reduce": {
|
|
2710
4323
|
const t = lowerer.typeOf(call);
|
|
@@ -2730,20 +4343,21 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
2730
4343
|
}
|
|
2731
4344
|
}
|
|
2732
4345
|
const fn = fnArg(2);
|
|
2733
|
-
const init = lowerOperatorValue(lowerer, args[1], "reduce's initial value", loc, false);
|
|
2734
|
-
|
|
4346
|
+
const init = bind(lowerOperatorValue(lowerer, args[1], "reduce's initial value", loc, false), "%opInit");
|
|
4347
|
+
const o = bind(opts(2), "%opOptions");
|
|
4348
|
+
const head = [recv, fn, init, boolLit(args.length >= 2, loc), o, numLit(kind, loc)];
|
|
4349
|
+
if (!takesOptions)
|
|
4350
|
+
return lib("readable.opReduce", head, { kind: "promise", inner });
|
|
4351
|
+
const setup = reduceSignalSetup(lowerer, o, loc);
|
|
4352
|
+
decls.push(...setup.stmts);
|
|
4353
|
+
return lib("readable.opReduceSignal", [...head, setup.abort, setup.cbOpts], {
|
|
4354
|
+
kind: "promise",
|
|
4355
|
+
inner,
|
|
4356
|
+
});
|
|
2735
4357
|
}
|
|
2736
4358
|
}
|
|
2737
4359
|
throw new InternalCompilerError(`unknown stream operator ${member}`);
|
|
2738
4360
|
}
|
|
2739
|
-
/** The literal 'buffer' encoding on write()/end(): Node 24 takes it for a
|
|
2740
|
-
* Buffer chunk and throws ERR_UNKNOWN_ENCODING for a string chunk. */
|
|
2741
|
-
function isBufferEncoding(lowerer, arg) {
|
|
2742
|
-
if (arg === undefined)
|
|
2743
|
-
return false;
|
|
2744
|
-
const t = lowerer.typeOf(arg);
|
|
2745
|
-
return t.isStringLiteralType() && t.value === "buffer";
|
|
2746
|
-
}
|
|
2747
4361
|
/** The one supported encoding argument: utf8 (Node's default), as a
|
|
2748
4362
|
* compile-time literal or absent. */
|
|
2749
4363
|
function checkUtf8Encoding(lowerer, member, arg) {
|
|
@@ -2779,7 +4393,7 @@ function pipeEndOption(lowerer, options, loc) {
|
|
|
2779
4393
|
function pipeIntoStdio(lowerer, call, access, target) {
|
|
2780
4394
|
const loc = locOf(call);
|
|
2781
4395
|
// JS order: the receiver, then the destination, then the options.
|
|
2782
|
-
const receiverValue = lowerer
|
|
4396
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
2783
4397
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
2784
4398
|
const stdio = lowerer.declareHiddenLocal("%pipeStdio", target.type);
|
|
2785
4399
|
const options = call.arguments.nodes[1];
|
|
@@ -2890,7 +4504,7 @@ function generalPipe(lowerer, dst) {
|
|
|
2890
4504
|
function pipeIntoDyn(lowerer, call, access, target) {
|
|
2891
4505
|
const loc = locOf(call);
|
|
2892
4506
|
noteUntypedStreamFlow(lowerer, null);
|
|
2893
|
-
const receiverValue = lowerer
|
|
4507
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
2894
4508
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
2895
4509
|
const destination = lowerer.declareHiddenLocal("%pipeDestination", target.type);
|
|
2896
4510
|
const stmts = [
|
|
@@ -2976,6 +4590,59 @@ function pipeIntoDyn(lowerer, call, access, target) {
|
|
|
2976
4590
|
loc,
|
|
2977
4591
|
};
|
|
2978
4592
|
}
|
|
4593
|
+
/** readable.compose(stage, options): compose(this, stage), with
|
|
4594
|
+
* addAbortSignal(options.signal, composed) when the signal is set
|
|
4595
|
+
* (operators.js). */
|
|
4596
|
+
function lowerReadableCompose(lowerer, call, access) {
|
|
4597
|
+
const loc = locOf(call);
|
|
4598
|
+
const args = call.arguments.nodes;
|
|
4599
|
+
if (args.length === 0 || args.length > 2 || args.some((a) => ts.isSpreadElement(a))) {
|
|
4600
|
+
lowerer.noLowering(`readable.compose with ${args.length === 0 ? "no stage" : "these arguments"}`, call, "the supported form is readable.compose(stage) or readable.compose(stage, { signal })");
|
|
4601
|
+
}
|
|
4602
|
+
let signalNode = null;
|
|
4603
|
+
const options = args[1];
|
|
4604
|
+
if (options !== undefined &&
|
|
4605
|
+
options.kind !== ts.SyntaxKind.NullKeyword &&
|
|
4606
|
+
!(ts.isIdentifier(options) && options.text === "undefined")) {
|
|
4607
|
+
if (!ts.isObjectLiteralExpression(options)) {
|
|
4608
|
+
lowerer.noLowering("readable.compose options that are not an object literal", options, "pass { signal } as an object literal");
|
|
4609
|
+
}
|
|
4610
|
+
for (const p of options.properties.nodes) {
|
|
4611
|
+
const key = (ts.isPropertyAssignment(p) || ts.isShorthandPropertyAssignment(p)) &&
|
|
4612
|
+
ts.isIdentifier(p.name)
|
|
4613
|
+
? p.name.text
|
|
4614
|
+
: null;
|
|
4615
|
+
if (key !== "signal") {
|
|
4616
|
+
lowerer.noLowering(key === null
|
|
4617
|
+
? "readable.compose options with this member"
|
|
4618
|
+
: `the readable.compose option '${key}'`, p, "signal is the readable.compose option");
|
|
4619
|
+
}
|
|
4620
|
+
const value = ts.isShorthandPropertyAssignment(p)
|
|
4621
|
+
? p.name
|
|
4622
|
+
: p.initializer;
|
|
4623
|
+
if (value.kind === ts.SyntaxKind.NullKeyword)
|
|
4624
|
+
continue;
|
|
4625
|
+
if (ts.isIdentifier(value) && value.text === "undefined")
|
|
4626
|
+
continue;
|
|
4627
|
+
// The signal is read after compose runs, so only values whose
|
|
4628
|
+
// evaluation has no effects.
|
|
4629
|
+
if (!sideEffectFreeOptionValue(value) && !pureRead(value)) {
|
|
4630
|
+
lowerer.noLowering("the readable.compose option 'signal' with this value", p, "pass a variable or property read (const signal = controller.signal)");
|
|
4631
|
+
}
|
|
4632
|
+
signalNode = value;
|
|
4633
|
+
}
|
|
4634
|
+
}
|
|
4635
|
+
const composed = lowerStreamCompose(lowerer, [access.expression, args[0]], loc);
|
|
4636
|
+
if (signalNode === null)
|
|
4637
|
+
return composed;
|
|
4638
|
+
return {
|
|
4639
|
+
kind: "libCall",
|
|
4640
|
+
fn: "stream.addAbortSignal",
|
|
4641
|
+
args: [composed, lowerer.lowerExprExpecting(signalNode, DYN)],
|
|
4642
|
+
type: composed.type,
|
|
4643
|
+
loc,
|
|
4644
|
+
};
|
|
4645
|
+
}
|
|
2979
4646
|
export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
2980
4647
|
const member = access.name.text;
|
|
2981
4648
|
if (STREAM_OPERATORS.has(member)) {
|
|
@@ -2983,6 +4650,12 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
2983
4650
|
if (opSides === "r" || opSides === "rw")
|
|
2984
4651
|
return lowerStreamOperator(lowerer, call, access, member);
|
|
2985
4652
|
}
|
|
4653
|
+
if (member === "compose") {
|
|
4654
|
+
const composeSides = streamSidesOf(lowerer, info);
|
|
4655
|
+
return composeSides === "r" || composeSides === "rw"
|
|
4656
|
+
? lowerReadableCompose(lowerer, call, access)
|
|
4657
|
+
: null;
|
|
4658
|
+
}
|
|
2986
4659
|
if (!STREAM_API_MEMBERS.has(member))
|
|
2987
4660
|
return null;
|
|
2988
4661
|
const sides = streamSidesOf(lowerer, info);
|
|
@@ -3037,7 +4710,16 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3037
4710
|
if (probed?.type.kind === "nullT")
|
|
3038
4711
|
return "null";
|
|
3039
4712
|
}
|
|
3040
|
-
|
|
4713
|
+
// Any other value is a checked-dynamic chunk: one entry on an
|
|
4714
|
+
// object-mode side, Node's chunk type error on a byte-mode one
|
|
4715
|
+
// (undefined, which a byte-mode push ignores, included).
|
|
4716
|
+
if (t?.kind === "void" || t?.kind === "undefinedT")
|
|
4717
|
+
return "dyn";
|
|
4718
|
+
if (t !== null &&
|
|
4719
|
+
t.kind !== "func" &&
|
|
4720
|
+
canConvertToDyn(t, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
4721
|
+
return "dyn";
|
|
4722
|
+
lowerer.noLowering(`${member} with a '${t ? lowerer.fmt(t) : "?"}' chunk`, node, "chunks are values that convert to checked-dynamic values: Buffers, strings, numbers, records, arrays and class instances");
|
|
3041
4723
|
};
|
|
3042
4724
|
if (member === "push" || member === "unshift") {
|
|
3043
4725
|
requireSide(readableSide, member);
|
|
@@ -3056,7 +4738,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3056
4738
|
if (canonical === undefined) {
|
|
3057
4739
|
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${t.value}`, BOOL, loc);
|
|
3058
4740
|
}
|
|
3059
|
-
const receiver = lowerer
|
|
4741
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3060
4742
|
const chunk = lowerer.lowerExprExpecting(args[0], STRING);
|
|
3061
4743
|
return {
|
|
3062
4744
|
kind: "libCall",
|
|
@@ -3070,9 +4752,19 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3070
4752
|
checkUtf8Encoding(lowerer, member, args[1]);
|
|
3071
4753
|
const kind = chunkKind(args[0]);
|
|
3072
4754
|
if ((kind === "null" || kind === "union" || kind === "dyn") && member === "unshift") {
|
|
3073
|
-
|
|
4755
|
+
// unshift(value): an object-mode stream's value at the front, null
|
|
4756
|
+
// the end of the stream, as Node's readableAddChunk takes them
|
|
4757
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
4758
|
+
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
4759
|
+
return {
|
|
4760
|
+
kind: "libCall",
|
|
4761
|
+
fn: "readable.unshiftDyn",
|
|
4762
|
+
args: [receiver, chunk],
|
|
4763
|
+
type: VOID,
|
|
4764
|
+
loc,
|
|
4765
|
+
};
|
|
3074
4766
|
}
|
|
3075
|
-
const receiver = lowerer
|
|
4767
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3076
4768
|
if (kind === "null") {
|
|
3077
4769
|
return { kind: "libCall", fn: "readable.pushNull", args: [receiver], type: BOOL, loc };
|
|
3078
4770
|
}
|
|
@@ -3123,7 +4815,21 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3123
4815
|
requireSide(readableSide, "read");
|
|
3124
4816
|
if (args.length > 1)
|
|
3125
4817
|
lowerer.noLowering(`read with ${args.length} arguments`, call);
|
|
3126
|
-
const receiver = lowerer
|
|
4818
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
4819
|
+
// JavaScript (and a result the declarations type as any) reads any
|
|
4820
|
+
// chunk: a Buffer, a string once encoded, or an object-mode value.
|
|
4821
|
+
const resultTs = lowerer.typeOf(call);
|
|
4822
|
+
if (isJsSourceFile(ts.getSourceFileOfNode(call)) ||
|
|
4823
|
+
(resultTs.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0) {
|
|
4824
|
+
const sizeDyn = args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc);
|
|
4825
|
+
return {
|
|
4826
|
+
kind: "libCall",
|
|
4827
|
+
fn: "readable.readDyn",
|
|
4828
|
+
args: [receiver, sizeDyn],
|
|
4829
|
+
type: DYN,
|
|
4830
|
+
loc,
|
|
4831
|
+
};
|
|
4832
|
+
}
|
|
3127
4833
|
const size = args[0] ? lowerer.lowerExprExpecting(args[0], F64) : numLit(-1, loc);
|
|
3128
4834
|
const type = unionOf(lowerer, [BYTES, { kind: "nullT" }]);
|
|
3129
4835
|
const read = {
|
|
@@ -3139,7 +4845,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3139
4845
|
requireSide(readableSide, member);
|
|
3140
4846
|
if (args.length !== 0)
|
|
3141
4847
|
lowerer.noLowering(`${member} with arguments`, call);
|
|
3142
|
-
const receiver = lowerer
|
|
4848
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3143
4849
|
return {
|
|
3144
4850
|
kind: "libCall",
|
|
3145
4851
|
fn: member === "pause" ? "readable.pause" : "readable.resume",
|
|
@@ -3152,7 +4858,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3152
4858
|
requireSide(readableSide, "isPaused");
|
|
3153
4859
|
if (args.length !== 0)
|
|
3154
4860
|
lowerer.noLowering(`isPaused with arguments`, call);
|
|
3155
|
-
const receiver = lowerer
|
|
4861
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3156
4862
|
return { kind: "libCall", fn: "readable.isPaused", args: [receiver], type: BOOL, loc };
|
|
3157
4863
|
}
|
|
3158
4864
|
if (member === "pipe") {
|
|
@@ -3160,10 +4866,11 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3160
4866
|
if (args.length === 0 || args.length > 2) {
|
|
3161
4867
|
lowerer.noLowering(`pipe with ${args.length} arguments`, call, "the supported forms are (destination) and (destination, { end })");
|
|
3162
4868
|
}
|
|
3163
|
-
// A Hash or
|
|
3164
|
-
// answers the
|
|
3165
|
-
|
|
3166
|
-
|
|
4869
|
+
// A Hash, Hmac, Cipheriv or Decipheriv destination pipes into its
|
|
4870
|
+
// Transform, and pipe() answers the value itself (the receiver
|
|
4871
|
+
// evaluates first, as in JS).
|
|
4872
|
+
if (isValueStream(lowerer, args[0])) {
|
|
4873
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
3167
4874
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
3168
4875
|
const hashValue = lowerer.lowerExpr(args[0]);
|
|
3169
4876
|
const hash = lowerer.declareHiddenLocal("%pipeHash", hashValue.type);
|
|
@@ -3180,7 +4887,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3180
4887
|
fn: "readable.pipe",
|
|
3181
4888
|
args: [
|
|
3182
4889
|
{ kind: "varRef", localId: source.id, type: receiverValue.type, loc },
|
|
3183
|
-
|
|
4890
|
+
valueStreamOf({ kind: "varRef", localId: hash.id, type: hashValue.type, loc }, true),
|
|
3184
4891
|
end,
|
|
3185
4892
|
],
|
|
3186
4893
|
type: { kind: "object", className: "%Transform" },
|
|
@@ -3207,7 +4914,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3207
4914
|
lowerer.noLowering(`pipe into a '${lowerer.fmt(dst.type)}'`, args[0], "the destination must be a stream Writable/Duplex, process.stdout or process.stderr (sockets are not pipe destinations yet)");
|
|
3208
4915
|
}
|
|
3209
4916
|
const end = pipeEndOption(lowerer, args[1], loc);
|
|
3210
|
-
const receiver = lowerer
|
|
4917
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3211
4918
|
return {
|
|
3212
4919
|
kind: "libCall",
|
|
3213
4920
|
fn: generalPipe(lowerer, dst.type),
|
|
@@ -3220,7 +4927,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3220
4927
|
requireSide(readableSide, "unpipe");
|
|
3221
4928
|
if (args.length > 1)
|
|
3222
4929
|
lowerer.noLowering(`unpipe with ${args.length} arguments`, call);
|
|
3223
|
-
const receiver = lowerer
|
|
4930
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3224
4931
|
if (args[0] !== undefined) {
|
|
3225
4932
|
const dst = lowerer.lowerExpr(args[0]);
|
|
3226
4933
|
if (dst.type.kind === "dyn")
|
|
@@ -3281,7 +4988,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3281
4988
|
if (member === "destroy") {
|
|
3282
4989
|
if (args.length > 1)
|
|
3283
4990
|
lowerer.noLowering(`destroy with ${args.length} arguments`, call);
|
|
3284
|
-
const receiver = lowerer
|
|
4991
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3285
4992
|
if (args[0] !== undefined) {
|
|
3286
4993
|
const err = lowerer.lowerExpr(args[0]);
|
|
3287
4994
|
const rootsAtError = (t) => {
|
|
@@ -3314,10 +5021,51 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3314
5021
|
const kind = chunkKind(args[0]);
|
|
3315
5022
|
if (kind === "null")
|
|
3316
5023
|
lowerer.noLowering("write(null)", call, "end() finishes a writable");
|
|
5024
|
+
const lowerWriteCb = (cbArg) => {
|
|
5025
|
+
const cb = callbackDeclaresParameters(cbArg)
|
|
5026
|
+
? null
|
|
5027
|
+
: lowerer.lowerExprExpecting(cbArg, funcOf([], VOID));
|
|
5028
|
+
if (cb === null || cb.type.kind !== "func" || cb.type.params.length > 0) {
|
|
5029
|
+
lowerer.noLowering("write completion callbacks taking the error argument", cbArg, "() => void callbacks are supported (listen for 'error' to observe failures)");
|
|
5030
|
+
}
|
|
5031
|
+
return cb;
|
|
5032
|
+
};
|
|
5033
|
+
// write(chunk, encoding[, cb]), and write(value, cb): the encoding
|
|
5034
|
+
// argument reaches an object-mode side's _write as passed, null when
|
|
5035
|
+
// the callback took its place (a byte-mode side encodes a string
|
|
5036
|
+
// chunk with it).
|
|
5037
|
+
const writeEnc = (encArg, cbArg) => {
|
|
5038
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
5039
|
+
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
5040
|
+
const tail = [];
|
|
5041
|
+
if (encArg !== undefined)
|
|
5042
|
+
tail.push(lowerer.lowerExprExpecting(encArg, DYN));
|
|
5043
|
+
if (cbArg !== undefined)
|
|
5044
|
+
tail.push(lowerWriteCb(cbArg));
|
|
5045
|
+
const flags = (encArg !== undefined ? 1 : 0) | (cbArg !== undefined ? 2 : 0);
|
|
5046
|
+
return {
|
|
5047
|
+
kind: "libCall",
|
|
5048
|
+
fn: "writable.writeEnc",
|
|
5049
|
+
args: [receiver, numLit(flags, loc), chunk, ...tail],
|
|
5050
|
+
type: BOOL,
|
|
5051
|
+
loc,
|
|
5052
|
+
};
|
|
5053
|
+
};
|
|
3317
5054
|
if (kind === "dyn") {
|
|
3318
|
-
if (args.length
|
|
3319
|
-
|
|
3320
|
-
|
|
5055
|
+
if (args.length === 3)
|
|
5056
|
+
return writeEnc(args[1], args[2]);
|
|
5057
|
+
if (args.length === 2) {
|
|
5058
|
+
// Node's write takes a function there as the callback, anything
|
|
5059
|
+
// else as the encoding
|
|
5060
|
+
const t = lowerer.mapTypeOf(lowerer.typeOf(args[1]));
|
|
5061
|
+
if (t?.kind === "func")
|
|
5062
|
+
return writeEnc(undefined, args[1]);
|
|
5063
|
+
if (t === null || t === undefined || t.kind === "dyn") {
|
|
5064
|
+
lowerer.noLowering("write with a dynamic second argument", args[1], "pass an encoding string or a completion callback");
|
|
5065
|
+
}
|
|
5066
|
+
return writeEnc(args[1], undefined);
|
|
5067
|
+
}
|
|
5068
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3321
5069
|
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
3322
5070
|
return { kind: "libCall", fn: "writable.writeDyn", args: [receiver, chunk], type: BOOL, loc };
|
|
3323
5071
|
}
|
|
@@ -3328,7 +5076,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3328
5076
|
// re-dispatch on its IR type.
|
|
3329
5077
|
if (args.length > 1)
|
|
3330
5078
|
lowerer.noLowering("write with a union chunk and more arguments", call);
|
|
3331
|
-
const receiver = lowerer
|
|
5079
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3332
5080
|
const chunk = lowerer.lowerExpr(args[0]);
|
|
3333
5081
|
const fn = chunk.type.kind === "union"
|
|
3334
5082
|
? "writable.writeU"
|
|
@@ -3340,36 +5088,24 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3340
5088
|
return { kind: "libCall", fn, args: [receiver, chunk], type: BOOL, loc };
|
|
3341
5089
|
}
|
|
3342
5090
|
// Disambiguate (chunk, cb?) vs (chunk, encoding, cb?) by the second
|
|
3343
|
-
// argument's static type.
|
|
5091
|
+
// argument's static type. A write with an encoding runs through
|
|
5092
|
+
// writeEnc, whose runtime checks and applies it as Node's _write does.
|
|
3344
5093
|
let cbArg;
|
|
3345
|
-
if (args.length
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
cbArg = args[2];
|
|
3349
|
-
}
|
|
3350
|
-
else if (args.length === 2) {
|
|
5094
|
+
if (args.length === 3)
|
|
5095
|
+
return writeEnc(args[1], args[2]);
|
|
5096
|
+
if (args.length === 2) {
|
|
3351
5097
|
const t = lowerer.mapTypeOf(lowerer.typeOf(args[1]));
|
|
3352
|
-
if (t?.kind === "string")
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
cbArg = args[1];
|
|
3356
|
-
}
|
|
3357
|
-
else if (args.length === 3) {
|
|
3358
|
-
checkUtf8Encoding(lowerer, "write", args[1]);
|
|
3359
|
-
cbArg = args[2];
|
|
5098
|
+
if (t?.kind === "string" || t?.kind === "nullT" || t?.kind === "undefinedT")
|
|
5099
|
+
return writeEnc(args[1], undefined);
|
|
5100
|
+
cbArg = args[1];
|
|
3360
5101
|
}
|
|
3361
|
-
const receiver = lowerer
|
|
5102
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3362
5103
|
const chunk = kind === "bytes"
|
|
3363
5104
|
? lowerer.lowerExprExpecting(args[0], BYTES)
|
|
3364
5105
|
: lowerer.lowerExprExpecting(args[0], STRING);
|
|
3365
5106
|
const fn = kind === "bytes" ? "writable.write" : "writable.writeStr";
|
|
3366
5107
|
if (cbArg !== undefined) {
|
|
3367
|
-
const cb =
|
|
3368
|
-
? null
|
|
3369
|
-
: lowerer.lowerExprExpecting(cbArg, funcOf([], VOID));
|
|
3370
|
-
if (cb === null || cb.type.kind !== "func" || cb.type.params.length > 0) {
|
|
3371
|
-
lowerer.noLowering("write completion callbacks taking the error argument", cbArg, "() => void callbacks are supported (listen for 'error' to observe failures)");
|
|
3372
|
-
}
|
|
5108
|
+
const cb = lowerWriteCb(cbArg);
|
|
3373
5109
|
return { kind: "libCall", fn, args: [receiver, chunk, cb], type: BOOL, loc };
|
|
3374
5110
|
}
|
|
3375
5111
|
return { kind: "libCall", fn, args: [receiver, chunk], type: BOOL, loc };
|
|
@@ -3381,6 +5117,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3381
5117
|
// Forms: (), (cb), (chunk), (chunk, cb), (chunk, encoding, cb).
|
|
3382
5118
|
let chunkNode;
|
|
3383
5119
|
let cbArg;
|
|
5120
|
+
let encNode;
|
|
3384
5121
|
if (args.length === 1) {
|
|
3385
5122
|
const t = lowerer.mapTypeOf(lowerer.typeOf(args[0]));
|
|
3386
5123
|
if (t?.kind === "func")
|
|
@@ -3388,35 +5125,26 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3388
5125
|
else
|
|
3389
5126
|
chunkNode = args[0];
|
|
3390
5127
|
}
|
|
3391
|
-
else if (args.length >= 2 && isBufferEncoding(lowerer, args[1])) {
|
|
3392
|
-
chunkNode = args[0];
|
|
3393
|
-
const endKind = chunkKind(args[0]);
|
|
3394
|
-
if (endKind === "string") {
|
|
3395
|
-
const endT = lowerer.mapTypeOf(lowerer.typeOf(call)) ?? DYN;
|
|
3396
|
-
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", "Unknown encoding: buffer", endT, loc);
|
|
3397
|
-
}
|
|
3398
|
-
if (endKind !== "bytes")
|
|
3399
|
-
checkUtf8Encoding(lowerer, "end", args[1]);
|
|
3400
|
-
cbArg = args[2];
|
|
3401
|
-
}
|
|
3402
5128
|
else if (args.length === 2) {
|
|
3403
5129
|
chunkNode = args[0];
|
|
3404
5130
|
const t = lowerer.mapTypeOf(lowerer.typeOf(args[1]));
|
|
3405
|
-
if (t?.kind === "string")
|
|
3406
|
-
|
|
5131
|
+
if (t?.kind === "string" || t?.kind === "nullT" || t?.kind === "undefinedT")
|
|
5132
|
+
encNode = args[1];
|
|
3407
5133
|
else
|
|
3408
5134
|
cbArg = args[1];
|
|
3409
5135
|
}
|
|
3410
5136
|
else if (args.length === 3) {
|
|
3411
5137
|
chunkNode = args[0];
|
|
3412
|
-
|
|
5138
|
+
encNode = args[1];
|
|
3413
5139
|
cbArg = args[2];
|
|
3414
5140
|
}
|
|
3415
|
-
const receiver = lowerer
|
|
5141
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3416
5142
|
let flags = 0;
|
|
3417
5143
|
const tail = [];
|
|
3418
5144
|
if (chunkNode !== undefined) {
|
|
3419
|
-
|
|
5145
|
+
// end(chunk, encoding[, cb]) writes the chunk with the encoding
|
|
5146
|
+
// argument as passed (flags 16), through the dyn write
|
|
5147
|
+
const kind = encNode !== undefined ? "dyn" : chunkKind(chunkNode);
|
|
3420
5148
|
if (kind === "null" || kind === "union")
|
|
3421
5149
|
lowerer.noLowering("end(null)", call);
|
|
3422
5150
|
flags |= kind === "bytes" ? 1 : kind === "dyn" ? 8 : 2;
|
|
@@ -3425,6 +5153,10 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3425
5153
|
: kind === "dyn"
|
|
3426
5154
|
? lowerer.lowerExprExpecting(chunkNode, DYN)
|
|
3427
5155
|
: lowerer.lowerExprExpecting(chunkNode, STRING));
|
|
5156
|
+
if (encNode !== undefined) {
|
|
5157
|
+
flags |= 16;
|
|
5158
|
+
tail.push(lowerer.lowerExprExpecting(encNode, DYN));
|
|
5159
|
+
}
|
|
3428
5160
|
}
|
|
3429
5161
|
if (cbArg !== undefined) {
|
|
3430
5162
|
const cb = callbackDeclaresParameters(cbArg)
|
|
@@ -3448,7 +5180,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3448
5180
|
requireSide(writableSide, member);
|
|
3449
5181
|
if (args.length !== 0)
|
|
3450
5182
|
lowerer.noLowering(`${member} with arguments`, call);
|
|
3451
|
-
const receiver = lowerer
|
|
5183
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3452
5184
|
return {
|
|
3453
5185
|
kind: "libCall",
|
|
3454
5186
|
fn: member === "cork" ? "writable.cork" : "writable.uncork",
|
|
@@ -3463,7 +5195,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3463
5195
|
lowerer.noLowering(`setEncoding with ${args.length} arguments`, call, "one literal encoding is the supported form");
|
|
3464
5196
|
}
|
|
3465
5197
|
const enc = bufEncoding(lowerer, "setEncoding", args[0]);
|
|
3466
|
-
const receiver = lowerer
|
|
5198
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3467
5199
|
return {
|
|
3468
5200
|
kind: "libCall",
|
|
3469
5201
|
fn: "readable.setEncoding",
|
|
@@ -3473,14 +5205,20 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3473
5205
|
};
|
|
3474
5206
|
}
|
|
3475
5207
|
if (member === "setDefaultEncoding") {
|
|
3476
|
-
// The write-side default:
|
|
3477
|
-
//
|
|
5208
|
+
// The write-side default: lowercased and validated (ERR_UNKNOWN_ENCODING,
|
|
5209
|
+
// thrown) at run time; answers the stream.
|
|
3478
5210
|
requireSide(writableSide, "setDefaultEncoding");
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
5211
|
+
if (args.length > 1)
|
|
5212
|
+
lowerer.noLowering(`setDefaultEncoding with ${args.length} arguments`, call);
|
|
5213
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
5214
|
+
const enc = args[0] ? lowerer.lowerExprExpecting(args[0], DYN) : dynUndefinedExpr(loc);
|
|
5215
|
+
return {
|
|
5216
|
+
kind: "libCall",
|
|
5217
|
+
fn: "writable.setDefaultEncoding",
|
|
5218
|
+
args: [receiver, enc],
|
|
5219
|
+
type: receiver.type,
|
|
5220
|
+
loc,
|
|
5221
|
+
};
|
|
3484
5222
|
}
|
|
3485
5223
|
return null;
|
|
3486
5224
|
}
|
|
@@ -3613,7 +5351,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
3613
5351
|
const propCall = (type) => ({
|
|
3614
5352
|
kind: "libCall",
|
|
3615
5353
|
fn: "stream.prop",
|
|
3616
|
-
args: [lowerer
|
|
5354
|
+
args: [streamReceiverExpr(lowerer, expr.expression), strLit(name, loc)],
|
|
3617
5355
|
type,
|
|
3618
5356
|
loc,
|
|
3619
5357
|
});
|
|
@@ -3631,7 +5369,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
3631
5369
|
const read = {
|
|
3632
5370
|
kind: "libCall",
|
|
3633
5371
|
fn: "readable.flowing",
|
|
3634
|
-
args: [lowerer
|
|
5372
|
+
args: [streamReceiverExpr(lowerer, expr.expression)],
|
|
3635
5373
|
type,
|
|
3636
5374
|
loc,
|
|
3637
5375
|
};
|
|
@@ -3645,7 +5383,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
3645
5383
|
const read = {
|
|
3646
5384
|
kind: "libCall",
|
|
3647
5385
|
fn: "stream.errored",
|
|
3648
|
-
args: [lowerer
|
|
5386
|
+
args: [streamReceiverExpr(lowerer, expr.expression)],
|
|
3649
5387
|
type,
|
|
3650
5388
|
loc,
|
|
3651
5389
|
};
|
|
@@ -3656,8 +5394,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
3656
5394
|
return propCall(BOOL);
|
|
3657
5395
|
}
|
|
3658
5396
|
if (name === "writableObjectMode" && writableSide) {
|
|
3659
|
-
|
|
3660
|
-
return boolLit(false, loc);
|
|
5397
|
+
return propCall(BOOL);
|
|
3661
5398
|
}
|
|
3662
5399
|
if (name === "allowHalfOpen" && sides === "rw") {
|
|
3663
5400
|
return propCall(BOOL);
|