@scriptc/compiler 0.4.2 → 0.4.4
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 +470 -66
- package/dist/backend/cycle-analysis.d.ts +4 -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 +7 -0
- package/dist/backend/cycle-mutability.js +19 -1
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +2 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.d.ts +6 -3
- package/dist/backend/immutability.js +33 -29
- package/dist/backend/immutability.js.map +1 -1
- package/dist/backend/library-pack.js +1 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +16 -1
- package/dist/backend/llvm/alloc.js +54 -4
- 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 +21 -9
- 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 +47 -5
- package/dist/backend/llvm/bytes-loop-versions.js +479 -32
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
- package/dist/backend/llvm/bytes-loop-versions.test.js +263 -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 +7 -5
- package/dist/backend/llvm/classes.js +44 -20
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +167 -7
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +9 -3
- package/dist/backend/llvm/common.js +9 -3
- 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 +83 -52
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +7 -0
- package/dist/backend/llvm/counted-loops.js +18 -0
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/debug-info.js +2 -5
- package/dist/backend/llvm/debug-info.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 +17 -1
- package/dist/backend/llvm/dense-array-loops.js +194 -5
- package/dist/backend/llvm/dense-array-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.test.js +90 -1
- 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 +30 -0
- package/dist/backend/llvm/dyn.js +373 -70
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.js +13 -28
- 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 +211 -33
- package/dist/backend/llvm/emit-module.js.map +1 -1
- package/dist/backend/llvm/emit-statements.d.ts +0 -4
- package/dist/backend/llvm/emit-statements.js +268 -84
- 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 +186 -37
- package/dist/backend/llvm/emitter.js +733 -90
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +65 -7
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +11 -13
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js +48 -20
- 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.js +28 -14
- 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 +143 -37
- 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-dynamic.js +18 -11
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +119 -38
- 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 +210 -69
- 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 +74 -20
- 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 +25 -1
- package/dist/backend/llvm/integer-values.js +95 -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 +213 -5
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +4 -4
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +4 -0
- 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 +37 -1
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +94 -2
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +35 -5
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +115 -19
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +14 -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 +10 -0
- package/dist/backend/llvm/publish.js +15 -3
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/receivers.js +6 -1
- 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-effects.js +3 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +7 -2
- package/dist/backend/llvm/reference-writes.js +89 -72
- package/dist/backend/llvm/reference-writes.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 +71 -15
- package/dist/backend/llvm/shapes.js +224 -40
- 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-captures.js +1 -5
- package/dist/backend/llvm/stack-captures.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-reads.d.ts +12 -0
- package/dist/backend/llvm/string-reads.js +44 -0
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/union-repr.d.ts +4 -3
- package/dist/backend/llvm/union-repr.js +6 -5
- package/dist/backend/llvm/union-repr.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 +101 -65
- package/dist/backend/llvm/walkers.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/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 +5 -0
- package/dist/backend/native/executable.js +7 -0
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +5 -3
- package/dist/backend/native-codegen-core.js +13 -6
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.test.js +6 -4
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +4 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- 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 +1 -0
- package/dist/backend/runtime-pack-core.js +1 -0
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +2 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +2 -1
- 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-cpu.d.ts +26 -0
- package/dist/backend/target-cpu.js +98 -0
- package/dist/backend/target-cpu.js.map +1 -0
- package/dist/backend/target-cpu.test.d.ts +1 -0
- package/dist/backend/target-cpu.test.js +38 -0
- package/dist/backend/target-cpu.test.js.map +1 -0
- package/dist/backend/target-diagnostics.js +5 -3
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/warm-cache.js +1 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/cli/command.js +20 -1
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +4 -1
- package/dist/cli/usage.js +10 -3
- 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/compile-types.d.ts +7 -0
- package/dist/contracts/check.js +4 -3
- 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.js +12 -3
- package/dist/coverage/report.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js +1 -1
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +3 -0
- package/dist/diagnostics/envelope.js +1 -0
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +5 -0
- package/dist/executable/executable-cache.js +5 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +3 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/decl-projection.d.ts +41 -0
- package/dist/frontend/decl-projection.js +949 -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/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/lowering/array-values.js +100 -2
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/builtins/async-context.d.ts +8 -2
- package/dist/frontend/lowering/builtins/async-context.js +62 -3
- package/dist/frontend/lowering/builtins/async-context.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.js +13 -2
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.js +87 -10
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/dates.js +4 -1
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js +3 -3
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-glob.js +6 -3
- package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-paths.d.ts +43 -5
- package/dist/frontend/lowering/builtins/fs-paths.js +245 -93
- package/dist/frontend/lowering/builtins/fs-paths.js.map +1 -1
- 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/module-calls.js +6 -3
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.js +9 -1
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +7 -1
- package/dist/frontend/lowering/builtins/promises.js +236 -139
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +5 -1
- package/dist/frontend/lowering/builtins/readline.js +35 -3
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.js +24 -1
- package/dist/frontend/lowering/builtins/url.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/call-signatures.js +0 -1
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/cjs-exports-object.js +1 -1
- package/dist/frontend/lowering/cjs-exports-object.js.map +1 -1
- package/dist/frontend/lowering/cjs-inline-require.d.ts +32 -0
- package/dist/frontend/lowering/cjs-inline-require.js +307 -4
- package/dist/frontend/lowering/cjs-inline-require.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 +4 -1
- package/dist/frontend/lowering/class-construction.js +17 -3
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +49 -2
- package/dist/frontend/lowering/class-dynamic-dispatch.js +880 -108
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +47 -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 +83 -24
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +25 -0
- package/dist/frontend/lowering/class-protocols.js +183 -1
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.js +31 -2
- 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/coercions/structural-plans.js +48 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +91 -1
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/completion-callbacks.d.ts +4 -0
- package/dist/frontend/lowering/completion-callbacks.js +146 -0
- package/dist/frontend/lowering/completion-callbacks.js.map +1 -0
- 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 +5 -4
- package/dist/frontend/lowering/containers/array-callbacks.js +345 -24
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +10 -0
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +5 -0
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.js +26 -3
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +19 -8
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.d.ts +25 -17
- package/dist/frontend/lowering/containers/bytes.js +455 -46
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +3 -0
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +7 -2
- 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 +46 -7
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +55 -9
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +43 -19
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/date-values.d.ts +11 -0
- package/dist/frontend/lowering/date-values.js +207 -0
- package/dist/frontend/lowering/date-values.js.map +1 -0
- package/dist/frontend/lowering/dispatch-sites.js +15 -1
- package/dist/frontend/lowering/dispatch-sites.js.map +1 -1
- package/dist/frontend/lowering/divergences.js +9 -1
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/error-methods.js +47 -2
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/expressions/array-literals.js +53 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/binary.js +100 -28
- package/dist/frontend/lowering/expressions/binary.js.map +1 -1
- package/dist/frontend/lowering/expressions/element-access.js +169 -13
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/identifiers.js +64 -5
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
- package/dist/frontend/lowering/expressions/narrowing.js +95 -1
- 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 -0
- package/dist/frontend/lowering/expressions/object-literals.js +138 -51
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +12 -0
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.js +168 -10
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
- package/dist/frontend/lowering/expressions/relational.js +212 -33
- package/dist/frontend/lowering/expressions/relational.js.map +1 -1
- package/dist/frontend/lowering/expressions/typeof.js +6 -0
- package/dist/frontend/lowering/expressions/typeof.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 +39 -3
- 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 +64 -0
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.js +7 -2
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/indexed-unions.d.ts +54 -0
- package/dist/frontend/lowering/indexed-unions.js +401 -0
- package/dist/frontend/lowering/indexed-unions.js.map +1 -0
- 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 +186 -1
- 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/key-order-witness.d.ts +18 -3
- package/dist/frontend/lowering/key-order-witness.js +974 -48
- package/dist/frontend/lowering/key-order-witness.js.map +1 -1
- package/dist/frontend/lowering/key-order-witness.test.js +530 -10
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +15 -3
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.js +4 -1
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +7 -0
- package/dist/frontend/lowering/lower-calls.js +462 -44
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +11 -2
- package/dist/frontend/lowering/lower-classes.js +324 -69
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +3 -1
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +215 -3
- 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 +83 -0
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.js +42 -32
- 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.d.ts +1 -1
- package/dist/frontend/lowering/lower-inspect.js +53 -17
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +53 -5
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.js +5 -1
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +2 -2
- 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 +30 -0
- 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 +553 -81
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +20 -2
- package/dist/frontend/lowering/lower-stream.js +1483 -156
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +107 -8
- package/dist/frontend/lowering/lowerer.js +381 -36
- package/dist/frontend/lowering/lowerer.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/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-factory-new.d.ts +5 -0
- package/dist/frontend/lowering/object-factory-new.js +20 -6
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/overload-choice.d.ts +33 -0
- package/dist/frontend/lowering/overload-choice.js +190 -0
- package/dist/frontend/lowering/overload-choice.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -0
- package/dist/frontend/lowering/surfaces.js +73 -8
- 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 +29 -13
- 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.js +4 -20
- 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 +19 -11
- 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-analysis.d.ts +5 -1
- package/dist/frontend/program-analysis.js +5 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +21 -6
- package/dist/frontend/program.js +681 -83
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +43 -3
- package/dist/frontend/program.test.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 +22 -0
- package/dist/frontend/ts7/ast-node.js +1048 -103
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +24 -0
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-wire.d.ts +4 -3
- package/dist/frontend/ts7/ast-wire.js +34 -24
- 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/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 +4 -0
- package/dist/frontend/ts7/checker.js +7 -0
- package/dist/frontend/ts7/checker.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 +25 -2
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +3 -0
- package/dist/frontend/ts7/semantic-model.js +5 -0
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +6 -1
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-types.d.ts +1 -1
- package/dist/frontend/ts7/semantic-types.js +1 -1
- package/dist/frontend/ts7/semantic-types.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +14 -1
- package/dist/frontend/ts7/session.js +22 -0
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +13 -1
- package/dist/frontend/type-mapper.js +229 -20
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +46 -4
- 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 +19 -6
- package/dist/ir/array-length-stability.js.map +1 -1
- package/dist/ir/array-length-stability.test.js +24 -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 +60 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +6 -4
- package/dist/ir/builtin-signatures.js +222 -13
- 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 +2 -1
- package/dist/ir/final-fields.js +14 -16
- 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 +3 -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 +24 -2
- package/dist/ir/int32-slots.js +266 -57
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +33 -0
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +3 -3
- package/dist/ir/integer-loops.js +28 -10
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +10 -0
- 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 +30 -0
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +83 -10
- package/dist/ir/ir.js +77 -6
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +23 -2
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/js-ic.d.ts +4 -0
- package/dist/ir/js-ic.js +17 -1
- package/dist/ir/js-ic.js.map +1 -1
- package/dist/ir/js-ic.test.js +46 -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 +34 -13
- package/dist/ir/runtime-features.js +177 -39
- 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/traverse.js +18 -6
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +167 -40
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/ir-policy.js +3 -0
- package/dist/library/ir-policy.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 +21 -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 +4 -2
- package/dist/native/prepare.js +130 -32
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/prepare.test.js +96 -20
- package/dist/native/prepare.test.js.map +1 -1
- package/dist/native/sanitizer.test.js +2 -0
- 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/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/surface-manifest.json +27 -7
|
@@ -48,6 +48,7 @@ import { bindingNeverReassigned } from "./binding-analysis.js";
|
|
|
48
48
|
import { extractIteratorValue, genStep, genValue, stepDrivable } from "./lower-generators.js";
|
|
49
49
|
import { LiftedFrame, driveGenerator } from "./containers/iterator-helpers.js";
|
|
50
50
|
import { lowerArrayIteratorValue, lowerStringIteratorValue } from "./iterator-adapters.js";
|
|
51
|
+
import { staticReadableStreamElementType } from "./lower-stdlib.js";
|
|
51
52
|
import { BOOL, DYN, F64, RUNTIME_STREAM_CLASSES, STRING, VOID, arrayOf, BYTES_U8, canBoxFuncIntoDyn, canConvertToDyn, funcOf, typeEquals, typeKey, UNDEFINED_T, } from "../../ir/ir.js";
|
|
52
53
|
const BYTES = BYTES_U8;
|
|
53
54
|
/** An expression that only reads bindings and properties (no calls,
|
|
@@ -70,6 +71,55 @@ function pureRead(node) {
|
|
|
70
71
|
}
|
|
71
72
|
return false;
|
|
72
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
|
+
}
|
|
73
123
|
/** The stream sides of a receiver class: the nearest stream-class
|
|
74
124
|
* ancestor's, or null off the stream hierarchy. */
|
|
75
125
|
export function streamSidesOf(lowerer, info) {
|
|
@@ -135,10 +185,23 @@ export const UNDERSCORE_METHODS = new Map([
|
|
|
135
185
|
["transform", "_transform"],
|
|
136
186
|
["flush", "_flush"],
|
|
137
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
|
+
}
|
|
138
199
|
/** The completion callback's parameter position in each underscore
|
|
139
200
|
* method that takes one (cbTuples' "fn" positions). */
|
|
140
201
|
export const STREAM_COMPLETION_CALLBACK_INDEX = new Map([
|
|
141
202
|
["_write", 2],
|
|
203
|
+
["_writev", 1],
|
|
204
|
+
["_construct", 0],
|
|
142
205
|
["_final", 0],
|
|
143
206
|
["_destroy", 1],
|
|
144
207
|
["_transform", 2],
|
|
@@ -256,9 +319,11 @@ function lowerStreamCallback(lowerer, which, node, thisType, fullTuple, chunkVal
|
|
|
256
319
|
// supertype of it (`Buffer | string`); an encoding of another type
|
|
257
320
|
// (`string | null | undefined`) converts from the encoding argument's
|
|
258
321
|
// value.
|
|
259
|
-
if (((i === 0 &&
|
|
322
|
+
if (((((i === 0 &&
|
|
323
|
+
(chunkValues || widensInto(lowerer, fullTuple[0], funcType.params[0], loc))) ||
|
|
260
324
|
i === 1) &&
|
|
261
|
-
(which === "write" || which === "transform")
|
|
325
|
+
(which === "write" || which === "transform")) ||
|
|
326
|
+
(i === 0 && which === "writev")) &&
|
|
262
327
|
funcType.params[i].kind !== "func" &&
|
|
263
328
|
canConvertToDyn(funcType.params[i], (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id)))
|
|
264
329
|
continue;
|
|
@@ -359,14 +424,20 @@ function streamObjectModes(lowerer, ctorName, optsLit) {
|
|
|
359
424
|
}
|
|
360
425
|
return out;
|
|
361
426
|
}
|
|
362
|
-
/** Whether an options literal
|
|
363
|
-
* `true` literal (objectMode, or writableObjectMode
|
|
364
|
-
*
|
|
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. */
|
|
365
431
|
function literalWritesValues(opts, duplexish) {
|
|
366
432
|
for (const prop of opts.properties?.nodes ?? []) {
|
|
367
433
|
if (!ts.isPropertyAssignment(prop))
|
|
368
434
|
continue;
|
|
369
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
|
+
}
|
|
370
441
|
if (name !== "objectMode" && !(duplexish && name === "writableObjectMode"))
|
|
371
442
|
continue;
|
|
372
443
|
if (prop.initializer.kind !== ts.SyntaxKind.FalseKeyword)
|
|
@@ -384,6 +455,8 @@ function cbTuples(lowerer) {
|
|
|
384
455
|
read: [F64],
|
|
385
456
|
write: [BYTES, STRING, "fn"],
|
|
386
457
|
final: ["fn"],
|
|
458
|
+
construct: ["fn"],
|
|
459
|
+
writev: [DYN, "fn"],
|
|
387
460
|
destroy: [errorOrNull(lowerer), "fn"],
|
|
388
461
|
transform: [BYTES, STRING, "fn"],
|
|
389
462
|
flush: ["fn"],
|
|
@@ -577,10 +650,57 @@ function pinAnyDataCompletion(lowerer, which, fnNode) {
|
|
|
577
650
|
const declared = lowerer.paramShape(param).type;
|
|
578
651
|
if (declared.kind !== "func" || declared.rest || declared.params[1]?.kind !== "dyn")
|
|
579
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;
|
|
580
659
|
const data = unionOf(lowerer, [BYTES, STRING, { kind: "undefinedT" }]);
|
|
581
660
|
lowerer.stageSourceTypes.set(symbol, funcOf([declared.params[0], data, ...declared.params.slice(2)], declared.ret));
|
|
582
661
|
return symbol;
|
|
583
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
|
+
}
|
|
584
704
|
/** Parses the options object literal of a stream constructor. `which`
|
|
585
705
|
* names the callbacks this class accepts, in canonical flag order. */
|
|
586
706
|
function parseStreamOptions(lowerer, ctorName, arg, thisType, accepted, loc,
|
|
@@ -601,11 +721,19 @@ fallbackCb) {
|
|
|
601
721
|
badEncoding: null,
|
|
602
722
|
pushEncoding: null,
|
|
603
723
|
signal: null,
|
|
724
|
+
valueDecls: [],
|
|
725
|
+
decodeStringsValue: null,
|
|
726
|
+
defaultEncodingValue: null,
|
|
604
727
|
readableObject: false,
|
|
605
728
|
writableObject: false,
|
|
729
|
+
decodeStringsOff: false,
|
|
730
|
+
writeEncoding: null,
|
|
731
|
+
extras: [],
|
|
606
732
|
flags: 0,
|
|
607
733
|
cbs: [],
|
|
608
734
|
};
|
|
735
|
+
const extraNames = streamExtraCallbacks(`%${ctorName}`);
|
|
736
|
+
const writableClass = ctorName !== "Readable";
|
|
609
737
|
const followed = followOptionsArg(lowerer, arg);
|
|
610
738
|
const optsLit = followed === null ? undefined : followed;
|
|
611
739
|
if (optsLit !== undefined && !ts.isObjectLiteralExpression(optsLit)) {
|
|
@@ -617,6 +745,22 @@ fallbackCb) {
|
|
|
617
745
|
const objectModes = streamObjectModes(lowerer, ctorName, optsLit !== undefined && ts.isObjectLiteralExpression(optsLit) ? optsLit : undefined);
|
|
618
746
|
out.readableObject = objectModes.readable;
|
|
619
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);
|
|
620
764
|
if (out.readableObject)
|
|
621
765
|
out.hwmR = numLit(16, loc);
|
|
622
766
|
if (out.writableObject)
|
|
@@ -634,7 +778,7 @@ fallbackCb) {
|
|
|
634
778
|
lowerer.unsupported("SC1090", prop, `computed or spread members in ${ctorName} options`);
|
|
635
779
|
}
|
|
636
780
|
// Callback members: shorthand methods and function-valued properties.
|
|
637
|
-
if (accepted.includes(name)) {
|
|
781
|
+
if (accepted.includes(name) || extraNames.includes(name)) {
|
|
638
782
|
let fnNode = null;
|
|
639
783
|
if (ts.isMethodDeclaration(prop))
|
|
640
784
|
fnNode = prop;
|
|
@@ -659,6 +803,7 @@ fallbackCb) {
|
|
|
659
803
|
}
|
|
660
804
|
const full = tuples[name].map((t) => (t === "fn" ? null : t));
|
|
661
805
|
const pinned = out.readableObject ? null : pinAnyDataCompletion(lowerer, name, fnNode);
|
|
806
|
+
let anyChunk;
|
|
662
807
|
try {
|
|
663
808
|
// The completion-callback tail: typed by the checker contextually;
|
|
664
809
|
// accept the user's declared func type as the tuple's entry so the
|
|
@@ -673,11 +818,22 @@ fallbackCb) {
|
|
|
673
818
|
}
|
|
674
819
|
return declared ?? funcOf([], VOID);
|
|
675
820
|
});
|
|
676
|
-
|
|
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));
|
|
677
831
|
}
|
|
678
832
|
finally {
|
|
679
833
|
if (pinned)
|
|
680
834
|
lowerer.stageSourceTypes.delete(pinned);
|
|
835
|
+
if (anyChunk)
|
|
836
|
+
lowerer.anySymbols.delete(anyChunk);
|
|
681
837
|
}
|
|
682
838
|
continue;
|
|
683
839
|
}
|
|
@@ -720,9 +876,29 @@ fallbackCb) {
|
|
|
720
876
|
// read up front (streamObjectModes)
|
|
721
877
|
break;
|
|
722
878
|
case "decodeStrings": {
|
|
879
|
+
// WritableState's `options.decodeStrings === false`; a Readable
|
|
880
|
+
// ignores the option
|
|
723
881
|
if (value.kind === ts.SyntaxKind.TrueKeyword)
|
|
724
882
|
break; // Node's default
|
|
725
|
-
|
|
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);
|
|
726
902
|
break;
|
|
727
903
|
}
|
|
728
904
|
case "encoding": {
|
|
@@ -758,12 +934,45 @@ fallbackCb) {
|
|
|
758
934
|
out.badEncoding = t.value;
|
|
759
935
|
break;
|
|
760
936
|
}
|
|
761
|
-
if (t.isStringLiteralType()
|
|
762
|
-
|
|
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;
|
|
763
945
|
break;
|
|
764
946
|
}
|
|
765
947
|
}
|
|
766
|
-
|
|
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
|
+
}
|
|
767
976
|
break;
|
|
768
977
|
case "signal": {
|
|
769
978
|
// `if (options.signal) addAbortSignal(options.signal, this)`:
|
|
@@ -813,11 +1022,8 @@ fallbackCb) {
|
|
|
813
1022
|
: "the final callback is supported on Writable and Duplex");
|
|
814
1023
|
break;
|
|
815
1024
|
}
|
|
816
|
-
case "construct":
|
|
817
|
-
lowerer.noLowering(`the ${ctorName} option 'construct'`, prop, "deferred construction (_construct) is not lowered yet");
|
|
818
|
-
break;
|
|
819
1025
|
case "writev":
|
|
820
|
-
lowerer.noLowering(`the ${ctorName} option 'writev'`, prop, "
|
|
1026
|
+
lowerer.noLowering(`the ${ctorName} option 'writev'`, prop, "a Readable has no writable side");
|
|
821
1027
|
break;
|
|
822
1028
|
default:
|
|
823
1029
|
lowerer.noLowering(`the ${ctorName} option '${name}'`, prop);
|
|
@@ -833,6 +1039,11 @@ fallbackCb) {
|
|
|
833
1039
|
out.cbs.push(cb);
|
|
834
1040
|
}
|
|
835
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
|
+
}
|
|
836
1047
|
return out;
|
|
837
1048
|
}
|
|
838
1049
|
/** The head + flags argument list of a stream construction/initialization
|
|
@@ -859,10 +1070,66 @@ function streamCtorArgs(lowerer, cls, arg, thisType, loc, fallbackCb) {
|
|
|
859
1070
|
badEncoding: o.badEncoding,
|
|
860
1071
|
pushEncoding: o.pushEncoding,
|
|
861
1072
|
signal: o.signal,
|
|
1073
|
+
valueDecls: o.valueDecls,
|
|
1074
|
+
decodeStringsValue: o.decodeStringsValue,
|
|
1075
|
+
defaultEncodingValue: o.defaultEncodingValue,
|
|
862
1076
|
readableObject: o.readableObject,
|
|
863
1077
|
writableObject: o.writableObject,
|
|
1078
|
+
decodeStringsOff: o.decodeStringsOff,
|
|
1079
|
+
writeEncoding: o.writeEncoding,
|
|
1080
|
+
extras: o.extras,
|
|
864
1081
|
};
|
|
865
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
|
+
}
|
|
866
1133
|
/** `new Readable(opts?)` and friends — called from lowerNew once the
|
|
867
1134
|
* callee resolved to a builtin stream class. */
|
|
868
1135
|
export function lowerStreamNew(lowerer, expr, info) {
|
|
@@ -906,6 +1173,18 @@ export function lowerStreamNew(lowerer, expr, info) {
|
|
|
906
1173
|
loc,
|
|
907
1174
|
};
|
|
908
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
|
+
}
|
|
909
1188
|
if (parsed.pushEncoding !== null) {
|
|
910
1189
|
// { defaultEncoding }: chain the push-side decode default (the
|
|
911
1190
|
// setEncoding chaining shape — answers the receiver +1).
|
|
@@ -928,17 +1207,45 @@ export function lowerStreamNew(lowerer, expr, info) {
|
|
|
928
1207
|
loc,
|
|
929
1208
|
};
|
|
930
1209
|
}
|
|
931
|
-
if (parsed.signal
|
|
932
|
-
|
|
933
|
-
|
|
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);
|
|
934
1227
|
return {
|
|
935
|
-
kind: "
|
|
936
|
-
|
|
937
|
-
|
|
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),
|
|
938
1235
|
type: thisType,
|
|
939
1236
|
loc,
|
|
940
1237
|
};
|
|
941
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
|
+
}
|
|
942
1249
|
/** True when a value of Node's argument type `passed` widens implicitly
|
|
943
1250
|
* into the declared parameter type `declared` (one of its union arms, or a
|
|
944
1251
|
* sub-union of it). */
|
|
@@ -1000,9 +1307,11 @@ function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, bl
|
|
|
1000
1307
|
else if (!typeEquals(got.type, want)) {
|
|
1001
1308
|
// A write or transform encoding of another type (`string | null |
|
|
1002
1309
|
// undefined`) converts from the encoding argument's value: an
|
|
1003
|
-
// object-mode write passes undefined, null or the name.
|
|
1004
|
-
|
|
1005
|
-
|
|
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") &&
|
|
1006
1315
|
got.type.kind !== "func" &&
|
|
1007
1316
|
canConvertToDyn(got.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
1008
1317
|
paramTypes.push(got.type);
|
|
@@ -1019,8 +1328,7 @@ function streamMethodWrapper(lowerer, info, which, methodName, thisType, loc, bl
|
|
|
1019
1328
|
// chunk's value when the method runs (an object-mode side's value),
|
|
1020
1329
|
// or throws a TypeError there; a byte-mode side's chunk is a Buffer.
|
|
1021
1330
|
if (i === 0 &&
|
|
1022
|
-
chunkValues &&
|
|
1023
|
-
(which === "write" || which === "transform") &&
|
|
1331
|
+
(which === "writev" || (chunkValues && (which === "write" || which === "transform"))) &&
|
|
1024
1332
|
got.type.kind !== "func" &&
|
|
1025
1333
|
canConvertToDyn(got.type, (id) => lowerer.shapes.get(id), (id) => lowerer.unions.get(id))) {
|
|
1026
1334
|
paramTypes.push(got.type);
|
|
@@ -1113,7 +1421,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1113
1421
|
(!ts.isObjectLiteralExpression(optsNode) ||
|
|
1114
1422
|
literalWritesValues(optsNode, cls !== "%Readable" && cls !== "%Writable"));
|
|
1115
1423
|
const fallback = (name) => {
|
|
1116
|
-
const methodName = UNDERSCORE_METHODS.get(name);
|
|
1424
|
+
const methodName = UNDERSCORE_METHODS.get(name) ?? STREAM_EXTRA_CALLBACKS.get(name);
|
|
1117
1425
|
return methodName
|
|
1118
1426
|
? streamMethodWrapper(lowerer, info, name, methodName, thisType, loc, blame, chunkValues)
|
|
1119
1427
|
: null;
|
|
@@ -1134,6 +1442,14 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1134
1442
|
cbs.push(cb);
|
|
1135
1443
|
}
|
|
1136
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
|
+
}
|
|
1137
1453
|
return [
|
|
1138
1454
|
{
|
|
1139
1455
|
kind: "exprStmt",
|
|
@@ -1146,6 +1462,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1146
1462
|
},
|
|
1147
1463
|
loc,
|
|
1148
1464
|
},
|
|
1465
|
+
...streamOptionFollowUps({ decodeStringsOff: false, writeEncoding: null, extras }, thisRef, thisType, loc, "stream.setWritevDefault"),
|
|
1149
1466
|
];
|
|
1150
1467
|
}
|
|
1151
1468
|
}
|
|
@@ -1162,6 +1479,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1162
1479
|
];
|
|
1163
1480
|
}
|
|
1164
1481
|
const out = [
|
|
1482
|
+
...parsed.valueDecls,
|
|
1165
1483
|
{
|
|
1166
1484
|
kind: "exprStmt",
|
|
1167
1485
|
expr: {
|
|
@@ -1187,6 +1505,20 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1187
1505
|
loc,
|
|
1188
1506
|
});
|
|
1189
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
|
+
}
|
|
1190
1522
|
if (parsed.pushEncoding !== null) {
|
|
1191
1523
|
out.push({
|
|
1192
1524
|
kind: "exprStmt",
|
|
@@ -1226,6 +1558,7 @@ export function lowerStreamSuperCall(lowerer, info, base, argNodes, thisLocal, l
|
|
|
1226
1558
|
loc,
|
|
1227
1559
|
});
|
|
1228
1560
|
}
|
|
1561
|
+
out.push(...streamOptionFollowUps(parsed, thisRef, thisType, loc));
|
|
1229
1562
|
return out;
|
|
1230
1563
|
}
|
|
1231
1564
|
/* ── the underscore-method assignment surface ─────────────────────────── */
|
|
@@ -1269,14 +1602,16 @@ export function lowerStreamUnderscoreAssign(lowerer, expr) {
|
|
|
1269
1602
|
const loc = locOf(expr);
|
|
1270
1603
|
const cls = base.def.name;
|
|
1271
1604
|
const clsName = cls.slice(1);
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
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);
|
|
1278
1613
|
const { accepted } = streamCtorShape(cls);
|
|
1279
|
-
if (!accepted.includes(which)) {
|
|
1614
|
+
if (!accepted.includes(which) && !streamExtraCallbacks(cls).includes(which)) {
|
|
1280
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`);
|
|
1281
1616
|
}
|
|
1282
1617
|
const thisType = recv.type;
|
|
@@ -1307,6 +1642,8 @@ export function lowerStreamUnderscoreAssign(lowerer, expr) {
|
|
|
1307
1642
|
destroy: "stream.setDestroy",
|
|
1308
1643
|
transform: "stream.setTransform",
|
|
1309
1644
|
flush: "stream.setFlush",
|
|
1645
|
+
writev: "stream.setWritev",
|
|
1646
|
+
construct: "stream.replaceConstruct",
|
|
1310
1647
|
};
|
|
1311
1648
|
return {
|
|
1312
1649
|
kind: "exprStmt",
|
|
@@ -1364,25 +1701,165 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1364
1701
|
}
|
|
1365
1702
|
}
|
|
1366
1703
|
}
|
|
1704
|
+
if (member === "fromWeb" && cls === "%Readable")
|
|
1705
|
+
return lowerReadableFromWeb(lowerer, call, loc);
|
|
1367
1706
|
if (member !== "from") {
|
|
1368
1707
|
lowerer.noLowering(`${cls.slice(1)}.${member}`, call);
|
|
1369
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
|
+
}
|
|
1370
1716
|
if (cls !== "%Readable") {
|
|
1371
|
-
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");
|
|
1372
1718
|
}
|
|
1373
1719
|
const args = call.arguments.nodes;
|
|
1374
1720
|
if (args.length > 2) {
|
|
1375
1721
|
lowerer.noLowering(`Readable.from with ${args.length} arguments`, call, "Readable.from(iterable, options) is the supported form");
|
|
1376
1722
|
}
|
|
1377
|
-
|
|
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;
|
|
1378
1815
|
const js = isJsSourceFile(ts.getSourceFileOfNode(call));
|
|
1379
|
-
|
|
1380
|
-
|
|
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
|
+
}
|
|
1381
1857
|
const srcT = srcNode ? lowerer.mapTypeOf(lowerer.typeOf(srcNode)) : null;
|
|
1382
1858
|
const typedElem = (t) => t?.kind === "string" ? "string" : t?.kind === "bytes" && t.elem === "u8" ? "bytes" : null;
|
|
1383
1859
|
const single = typedElem(srcT);
|
|
1384
1860
|
const elem = srcT?.kind === "array" ? typedElem(srcT.elem) : null;
|
|
1385
|
-
const
|
|
1861
|
+
const opts0 = optsNode ? fromOptions(lowerer, optsNode) : { flags: 0, hwm: null };
|
|
1862
|
+
const opts = opts0 ? { ...opts0, flags: opts0.flags | duplexFlag } : opts0;
|
|
1386
1863
|
// A class whose [Symbol.iterator]() or [Symbol.asyncIterator]() is a
|
|
1387
1864
|
// generator method: from.js calls the method when the stream is built,
|
|
1388
1865
|
// then reads the generator like any other.
|
|
@@ -1473,13 +1950,15 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1473
1950
|
// The checked-dynamic form: the runtime takes from.js's ladder
|
|
1474
1951
|
// (ERR_INVALID_ARG_TYPE for a non-iterable, the options, null values).
|
|
1475
1952
|
const src = srcNode ? lowerer.lowerExprExpecting(srcNode, DYN) : dynUndefinedExpr(loc);
|
|
1953
|
+
if (duplex)
|
|
1954
|
+
return { kind: "libCall", fn: "stream.duplexFromDyn", args: [src], type, loc };
|
|
1476
1955
|
const o = lowerOperatorValue(lowerer, optsNode, "Readable.from options", loc, true);
|
|
1477
1956
|
return { kind: "libCall", fn: "readable.fromDyn", args: [src, o], type, loc };
|
|
1478
1957
|
}
|
|
1479
1958
|
if (srcNode && (single || elem)) {
|
|
1480
1959
|
lowerer.noLowering("Readable.from with these options", optsNode, "an object literal with 'objectMode' (true or false) and a number 'highWaterMark' is supported");
|
|
1481
1960
|
}
|
|
1482
|
-
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");
|
|
1483
1962
|
}
|
|
1484
1963
|
/** Whether a generator's yields can be stream chunks: values that box
|
|
1485
1964
|
* into checked-dynamic values (null included: the runtime destroys the
|
|
@@ -1960,6 +2439,24 @@ class StreamArgTypeThrow extends Error {
|
|
|
1960
2439
|
this.expr = expr;
|
|
1961
2440
|
}
|
|
1962
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
|
+
}
|
|
1963
2460
|
/** The finished/pipeline completion callback: an inline function lowers
|
|
1964
2461
|
* through the option-callback machinery (leading `this`, an `Error |
|
|
1965
2462
|
* null` prefix — Node binds the stream and passes the error); any other
|
|
@@ -2159,18 +2656,28 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2159
2656
|
: null;
|
|
2160
2657
|
const stageArgs = opts ? args.slice(0, -1) : args;
|
|
2161
2658
|
if (hasPipelineFunctionStage(lowerer, stageArgs)) {
|
|
2162
|
-
if (opts) {
|
|
2163
|
-
lowerer.noLowering("pipeline with function stages or iterable sources and options", lastArg, "pipeline(source, async function* (source) { ... }, destination) without options is supported");
|
|
2164
|
-
}
|
|
2165
2659
|
const staged = lowerPipelineStages(lowerer, stageArgs, loc);
|
|
2660
|
+
const type = staged.destPromise ?? { kind: "promise", inner: VOID };
|
|
2166
2661
|
// A promise destination's value settles the result (same type).
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
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 });
|
|
2174
2681
|
}
|
|
2175
2682
|
let streams;
|
|
2176
2683
|
try {
|
|
@@ -2328,18 +2835,28 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2328
2835
|
}
|
|
2329
2836
|
if (hasPipelineFunctionStage(lowerer, args.slice(0, -1))) {
|
|
2330
2837
|
const staged = lowerPipelineStages(lowerer, args.slice(0, -1), loc);
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
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.
|
|
2338
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);
|
|
2339
2856
|
return staged.wrap({
|
|
2340
2857
|
kind: "libCall",
|
|
2341
2858
|
fn: "stream.pipelineStagesDyn",
|
|
2342
|
-
args: [...
|
|
2859
|
+
args: [...stagedArgs, cb],
|
|
2343
2860
|
type: staged.last,
|
|
2344
2861
|
loc,
|
|
2345
2862
|
});
|
|
@@ -2372,8 +2889,12 @@ export function lowerStreamModuleCall(lowerer, call, bi, loc) {
|
|
|
2372
2889
|
loc,
|
|
2373
2890
|
};
|
|
2374
2891
|
}
|
|
2375
|
-
if (bi.member === "compose")
|
|
2376
|
-
|
|
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
|
+
}
|
|
2377
2898
|
return null;
|
|
2378
2899
|
}
|
|
2379
2900
|
/** The function a pipeline() argument writes or names, or null when the
|
|
@@ -2424,6 +2945,9 @@ function hasPipelineFunctionStage(lowerer, args) {
|
|
|
2424
2945
|
function iterableSourceType(lowerer, node) {
|
|
2425
2946
|
if (pipelineStageFunction(lowerer, node) !== null)
|
|
2426
2947
|
return null;
|
|
2948
|
+
const webElem = staticReadableStreamElementType(lowerer, node);
|
|
2949
|
+
if (webElem !== null)
|
|
2950
|
+
return webElem;
|
|
2427
2951
|
let t;
|
|
2428
2952
|
try {
|
|
2429
2953
|
t = lowerer.mapTypeOf(lowerer.typeOf(node));
|
|
@@ -2446,7 +2970,229 @@ function iterableSourceType(lowerer, node) {
|
|
|
2446
2970
|
* through an async-from-sync iterator, and an async generator that
|
|
2447
2971
|
* yields the same elements resumes its consumer on the same ticks. Null
|
|
2448
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
|
+
}
|
|
2449
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
|
+
}
|
|
2450
3196
|
let value;
|
|
2451
3197
|
if (fn !== null) {
|
|
2452
3198
|
if (fn.parameters.nodes.length > 0) {
|
|
@@ -2563,13 +3309,14 @@ function lowerIterableSource(lowerer, node, fn, loc) {
|
|
|
2563
3309
|
/** pipeline(...) with function stages (pipeline.js). A function may
|
|
2564
3310
|
* start the pipeline (a source function, called with `{ signal }`), may
|
|
2565
3311
|
* end it (an async function whose promise's value reaches the callback or
|
|
2566
|
-
* the promise
|
|
2567
|
-
* streams; the last generator of a
|
|
2568
|
-
*
|
|
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
|
|
2569
3316
|
* pipeline passes it: makeAsyncIterable answers the previous stream
|
|
2570
3317
|
* itself (a Readable is async iterable) or the previous stage's
|
|
2571
3318
|
* generator. */
|
|
2572
|
-
function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
3319
|
+
function lowerPipelineStages(lowerer, stageArgs, loc, preLowered) {
|
|
2573
3320
|
if (stageArgs.length > 52) {
|
|
2574
3321
|
lowerer.noLowering("pipeline with function stages and more than 52 stages", stageArgs[52], "split the pipeline");
|
|
2575
3322
|
}
|
|
@@ -2589,13 +3336,16 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2589
3336
|
const argOrder = [];
|
|
2590
3337
|
for (let j = 0; j < stageArgs.length; j++) {
|
|
2591
3338
|
const arg = stageArgs[j];
|
|
2592
|
-
|
|
3339
|
+
// compose's head and tail functions arrive as Duplex.from streams
|
|
3340
|
+
const fn = preLowered?.has(j) ? null : pipelineStageFunction(lowerer, arg);
|
|
2593
3341
|
const syncSourceFn = j === 0 &&
|
|
2594
3342
|
fn !== null &&
|
|
2595
3343
|
!ts.isArrowFunction(fn) &&
|
|
2596
3344
|
fn.asteriskToken !== undefined &&
|
|
2597
3345
|
!(fn.modifiers?.nodes ?? []).some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
|
|
2598
|
-
if (j === 0 &&
|
|
3346
|
+
if (j === 0 &&
|
|
3347
|
+
!preLowered?.has(j) &&
|
|
3348
|
+
(syncSourceFn || (fn === null && iterableSourceType(lowerer, arg) !== null))) {
|
|
2599
3349
|
const source = lowerIterableSource(lowerer, arg, syncSourceFn ? fn : null, loc);
|
|
2600
3350
|
if (source === null)
|
|
2601
3351
|
lowerer.noLowering("pipeline over this source", arg);
|
|
@@ -2618,7 +3368,7 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2618
3368
|
}
|
|
2619
3369
|
let stream;
|
|
2620
3370
|
try {
|
|
2621
|
-
stream = lowerStreamArg(lowerer, arg, "pipeline");
|
|
3371
|
+
stream = preLowered?.get(j) ?? lowerStreamArg(lowerer, arg, "pipeline");
|
|
2622
3372
|
}
|
|
2623
3373
|
catch (e) {
|
|
2624
3374
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -2633,11 +3383,6 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2633
3383
|
const isLast = j === stageArgs.length - 1;
|
|
2634
3384
|
const isAsync = (fn.modifiers?.nodes ?? []).some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
|
|
2635
3385
|
const isGen = !ts.isArrowFunction(fn) && fn.asteriskToken !== undefined;
|
|
2636
|
-
if (isLast && isGen) {
|
|
2637
|
-
// pipeline() pumps it into an object-mode PassThrough, whose
|
|
2638
|
-
// buffering decides when the pipeline finishes
|
|
2639
|
-
lowerer.noLowering("a pipeline destination that is an async generator function", arg, "end the pipeline with a stream or an async function (source) { for await (const chunk of source) ... }");
|
|
2640
|
-
}
|
|
2641
3386
|
if (!isAsync || (!isGen && !isLast)) {
|
|
2642
3387
|
lowerer.noLowering(isLast
|
|
2643
3388
|
? "a pipeline destination that is not an async function"
|
|
@@ -2665,6 +3410,16 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2665
3410
|
destPromise = lowered.out;
|
|
2666
3411
|
srcT = null;
|
|
2667
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
|
+
}
|
|
2668
3423
|
else {
|
|
2669
3424
|
srcT = lowered.out;
|
|
2670
3425
|
}
|
|
@@ -2690,7 +3445,8 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2690
3445
|
const bindArgs = (call) => argDecls.length === 0
|
|
2691
3446
|
? call
|
|
2692
3447
|
: { kind: "seqExpr", stmts: argDecls, result: call, type: call.type, loc };
|
|
2693
|
-
// SCR_PIPE_* flags: bits 1-2 the destination, bit 5 the signal and
|
|
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).
|
|
2694
3450
|
const flags = (dest << 1) | (mask !== 0 ? 32 : 0);
|
|
2695
3451
|
const head = [
|
|
2696
3452
|
numLit(streams.length, loc),
|
|
@@ -2702,7 +3458,7 @@ function lowerPipelineStages(lowerer, stageArgs, loc) {
|
|
|
2702
3458
|
...stages,
|
|
2703
3459
|
...helperArgs,
|
|
2704
3460
|
];
|
|
2705
|
-
const last = dest
|
|
3461
|
+
const last = dest !== 0 ? { kind: "object", className: "%PassThrough" } : streams[streams.length - 1].type;
|
|
2706
3462
|
if (mask === 0)
|
|
2707
3463
|
return { args: head, last, dest, destPromise, wrap: bindArgs };
|
|
2708
3464
|
// const ac = new AbortController(): its signal goes to the stages, and
|
|
@@ -2765,21 +3521,22 @@ function pipelineBoxHelper(lowerer, promiseT, loc) {
|
|
|
2765
3521
|
}
|
|
2766
3522
|
/** `() => ac.abort()` over the pipeline's AbortController: an interned
|
|
2767
3523
|
* lifted function takes the controller and answers the closure. */
|
|
2768
|
-
function pipelineAbortHelper(lowerer, ac, loc) {
|
|
2769
|
-
const key = "pipelineAbort";
|
|
3524
|
+
function pipelineAbortHelper(lowerer, ac, loc, withReason = false) {
|
|
3525
|
+
const key = withReason ? "pipelineAbortReason" : "pipelineAbort";
|
|
2770
3526
|
let name = lowerer.valueHelpers.get(key);
|
|
2771
|
-
const abortT = funcOf([], VOID);
|
|
3527
|
+
const abortT = funcOf(withReason ? [DYN] : [], VOID);
|
|
2772
3528
|
if (!name) {
|
|
2773
3529
|
name = keyedHelperName(lowerer, "%stream.pipelineAbort", key);
|
|
2774
3530
|
lowerer.valueHelpers.set(key, name);
|
|
2775
3531
|
const acLocal = { id: "ac.0", name: "ac", type: DYN, mutable: false, boxed: true };
|
|
2776
3532
|
const acRef = varRef(acLocal.id, DYN, loc);
|
|
3533
|
+
const reasonLocal = { id: "reason.0", name: "reason", type: DYN, mutable: false };
|
|
2777
3534
|
lowerer.liftedFns.push({
|
|
2778
3535
|
name: `${name}.abort`,
|
|
2779
|
-
params: [],
|
|
3536
|
+
params: withReason ? [{ localId: reasonLocal.id, name: reasonLocal.name, type: DYN }] : [],
|
|
2780
3537
|
returnType: VOID,
|
|
2781
3538
|
captures: [{ localId: acLocal.id, name: acLocal.name, type: DYN }],
|
|
2782
|
-
locals: [acLocal],
|
|
3539
|
+
locals: withReason ? [acLocal, reasonLocal] : [acLocal],
|
|
2783
3540
|
body: [
|
|
2784
3541
|
{
|
|
2785
3542
|
kind: "exprStmt",
|
|
@@ -2788,7 +3545,7 @@ function pipelineAbortHelper(lowerer, ac, loc) {
|
|
|
2788
3545
|
recv: acRef,
|
|
2789
3546
|
method: "abort",
|
|
2790
3547
|
calleeName: "ac.abort",
|
|
2791
|
-
args: [],
|
|
3548
|
+
args: withReason ? [varRef(reasonLocal.id, DYN, loc)] : [],
|
|
2792
3549
|
type: DYN,
|
|
2793
3550
|
loc,
|
|
2794
3551
|
},
|
|
@@ -2890,6 +3647,328 @@ function lowerStageFunction(lowerer, fn, srcT) {
|
|
|
2890
3647
|
lowerer.implicitParamTypes = previousImplicit;
|
|
2891
3648
|
}
|
|
2892
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
|
+
});
|
|
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
|
+
}
|
|
2893
3972
|
/** The checker type of a stage's string or Buffer chunks, or null for
|
|
2894
3973
|
* other chunk types. */
|
|
2895
3974
|
function stageChunkCheckerType(lowerer, chunk, at) {
|
|
@@ -2905,18 +3984,51 @@ function stageChunkCheckerType(lowerer, chunk, at) {
|
|
|
2905
3984
|
* classes fix which positions can be readable and writable; a stream in
|
|
2906
3985
|
* the wrong position, a single Readable or Writable (Duplex.from wraps
|
|
2907
3986
|
* those), and functions, iterables or web streams have no lowering. */
|
|
2908
|
-
function lowerStreamCompose(lowerer,
|
|
2909
|
-
const args = call.arguments.nodes;
|
|
3987
|
+
function lowerStreamCompose(lowerer, args, loc) {
|
|
2910
3988
|
const duplex = { kind: "object", className: "%Duplex" };
|
|
2911
|
-
if (args.some((a) => ts.isSpreadElement(a))) {
|
|
2912
|
-
lowerer.noLowering("compose with spread arguments", call, "pass the streams directly");
|
|
2913
|
-
}
|
|
2914
3989
|
if (args.length === 0) {
|
|
2915
3990
|
return nodeThrowExpr(1, "ERR_MISSING_ARGS", 'The "streams" argument must be specified', duplex, loc);
|
|
2916
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
|
+
}
|
|
2917
4029
|
let streams;
|
|
2918
4030
|
try {
|
|
2919
|
-
streams = args.map((a) => lowerStreamArg(lowerer, a, "compose"));
|
|
4031
|
+
streams = args.map((a, i) => pre.get(i) ?? lowerStreamArg(lowerer, a, "compose"));
|
|
2920
4032
|
}
|
|
2921
4033
|
catch (e) {
|
|
2922
4034
|
if (e instanceof StreamArgTypeThrow)
|
|
@@ -2948,6 +4060,28 @@ function lowerStreamCompose(lowerer, call, loc) {
|
|
|
2948
4060
|
/* ── the method surface ───────────────────────────────────────────────── */
|
|
2949
4061
|
/* ── the Readable operators ──────────────────────────────────────────── */
|
|
2950
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
|
+
}
|
|
2951
4085
|
export const STREAM_OPERATORS = new Set([
|
|
2952
4086
|
"map",
|
|
2953
4087
|
"filter",
|
|
@@ -2961,50 +4095,125 @@ export const STREAM_OPERATORS = new Set([
|
|
|
2961
4095
|
"find",
|
|
2962
4096
|
"reduce",
|
|
2963
4097
|
]);
|
|
2964
|
-
/** An operator callback as a checked-dynamic function value
|
|
2965
|
-
*
|
|
2966
|
-
*
|
|
2967
|
-
*
|
|
2968
|
-
* 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*). */
|
|
2969
4102
|
function lowerOperatorCallback(lowerer, node, member, maxParams) {
|
|
2970
4103
|
const loc = locOf(node);
|
|
2971
|
-
const optionsParam = (at) => lowerer.noLowering(`${member} callbacks
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
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;
|
|
2975
4110
|
}
|
|
2976
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.
|
|
2977
4114
|
if (v.type.kind === "dyn")
|
|
2978
|
-
return v;
|
|
4115
|
+
return { fn: v, takesOptions: true };
|
|
2979
4116
|
if (v.type.kind !== "func" &&
|
|
2980
4117
|
isJsSourceFile(ts.getSourceFileOfNode(node)) &&
|
|
2981
4118
|
lowerer.dynConvertible(v.type)) {
|
|
2982
4119
|
// JavaScript passes any value; Node's validateFunction throws.
|
|
2983
|
-
return { kind: "dynFrom", value: v, type: DYN, loc };
|
|
4120
|
+
return { fn: { kind: "dynFrom", value: v, type: DYN, loc }, takesOptions: false };
|
|
2984
4121
|
}
|
|
2985
4122
|
if (v.type.kind !== "func") {
|
|
2986
4123
|
lowerer.noLowering(`${member} with a '${lowerer.fmt(v.type)}' callback`, node, "pass a function");
|
|
2987
4124
|
}
|
|
2988
|
-
if (v.type.params.length > maxParams)
|
|
4125
|
+
if (v.type.params.length > maxParams + 1)
|
|
2989
4126
|
optionsParam(node);
|
|
2990
|
-
if (
|
|
2991
|
-
|
|
2992
|
-
const chunk = (t) => t.kind === "string" || t.kind === "dyn" || (t.kind === "bytes" && t.elem === "u8");
|
|
2993
|
-
const ok = member === "map"
|
|
2994
|
-
? chunk(ret)
|
|
2995
|
-
: ret.kind === "dyn" || ret.kind === "string" || (ret.kind === "array" && chunk(ret.elem));
|
|
2996
|
-
if (!ok) {
|
|
2997
|
-
lowerer.noLowering(`${member} callbacks that return '${lowerer.fmt(ret)}'`, node, member === "map"
|
|
2998
|
-
? "map results are stream chunks: strings or Buffers (object-mode streams of other values are not lowered)"
|
|
2999
|
-
: "flatMap results are arrays of strings or Buffers, or strings");
|
|
3000
|
-
}
|
|
3001
|
-
}
|
|
4127
|
+
if (v.type.params.length > maxParams)
|
|
4128
|
+
takesOptions = true;
|
|
3002
4129
|
const getRecord = (id) => lowerer.shapes.get(id);
|
|
3003
4130
|
const getUnion = (id) => lowerer.unions.get(id);
|
|
3004
4131
|
if (!canBoxFuncIntoDyn(v.type, getRecord, getUnion)) {
|
|
3005
4132
|
lowerer.noLowering(`${member} with this callback`, node, "the callback's parameter and result types must cross the checked-dynamic boundary");
|
|
3006
4133
|
}
|
|
3007
|
-
|
|
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
|
+
};
|
|
3008
4217
|
}
|
|
3009
4218
|
/** An operator's options (or reduce's initial value): an object literal
|
|
3010
4219
|
* becomes a checked-dynamic object, checked-dynamic values pass through,
|
|
@@ -3028,21 +4237,37 @@ function lowerOperatorValue(lowerer, node, what, loc, literalObject) {
|
|
|
3028
4237
|
function lowerStreamOperator(lowerer, call, access, member) {
|
|
3029
4238
|
const loc = locOf(call);
|
|
3030
4239
|
const args = call.arguments.nodes;
|
|
3031
|
-
|
|
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");
|
|
3032
4249
|
const readable = { kind: "object", className: "%Readable" };
|
|
3033
4250
|
const opts = (i) => lowerOperatorValue(lowerer, args[i], `${member} options`, loc, true);
|
|
4251
|
+
let takesOptions = false;
|
|
4252
|
+
let callbackGen;
|
|
3034
4253
|
const fnArg = (maxParams) => {
|
|
3035
4254
|
if (args[0] === undefined)
|
|
3036
4255
|
return dynUndefinedExpr(loc);
|
|
3037
|
-
|
|
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)];
|
|
3038
4270
|
};
|
|
3039
|
-
const lib = (fn, a, type) => ({
|
|
3040
|
-
kind: "libCall",
|
|
3041
|
-
fn: fn,
|
|
3042
|
-
args: a,
|
|
3043
|
-
type,
|
|
3044
|
-
loc,
|
|
3045
|
-
});
|
|
3046
4271
|
switch (member) {
|
|
3047
4272
|
case "map":
|
|
3048
4273
|
case "filter":
|
|
@@ -3053,7 +4278,12 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
3053
4278
|
: member === "filter"
|
|
3054
4279
|
? "readable.opFilter"
|
|
3055
4280
|
: "readable.opFlatMap";
|
|
3056
|
-
|
|
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);
|
|
3057
4287
|
}
|
|
3058
4288
|
case "drop":
|
|
3059
4289
|
case "take": {
|
|
@@ -3062,12 +4292,17 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
3062
4292
|
}
|
|
3063
4293
|
case "toArray":
|
|
3064
4294
|
return lib("readable.opToArray", [recv, opts(0)], { kind: "promise", inner: DYN });
|
|
3065
|
-
case "forEach":
|
|
3066
|
-
|
|
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
|
+
}
|
|
3067
4302
|
case "some":
|
|
3068
4303
|
case "every": {
|
|
3069
4304
|
const fn = fnArg(1);
|
|
3070
|
-
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))], {
|
|
3071
4306
|
kind: "promise",
|
|
3072
4307
|
inner: BOOL,
|
|
3073
4308
|
});
|
|
@@ -3078,7 +4313,11 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
3078
4313
|
if (inner && !(inner.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown))) {
|
|
3079
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");
|
|
3080
4315
|
}
|
|
3081
|
-
|
|
4316
|
+
const fn = fnArg(1);
|
|
4317
|
+
return lib("readable.opFind", [recv, fn, ...withSignal(opts(1))], {
|
|
4318
|
+
kind: "promise",
|
|
4319
|
+
inner: DYN,
|
|
4320
|
+
});
|
|
3082
4321
|
}
|
|
3083
4322
|
case "reduce": {
|
|
3084
4323
|
const t = lowerer.typeOf(call);
|
|
@@ -3104,8 +4343,17 @@ function lowerStreamOperator(lowerer, call, access, member) {
|
|
|
3104
4343
|
}
|
|
3105
4344
|
}
|
|
3106
4345
|
const fn = fnArg(2);
|
|
3107
|
-
const init = lowerOperatorValue(lowerer, args[1], "reduce's initial value", loc, false);
|
|
3108
|
-
|
|
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
|
+
});
|
|
3109
4357
|
}
|
|
3110
4358
|
}
|
|
3111
4359
|
throw new InternalCompilerError(`unknown stream operator ${member}`);
|
|
@@ -3145,7 +4393,7 @@ function pipeEndOption(lowerer, options, loc) {
|
|
|
3145
4393
|
function pipeIntoStdio(lowerer, call, access, target) {
|
|
3146
4394
|
const loc = locOf(call);
|
|
3147
4395
|
// JS order: the receiver, then the destination, then the options.
|
|
3148
|
-
const receiverValue = lowerer
|
|
4396
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
3149
4397
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
3150
4398
|
const stdio = lowerer.declareHiddenLocal("%pipeStdio", target.type);
|
|
3151
4399
|
const options = call.arguments.nodes[1];
|
|
@@ -3256,7 +4504,7 @@ function generalPipe(lowerer, dst) {
|
|
|
3256
4504
|
function pipeIntoDyn(lowerer, call, access, target) {
|
|
3257
4505
|
const loc = locOf(call);
|
|
3258
4506
|
noteUntypedStreamFlow(lowerer, null);
|
|
3259
|
-
const receiverValue = lowerer
|
|
4507
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
3260
4508
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
3261
4509
|
const destination = lowerer.declareHiddenLocal("%pipeDestination", target.type);
|
|
3262
4510
|
const stmts = [
|
|
@@ -3342,6 +4590,59 @@ function pipeIntoDyn(lowerer, call, access, target) {
|
|
|
3342
4590
|
loc,
|
|
3343
4591
|
};
|
|
3344
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
|
+
}
|
|
3345
4646
|
export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
3346
4647
|
const member = access.name.text;
|
|
3347
4648
|
if (STREAM_OPERATORS.has(member)) {
|
|
@@ -3349,6 +4650,12 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3349
4650
|
if (opSides === "r" || opSides === "rw")
|
|
3350
4651
|
return lowerStreamOperator(lowerer, call, access, member);
|
|
3351
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
|
+
}
|
|
3352
4659
|
if (!STREAM_API_MEMBERS.has(member))
|
|
3353
4660
|
return null;
|
|
3354
4661
|
const sides = streamSidesOf(lowerer, info);
|
|
@@ -3431,7 +4738,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3431
4738
|
if (canonical === undefined) {
|
|
3432
4739
|
return nodeThrowExpr(1, "ERR_UNKNOWN_ENCODING", `Unknown encoding: ${t.value}`, BOOL, loc);
|
|
3433
4740
|
}
|
|
3434
|
-
const receiver = lowerer
|
|
4741
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3435
4742
|
const chunk = lowerer.lowerExprExpecting(args[0], STRING);
|
|
3436
4743
|
return {
|
|
3437
4744
|
kind: "libCall",
|
|
@@ -3447,7 +4754,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3447
4754
|
if ((kind === "null" || kind === "union" || kind === "dyn") && member === "unshift") {
|
|
3448
4755
|
// unshift(value): an object-mode stream's value at the front, null
|
|
3449
4756
|
// the end of the stream, as Node's readableAddChunk takes them
|
|
3450
|
-
const receiver = lowerer
|
|
4757
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3451
4758
|
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
3452
4759
|
return {
|
|
3453
4760
|
kind: "libCall",
|
|
@@ -3457,7 +4764,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3457
4764
|
loc,
|
|
3458
4765
|
};
|
|
3459
4766
|
}
|
|
3460
|
-
const receiver = lowerer
|
|
4767
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3461
4768
|
if (kind === "null") {
|
|
3462
4769
|
return { kind: "libCall", fn: "readable.pushNull", args: [receiver], type: BOOL, loc };
|
|
3463
4770
|
}
|
|
@@ -3508,7 +4815,21 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3508
4815
|
requireSide(readableSide, "read");
|
|
3509
4816
|
if (args.length > 1)
|
|
3510
4817
|
lowerer.noLowering(`read with ${args.length} arguments`, call);
|
|
3511
|
-
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
|
+
}
|
|
3512
4833
|
const size = args[0] ? lowerer.lowerExprExpecting(args[0], F64) : numLit(-1, loc);
|
|
3513
4834
|
const type = unionOf(lowerer, [BYTES, { kind: "nullT" }]);
|
|
3514
4835
|
const read = {
|
|
@@ -3524,7 +4845,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3524
4845
|
requireSide(readableSide, member);
|
|
3525
4846
|
if (args.length !== 0)
|
|
3526
4847
|
lowerer.noLowering(`${member} with arguments`, call);
|
|
3527
|
-
const receiver = lowerer
|
|
4848
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3528
4849
|
return {
|
|
3529
4850
|
kind: "libCall",
|
|
3530
4851
|
fn: member === "pause" ? "readable.pause" : "readable.resume",
|
|
@@ -3537,7 +4858,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3537
4858
|
requireSide(readableSide, "isPaused");
|
|
3538
4859
|
if (args.length !== 0)
|
|
3539
4860
|
lowerer.noLowering(`isPaused with arguments`, call);
|
|
3540
|
-
const receiver = lowerer
|
|
4861
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3541
4862
|
return { kind: "libCall", fn: "readable.isPaused", args: [receiver], type: BOOL, loc };
|
|
3542
4863
|
}
|
|
3543
4864
|
if (member === "pipe") {
|
|
@@ -3549,7 +4870,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3549
4870
|
// Transform, and pipe() answers the value itself (the receiver
|
|
3550
4871
|
// evaluates first, as in JS).
|
|
3551
4872
|
if (isValueStream(lowerer, args[0])) {
|
|
3552
|
-
const receiverValue = lowerer
|
|
4873
|
+
const receiverValue = streamReceiverExpr(lowerer, access.expression);
|
|
3553
4874
|
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
3554
4875
|
const hashValue = lowerer.lowerExpr(args[0]);
|
|
3555
4876
|
const hash = lowerer.declareHiddenLocal("%pipeHash", hashValue.type);
|
|
@@ -3593,7 +4914,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3593
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)");
|
|
3594
4915
|
}
|
|
3595
4916
|
const end = pipeEndOption(lowerer, args[1], loc);
|
|
3596
|
-
const receiver = lowerer
|
|
4917
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3597
4918
|
return {
|
|
3598
4919
|
kind: "libCall",
|
|
3599
4920
|
fn: generalPipe(lowerer, dst.type),
|
|
@@ -3606,7 +4927,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3606
4927
|
requireSide(readableSide, "unpipe");
|
|
3607
4928
|
if (args.length > 1)
|
|
3608
4929
|
lowerer.noLowering(`unpipe with ${args.length} arguments`, call);
|
|
3609
|
-
const receiver = lowerer
|
|
4930
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3610
4931
|
if (args[0] !== undefined) {
|
|
3611
4932
|
const dst = lowerer.lowerExpr(args[0]);
|
|
3612
4933
|
if (dst.type.kind === "dyn")
|
|
@@ -3667,7 +4988,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3667
4988
|
if (member === "destroy") {
|
|
3668
4989
|
if (args.length > 1)
|
|
3669
4990
|
lowerer.noLowering(`destroy with ${args.length} arguments`, call);
|
|
3670
|
-
const receiver = lowerer
|
|
4991
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3671
4992
|
if (args[0] !== undefined) {
|
|
3672
4993
|
const err = lowerer.lowerExpr(args[0]);
|
|
3673
4994
|
const rootsAtError = (t) => {
|
|
@@ -3714,7 +5035,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3714
5035
|
// the callback took its place (a byte-mode side encodes a string
|
|
3715
5036
|
// chunk with it).
|
|
3716
5037
|
const writeEnc = (encArg, cbArg) => {
|
|
3717
|
-
const receiver = lowerer
|
|
5038
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3718
5039
|
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
3719
5040
|
const tail = [];
|
|
3720
5041
|
if (encArg !== undefined)
|
|
@@ -3744,7 +5065,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3744
5065
|
}
|
|
3745
5066
|
return writeEnc(args[1], undefined);
|
|
3746
5067
|
}
|
|
3747
|
-
const receiver = lowerer
|
|
5068
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3748
5069
|
const chunk = lowerer.lowerExprExpecting(args[0], DYN);
|
|
3749
5070
|
return { kind: "libCall", fn: "writable.writeDyn", args: [receiver, chunk], type: BOOL, loc };
|
|
3750
5071
|
}
|
|
@@ -3755,7 +5076,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3755
5076
|
// re-dispatch on its IR type.
|
|
3756
5077
|
if (args.length > 1)
|
|
3757
5078
|
lowerer.noLowering("write with a union chunk and more arguments", call);
|
|
3758
|
-
const receiver = lowerer
|
|
5079
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3759
5080
|
const chunk = lowerer.lowerExpr(args[0]);
|
|
3760
5081
|
const fn = chunk.type.kind === "union"
|
|
3761
5082
|
? "writable.writeU"
|
|
@@ -3778,7 +5099,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3778
5099
|
return writeEnc(args[1], undefined);
|
|
3779
5100
|
cbArg = args[1];
|
|
3780
5101
|
}
|
|
3781
|
-
const receiver = lowerer
|
|
5102
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3782
5103
|
const chunk = kind === "bytes"
|
|
3783
5104
|
? lowerer.lowerExprExpecting(args[0], BYTES)
|
|
3784
5105
|
: lowerer.lowerExprExpecting(args[0], STRING);
|
|
@@ -3817,7 +5138,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3817
5138
|
encNode = args[1];
|
|
3818
5139
|
cbArg = args[2];
|
|
3819
5140
|
}
|
|
3820
|
-
const receiver = lowerer
|
|
5141
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3821
5142
|
let flags = 0;
|
|
3822
5143
|
const tail = [];
|
|
3823
5144
|
if (chunkNode !== undefined) {
|
|
@@ -3859,7 +5180,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3859
5180
|
requireSide(writableSide, member);
|
|
3860
5181
|
if (args.length !== 0)
|
|
3861
5182
|
lowerer.noLowering(`${member} with arguments`, call);
|
|
3862
|
-
const receiver = lowerer
|
|
5183
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3863
5184
|
return {
|
|
3864
5185
|
kind: "libCall",
|
|
3865
5186
|
fn: member === "cork" ? "writable.cork" : "writable.uncork",
|
|
@@ -3874,7 +5195,7 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3874
5195
|
lowerer.noLowering(`setEncoding with ${args.length} arguments`, call, "one literal encoding is the supported form");
|
|
3875
5196
|
}
|
|
3876
5197
|
const enc = bufEncoding(lowerer, "setEncoding", args[0]);
|
|
3877
|
-
const receiver = lowerer
|
|
5198
|
+
const receiver = streamReceiverExpr(lowerer, access.expression);
|
|
3878
5199
|
return {
|
|
3879
5200
|
kind: "libCall",
|
|
3880
5201
|
fn: "readable.setEncoding",
|
|
@@ -3884,14 +5205,20 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
3884
5205
|
};
|
|
3885
5206
|
}
|
|
3886
5207
|
if (member === "setDefaultEncoding") {
|
|
3887
|
-
// The write-side default:
|
|
3888
|
-
//
|
|
5208
|
+
// The write-side default: lowercased and validated (ERR_UNKNOWN_ENCODING,
|
|
5209
|
+
// thrown) at run time; answers the stream.
|
|
3889
5210
|
requireSide(writableSide, "setDefaultEncoding");
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
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
|
+
};
|
|
3895
5222
|
}
|
|
3896
5223
|
return null;
|
|
3897
5224
|
}
|
|
@@ -4024,7 +5351,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
4024
5351
|
const propCall = (type) => ({
|
|
4025
5352
|
kind: "libCall",
|
|
4026
5353
|
fn: "stream.prop",
|
|
4027
|
-
args: [lowerer
|
|
5354
|
+
args: [streamReceiverExpr(lowerer, expr.expression), strLit(name, loc)],
|
|
4028
5355
|
type,
|
|
4029
5356
|
loc,
|
|
4030
5357
|
});
|
|
@@ -4042,7 +5369,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
4042
5369
|
const read = {
|
|
4043
5370
|
kind: "libCall",
|
|
4044
5371
|
fn: "readable.flowing",
|
|
4045
|
-
args: [lowerer
|
|
5372
|
+
args: [streamReceiverExpr(lowerer, expr.expression)],
|
|
4046
5373
|
type,
|
|
4047
5374
|
loc,
|
|
4048
5375
|
};
|
|
@@ -4056,7 +5383,7 @@ export function lowerStreamProperty(lowerer, expr, info) {
|
|
|
4056
5383
|
const read = {
|
|
4057
5384
|
kind: "libCall",
|
|
4058
5385
|
fn: "stream.errored",
|
|
4059
|
-
args: [lowerer
|
|
5386
|
+
args: [streamReceiverExpr(lowerer, expr.expression)],
|
|
4060
5387
|
type,
|
|
4061
5388
|
loc,
|
|
4062
5389
|
};
|