@cj-tech-master/excelts 4.2.1 → 4.2.2-canary.20260115044841.88820eb
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/THIRD_PARTY_NOTICES.md +0 -31
- package/dist/browser/index.browser.d.ts +1 -0
- package/dist/browser/index.browser.js +12 -0
- package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.base.js +1 -1
- package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.browser.d.ts +2 -8
- package/dist/browser/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
- package/dist/browser/modules/archive/{compress.d.ts → compression/compress.d.ts} +2 -2
- package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.js +1 -1
- package/dist/browser/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +1 -1
- package/dist/browser/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +1 -1
- package/dist/browser/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/browser/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/browser/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +2 -2
- package/dist/browser/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/browser/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +2 -2
- package/dist/browser/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/browser/modules/archive/defaults.d.ts +1 -0
- package/dist/browser/modules/archive/defaults.js +6 -3
- package/dist/browser/modules/archive/index.base.d.ts +4 -4
- package/dist/browser/modules/archive/index.base.js +3 -6
- package/dist/browser/modules/archive/index.browser.d.ts +3 -4
- package/dist/browser/modules/archive/index.browser.js +3 -7
- package/dist/browser/modules/archive/index.d.ts +3 -4
- package/dist/browser/modules/archive/index.js +3 -5
- package/dist/browser/modules/archive/internal/byte-queue.d.ts +33 -0
- package/dist/browser/modules/archive/internal/byte-queue.js +407 -0
- package/dist/browser/modules/archive/io/archive-sink.d.ts +8 -0
- package/dist/browser/modules/archive/io/archive-sink.js +45 -0
- package/dist/browser/modules/archive/io/archive-source.d.ts +6 -0
- package/dist/browser/modules/archive/io/archive-source.js +100 -0
- package/dist/browser/modules/archive/{extract.d.ts → unzip/extract.d.ts} +2 -2
- package/dist/browser/modules/archive/unzip/index.d.ts +40 -0
- package/dist/browser/modules/archive/unzip/index.js +164 -0
- package/dist/browser/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +36 -2
- package/dist/browser/modules/archive/unzip/stream.base.js +1022 -0
- package/dist/browser/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +1 -1
- package/dist/browser/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
- package/dist/browser/modules/archive/{parse.d.ts → unzip/stream.d.ts} +2 -2
- package/dist/{esm/modules/archive/parse.js → browser/modules/archive/unzip/stream.js} +6 -5
- package/dist/browser/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
- package/dist/{esm/modules/archive → browser/modules/archive/unzip}/zip-parser.js +38 -24
- package/dist/browser/modules/archive/utils/async-queue.d.ts +7 -0
- package/dist/browser/modules/archive/utils/async-queue.js +103 -0
- package/dist/browser/modules/archive/utils/bytes.js +16 -16
- package/dist/browser/modules/archive/utils/compressibility.d.ts +10 -0
- package/dist/browser/modules/archive/utils/compressibility.js +57 -0
- package/dist/browser/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +21 -0
- package/dist/browser/modules/archive/utils/pattern-scanner.js +27 -0
- package/dist/browser/modules/archive/utils/timestamps.js +62 -1
- package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/browser/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/browser/modules/archive/zip/index.d.ts +42 -0
- package/dist/browser/modules/archive/zip/index.js +157 -0
- package/dist/browser/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +28 -5
- package/dist/browser/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
- package/dist/browser/modules/archive/zip/zip-bytes.d.ts +73 -0
- package/dist/browser/modules/archive/zip/zip-bytes.js +239 -0
- package/dist/{esm/modules/archive → browser/modules/archive/zip}/zip-entry-metadata.js +3 -3
- package/dist/browser/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
- package/dist/browser/modules/archive/zip-spec/zip-records.js +126 -0
- package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
- package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
- package/dist/browser/modules/excel/utils/ooxml-validator.d.ts +48 -0
- package/dist/browser/modules/excel/utils/ooxml-validator.js +469 -0
- package/dist/browser/modules/excel/utils/parse-sax.d.ts +3 -0
- package/dist/browser/modules/excel/utils/parse-sax.js +32 -13
- package/dist/browser/modules/excel/worksheet.js +5 -2
- package/dist/browser/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/browser/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
- package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
- package/dist/browser/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
- package/dist/browser/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
- package/dist/browser/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
- package/dist/browser/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
- package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
- package/dist/browser/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/browser/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/browser/modules/excel/xlsx/xlsx.browser.js +11 -10
- package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/browser/modules/stream/base-transform.d.ts +3 -0
- package/dist/browser/modules/stream/base-transform.js +34 -20
- package/dist/browser/modules/stream/buffered-stream.d.ts +2 -12
- package/dist/browser/modules/stream/chunked-builder.js +4 -4
- package/dist/browser/modules/stream/index.browser.d.ts +13 -19
- package/dist/browser/modules/stream/index.browser.js +10 -22
- package/dist/browser/modules/stream/index.d.ts +18 -41
- package/dist/browser/modules/stream/index.js +15 -44
- package/dist/browser/modules/stream/internal/event-utils.d.ts +17 -0
- package/dist/browser/modules/stream/internal/event-utils.js +40 -0
- package/dist/browser/modules/stream/internal/type-guards.d.ts +9 -0
- package/dist/browser/modules/stream/internal/type-guards.js +24 -0
- package/dist/browser/modules/stream/pull-stream.d.ts +5 -6
- package/dist/browser/modules/stream/pull-stream.js +107 -43
- package/dist/browser/modules/stream/shared.d.ts +1 -1
- package/dist/browser/modules/stream/shared.js +7 -4
- package/dist/browser/modules/stream/streams.browser.d.ts +32 -44
- package/dist/browser/modules/stream/streams.browser.js +921 -836
- package/dist/browser/modules/stream/streams.d.ts +4 -20
- package/dist/browser/modules/stream/streams.js +146 -95
- package/dist/browser/modules/stream/utils.js +5 -38
- package/dist/cjs/modules/archive/{compress.base.js → compression/compress.base.js} +1 -1
- package/dist/cjs/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
- package/dist/cjs/modules/archive/{compress.js → compression/compress.js} +1 -1
- package/dist/cjs/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/cjs/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/cjs/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/cjs/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/cjs/modules/archive/defaults.js +7 -4
- package/dist/cjs/modules/archive/index.base.js +9 -19
- package/dist/cjs/modules/archive/index.browser.js +4 -10
- package/dist/cjs/modules/archive/index.js +4 -8
- package/dist/cjs/modules/archive/internal/byte-queue.js +411 -0
- package/dist/cjs/modules/archive/io/archive-sink.js +49 -0
- package/dist/cjs/modules/archive/io/archive-source.js +105 -0
- package/dist/cjs/modules/archive/unzip/index.js +170 -0
- package/dist/cjs/modules/archive/unzip/stream.base.js +1044 -0
- package/dist/cjs/modules/archive/{parse.browser.js → unzip/stream.browser.js} +372 -111
- package/dist/cjs/modules/archive/{parse.js → unzip/stream.js} +9 -8
- package/dist/cjs/modules/archive/{zip-parser.js → unzip/zip-parser.js} +47 -33
- package/dist/cjs/modules/archive/utils/async-queue.js +106 -0
- package/dist/cjs/modules/archive/utils/bytes.js +16 -16
- package/dist/cjs/modules/archive/utils/compressibility.js +60 -0
- package/dist/cjs/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/cjs/modules/archive/utils/pattern-scanner.js +31 -0
- package/dist/cjs/modules/archive/utils/timestamps.js +64 -3
- package/dist/cjs/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/cjs/modules/archive/zip/index.js +162 -0
- package/dist/cjs/modules/archive/{streaming-zip.js → zip/stream.js} +194 -50
- package/dist/cjs/modules/archive/zip/zip-bytes.js +242 -0
- package/dist/cjs/modules/archive/{zip-entry-metadata.js → zip/zip-entry-metadata.js} +5 -5
- package/dist/cjs/modules/archive/zip-spec/zip-records.js +136 -0
- package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
- package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
- package/dist/cjs/modules/excel/utils/ooxml-validator.js +475 -0
- package/dist/cjs/modules/excel/utils/parse-sax.js +32 -13
- package/dist/cjs/modules/excel/worksheet.js +5 -2
- package/dist/cjs/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/cjs/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/cjs/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
- package/dist/cjs/modules/excel/xlsx/xform/drawing/sp-xform.js +115 -0
- package/dist/cjs/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
- package/dist/cjs/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
- package/dist/cjs/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/cjs/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
- package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
- package/dist/cjs/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/cjs/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +14 -13
- package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
- package/dist/cjs/modules/stream/base-transform.js +34 -20
- package/dist/cjs/modules/stream/chunked-builder.js +4 -4
- package/dist/cjs/modules/stream/index.browser.js +10 -17
- package/dist/cjs/modules/stream/index.js +15 -39
- package/dist/cjs/modules/stream/internal/event-utils.js +43 -0
- package/dist/cjs/modules/stream/internal/type-guards.js +30 -0
- package/dist/cjs/modules/stream/pull-stream.js +107 -43
- package/dist/cjs/modules/stream/shared.js +7 -4
- package/dist/cjs/modules/stream/streams.browser.js +927 -847
- package/dist/cjs/modules/stream/streams.js +156 -107
- package/dist/cjs/modules/stream/utils.js +3 -36
- package/dist/esm/index.browser.js +12 -0
- package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.base.js +1 -1
- package/dist/esm/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
- package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.js +1 -1
- package/dist/esm/modules/archive/{crc32.js → compression/crc32.js} +1 -1
- package/dist/esm/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
- package/dist/esm/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
- package/dist/esm/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
- package/dist/esm/modules/archive/defaults.js +6 -3
- package/dist/esm/modules/archive/index.base.js +3 -6
- package/dist/esm/modules/archive/index.browser.js +3 -7
- package/dist/esm/modules/archive/index.js +3 -5
- package/dist/esm/modules/archive/internal/byte-queue.js +407 -0
- package/dist/esm/modules/archive/io/archive-sink.js +45 -0
- package/dist/esm/modules/archive/io/archive-source.js +100 -0
- package/dist/esm/modules/archive/unzip/index.js +164 -0
- package/dist/esm/modules/archive/unzip/stream.base.js +1022 -0
- package/dist/esm/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
- package/dist/{browser/modules/archive/parse.js → esm/modules/archive/unzip/stream.js} +6 -5
- package/dist/{browser/modules/archive → esm/modules/archive/unzip}/zip-parser.js +38 -24
- package/dist/esm/modules/archive/utils/async-queue.js +103 -0
- package/dist/esm/modules/archive/utils/bytes.js +16 -16
- package/dist/esm/modules/archive/utils/compressibility.js +57 -0
- package/dist/esm/modules/archive/utils/parse-buffer.js +21 -23
- package/dist/esm/modules/archive/utils/pattern-scanner.js +27 -0
- package/dist/esm/modules/archive/utils/timestamps.js +62 -1
- package/dist/esm/modules/archive/utils/zip-extra-fields.js +26 -14
- package/dist/esm/modules/archive/zip/index.js +157 -0
- package/dist/esm/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
- package/dist/esm/modules/archive/zip/zip-bytes.js +239 -0
- package/dist/{browser/modules/archive → esm/modules/archive/zip}/zip-entry-metadata.js +3 -3
- package/dist/esm/modules/archive/zip-spec/zip-records.js +126 -0
- package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
- package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
- package/dist/esm/modules/excel/utils/ooxml-validator.js +469 -0
- package/dist/esm/modules/excel/utils/parse-sax.js +32 -13
- package/dist/esm/modules/excel/worksheet.js +5 -2
- package/dist/esm/modules/excel/xlsx/xform/core/app-xform.js +3 -3
- package/dist/esm/modules/excel/xlsx/xform/core/core-xform.js +56 -68
- package/dist/esm/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.js +13 -1
- package/dist/esm/modules/excel/xlsx/xform/drawing/sp-xform.js +112 -0
- package/dist/esm/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.js +30 -2
- package/dist/esm/modules/excel/xlsx/xform/drawing/vml-drawing-xform.js +11 -0
- package/dist/esm/modules/excel/xlsx/xform/list-xform.js +8 -10
- package/dist/esm/modules/excel/xlsx/xform/sheet/page-setup-xform.js +16 -2
- package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +110 -12
- package/dist/esm/modules/excel/xlsx/xform/strings/shared-string-xform.js +2 -3
- package/dist/esm/modules/excel/xlsx/xform/strings/text-xform.js +5 -7
- package/dist/esm/modules/excel/xlsx/xlsx.browser.js +11 -10
- package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/esm/modules/stream/base-transform.js +34 -20
- package/dist/esm/modules/stream/chunked-builder.js +4 -4
- package/dist/esm/modules/stream/index.browser.js +10 -22
- package/dist/esm/modules/stream/index.js +15 -44
- package/dist/esm/modules/stream/internal/event-utils.js +40 -0
- package/dist/esm/modules/stream/internal/type-guards.js +24 -0
- package/dist/esm/modules/stream/pull-stream.js +107 -43
- package/dist/esm/modules/stream/shared.js +7 -4
- package/dist/esm/modules/stream/streams.browser.js +921 -836
- package/dist/esm/modules/stream/streams.js +146 -95
- package/dist/esm/modules/stream/utils.js +5 -38
- package/dist/iife/THIRD_PARTY_NOTICES.md +0 -31
- package/dist/iife/excelts.iife.js +6592 -4537
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +103 -31
- package/dist/types/index.browser.d.ts +1 -0
- package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.browser.d.ts +2 -8
- package/dist/types/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +1 -1
- package/dist/types/modules/archive/defaults.d.ts +1 -0
- package/dist/types/modules/archive/index.base.d.ts +4 -4
- package/dist/types/modules/archive/index.browser.d.ts +3 -4
- package/dist/types/modules/archive/index.d.ts +3 -4
- package/dist/types/modules/archive/internal/byte-queue.d.ts +33 -0
- package/dist/types/modules/archive/io/archive-sink.d.ts +8 -0
- package/dist/types/modules/archive/io/archive-source.d.ts +6 -0
- package/dist/types/modules/archive/unzip/index.d.ts +40 -0
- package/dist/types/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +38 -4
- package/dist/types/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +2 -2
- package/dist/types/modules/archive/{parse.d.ts → unzip/stream.d.ts} +3 -3
- package/dist/types/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
- package/dist/types/modules/archive/utils/async-queue.d.ts +7 -0
- package/dist/types/modules/archive/utils/compressibility.d.ts +10 -0
- package/dist/types/modules/archive/utils/pattern-scanner.d.ts +21 -0
- package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/types/modules/archive/zip/index.d.ts +42 -0
- package/dist/types/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +29 -6
- package/dist/types/modules/archive/zip/zip-bytes.d.ts +73 -0
- package/dist/types/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +1 -1
- package/dist/types/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
- package/dist/types/modules/excel/utils/ooxml-validator.d.ts +48 -0
- package/dist/types/modules/excel/utils/parse-sax.d.ts +3 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/ctrl-prop-xform.d.ts +1 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/sp-xform.d.ts +18 -0
- package/dist/types/modules/excel/xlsx/xform/drawing/two-cell-anchor-xform.d.ts +6 -1
- package/dist/types/modules/excel/xlsx/xform/sheet/page-setup-xform.d.ts +1 -0
- package/dist/types/modules/stream/base-transform.d.ts +3 -0
- package/dist/types/modules/stream/buffered-stream.d.ts +2 -12
- package/dist/types/modules/stream/index.browser.d.ts +13 -19
- package/dist/types/modules/stream/index.d.ts +18 -41
- package/dist/types/modules/stream/internal/event-utils.d.ts +17 -0
- package/dist/types/modules/stream/internal/type-guards.d.ts +9 -0
- package/dist/types/modules/stream/pull-stream.d.ts +5 -6
- package/dist/types/modules/stream/shared.d.ts +1 -1
- package/dist/types/modules/stream/streams.browser.d.ts +32 -44
- package/dist/types/modules/stream/streams.d.ts +4 -20
- package/package.json +14 -10
- package/dist/browser/modules/archive/byte-queue.d.ts +0 -18
- package/dist/browser/modules/archive/byte-queue.js +0 -125
- package/dist/browser/modules/archive/parse.base.js +0 -644
- package/dist/browser/modules/archive/utils/zip-extra.d.ts +0 -18
- package/dist/browser/modules/archive/utils/zip-extra.js +0 -68
- package/dist/browser/modules/archive/zip-builder.d.ts +0 -117
- package/dist/browser/modules/archive/zip-builder.js +0 -292
- package/dist/browser/modules/archive/zip-constants.d.ts +0 -18
- package/dist/browser/modules/archive/zip-constants.js +0 -23
- package/dist/browser/modules/archive/zip-records.js +0 -84
- package/dist/cjs/modules/archive/byte-queue.js +0 -129
- package/dist/cjs/modules/archive/parse.base.js +0 -666
- package/dist/cjs/modules/archive/utils/zip-extra.js +0 -74
- package/dist/cjs/modules/archive/zip-builder.js +0 -297
- package/dist/cjs/modules/archive/zip-constants.js +0 -26
- package/dist/cjs/modules/archive/zip-records.js +0 -90
- package/dist/esm/modules/archive/byte-queue.js +0 -125
- package/dist/esm/modules/archive/parse.base.js +0 -644
- package/dist/esm/modules/archive/utils/zip-extra.js +0 -68
- package/dist/esm/modules/archive/zip-builder.js +0 -292
- package/dist/esm/modules/archive/zip-constants.js +0 -23
- package/dist/esm/modules/archive/zip-records.js +0 -84
- package/dist/types/modules/archive/byte-queue.d.ts +0 -18
- package/dist/types/modules/archive/utils/zip-extra.d.ts +0 -18
- package/dist/types/modules/archive/zip-builder.d.ts +0 -117
- package/dist/types/modules/archive/zip-constants.d.ts +0 -18
- /package/dist/browser/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/browser/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/browser/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
- /package/dist/browser/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/browser/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
- /package/dist/browser/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/cjs/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/cjs/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/cjs/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/cjs/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/cjs/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/esm/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
- /package/dist/esm/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
- /package/dist/esm/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
- /package/dist/esm/modules/archive/{extract.js → unzip/extract.js} +0 -0
- /package/dist/esm/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
- /package/dist/types/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{compress.d.ts → compression/compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +0 -0
- /package/dist/types/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +0 -0
- /package/dist/types/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
- /package/dist/types/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{extract.d.ts → unzip/extract.d.ts} +0 -0
- /package/dist/types/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* - Edge >= 89
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.promises = exports.consumers = exports.streamToBuffer = exports.
|
|
15
|
+
exports.promises = exports.consumers = exports.streamToBuffer = exports.BufferChunk = exports.StringChunk = exports.BufferedStream = exports.PullStream = exports.Collector = exports.PassThrough = exports.Duplex = exports.Transform = exports.Writable = exports.Readable = void 0;
|
|
16
16
|
exports.normalizeWritable = normalizeWritable;
|
|
17
17
|
exports.createReadable = createReadable;
|
|
18
18
|
exports.createReadableFromAsyncIterable = createReadableFromAsyncIterable;
|
|
@@ -53,8 +53,47 @@ exports.isWritable = isWritable;
|
|
|
53
53
|
exports.duplexPair = duplexPair;
|
|
54
54
|
const event_emitter_1 = require("./event-emitter.js");
|
|
55
55
|
const pull_stream_1 = require("./pull-stream.js");
|
|
56
|
+
Object.defineProperty(exports, "PullStream", { enumerable: true, get: function () { return pull_stream_1.PullStream; } });
|
|
56
57
|
const buffered_stream_1 = require("./buffered-stream.js");
|
|
58
|
+
Object.defineProperty(exports, "BufferedStream", { enumerable: true, get: function () { return buffered_stream_1.BufferedStream; } });
|
|
59
|
+
Object.defineProperty(exports, "BufferChunk", { enumerable: true, get: function () { return buffered_stream_1.BufferChunk; } });
|
|
60
|
+
Object.defineProperty(exports, "StringChunk", { enumerable: true, get: function () { return buffered_stream_1.StringChunk; } });
|
|
57
61
|
const shared_1 = require("./shared.js");
|
|
62
|
+
const type_guards_1 = require("./internal/type-guards.js");
|
|
63
|
+
const removeEmitterListener = (emitter, event, listener) => {
|
|
64
|
+
if (typeof emitter.off === "function") {
|
|
65
|
+
emitter.off(event, listener);
|
|
66
|
+
}
|
|
67
|
+
else if (typeof emitter.removeListener === "function") {
|
|
68
|
+
emitter.removeListener(event, listener);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const addEmitterListener = (emitter, event, listener, options) => {
|
|
72
|
+
if (options?.once && typeof emitter.once === "function") {
|
|
73
|
+
emitter.once(event, listener);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
emitter.on(event, listener);
|
|
77
|
+
}
|
|
78
|
+
return () => removeEmitterListener(emitter, event, listener);
|
|
79
|
+
};
|
|
80
|
+
const createListenerRegistry = () => {
|
|
81
|
+
const listeners = [];
|
|
82
|
+
return {
|
|
83
|
+
add: (emitter, event, listener) => {
|
|
84
|
+
listeners.push(addEmitterListener(emitter, event, listener));
|
|
85
|
+
},
|
|
86
|
+
once: (emitter, event, listener) => {
|
|
87
|
+
listeners.push(addEmitterListener(emitter, event, listener, { once: true }));
|
|
88
|
+
},
|
|
89
|
+
cleanup: () => {
|
|
90
|
+
for (let i = listeners.length - 1; i >= 0; i--) {
|
|
91
|
+
listeners[i]();
|
|
92
|
+
}
|
|
93
|
+
listeners.length = 0;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
};
|
|
58
97
|
// =============================================================================
|
|
59
98
|
// Readable Stream Wrapper
|
|
60
99
|
// =============================================================================
|
|
@@ -71,6 +110,7 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
71
110
|
this._bufferSize = 0;
|
|
72
111
|
this._reading = false;
|
|
73
112
|
this._ended = false;
|
|
113
|
+
this._endEmitted = false;
|
|
74
114
|
this._destroyed = false;
|
|
75
115
|
this._errored = null;
|
|
76
116
|
this._closed = false;
|
|
@@ -127,20 +167,7 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
127
167
|
*/
|
|
128
168
|
static from(iterable, options) {
|
|
129
169
|
const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
|
|
130
|
-
(
|
|
131
|
-
try {
|
|
132
|
-
for await (const chunk of iterable) {
|
|
133
|
-
if (!readable.push(chunk)) {
|
|
134
|
-
// Backpressure
|
|
135
|
-
await new Promise(resolve => setTimeout(resolve, 0));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
readable.push(null);
|
|
139
|
-
}
|
|
140
|
-
catch (err) {
|
|
141
|
-
readable.destroy(err);
|
|
142
|
-
}
|
|
143
|
-
})();
|
|
170
|
+
pumpAsyncIterableToReadable(readable, toAsyncIterable(iterable));
|
|
144
171
|
return readable;
|
|
145
172
|
}
|
|
146
173
|
/**
|
|
@@ -185,16 +212,30 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
185
212
|
// Controller may already be closed
|
|
186
213
|
}
|
|
187
214
|
}
|
|
188
|
-
|
|
215
|
+
// Emit 'end' only after buffered data is fully drained.
|
|
216
|
+
// This avoids premature 'end' when producers push null while paused.
|
|
217
|
+
if (this._bufferedLength() === 0) {
|
|
218
|
+
this._emitEndOnce();
|
|
219
|
+
}
|
|
189
220
|
// Note: Don't call destroy() here, let the stream be consumed naturally
|
|
190
221
|
// The reader will return done:true when it finishes reading
|
|
191
222
|
return false;
|
|
192
223
|
}
|
|
224
|
+
// Keep the internal Web ReadableStream in sync for controllable streams.
|
|
225
|
+
// For external Web streams (_webStreamMode=true), push() is not the data source.
|
|
226
|
+
if (controller && !this._webStreamMode) {
|
|
227
|
+
try {
|
|
228
|
+
controller.enqueue(chunk);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Controller may be closed/errored; Node-side buffering/events still work.
|
|
232
|
+
}
|
|
233
|
+
}
|
|
193
234
|
if (this._flowing) {
|
|
194
235
|
// In flowing mode, emit data directly without buffering or enqueueing
|
|
195
236
|
// const chunkStr = chunk instanceof Uint8Array ? new TextDecoder().decode(chunk.slice(0, 50)) : String(chunk).slice(0, 50);
|
|
196
237
|
// console.log(`[Readable#${this._id}.push FLOWING] emit data size:${(chunk as any).length || (chunk as any).byteLength} start:"${chunkStr}"`);
|
|
197
|
-
this.emit("data", chunk);
|
|
238
|
+
this.emit("data", this._applyEncoding(chunk));
|
|
198
239
|
// Check if stream was paused during emit (backpressure from consumer)
|
|
199
240
|
if (!this._flowing) {
|
|
200
241
|
return false;
|
|
@@ -219,10 +260,8 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
219
260
|
if (!this.objectMode) {
|
|
220
261
|
this._bufferSize += this._getChunkSize(chunk);
|
|
221
262
|
}
|
|
222
|
-
// NOTE:
|
|
223
|
-
//
|
|
224
|
-
// Web Stream is only used for async iteration when not in push mode.
|
|
225
|
-
// Enqueueing here would cause data duplication when _startReading is also running.
|
|
263
|
+
// NOTE: We still buffer for Node-style read()/data semantics.
|
|
264
|
+
// The internal Web ReadableStream is also fed via controller.enqueue() above.
|
|
226
265
|
// Emit readable event when buffer goes from empty to having data
|
|
227
266
|
if (wasEmpty) {
|
|
228
267
|
queueMicrotask(() => this.emit("readable"));
|
|
@@ -236,6 +275,13 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
236
275
|
return this._bufferSize < this.readableHighWaterMark;
|
|
237
276
|
}
|
|
238
277
|
}
|
|
278
|
+
_emitEndOnce() {
|
|
279
|
+
if (this._endEmitted) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this._endEmitted = true;
|
|
283
|
+
this.emit("end");
|
|
284
|
+
}
|
|
239
285
|
/**
|
|
240
286
|
* Put a chunk back at the front of the buffer
|
|
241
287
|
* Note: unshift is allowed even after end, as it's used to put back already read data
|
|
@@ -260,14 +306,22 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
260
306
|
if (!this.objectMode) {
|
|
261
307
|
this._bufferSize -= this._getChunkSize(chunk);
|
|
262
308
|
}
|
|
263
|
-
|
|
309
|
+
const decoded = this._applyEncoding(chunk);
|
|
310
|
+
if (this._ended && this._bufferedLength() === 0) {
|
|
311
|
+
queueMicrotask(() => this._emitEndOnce());
|
|
312
|
+
}
|
|
313
|
+
return decoded;
|
|
264
314
|
}
|
|
265
315
|
// For binary mode, handle size
|
|
266
316
|
const chunk = this._bufferShift();
|
|
267
317
|
if (!this.objectMode) {
|
|
268
318
|
this._bufferSize -= this._getChunkSize(chunk);
|
|
269
319
|
}
|
|
270
|
-
|
|
320
|
+
const decoded = this._applyEncoding(chunk);
|
|
321
|
+
if (this._ended && this._bufferedLength() === 0) {
|
|
322
|
+
queueMicrotask(() => this._emitEndOnce());
|
|
323
|
+
}
|
|
324
|
+
return decoded;
|
|
271
325
|
}
|
|
272
326
|
return null;
|
|
273
327
|
}
|
|
@@ -373,11 +427,11 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
373
427
|
if (!this.objectMode) {
|
|
374
428
|
this._bufferSize -= this._getChunkSize(chunk);
|
|
375
429
|
}
|
|
376
|
-
this.emit("data", chunk);
|
|
430
|
+
this.emit("data", this._applyEncoding(chunk));
|
|
377
431
|
}
|
|
378
432
|
// If already ended, emit end event
|
|
379
433
|
if (this._ended && this._bufferedLength() === 0) {
|
|
380
|
-
this.
|
|
434
|
+
this._emitEndOnce();
|
|
381
435
|
}
|
|
382
436
|
else if (this._read) {
|
|
383
437
|
// Call user-provided read function asynchronously
|
|
@@ -440,26 +494,36 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
440
494
|
}
|
|
441
495
|
this._pipeTo.push(dest);
|
|
442
496
|
// Create listeners that we can later remove
|
|
497
|
+
let drainListener;
|
|
498
|
+
const removeDrainListener = () => {
|
|
499
|
+
if (!drainListener) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (typeof eventTarget.off === "function") {
|
|
503
|
+
eventTarget.off("drain", drainListener);
|
|
504
|
+
}
|
|
505
|
+
else if (typeof eventTarget.removeListener === "function") {
|
|
506
|
+
eventTarget.removeListener("drain", drainListener);
|
|
507
|
+
}
|
|
508
|
+
drainListener = undefined;
|
|
509
|
+
};
|
|
443
510
|
const dataListener = (chunk) => {
|
|
444
511
|
// Call destination's write() method (not internal _writable.write())
|
|
445
512
|
// This ensures Transform.write() logic runs properly
|
|
446
513
|
const canWrite = dest.write(chunk);
|
|
447
514
|
if (!canWrite) {
|
|
448
515
|
this.pause();
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
const resumeOnce = () => {
|
|
454
|
-
if (typeof eventTarget.off === "function") {
|
|
455
|
-
eventTarget.off("drain", resumeOnce);
|
|
456
|
-
}
|
|
457
|
-
else if (typeof eventTarget.removeListener === "function") {
|
|
458
|
-
eventTarget.removeListener("drain", resumeOnce);
|
|
459
|
-
}
|
|
516
|
+
// Install a removable, once-style drain listener.
|
|
517
|
+
if (!drainListener) {
|
|
518
|
+
drainListener = () => {
|
|
519
|
+
removeDrainListener();
|
|
460
520
|
this.resume();
|
|
461
521
|
};
|
|
462
|
-
eventTarget.on("drain",
|
|
522
|
+
eventTarget.on("drain", drainListener);
|
|
523
|
+
const entry = this._pipeListeners.get(dest);
|
|
524
|
+
if (entry) {
|
|
525
|
+
entry.drain = drainListener;
|
|
526
|
+
}
|
|
463
527
|
}
|
|
464
528
|
}
|
|
465
529
|
};
|
|
@@ -479,7 +543,8 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
479
543
|
this._pipeListeners.set(dest, {
|
|
480
544
|
data: dataListener,
|
|
481
545
|
end: endListener,
|
|
482
|
-
error: errorListener
|
|
546
|
+
error: errorListener,
|
|
547
|
+
eventTarget
|
|
483
548
|
});
|
|
484
549
|
this.on("data", dataListener);
|
|
485
550
|
this.once("end", endListener);
|
|
@@ -502,6 +567,14 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
502
567
|
this.off("data", listeners.data);
|
|
503
568
|
this.off("end", listeners.end);
|
|
504
569
|
this.off("error", listeners.error);
|
|
570
|
+
if (listeners.drain) {
|
|
571
|
+
if (typeof listeners.eventTarget?.off === "function") {
|
|
572
|
+
listeners.eventTarget.off("drain", listeners.drain);
|
|
573
|
+
}
|
|
574
|
+
else if (typeof listeners.eventTarget?.removeListener === "function") {
|
|
575
|
+
listeners.eventTarget.removeListener("drain", listeners.drain);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
505
578
|
this._pipeListeners.delete(destination);
|
|
506
579
|
}
|
|
507
580
|
}
|
|
@@ -513,6 +586,14 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
513
586
|
this.off("data", listeners.data);
|
|
514
587
|
this.off("end", listeners.end);
|
|
515
588
|
this.off("error", listeners.error);
|
|
589
|
+
if (listeners.drain) {
|
|
590
|
+
if (typeof listeners.eventTarget?.off === "function") {
|
|
591
|
+
listeners.eventTarget.off("drain", listeners.drain);
|
|
592
|
+
}
|
|
593
|
+
else if (typeof listeners.eventTarget?.removeListener === "function") {
|
|
594
|
+
listeners.eventTarget.removeListener("drain", listeners.drain);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
516
597
|
this._pipeListeners.delete(target);
|
|
517
598
|
}
|
|
518
599
|
}
|
|
@@ -531,12 +612,26 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
531
612
|
}
|
|
532
613
|
this._destroyed = true;
|
|
533
614
|
this._ended = true;
|
|
615
|
+
// Ensure we detach from destinations to avoid leaking listeners.
|
|
616
|
+
this.unpipe();
|
|
534
617
|
if (error) {
|
|
535
618
|
this._errored = error;
|
|
536
619
|
this.emit("error", error);
|
|
537
620
|
}
|
|
538
621
|
if (this._reader) {
|
|
539
|
-
this._reader
|
|
622
|
+
const reader = this._reader;
|
|
623
|
+
this._reader = null;
|
|
624
|
+
reader
|
|
625
|
+
.cancel()
|
|
626
|
+
.catch(() => { })
|
|
627
|
+
.finally(() => {
|
|
628
|
+
try {
|
|
629
|
+
reader.releaseLock();
|
|
630
|
+
}
|
|
631
|
+
catch {
|
|
632
|
+
// Ignore if a read is still pending
|
|
633
|
+
}
|
|
634
|
+
});
|
|
540
635
|
}
|
|
541
636
|
this._closed = true;
|
|
542
637
|
this.emit("close");
|
|
@@ -615,18 +710,38 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
615
710
|
const { done, value } = await this._reader.read();
|
|
616
711
|
// Check _pushMode again after async read - if push() was called, stop reading
|
|
617
712
|
if (this._pushMode) {
|
|
713
|
+
if (this._reader) {
|
|
714
|
+
const reader = this._reader;
|
|
715
|
+
this._reader = null;
|
|
716
|
+
try {
|
|
717
|
+
reader.releaseLock();
|
|
718
|
+
}
|
|
719
|
+
catch {
|
|
720
|
+
// Ignore if a read is still pending
|
|
721
|
+
}
|
|
722
|
+
}
|
|
618
723
|
break;
|
|
619
724
|
}
|
|
620
725
|
if (done) {
|
|
621
726
|
this._ended = true;
|
|
622
|
-
this.
|
|
727
|
+
this._emitEndOnce();
|
|
728
|
+
if (this._reader) {
|
|
729
|
+
const reader = this._reader;
|
|
730
|
+
this._reader = null;
|
|
731
|
+
try {
|
|
732
|
+
reader.releaseLock();
|
|
733
|
+
}
|
|
734
|
+
catch {
|
|
735
|
+
// Ignore if a read is still pending
|
|
736
|
+
}
|
|
737
|
+
}
|
|
623
738
|
break;
|
|
624
739
|
}
|
|
625
740
|
if (value !== undefined) {
|
|
626
741
|
// In flowing mode, emit data directly without buffering
|
|
627
742
|
// Only buffer if not flowing (paused mode)
|
|
628
743
|
if (this._flowing) {
|
|
629
|
-
this.emit("data", value);
|
|
744
|
+
this.emit("data", this._applyEncoding(value));
|
|
630
745
|
}
|
|
631
746
|
else {
|
|
632
747
|
this._buffer.push(value);
|
|
@@ -639,6 +754,16 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
639
754
|
}
|
|
640
755
|
catch (err) {
|
|
641
756
|
this.emit("error", err);
|
|
757
|
+
if (this._reader) {
|
|
758
|
+
const reader = this._reader;
|
|
759
|
+
this._reader = null;
|
|
760
|
+
try {
|
|
761
|
+
reader.releaseLock();
|
|
762
|
+
}
|
|
763
|
+
catch {
|
|
764
|
+
// Ignore if a read is still pending
|
|
765
|
+
}
|
|
766
|
+
}
|
|
642
767
|
}
|
|
643
768
|
finally {
|
|
644
769
|
this._reading = false;
|
|
@@ -646,7 +771,8 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
646
771
|
}
|
|
647
772
|
/**
|
|
648
773
|
* Async iterator support
|
|
649
|
-
* Uses
|
|
774
|
+
* Uses a unified event-queue iterator with simple backpressure.
|
|
775
|
+
* This matches Node's behavior more closely (iterator drives flowing mode).
|
|
650
776
|
*/
|
|
651
777
|
async *[Symbol.asyncIterator]() {
|
|
652
778
|
// First yield any buffered data
|
|
@@ -655,117 +781,124 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
655
781
|
if (!this.objectMode) {
|
|
656
782
|
this._bufferSize -= this._getChunkSize(chunk);
|
|
657
783
|
}
|
|
658
|
-
yield chunk;
|
|
784
|
+
yield this._applyEncoding(chunk);
|
|
659
785
|
}
|
|
660
|
-
// If already ended, we're done
|
|
661
786
|
if (this._ended) {
|
|
662
787
|
return;
|
|
663
788
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
let resolveNext = null;
|
|
670
|
-
let rejectNext = null;
|
|
671
|
-
let done = false;
|
|
672
|
-
let streamError = null;
|
|
673
|
-
let dataQueueIndex = 0;
|
|
674
|
-
const dataHandler = (chunk) => {
|
|
675
|
-
if (resolveNext) {
|
|
676
|
-
resolveNext(chunk);
|
|
677
|
-
resolveNext = null;
|
|
678
|
-
rejectNext = null;
|
|
679
|
-
}
|
|
680
|
-
else {
|
|
681
|
-
dataQueue.push(chunk);
|
|
682
|
-
}
|
|
683
|
-
};
|
|
684
|
-
const endHandler = () => {
|
|
685
|
-
done = true;
|
|
686
|
-
if (resolveNext) {
|
|
687
|
-
resolveNext(null);
|
|
688
|
-
resolveNext = null;
|
|
689
|
-
rejectNext = null;
|
|
690
|
-
}
|
|
691
|
-
};
|
|
692
|
-
const errorHandler = (err) => {
|
|
693
|
-
done = true;
|
|
694
|
-
streamError = err;
|
|
695
|
-
if (rejectNext) {
|
|
696
|
-
rejectNext(err);
|
|
697
|
-
resolveNext = null;
|
|
698
|
-
rejectNext = null;
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
const closeHandler = () => {
|
|
702
|
-
// If stream closed without end event (e.g., after destroy()),
|
|
703
|
-
// treat it as done
|
|
704
|
-
done = true;
|
|
705
|
-
if (resolveNext) {
|
|
706
|
-
resolveNext(null);
|
|
707
|
-
resolveNext = null;
|
|
708
|
-
rejectNext = null;
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
this.on("data", dataHandler);
|
|
712
|
-
this.on("end", endHandler);
|
|
713
|
-
this.on("error", errorHandler);
|
|
714
|
-
this.on("close", closeHandler);
|
|
715
|
-
try {
|
|
716
|
-
// Enter flowing mode
|
|
717
|
-
this.resume();
|
|
718
|
-
while (!done || dataQueueIndex < dataQueue.length) {
|
|
719
|
-
// Check for error before processing
|
|
720
|
-
if (streamError) {
|
|
721
|
-
throw streamError;
|
|
722
|
-
}
|
|
723
|
-
if (dataQueueIndex < dataQueue.length) {
|
|
724
|
-
const chunk = dataQueue[dataQueueIndex++];
|
|
725
|
-
if (dataQueueIndex >= 1024 && dataQueueIndex * 2 >= dataQueue.length) {
|
|
726
|
-
dataQueue.splice(0, dataQueueIndex);
|
|
727
|
-
dataQueueIndex = 0;
|
|
728
|
-
}
|
|
729
|
-
yield chunk;
|
|
730
|
-
}
|
|
731
|
-
else if (!done) {
|
|
732
|
-
const chunk = await new Promise((resolve, reject) => {
|
|
733
|
-
resolveNext = resolve;
|
|
734
|
-
rejectNext = reject;
|
|
735
|
-
});
|
|
736
|
-
if (chunk !== null) {
|
|
737
|
-
yield chunk;
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
// Check for error after loop
|
|
742
|
-
if (streamError) {
|
|
743
|
-
throw streamError;
|
|
744
|
-
}
|
|
789
|
+
const highWaterMark = this.readableHighWaterMark;
|
|
790
|
+
const lowWaterMark = Math.max(0, Math.floor(highWaterMark / 2));
|
|
791
|
+
const chunkSizeForBackpressure = (chunk) => {
|
|
792
|
+
if (this.objectMode) {
|
|
793
|
+
return 1;
|
|
745
794
|
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
this.off("end", endHandler);
|
|
749
|
-
this.off("error", errorHandler);
|
|
750
|
-
this.off("close", closeHandler);
|
|
795
|
+
if (chunk instanceof Uint8Array) {
|
|
796
|
+
return chunk.byteLength;
|
|
751
797
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
798
|
+
if (typeof chunk === "string") {
|
|
799
|
+
return chunk.length;
|
|
800
|
+
}
|
|
801
|
+
return 1;
|
|
802
|
+
};
|
|
803
|
+
const dataQueue = [];
|
|
804
|
+
let dataQueueIndex = 0;
|
|
805
|
+
let queuedSize = 0;
|
|
806
|
+
let resolveNext = null;
|
|
807
|
+
let rejectNext = null;
|
|
808
|
+
let done = false;
|
|
809
|
+
let pausedByIterator = false;
|
|
810
|
+
let streamError = null;
|
|
811
|
+
const dataHandler = (chunk) => {
|
|
812
|
+
// data events are already encoding-aware; do not decode again here.
|
|
813
|
+
if (resolveNext) {
|
|
814
|
+
resolveNext(chunk);
|
|
815
|
+
resolveNext = null;
|
|
816
|
+
rejectNext = null;
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
dataQueue.push(chunk);
|
|
820
|
+
}
|
|
821
|
+
queuedSize += chunkSizeForBackpressure(chunk);
|
|
822
|
+
if (!pausedByIterator && queuedSize >= highWaterMark) {
|
|
823
|
+
pausedByIterator = true;
|
|
824
|
+
this.pause();
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
const endHandler = () => {
|
|
828
|
+
done = true;
|
|
829
|
+
if (resolveNext) {
|
|
830
|
+
resolveNext(null);
|
|
831
|
+
resolveNext = null;
|
|
832
|
+
rejectNext = null;
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
const closeHandler = () => {
|
|
836
|
+
done = true;
|
|
837
|
+
if (resolveNext) {
|
|
838
|
+
resolveNext(null);
|
|
839
|
+
resolveNext = null;
|
|
840
|
+
rejectNext = null;
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
const errorHandler = (err) => {
|
|
844
|
+
done = true;
|
|
845
|
+
streamError = err;
|
|
846
|
+
if (rejectNext) {
|
|
847
|
+
rejectNext(err);
|
|
848
|
+
resolveNext = null;
|
|
849
|
+
rejectNext = null;
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
this.on("data", dataHandler);
|
|
853
|
+
this.on("end", endHandler);
|
|
854
|
+
this.on("error", errorHandler);
|
|
855
|
+
this.on("close", closeHandler);
|
|
758
856
|
try {
|
|
857
|
+
// Iterator consumption should drive the stream.
|
|
858
|
+
this.resume();
|
|
759
859
|
while (true) {
|
|
760
|
-
|
|
860
|
+
if (streamError) {
|
|
861
|
+
throw streamError;
|
|
862
|
+
}
|
|
863
|
+
if (dataQueueIndex < dataQueue.length) {
|
|
864
|
+
const chunk = dataQueue[dataQueueIndex++];
|
|
865
|
+
queuedSize -= chunkSizeForBackpressure(chunk);
|
|
866
|
+
if (dataQueueIndex >= 1024 && dataQueueIndex * 2 >= dataQueue.length) {
|
|
867
|
+
dataQueue.splice(0, dataQueueIndex);
|
|
868
|
+
dataQueueIndex = 0;
|
|
869
|
+
}
|
|
870
|
+
if (pausedByIterator && queuedSize <= lowWaterMark && !done && !this._destroyed) {
|
|
871
|
+
pausedByIterator = false;
|
|
872
|
+
this.resume();
|
|
873
|
+
}
|
|
874
|
+
yield chunk;
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
761
877
|
if (done) {
|
|
762
878
|
break;
|
|
763
879
|
}
|
|
764
|
-
|
|
880
|
+
const chunk = await new Promise((resolve, reject) => {
|
|
881
|
+
resolveNext = resolve;
|
|
882
|
+
rejectNext = reject;
|
|
883
|
+
});
|
|
884
|
+
if (chunk !== null) {
|
|
885
|
+
queuedSize -= chunkSizeForBackpressure(chunk);
|
|
886
|
+
if (pausedByIterator && queuedSize <= lowWaterMark && !done && !this._destroyed) {
|
|
887
|
+
pausedByIterator = false;
|
|
888
|
+
this.resume();
|
|
889
|
+
}
|
|
890
|
+
yield chunk;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (streamError) {
|
|
894
|
+
throw streamError;
|
|
765
895
|
}
|
|
766
896
|
}
|
|
767
897
|
finally {
|
|
768
|
-
this.
|
|
898
|
+
this.off("data", dataHandler);
|
|
899
|
+
this.off("end", endHandler);
|
|
900
|
+
this.off("error", errorHandler);
|
|
901
|
+
this.off("close", closeHandler);
|
|
769
902
|
}
|
|
770
903
|
}
|
|
771
904
|
/**
|
|
@@ -985,6 +1118,32 @@ class Readable extends event_emitter_1.EventEmitter {
|
|
|
985
1118
|
}
|
|
986
1119
|
}
|
|
987
1120
|
exports.Readable = Readable;
|
|
1121
|
+
function toAsyncIterable(iterable) {
|
|
1122
|
+
if (iterable && typeof iterable[Symbol.asyncIterator] === "function") {
|
|
1123
|
+
return iterable;
|
|
1124
|
+
}
|
|
1125
|
+
return (async function* () {
|
|
1126
|
+
for (const item of iterable) {
|
|
1127
|
+
yield item;
|
|
1128
|
+
}
|
|
1129
|
+
})();
|
|
1130
|
+
}
|
|
1131
|
+
function pumpAsyncIterableToReadable(readable, iterable) {
|
|
1132
|
+
(async () => {
|
|
1133
|
+
try {
|
|
1134
|
+
for await (const chunk of iterable) {
|
|
1135
|
+
if (!readable.push(chunk)) {
|
|
1136
|
+
// Simple backpressure: yield to consumer.
|
|
1137
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
readable.push(null);
|
|
1141
|
+
}
|
|
1142
|
+
catch (err) {
|
|
1143
|
+
readable.destroy(err);
|
|
1144
|
+
}
|
|
1145
|
+
})();
|
|
1146
|
+
}
|
|
988
1147
|
// =============================================================================
|
|
989
1148
|
// Writable Stream Wrapper
|
|
990
1149
|
// =============================================================================
|
|
@@ -1002,10 +1161,12 @@ class Writable extends event_emitter_1.EventEmitter {
|
|
|
1002
1161
|
this._closed = false;
|
|
1003
1162
|
this._pendingWrites = 0;
|
|
1004
1163
|
this._writableLength = 0;
|
|
1164
|
+
this._needDrain = false;
|
|
1005
1165
|
this._corked = 0;
|
|
1006
1166
|
this._corkedChunks = [];
|
|
1007
1167
|
this._defaultEncoding = "utf8";
|
|
1008
1168
|
this._aborted = false;
|
|
1169
|
+
this._ownsStream = false;
|
|
1009
1170
|
this.objectMode = options?.objectMode ?? false;
|
|
1010
1171
|
this.writableHighWaterMark = options?.highWaterMark ?? 16384;
|
|
1011
1172
|
this.autoDestroy = options?.autoDestroy ?? true;
|
|
@@ -1021,8 +1182,10 @@ class Writable extends event_emitter_1.EventEmitter {
|
|
|
1021
1182
|
}
|
|
1022
1183
|
if (options?.stream) {
|
|
1023
1184
|
this._stream = options.stream;
|
|
1185
|
+
this._ownsStream = false;
|
|
1024
1186
|
}
|
|
1025
1187
|
else {
|
|
1188
|
+
this._ownsStream = true;
|
|
1026
1189
|
// Create bound references to instance properties/methods for use in WritableStream callbacks
|
|
1027
1190
|
const getWriteFunc = () => this._writeFunc;
|
|
1028
1191
|
const getFinalFunc = () => this._finalFunc;
|
|
@@ -1129,25 +1292,37 @@ class Writable extends event_emitter_1.EventEmitter {
|
|
|
1129
1292
|
this._writableLength += chunkSize;
|
|
1130
1293
|
return this._writableLength < this.writableHighWaterMark;
|
|
1131
1294
|
}
|
|
1132
|
-
|
|
1295
|
+
const ok = this._doWrite(chunk, cb);
|
|
1296
|
+
if (!ok) {
|
|
1297
|
+
this._needDrain = true;
|
|
1298
|
+
}
|
|
1299
|
+
return ok;
|
|
1133
1300
|
}
|
|
1134
1301
|
_doWrite(chunk, callback) {
|
|
1135
1302
|
// Track pending writes for writableLength
|
|
1136
1303
|
const chunkSize = this._getChunkSize(chunk);
|
|
1137
1304
|
this._pendingWrites++;
|
|
1138
1305
|
this._writableLength += chunkSize;
|
|
1139
|
-
this._getWriter()
|
|
1306
|
+
const writer = this._getWriter();
|
|
1307
|
+
writer
|
|
1140
1308
|
.write(chunk)
|
|
1141
1309
|
.then(() => {
|
|
1142
1310
|
this._pendingWrites--;
|
|
1143
1311
|
this._writableLength -= chunkSize;
|
|
1144
|
-
this.
|
|
1312
|
+
if (this._needDrain && this._writableLength < this.writableHighWaterMark) {
|
|
1313
|
+
this._needDrain = false;
|
|
1314
|
+
this.emit("drain");
|
|
1315
|
+
}
|
|
1145
1316
|
callback?.(null);
|
|
1146
1317
|
})
|
|
1147
1318
|
.catch(err => {
|
|
1148
1319
|
this._pendingWrites--;
|
|
1149
1320
|
this._writableLength -= chunkSize;
|
|
1150
|
-
|
|
1321
|
+
// Avoid double-emitting if we're already in an errored/destroyed state.
|
|
1322
|
+
if (!this._destroyed) {
|
|
1323
|
+
this._errored = err;
|
|
1324
|
+
this.emit("error", err);
|
|
1325
|
+
}
|
|
1151
1326
|
callback?.(err);
|
|
1152
1327
|
});
|
|
1153
1328
|
// Return false if we've exceeded high water mark (for backpressure)
|
|
@@ -1178,12 +1353,29 @@ class Writable extends event_emitter_1.EventEmitter {
|
|
|
1178
1353
|
: callback;
|
|
1179
1354
|
const finish = async () => {
|
|
1180
1355
|
try {
|
|
1356
|
+
const writer = this._getWriter();
|
|
1181
1357
|
if (chunk !== undefined) {
|
|
1182
|
-
await
|
|
1358
|
+
await writer.write(chunk);
|
|
1359
|
+
}
|
|
1360
|
+
await writer.close();
|
|
1361
|
+
if (this._writer === writer) {
|
|
1362
|
+
this._writer = null;
|
|
1363
|
+
try {
|
|
1364
|
+
writer.releaseLock();
|
|
1365
|
+
}
|
|
1366
|
+
catch {
|
|
1367
|
+
// Ignore
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
// If we own the underlying Web WritableStream, its `close()` handler already
|
|
1371
|
+
// emits finish/close. For external streams, we must emit finish ourselves.
|
|
1372
|
+
if (!this._ownsStream) {
|
|
1373
|
+
this._finished = true;
|
|
1374
|
+
this.emit("finish");
|
|
1375
|
+
if (this.emitClose) {
|
|
1376
|
+
this.emit("close");
|
|
1377
|
+
}
|
|
1183
1378
|
}
|
|
1184
|
-
await this._getWriter().close();
|
|
1185
|
-
this._finished = true;
|
|
1186
|
-
this.emit("finish");
|
|
1187
1379
|
if (cb) {
|
|
1188
1380
|
cb();
|
|
1189
1381
|
}
|
|
@@ -1204,12 +1396,24 @@ class Writable extends event_emitter_1.EventEmitter {
|
|
|
1204
1396
|
}
|
|
1205
1397
|
this._destroyed = true;
|
|
1206
1398
|
this._ended = true;
|
|
1207
|
-
if (error) {
|
|
1399
|
+
if (error && !this._errored) {
|
|
1208
1400
|
this._errored = error;
|
|
1209
1401
|
this.emit("error", error);
|
|
1210
1402
|
}
|
|
1211
1403
|
if (this._writer) {
|
|
1212
|
-
this._writer
|
|
1404
|
+
const writer = this._writer;
|
|
1405
|
+
this._writer = null;
|
|
1406
|
+
writer
|
|
1407
|
+
.abort(error)
|
|
1408
|
+
.catch(() => { })
|
|
1409
|
+
.finally(() => {
|
|
1410
|
+
try {
|
|
1411
|
+
writer.releaseLock();
|
|
1412
|
+
}
|
|
1413
|
+
catch {
|
|
1414
|
+
// Ignore
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1213
1417
|
}
|
|
1214
1418
|
this._closed = true;
|
|
1215
1419
|
this.emit("close");
|
|
@@ -1361,342 +1565,259 @@ function normalizeWritable(stream) {
|
|
|
1361
1565
|
*/
|
|
1362
1566
|
class Transform extends event_emitter_1.EventEmitter {
|
|
1363
1567
|
/**
|
|
1364
|
-
* Push data to the readable side (Node.js compatibility)
|
|
1365
|
-
*
|
|
1568
|
+
* Push data to the readable side (Node.js compatibility).
|
|
1569
|
+
* Intended to be called from within transform/flush.
|
|
1366
1570
|
*/
|
|
1367
1571
|
push(chunk) {
|
|
1368
|
-
|
|
1369
|
-
return false;
|
|
1370
|
-
}
|
|
1371
|
-
if (this._transformController) {
|
|
1372
|
-
// If we're in a transform callback, enqueue directly
|
|
1373
|
-
this._transformController.enqueue(chunk);
|
|
1374
|
-
}
|
|
1375
|
-
else {
|
|
1376
|
-
// Otherwise buffer for later
|
|
1377
|
-
this._pushBuffer.push(chunk);
|
|
1378
|
-
}
|
|
1379
|
-
return true;
|
|
1572
|
+
return this._readable.push(chunk);
|
|
1380
1573
|
}
|
|
1381
1574
|
constructor(options) {
|
|
1382
1575
|
super();
|
|
1383
|
-
this._ended = false;
|
|
1384
1576
|
this._destroyed = false;
|
|
1577
|
+
this._ended = false;
|
|
1385
1578
|
this._errored = false;
|
|
1386
|
-
// Buffer for Node.js style push() calls during transform
|
|
1387
|
-
this._pushBuffer = [];
|
|
1388
|
-
// Controller for enqueueing pushed data (set during transform execution)
|
|
1389
|
-
this._transformController = null;
|
|
1390
|
-
// Buffer for writes that occur after end() but before writable is closed
|
|
1391
|
-
this._pendingEndWrites = [];
|
|
1392
|
-
// Whether end() has been called but writable not yet closed
|
|
1393
|
-
this._endPending = false;
|
|
1394
|
-
// Track if we've already set up data forwarding
|
|
1395
1579
|
this._dataForwardingSetup = false;
|
|
1396
|
-
|
|
1397
|
-
this.
|
|
1398
|
-
|
|
1399
|
-
this._readableConsuming = false;
|
|
1400
|
-
/** @internal - buffer for auto-consumed data */
|
|
1401
|
-
this._autoConsumedBuffer = [];
|
|
1402
|
-
this._autoConsumedBufferIndex = 0;
|
|
1403
|
-
/** @internal - whether auto-consume has ended */
|
|
1404
|
-
this._autoConsumeEnded = false;
|
|
1405
|
-
/** @internal - promise that resolves when auto-consume finishes */
|
|
1406
|
-
this._autoConsumePromise = null;
|
|
1407
|
-
/** @internal - list of piped destinations for forwarding auto-consumed data */
|
|
1408
|
-
this._pipeDestinations = [];
|
|
1580
|
+
this._endTimer = null;
|
|
1581
|
+
this._webStream = null;
|
|
1582
|
+
this._sideForwardingCleanup = null;
|
|
1409
1583
|
this.objectMode = options?.objectMode ?? false;
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1584
|
+
this._transformImpl = options?.transform;
|
|
1585
|
+
this._flushImpl = options?.flush;
|
|
1586
|
+
this._readable = new Readable({
|
|
1587
|
+
objectMode: this.objectMode
|
|
1588
|
+
});
|
|
1589
|
+
this._writable = new Writable({
|
|
1590
|
+
objectMode: this.objectMode,
|
|
1591
|
+
write: (chunk, _encoding, callback) => {
|
|
1592
|
+
this._runTransform(chunk)
|
|
1593
|
+
.then(() => callback(null))
|
|
1594
|
+
.catch(err => callback(err));
|
|
1595
|
+
},
|
|
1596
|
+
final: callback => {
|
|
1597
|
+
this._runFlush()
|
|
1598
|
+
.then(() => {
|
|
1599
|
+
this._readable.push(null);
|
|
1600
|
+
callback(null);
|
|
1601
|
+
})
|
|
1602
|
+
.catch(err => callback(err));
|
|
1425
1603
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1604
|
+
});
|
|
1605
|
+
this._setupSideForwarding();
|
|
1606
|
+
}
|
|
1607
|
+
_setupSideForwarding() {
|
|
1608
|
+
if (this._sideForwardingCleanup) {
|
|
1609
|
+
this._sideForwardingCleanup();
|
|
1610
|
+
this._sideForwardingCleanup = null;
|
|
1611
|
+
}
|
|
1612
|
+
const registry = createListenerRegistry();
|
|
1613
|
+
registry.once(this._readable, "end", () => this.emit("end"));
|
|
1614
|
+
registry.add(this._readable, "error", err => this._emitErrorOnce(err));
|
|
1615
|
+
registry.once(this._writable, "finish", () => this.emit("finish"));
|
|
1616
|
+
registry.add(this._writable, "drain", () => this.emit("drain"));
|
|
1617
|
+
registry.add(this._writable, "error", err => this._emitErrorOnce(err));
|
|
1618
|
+
this._sideForwardingCleanup = () => registry.cleanup();
|
|
1619
|
+
}
|
|
1620
|
+
_scheduleEnd() {
|
|
1621
|
+
if (this._destroyed || this._errored) {
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
if (this._writable.writableEnded) {
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
if (this._endTimer) {
|
|
1628
|
+
clearTimeout(this._endTimer);
|
|
1629
|
+
}
|
|
1630
|
+
// Defer closing to allow writes triggered during 'data' callbacks.
|
|
1631
|
+
this._endTimer = setTimeout(() => {
|
|
1632
|
+
this._endTimer = null;
|
|
1633
|
+
if (this._destroyed || this._errored || this._writable.writableEnded) {
|
|
1634
|
+
return;
|
|
1435
1635
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1636
|
+
this._writable.end();
|
|
1637
|
+
}, 0);
|
|
1638
|
+
}
|
|
1639
|
+
_emitErrorOnce(err) {
|
|
1640
|
+
if (this._errored) {
|
|
1641
|
+
return;
|
|
1642
|
+
}
|
|
1643
|
+
this._errored = true;
|
|
1644
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1645
|
+
this.emit("error", error);
|
|
1646
|
+
if (!this._destroyed) {
|
|
1647
|
+
this._destroyed = true;
|
|
1648
|
+
this._readable.destroy(error);
|
|
1649
|
+
this._writable.destroy(error);
|
|
1650
|
+
queueMicrotask(() => this.emit("close"));
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
_hasSubclassTransform() {
|
|
1654
|
+
if (this._transformImpl) {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
const proto = Object.getPrototypeOf(this);
|
|
1658
|
+
return proto._transform !== Transform.prototype._transform;
|
|
1659
|
+
}
|
|
1660
|
+
_hasSubclassFlush() {
|
|
1661
|
+
if (this._flushImpl) {
|
|
1662
|
+
return false;
|
|
1663
|
+
}
|
|
1664
|
+
const proto = Object.getPrototypeOf(this);
|
|
1665
|
+
return proto._flush !== Transform.prototype._flush;
|
|
1666
|
+
}
|
|
1667
|
+
async _runTransform(chunk) {
|
|
1668
|
+
if (this._destroyed || this._errored) {
|
|
1669
|
+
throw new Error(this._errored ? "Cannot write after stream errored" : "Cannot write after stream destroyed");
|
|
1670
|
+
}
|
|
1671
|
+
try {
|
|
1672
|
+
if (this._hasSubclassTransform()) {
|
|
1673
|
+
await new Promise((resolve, reject) => {
|
|
1674
|
+
this._transform(chunk, "utf8", (err, data) => {
|
|
1675
|
+
if (err) {
|
|
1676
|
+
reject(err);
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
if (data !== undefined) {
|
|
1680
|
+
this.push(data);
|
|
1681
|
+
}
|
|
1682
|
+
resolve();
|
|
1683
|
+
});
|
|
1684
|
+
});
|
|
1685
|
+
return;
|
|
1443
1686
|
}
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
// Check for subclass _transform override first
|
|
1457
|
-
if (hasSubclassTransform()) {
|
|
1458
|
-
// Call subclass _transform method (Node.js style)
|
|
1459
|
-
// _transform signature is (chunk, encoding, callback)
|
|
1460
|
-
await new Promise((resolve, reject) => {
|
|
1461
|
-
this._transform(chunk, "utf8", (err, data) => {
|
|
1462
|
-
if (err) {
|
|
1463
|
-
reject(err);
|
|
1464
|
-
}
|
|
1465
|
-
else {
|
|
1466
|
-
if (data !== undefined) {
|
|
1467
|
-
controller.enqueue(data);
|
|
1468
|
-
}
|
|
1469
|
-
resolve();
|
|
1470
|
-
}
|
|
1471
|
-
});
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
else if (userTransform) {
|
|
1475
|
-
const transformParamCount = userTransform.length;
|
|
1476
|
-
if (transformParamCount >= 3) {
|
|
1477
|
-
// Node.js style: transform(chunk, encoding, callback)
|
|
1478
|
-
await new Promise((resolve, reject) => {
|
|
1479
|
-
userTransform.call(getInstance(), chunk, "utf8", (err, data) => {
|
|
1480
|
-
if (err) {
|
|
1481
|
-
reject(err);
|
|
1482
|
-
}
|
|
1483
|
-
else {
|
|
1484
|
-
if (data !== undefined) {
|
|
1485
|
-
controller.enqueue(data);
|
|
1486
|
-
}
|
|
1487
|
-
resolve();
|
|
1488
|
-
}
|
|
1489
|
-
});
|
|
1490
|
-
});
|
|
1687
|
+
const userTransform = this._transformImpl;
|
|
1688
|
+
if (!userTransform) {
|
|
1689
|
+
this.push(chunk);
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
const paramCount = userTransform.length;
|
|
1693
|
+
if (paramCount >= 3) {
|
|
1694
|
+
await new Promise((resolve, reject) => {
|
|
1695
|
+
userTransform.call(this, chunk, "utf8", (err, data) => {
|
|
1696
|
+
if (err) {
|
|
1697
|
+
reject(err);
|
|
1698
|
+
return;
|
|
1491
1699
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
userTransform.call(getInstance(), chunk, (err, data) => {
|
|
1495
|
-
if (err) {
|
|
1496
|
-
reject(err);
|
|
1497
|
-
}
|
|
1498
|
-
else {
|
|
1499
|
-
if (data !== undefined) {
|
|
1500
|
-
controller.enqueue(data);
|
|
1501
|
-
}
|
|
1502
|
-
resolve();
|
|
1503
|
-
}
|
|
1504
|
-
});
|
|
1505
|
-
});
|
|
1700
|
+
if (data !== undefined) {
|
|
1701
|
+
this.push(data);
|
|
1506
1702
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
controller.enqueue(result);
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1703
|
+
resolve();
|
|
1704
|
+
});
|
|
1705
|
+
});
|
|
1706
|
+
return;
|
|
1707
|
+
}
|
|
1708
|
+
if (paramCount === 2) {
|
|
1709
|
+
await new Promise((resolve, reject) => {
|
|
1710
|
+
userTransform.call(this, chunk, (err, data) => {
|
|
1711
|
+
if (err) {
|
|
1712
|
+
reject(err);
|
|
1713
|
+
return;
|
|
1521
1714
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1715
|
+
if (data !== undefined) {
|
|
1716
|
+
this.push(data);
|
|
1717
|
+
}
|
|
1718
|
+
resolve();
|
|
1719
|
+
});
|
|
1720
|
+
});
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
const result = userTransform.call(this, chunk);
|
|
1724
|
+
if (result && typeof result.then === "function") {
|
|
1725
|
+
const awaited = await result;
|
|
1726
|
+
if (awaited !== undefined) {
|
|
1727
|
+
this.push(awaited);
|
|
1534
1728
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
if (flushParamCount >= 1) {
|
|
1558
|
-
// Node.js style: flush(callback)
|
|
1559
|
-
await new Promise((resolve, reject) => {
|
|
1560
|
-
userFlush.call(getInstance(), (err, data) => {
|
|
1561
|
-
if (err) {
|
|
1562
|
-
reject(err);
|
|
1563
|
-
}
|
|
1564
|
-
else {
|
|
1565
|
-
if (data !== undefined) {
|
|
1566
|
-
controller.enqueue(data);
|
|
1567
|
-
}
|
|
1568
|
-
resolve();
|
|
1569
|
-
}
|
|
1570
|
-
});
|
|
1571
|
-
});
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
if (result !== undefined) {
|
|
1732
|
+
this.push(result);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
catch (err) {
|
|
1736
|
+
this._emitErrorOnce(err);
|
|
1737
|
+
throw err;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
async _runFlush() {
|
|
1741
|
+
if (this._destroyed || this._errored) {
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
try {
|
|
1745
|
+
if (this._hasSubclassFlush()) {
|
|
1746
|
+
await new Promise((resolve, reject) => {
|
|
1747
|
+
this._flush((err, data) => {
|
|
1748
|
+
if (err) {
|
|
1749
|
+
reject(err);
|
|
1750
|
+
return;
|
|
1572
1751
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
const result = userFlush.call(getInstance());
|
|
1576
|
-
if (result && typeof result.then === "function") {
|
|
1577
|
-
const awaitedResult = await result;
|
|
1578
|
-
if (awaitedResult !== undefined && awaitedResult !== null) {
|
|
1579
|
-
controller.enqueue(awaitedResult);
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
else {
|
|
1583
|
-
if (result !== undefined && result !== null) {
|
|
1584
|
-
controller.enqueue(result);
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1752
|
+
if (data !== undefined) {
|
|
1753
|
+
this.push(data);
|
|
1587
1754
|
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
controller.error(err);
|
|
1593
|
-
emitEvent("error", err);
|
|
1594
|
-
}
|
|
1595
|
-
finally {
|
|
1596
|
-
setController(null);
|
|
1597
|
-
}
|
|
1755
|
+
resolve();
|
|
1756
|
+
});
|
|
1757
|
+
});
|
|
1758
|
+
return;
|
|
1598
1759
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1760
|
+
const userFlush = this._flushImpl;
|
|
1761
|
+
if (!userFlush) {
|
|
1762
|
+
return;
|
|
1763
|
+
}
|
|
1764
|
+
const paramCount = userFlush.length;
|
|
1765
|
+
if (paramCount >= 1) {
|
|
1766
|
+
await new Promise((resolve, reject) => {
|
|
1767
|
+
userFlush.call(this, (err, data) => {
|
|
1768
|
+
if (err) {
|
|
1769
|
+
reject(err);
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
if (data !== undefined) {
|
|
1773
|
+
this.push(data);
|
|
1774
|
+
}
|
|
1775
|
+
resolve();
|
|
1776
|
+
});
|
|
1777
|
+
});
|
|
1778
|
+
return;
|
|
1615
1779
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
this.emit("error", err);
|
|
1780
|
+
const result = userFlush.call(this);
|
|
1781
|
+
if (result && typeof result.then === "function") {
|
|
1782
|
+
const awaited = await result;
|
|
1783
|
+
if (awaited !== undefined && awaited !== null) {
|
|
1784
|
+
this.push(awaited);
|
|
1785
|
+
}
|
|
1786
|
+
return;
|
|
1624
1787
|
}
|
|
1625
|
-
|
|
1788
|
+
if (result !== undefined && result !== null) {
|
|
1789
|
+
this.push(result);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
catch (err) {
|
|
1793
|
+
this._emitErrorOnce(err);
|
|
1794
|
+
throw err;
|
|
1795
|
+
}
|
|
1626
1796
|
}
|
|
1627
1797
|
/**
|
|
1628
|
-
* Override on to
|
|
1798
|
+
* Override on() to lazily forward readable 'data' events.
|
|
1799
|
+
* Avoids starting flowing mode unless requested.
|
|
1629
1800
|
*/
|
|
1630
1801
|
on(event, listener) {
|
|
1631
|
-
// Set up data forwarding when first external data listener is added
|
|
1632
1802
|
if (event === "data" && !this._dataForwardingSetup) {
|
|
1633
1803
|
this._dataForwardingSetup = true;
|
|
1634
|
-
this._readable.on("data",
|
|
1635
|
-
}
|
|
1636
|
-
super.on(event, listener);
|
|
1637
|
-
// When data listener is added, mark as having consumer
|
|
1638
|
-
// and start the readable in flowing mode
|
|
1639
|
-
if (event === "data") {
|
|
1640
|
-
this._hasDataConsumer = true;
|
|
1641
|
-
this._readable.resume();
|
|
1804
|
+
this._readable.on("data", chunk => this.emit("data", chunk));
|
|
1642
1805
|
}
|
|
1643
|
-
return
|
|
1806
|
+
return super.on(event, listener);
|
|
1644
1807
|
}
|
|
1645
1808
|
write(chunk, encodingOrCallback, callback) {
|
|
1646
1809
|
const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
cb?.(err);
|
|
1651
|
-
return false;
|
|
1652
|
-
}
|
|
1653
|
-
// Ensure readable is being consumed to allow transform to execute
|
|
1654
|
-
// This matches Node.js behavior where transform executes immediately on write
|
|
1655
|
-
// Only auto-consume if no explicit consumer (data listener or pipe)
|
|
1656
|
-
if (!this._readableConsuming && !this._hasDataConsumer) {
|
|
1657
|
-
this._readableConsuming = true;
|
|
1658
|
-
this._startAutoConsume();
|
|
1659
|
-
}
|
|
1660
|
-
// If end() was called but writable not yet closed, buffer the write
|
|
1661
|
-
// This allows writes during data event handlers to be processed
|
|
1662
|
-
if (this._endPending) {
|
|
1663
|
-
this._pendingEndWrites.push({ chunk, callback: cb });
|
|
1664
|
-
return true;
|
|
1810
|
+
// If end() has been requested, keep the close deferred as long as writes continue.
|
|
1811
|
+
if (this._ended && !this._writable.writableEnded) {
|
|
1812
|
+
this._scheduleEnd();
|
|
1665
1813
|
}
|
|
1666
1814
|
return this._writable.write(chunk, cb);
|
|
1667
1815
|
}
|
|
1668
|
-
/** @internal - auto-consume readable to allow transform to execute */
|
|
1669
|
-
_startAutoConsume() {
|
|
1670
|
-
this._autoConsumePromise = (async () => {
|
|
1671
|
-
try {
|
|
1672
|
-
for await (const chunk of this._readable) {
|
|
1673
|
-
// Buffer the data for later retrieval
|
|
1674
|
-
this._autoConsumedBuffer.push(chunk);
|
|
1675
|
-
// Forward to any piped destinations
|
|
1676
|
-
for (const dest of this._pipeDestinations) {
|
|
1677
|
-
dest.write(chunk);
|
|
1678
|
-
}
|
|
1679
|
-
// Also emit data event for listeners
|
|
1680
|
-
this.emit("data", chunk);
|
|
1681
|
-
}
|
|
1682
|
-
this._autoConsumeEnded = true;
|
|
1683
|
-
// End all piped destinations
|
|
1684
|
-
for (const dest of this._pipeDestinations) {
|
|
1685
|
-
dest.end();
|
|
1686
|
-
}
|
|
1687
|
-
this.emit("end");
|
|
1688
|
-
}
|
|
1689
|
-
catch (err) {
|
|
1690
|
-
this.emit("error", err);
|
|
1691
|
-
}
|
|
1692
|
-
})();
|
|
1693
|
-
}
|
|
1694
1816
|
end(chunkOrCallback, encodingOrCallback, callback) {
|
|
1695
1817
|
if (this._ended) {
|
|
1696
1818
|
return this;
|
|
1697
1819
|
}
|
|
1698
1820
|
this._ended = true;
|
|
1699
|
-
this._endPending = true;
|
|
1700
1821
|
const chunk = typeof chunkOrCallback === "function" ? undefined : chunkOrCallback;
|
|
1701
1822
|
const cb = typeof chunkOrCallback === "function"
|
|
1702
1823
|
? chunkOrCallback
|
|
@@ -1709,18 +1830,7 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1709
1830
|
if (chunk !== undefined) {
|
|
1710
1831
|
this._writable.write(chunk);
|
|
1711
1832
|
}
|
|
1712
|
-
|
|
1713
|
-
// processing and data events complete before we close the writable.
|
|
1714
|
-
// Microtasks run before the TransformStream processes data.
|
|
1715
|
-
setTimeout(() => {
|
|
1716
|
-
// Process any writes that occurred during data events
|
|
1717
|
-
for (const { chunk: pendingChunk, callback } of this._pendingEndWrites) {
|
|
1718
|
-
this._writable.write(pendingChunk, callback);
|
|
1719
|
-
}
|
|
1720
|
-
this._pendingEndWrites = [];
|
|
1721
|
-
this._endPending = false;
|
|
1722
|
-
this._writable.end();
|
|
1723
|
-
}, 0);
|
|
1833
|
+
this._scheduleEnd();
|
|
1724
1834
|
return this;
|
|
1725
1835
|
}
|
|
1726
1836
|
/**
|
|
@@ -1730,31 +1840,9 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1730
1840
|
return this._readable.read(size);
|
|
1731
1841
|
}
|
|
1732
1842
|
/**
|
|
1733
|
-
* Pipe
|
|
1843
|
+
* Pipe readable side to destination
|
|
1734
1844
|
*/
|
|
1735
1845
|
pipe(destination) {
|
|
1736
|
-
// Mark as having consumer to prevent new auto-consume from starting
|
|
1737
|
-
this._hasDataConsumer = true;
|
|
1738
|
-
// Get the writable target - handle both Transform (with internal _writable) and plain Writable
|
|
1739
|
-
const dest = destination;
|
|
1740
|
-
const target = dest?._writable ?? dest;
|
|
1741
|
-
// Register destination for forwarding
|
|
1742
|
-
this._pipeDestinations.push(target);
|
|
1743
|
-
// If auto-consume is running or has run, we need to handle buffered data ourselves
|
|
1744
|
-
if (this._readableConsuming) {
|
|
1745
|
-
// Forward any buffered data from auto-consume to the destination
|
|
1746
|
-
for (let i = 0; i < this._autoConsumedBuffer.length; i++) {
|
|
1747
|
-
target.write(this._autoConsumedBuffer[i]);
|
|
1748
|
-
}
|
|
1749
|
-
// If auto-consume has ended, end the destination too
|
|
1750
|
-
if (this._autoConsumeEnded) {
|
|
1751
|
-
target.end();
|
|
1752
|
-
}
|
|
1753
|
-
// Don't call _readable.pipe() - auto-consume already consumed _readable
|
|
1754
|
-
// Future data will be forwarded via the 'data' event listener below
|
|
1755
|
-
return destination;
|
|
1756
|
-
}
|
|
1757
|
-
// No auto-consume running - use normal pipe through _readable
|
|
1758
1846
|
return this._readable.pipe(destination);
|
|
1759
1847
|
}
|
|
1760
1848
|
/**
|
|
@@ -1792,6 +1880,10 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1792
1880
|
return;
|
|
1793
1881
|
}
|
|
1794
1882
|
this._destroyed = true;
|
|
1883
|
+
if (this._sideForwardingCleanup) {
|
|
1884
|
+
this._sideForwardingCleanup();
|
|
1885
|
+
this._sideForwardingCleanup = null;
|
|
1886
|
+
}
|
|
1795
1887
|
this._readable.destroy(error);
|
|
1796
1888
|
this._writable.destroy(error);
|
|
1797
1889
|
queueMicrotask(() => this.emit("close"));
|
|
@@ -1800,7 +1892,44 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1800
1892
|
* Get the underlying Web TransformStream
|
|
1801
1893
|
*/
|
|
1802
1894
|
get webStream() {
|
|
1803
|
-
|
|
1895
|
+
if (this._webStream) {
|
|
1896
|
+
return this._webStream;
|
|
1897
|
+
}
|
|
1898
|
+
// Web Streams interop layer.
|
|
1899
|
+
const iterator = this[Symbol.asyncIterator]();
|
|
1900
|
+
const readable = new ReadableStream({
|
|
1901
|
+
pull: async (controller) => {
|
|
1902
|
+
const { done, value } = await iterator.next();
|
|
1903
|
+
if (done) {
|
|
1904
|
+
controller.close();
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
controller.enqueue(value);
|
|
1908
|
+
},
|
|
1909
|
+
cancel: reason => {
|
|
1910
|
+
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
const writable = new WritableStream({
|
|
1914
|
+
write: chunk => new Promise((resolve, reject) => {
|
|
1915
|
+
this.write(chunk, err => {
|
|
1916
|
+
if (err) {
|
|
1917
|
+
reject(err);
|
|
1918
|
+
}
|
|
1919
|
+
else {
|
|
1920
|
+
resolve();
|
|
1921
|
+
}
|
|
1922
|
+
});
|
|
1923
|
+
}),
|
|
1924
|
+
close: () => new Promise(resolve => {
|
|
1925
|
+
this.end(() => resolve());
|
|
1926
|
+
}),
|
|
1927
|
+
abort: reason => {
|
|
1928
|
+
this.destroy(reason instanceof Error ? reason : new Error(String(reason)));
|
|
1929
|
+
}
|
|
1930
|
+
});
|
|
1931
|
+
this._webStream = { readable, writable };
|
|
1932
|
+
return this._webStream;
|
|
1804
1933
|
}
|
|
1805
1934
|
get readable() {
|
|
1806
1935
|
return this._readable.readable;
|
|
@@ -1842,19 +1971,6 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1842
1971
|
* Async iterator support
|
|
1843
1972
|
*/
|
|
1844
1973
|
async *[Symbol.asyncIterator]() {
|
|
1845
|
-
// If auto-consume is running, wait for it to finish and use its buffer
|
|
1846
|
-
if (this._autoConsumePromise) {
|
|
1847
|
-
await this._autoConsumePromise;
|
|
1848
|
-
// Yield all buffered data
|
|
1849
|
-
while (this._autoConsumedBufferIndex < this._autoConsumedBuffer.length) {
|
|
1850
|
-
yield this._autoConsumedBuffer[this._autoConsumedBufferIndex++];
|
|
1851
|
-
}
|
|
1852
|
-
// Reset when drained to avoid prefix growth
|
|
1853
|
-
this._autoConsumedBuffer.length = 0;
|
|
1854
|
-
this._autoConsumedBufferIndex = 0;
|
|
1855
|
-
return;
|
|
1856
|
-
}
|
|
1857
|
-
// Otherwise delegate to readable's iterator
|
|
1858
1974
|
yield* this._readable[Symbol.asyncIterator]();
|
|
1859
1975
|
}
|
|
1860
1976
|
// =========================================================================
|
|
@@ -1865,23 +1981,18 @@ class Transform extends event_emitter_1.EventEmitter {
|
|
|
1865
1981
|
*/
|
|
1866
1982
|
static fromWeb(webStream, options) {
|
|
1867
1983
|
const transform = new Transform(options);
|
|
1868
|
-
|
|
1869
|
-
transform._stream = webStream;
|
|
1984
|
+
transform._webStream = webStream;
|
|
1870
1985
|
// Replace internal streams with the ones from the web stream
|
|
1871
1986
|
const newReadable = Readable.fromWeb(webStream.readable, { objectMode: options?.objectMode });
|
|
1872
1987
|
const newWritable = Writable.fromWeb(webStream.writable, { objectMode: options?.objectMode });
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1988
|
+
if (transform._sideForwardingCleanup) {
|
|
1989
|
+
transform._sideForwardingCleanup();
|
|
1990
|
+
transform._sideForwardingCleanup = null;
|
|
1991
|
+
}
|
|
1876
1992
|
transform._readable = newReadable;
|
|
1877
1993
|
transform._writable = newWritable;
|
|
1878
|
-
// Re-connect event forwarding
|
|
1879
|
-
|
|
1880
|
-
newReadable.on("end", () => transform.emit("end"));
|
|
1881
|
-
newReadable.on("error", (err) => transform.emit("error", err));
|
|
1882
|
-
newWritable.on("finish", () => transform.emit("finish"));
|
|
1883
|
-
newWritable.on("drain", () => transform.emit("drain"));
|
|
1884
|
-
newWritable.on("error", (err) => transform.emit("error", err));
|
|
1994
|
+
// Re-connect event forwarding (data forwarding remains lazy via Transform.on)
|
|
1995
|
+
transform._setupSideForwarding();
|
|
1885
1996
|
return transform;
|
|
1886
1997
|
}
|
|
1887
1998
|
/**
|
|
@@ -1938,7 +2049,13 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
1938
2049
|
callback();
|
|
1939
2050
|
}
|
|
1940
2051
|
});
|
|
1941
|
-
|
|
2052
|
+
const onError = (err) => {
|
|
2053
|
+
duplex.emit("error", err);
|
|
2054
|
+
};
|
|
2055
|
+
const cleanupError = addEmitterListener(readable, "error", onError);
|
|
2056
|
+
addEmitterListener(readable, "end", cleanupError, { once: true });
|
|
2057
|
+
addEmitterListener(readable, "close", cleanupError, { once: true });
|
|
2058
|
+
addEmitterListener(sink, "finish", cleanupError, { once: true });
|
|
1942
2059
|
readable.pipe(sink);
|
|
1943
2060
|
};
|
|
1944
2061
|
// If it has readable and/or writable properties
|
|
@@ -1946,21 +2063,25 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
1946
2063
|
source !== null &&
|
|
1947
2064
|
"readable" in source &&
|
|
1948
2065
|
"writable" in source) {
|
|
1949
|
-
const duplex = new Duplex();
|
|
1950
2066
|
const pair = source;
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2067
|
+
// Create one duplex that can bridge both sides.
|
|
2068
|
+
// (Previous behavior returned a new writable-only Duplex and dropped the readable side.)
|
|
2069
|
+
const duplex = new Duplex({
|
|
2070
|
+
readableObjectMode: pair.readable?.readableObjectMode,
|
|
2071
|
+
writableObjectMode: pair.writable?.writableObjectMode,
|
|
2072
|
+
write: pair.writable
|
|
2073
|
+
? (chunk, encoding, callback) => {
|
|
1958
2074
|
pair.writable.write(chunk, encoding, callback);
|
|
1959
|
-
}
|
|
1960
|
-
|
|
2075
|
+
}
|
|
2076
|
+
: undefined,
|
|
2077
|
+
final: pair.writable
|
|
2078
|
+
? callback => {
|
|
1961
2079
|
pair.writable.end(callback);
|
|
1962
2080
|
}
|
|
1963
|
-
|
|
2081
|
+
: undefined
|
|
2082
|
+
});
|
|
2083
|
+
if (pair.readable) {
|
|
2084
|
+
forwardReadableToDuplex(pair.readable, duplex);
|
|
1964
2085
|
}
|
|
1965
2086
|
return duplex;
|
|
1966
2087
|
}
|
|
@@ -1998,9 +2119,22 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
1998
2119
|
*/
|
|
1999
2120
|
static fromWeb(pair, options) {
|
|
2000
2121
|
const duplex = new Duplex(options);
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2122
|
+
const newReadable = new Readable({
|
|
2123
|
+
stream: pair.readable,
|
|
2124
|
+
objectMode: duplex.readableObjectMode
|
|
2125
|
+
});
|
|
2126
|
+
const newWritable = new Writable({
|
|
2127
|
+
stream: pair.writable,
|
|
2128
|
+
objectMode: duplex.writableObjectMode
|
|
2129
|
+
});
|
|
2130
|
+
if (duplex._sideForwardingCleanup) {
|
|
2131
|
+
duplex._sideForwardingCleanup();
|
|
2132
|
+
duplex._sideForwardingCleanup = null;
|
|
2133
|
+
}
|
|
2134
|
+
duplex._readable = newReadable;
|
|
2135
|
+
duplex._writable = newWritable;
|
|
2136
|
+
// Re-wire event forwarding (data forwarding remains lazy via Duplex.on)
|
|
2137
|
+
duplex._setupSideForwarding();
|
|
2004
2138
|
return duplex;
|
|
2005
2139
|
}
|
|
2006
2140
|
/**
|
|
@@ -2016,6 +2150,7 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
2016
2150
|
super();
|
|
2017
2151
|
// Track if we've already set up data forwarding
|
|
2018
2152
|
this._dataForwardingSetup = false;
|
|
2153
|
+
this._sideForwardingCleanup = null;
|
|
2019
2154
|
this.allowHalfOpen = options?.allowHalfOpen ?? true;
|
|
2020
2155
|
// Support shorthand objectMode option
|
|
2021
2156
|
const objectMode = options?.objectMode ?? false;
|
|
@@ -2032,23 +2167,31 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
2032
2167
|
write: options?.write?.bind(this),
|
|
2033
2168
|
final: options?.final?.bind(this)
|
|
2034
2169
|
});
|
|
2170
|
+
this._setupSideForwarding();
|
|
2171
|
+
}
|
|
2172
|
+
_setupSideForwarding() {
|
|
2173
|
+
if (this._sideForwardingCleanup) {
|
|
2174
|
+
this._sideForwardingCleanup();
|
|
2175
|
+
this._sideForwardingCleanup = null;
|
|
2176
|
+
}
|
|
2177
|
+
const registry = createListenerRegistry();
|
|
2035
2178
|
// Forward non-data events (data forwarding is lazy to avoid premature flowing)
|
|
2036
|
-
this._readable
|
|
2179
|
+
registry.once(this._readable, "end", () => {
|
|
2037
2180
|
this.emit("end");
|
|
2038
|
-
// If not allowHalfOpen, end the writable side too
|
|
2039
2181
|
if (!this.allowHalfOpen) {
|
|
2040
2182
|
this._writable.end();
|
|
2041
2183
|
}
|
|
2042
2184
|
});
|
|
2043
|
-
this._readable
|
|
2044
|
-
this._writable
|
|
2045
|
-
this._writable
|
|
2046
|
-
this._writable
|
|
2047
|
-
|
|
2185
|
+
registry.add(this._readable, "error", err => this.emit("error", err));
|
|
2186
|
+
registry.add(this._writable, "error", err => this.emit("error", err));
|
|
2187
|
+
registry.once(this._writable, "finish", () => this.emit("finish"));
|
|
2188
|
+
registry.add(this._writable, "drain", () => this.emit("drain"));
|
|
2189
|
+
registry.once(this._writable, "close", () => {
|
|
2048
2190
|
if (!this.allowHalfOpen && !this._readable.destroyed) {
|
|
2049
2191
|
this._readable.destroy();
|
|
2050
2192
|
}
|
|
2051
2193
|
});
|
|
2194
|
+
this._sideForwardingCleanup = () => registry.cleanup();
|
|
2052
2195
|
}
|
|
2053
2196
|
/**
|
|
2054
2197
|
* Override on() to set up data forwarding lazily
|
|
@@ -2167,6 +2310,10 @@ class Duplex extends event_emitter_1.EventEmitter {
|
|
|
2167
2310
|
* Destroy both sides
|
|
2168
2311
|
*/
|
|
2169
2312
|
destroy(error) {
|
|
2313
|
+
if (this._sideForwardingCleanup) {
|
|
2314
|
+
this._sideForwardingCleanup();
|
|
2315
|
+
this._sideForwardingCleanup = null;
|
|
2316
|
+
}
|
|
2170
2317
|
this._readable.destroy(error);
|
|
2171
2318
|
this._writable.destroy(error);
|
|
2172
2319
|
return this;
|
|
@@ -2308,64 +2455,22 @@ class Collector extends Writable {
|
|
|
2308
2455
|
}
|
|
2309
2456
|
exports.Collector = Collector;
|
|
2310
2457
|
// =============================================================================
|
|
2311
|
-
// PullStream / BufferedStream / DataChunk helpers
|
|
2312
|
-
// =============================================================================
|
|
2313
|
-
class PullStream extends pull_stream_1.PullStream {
|
|
2314
|
-
// Keep constructor signature aligned with streams.browser.ts public API
|
|
2315
|
-
constructor(options) {
|
|
2316
|
-
super(options);
|
|
2317
|
-
}
|
|
2318
|
-
}
|
|
2319
|
-
exports.PullStream = PullStream;
|
|
2320
|
-
class StringChunk extends buffered_stream_1.StringChunk {
|
|
2321
|
-
}
|
|
2322
|
-
exports.StringChunk = StringChunk;
|
|
2323
|
-
class BufferChunk extends buffered_stream_1.BufferChunk {
|
|
2324
|
-
}
|
|
2325
|
-
exports.BufferChunk = BufferChunk;
|
|
2326
|
-
class BufferedStream extends buffered_stream_1.BufferedStream {
|
|
2327
|
-
constructor(options) {
|
|
2328
|
-
super(options);
|
|
2329
|
-
}
|
|
2330
|
-
}
|
|
2331
|
-
exports.BufferedStream = BufferedStream;
|
|
2332
|
-
// =============================================================================
|
|
2333
2458
|
// Stream Creation Functions
|
|
2334
2459
|
// =============================================================================
|
|
2335
2460
|
/**
|
|
2336
2461
|
* Create a readable stream with custom read implementation
|
|
2337
2462
|
*/
|
|
2338
2463
|
function createReadable(options) {
|
|
2339
|
-
|
|
2340
|
-
//
|
|
2341
|
-
|
|
2342
|
-
const originalRead = readable.read.bind(readable);
|
|
2343
|
-
readable.read = function (size) {
|
|
2344
|
-
options.read(size ?? 16384);
|
|
2345
|
-
return originalRead(size);
|
|
2346
|
-
};
|
|
2347
|
-
}
|
|
2348
|
-
return readable;
|
|
2464
|
+
// Readable already supports Node-style `read()` via the constructor option.
|
|
2465
|
+
// Keep this helper minimal to avoid accidental double-read behavior.
|
|
2466
|
+
return new Readable(options);
|
|
2349
2467
|
}
|
|
2350
2468
|
/**
|
|
2351
2469
|
* Create a readable stream from an async iterable
|
|
2352
2470
|
*/
|
|
2353
2471
|
function createReadableFromAsyncIterable(iterable, options) {
|
|
2354
2472
|
const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
|
|
2355
|
-
(
|
|
2356
|
-
try {
|
|
2357
|
-
for await (const chunk of iterable) {
|
|
2358
|
-
if (!readable.push(chunk)) {
|
|
2359
|
-
// Backpressure - wait a bit
|
|
2360
|
-
await new Promise(resolve => setTimeout(resolve, 0));
|
|
2361
|
-
}
|
|
2362
|
-
}
|
|
2363
|
-
readable.push(null);
|
|
2364
|
-
}
|
|
2365
|
-
catch (err) {
|
|
2366
|
-
readable.destroy(err);
|
|
2367
|
-
}
|
|
2368
|
-
})();
|
|
2473
|
+
pumpAsyncIterableToReadable(readable, iterable);
|
|
2369
2474
|
return readable;
|
|
2370
2475
|
}
|
|
2371
2476
|
/**
|
|
@@ -2394,38 +2499,8 @@ function createReadableFromArray(data, options) {
|
|
|
2394
2499
|
* Create a writable stream with custom write implementation
|
|
2395
2500
|
*/
|
|
2396
2501
|
function createWritable(options) {
|
|
2397
|
-
//
|
|
2398
|
-
|
|
2399
|
-
write: async (chunk) => {
|
|
2400
|
-
if (options?.write) {
|
|
2401
|
-
return new Promise((resolve, reject) => {
|
|
2402
|
-
options.write(chunk, "utf8", err => {
|
|
2403
|
-
if (err) {
|
|
2404
|
-
reject(err);
|
|
2405
|
-
}
|
|
2406
|
-
else {
|
|
2407
|
-
resolve();
|
|
2408
|
-
}
|
|
2409
|
-
});
|
|
2410
|
-
});
|
|
2411
|
-
}
|
|
2412
|
-
},
|
|
2413
|
-
close: async () => {
|
|
2414
|
-
if (options?.final) {
|
|
2415
|
-
return new Promise((resolve, reject) => {
|
|
2416
|
-
options.final(err => {
|
|
2417
|
-
if (err) {
|
|
2418
|
-
reject(err);
|
|
2419
|
-
}
|
|
2420
|
-
else {
|
|
2421
|
-
resolve();
|
|
2422
|
-
}
|
|
2423
|
-
});
|
|
2424
|
-
});
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
});
|
|
2428
|
-
return new Writable({ ...options, stream });
|
|
2502
|
+
// Writable already supports Node-style `write()` / `final()` via the constructor.
|
|
2503
|
+
return new Writable(options);
|
|
2429
2504
|
}
|
|
2430
2505
|
/**
|
|
2431
2506
|
* Create a transform stream from a transform function
|
|
@@ -2453,28 +2528,14 @@ function createPassThrough(options) {
|
|
|
2453
2528
|
* Create a pull stream
|
|
2454
2529
|
*/
|
|
2455
2530
|
function createPullStream(options) {
|
|
2456
|
-
return new PullStream(options);
|
|
2531
|
+
return new pull_stream_1.PullStream(options);
|
|
2457
2532
|
}
|
|
2458
2533
|
/**
|
|
2459
2534
|
* Create a buffered stream
|
|
2460
2535
|
*/
|
|
2461
2536
|
function createBufferedStream(options) {
|
|
2462
|
-
return new BufferedStream(options);
|
|
2537
|
+
return new buffered_stream_1.BufferedStream(options);
|
|
2463
2538
|
}
|
|
2464
|
-
const isReadableStream = (value) => !!value && typeof value === "object" && typeof value.getReader === "function";
|
|
2465
|
-
const isAsyncIterable = (value) => {
|
|
2466
|
-
if (!value || (typeof value !== "object" && typeof value !== "function")) {
|
|
2467
|
-
return false;
|
|
2468
|
-
}
|
|
2469
|
-
return typeof value[Symbol.asyncIterator] === "function";
|
|
2470
|
-
};
|
|
2471
|
-
const isWritableStream = (value) => !!value && typeof value === "object" && typeof value.getWriter === "function";
|
|
2472
|
-
const isTransformStream = (value) => !!value &&
|
|
2473
|
-
typeof value === "object" &&
|
|
2474
|
-
!!value.readable &&
|
|
2475
|
-
!!value.writable &&
|
|
2476
|
-
isReadableStream(value.readable) &&
|
|
2477
|
-
isWritableStream(value.writable);
|
|
2478
2539
|
const isPipelineOptions = (value) => {
|
|
2479
2540
|
if (!value || typeof value !== "object") {
|
|
2480
2541
|
return false;
|
|
@@ -2499,13 +2560,13 @@ const toBrowserPipelineStream = (stream) => {
|
|
|
2499
2560
|
stream instanceof Duplex) {
|
|
2500
2561
|
return stream;
|
|
2501
2562
|
}
|
|
2502
|
-
if (isTransformStream(stream)) {
|
|
2563
|
+
if ((0, type_guards_1.isTransformStream)(stream)) {
|
|
2503
2564
|
return Transform.fromWeb(stream);
|
|
2504
2565
|
}
|
|
2505
|
-
if (isReadableStream(stream)) {
|
|
2566
|
+
if ((0, type_guards_1.isReadableStream)(stream)) {
|
|
2506
2567
|
return Readable.fromWeb(stream);
|
|
2507
2568
|
}
|
|
2508
|
-
if (isWritableStream(stream)) {
|
|
2569
|
+
if ((0, type_guards_1.isWritableStream)(stream)) {
|
|
2509
2570
|
return Writable.fromWeb(stream);
|
|
2510
2571
|
}
|
|
2511
2572
|
return stream;
|
|
@@ -2560,11 +2621,17 @@ function pipeline(...args) {
|
|
|
2560
2621
|
const transforms = normalized.slice(1, -1);
|
|
2561
2622
|
let completed = false;
|
|
2562
2623
|
const allStreams = [source, ...transforms, destination];
|
|
2563
|
-
const
|
|
2624
|
+
const registry = createListenerRegistry();
|
|
2625
|
+
let onAbort;
|
|
2626
|
+
const cleanupWithSignal = (error) => {
|
|
2564
2627
|
if (completed) {
|
|
2565
2628
|
return;
|
|
2566
2629
|
}
|
|
2567
2630
|
completed = true;
|
|
2631
|
+
registry.cleanup();
|
|
2632
|
+
if (onAbort && options.signal) {
|
|
2633
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
2634
|
+
}
|
|
2568
2635
|
// Destroy all streams on error
|
|
2569
2636
|
if (error) {
|
|
2570
2637
|
for (const stream of allStreams) {
|
|
@@ -2581,12 +2648,11 @@ function pipeline(...args) {
|
|
|
2581
2648
|
// Handle abort signal
|
|
2582
2649
|
if (options.signal) {
|
|
2583
2650
|
if (options.signal.aborted) {
|
|
2584
|
-
|
|
2651
|
+
cleanupWithSignal(new Error("Pipeline aborted"));
|
|
2585
2652
|
return;
|
|
2586
2653
|
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
});
|
|
2654
|
+
onAbort = () => cleanupWithSignal(new Error("Pipeline aborted"));
|
|
2655
|
+
options.signal.addEventListener("abort", onAbort);
|
|
2590
2656
|
}
|
|
2591
2657
|
// Chain the streams
|
|
2592
2658
|
let current = source;
|
|
@@ -2600,13 +2666,35 @@ function pipeline(...args) {
|
|
|
2600
2666
|
}
|
|
2601
2667
|
else {
|
|
2602
2668
|
// Don't end destination
|
|
2603
|
-
|
|
2669
|
+
let paused = false;
|
|
2670
|
+
let waitingForDrain = false;
|
|
2671
|
+
const onDrain = () => {
|
|
2672
|
+
waitingForDrain = false;
|
|
2673
|
+
if (paused && typeof current.resume === "function") {
|
|
2674
|
+
paused = false;
|
|
2675
|
+
current.resume();
|
|
2676
|
+
}
|
|
2677
|
+
};
|
|
2678
|
+
const onData = (chunk) => {
|
|
2679
|
+
const ok = destination.write(chunk);
|
|
2680
|
+
if (!ok && !waitingForDrain) {
|
|
2681
|
+
waitingForDrain = true;
|
|
2682
|
+
if (!paused && typeof current.pause === "function") {
|
|
2683
|
+
paused = true;
|
|
2684
|
+
current.pause();
|
|
2685
|
+
}
|
|
2686
|
+
registry.once(destination, "drain", onDrain);
|
|
2687
|
+
}
|
|
2688
|
+
};
|
|
2689
|
+
const onEnd = () => cleanupWithSignal();
|
|
2690
|
+
registry.add(current, "data", onData);
|
|
2691
|
+
registry.once(current, "end", onEnd);
|
|
2604
2692
|
}
|
|
2605
2693
|
// Handle completion
|
|
2606
|
-
|
|
2694
|
+
registry.once(destination, "finish", () => cleanupWithSignal());
|
|
2607
2695
|
// Handle errors on all streams
|
|
2608
2696
|
for (const stream of allStreams) {
|
|
2609
|
-
|
|
2697
|
+
registry.once(stream, "error", (err) => cleanupWithSignal(err));
|
|
2610
2698
|
}
|
|
2611
2699
|
});
|
|
2612
2700
|
// If callback provided, use it
|
|
@@ -2646,11 +2734,20 @@ function finished(stream, optionsOrCallback, callback) {
|
|
|
2646
2734
|
const promise = new Promise((resolve, reject) => {
|
|
2647
2735
|
const normalizedStream = toBrowserPipelineStream(stream);
|
|
2648
2736
|
let resolved = false;
|
|
2737
|
+
const registry = createListenerRegistry();
|
|
2738
|
+
let onAbort;
|
|
2739
|
+
const cleanup = () => {
|
|
2740
|
+
registry.cleanup();
|
|
2741
|
+
if (onAbort && options.signal) {
|
|
2742
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
2743
|
+
}
|
|
2744
|
+
};
|
|
2649
2745
|
const done = (err) => {
|
|
2650
2746
|
if (resolved) {
|
|
2651
2747
|
return;
|
|
2652
2748
|
}
|
|
2653
2749
|
resolved = true;
|
|
2750
|
+
cleanup();
|
|
2654
2751
|
if (err && !options.error) {
|
|
2655
2752
|
reject(err);
|
|
2656
2753
|
}
|
|
@@ -2664,9 +2761,8 @@ function finished(stream, optionsOrCallback, callback) {
|
|
|
2664
2761
|
done(new Error("Aborted"));
|
|
2665
2762
|
return;
|
|
2666
2763
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
});
|
|
2764
|
+
onAbort = () => done(new Error("Aborted"));
|
|
2765
|
+
options.signal.addEventListener("abort", onAbort);
|
|
2670
2766
|
}
|
|
2671
2767
|
const checkReadable = options.readable !== false;
|
|
2672
2768
|
const checkWritable = options.writable !== false;
|
|
@@ -2681,13 +2777,13 @@ function finished(stream, optionsOrCallback, callback) {
|
|
|
2681
2777
|
}
|
|
2682
2778
|
// Listen for events
|
|
2683
2779
|
if (checkWritable) {
|
|
2684
|
-
|
|
2780
|
+
registry.once(normalizedStream, "finish", () => done());
|
|
2685
2781
|
}
|
|
2686
2782
|
if (checkReadable) {
|
|
2687
|
-
|
|
2783
|
+
registry.once(normalizedStream, "end", () => done());
|
|
2688
2784
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2785
|
+
registry.once(normalizedStream, "error", (err) => done(err));
|
|
2786
|
+
registry.once(normalizedStream, "close", () => done());
|
|
2691
2787
|
});
|
|
2692
2788
|
// If callback provided, use it
|
|
2693
2789
|
if (cb) {
|
|
@@ -2709,38 +2805,8 @@ async function streamToPromise(stream) {
|
|
|
2709
2805
|
* (Browser equivalent of Node.js streamToBuffer)
|
|
2710
2806
|
*/
|
|
2711
2807
|
async function streamToUint8Array(stream) {
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
iterable = Readable.fromWeb(stream);
|
|
2715
|
-
}
|
|
2716
|
-
else if (isAsyncIterable(stream)) {
|
|
2717
|
-
iterable = stream;
|
|
2718
|
-
}
|
|
2719
|
-
else {
|
|
2720
|
-
throw new Error("streamToUint8Array: unsupported stream type");
|
|
2721
|
-
}
|
|
2722
|
-
const chunks = [];
|
|
2723
|
-
let totalLength = 0;
|
|
2724
|
-
for await (const chunk of iterable) {
|
|
2725
|
-
chunks.push(chunk);
|
|
2726
|
-
totalLength += chunk.length;
|
|
2727
|
-
}
|
|
2728
|
-
// Fast paths
|
|
2729
|
-
const len = chunks.length;
|
|
2730
|
-
if (len === 0) {
|
|
2731
|
-
return new Uint8Array(0);
|
|
2732
|
-
}
|
|
2733
|
-
if (len === 1) {
|
|
2734
|
-
return chunks[0];
|
|
2735
|
-
}
|
|
2736
|
-
// Use precalculated total length
|
|
2737
|
-
const result = new Uint8Array(totalLength);
|
|
2738
|
-
let offset = 0;
|
|
2739
|
-
for (let i = 0; i < len; i++) {
|
|
2740
|
-
result.set(chunks[i], offset);
|
|
2741
|
-
offset += chunks[i].length;
|
|
2742
|
-
}
|
|
2743
|
-
return result;
|
|
2808
|
+
const [chunks, totalLength] = await collectStreamChunks(stream);
|
|
2809
|
+
return (0, shared_1.concatUint8Arrays)(chunks, totalLength);
|
|
2744
2810
|
}
|
|
2745
2811
|
/**
|
|
2746
2812
|
* Alias for streamToUint8Array (Node.js compatibility)
|
|
@@ -2750,23 +2816,16 @@ exports.streamToBuffer = streamToUint8Array;
|
|
|
2750
2816
|
* Collect all data from a readable stream into a string
|
|
2751
2817
|
*/
|
|
2752
2818
|
async function streamToString(stream, encoding) {
|
|
2753
|
-
const
|
|
2754
|
-
|
|
2819
|
+
const [chunks, totalLength] = await collectStreamChunks(stream);
|
|
2820
|
+
const combined = (0, shared_1.concatUint8Arrays)(chunks, totalLength);
|
|
2821
|
+
const decoder = encoding ? (0, shared_1.getTextDecoder)(encoding) : shared_1.textDecoder;
|
|
2822
|
+
return decoder.decode(combined);
|
|
2755
2823
|
}
|
|
2756
2824
|
/**
|
|
2757
2825
|
* Drain a stream (consume all data without processing)
|
|
2758
2826
|
*/
|
|
2759
2827
|
async function drainStream(stream) {
|
|
2760
|
-
|
|
2761
|
-
if (isReadableStream(stream)) {
|
|
2762
|
-
iterable = Readable.fromWeb(stream);
|
|
2763
|
-
}
|
|
2764
|
-
else if (isAsyncIterable(stream)) {
|
|
2765
|
-
iterable = stream;
|
|
2766
|
-
}
|
|
2767
|
-
else {
|
|
2768
|
-
throw new Error("drainStream: unsupported stream type");
|
|
2769
|
-
}
|
|
2828
|
+
const iterable = toReadableAsyncIterable(stream, "drainStream");
|
|
2770
2829
|
for await (const _chunk of iterable) {
|
|
2771
2830
|
// Consume data
|
|
2772
2831
|
}
|
|
@@ -2839,14 +2898,19 @@ function addAbortSignal(signal, stream) {
|
|
|
2839
2898
|
stream.destroy(new Error("Aborted"));
|
|
2840
2899
|
return stream;
|
|
2841
2900
|
}
|
|
2901
|
+
const cleanup = () => {
|
|
2902
|
+
signal.removeEventListener("abort", onAbort);
|
|
2903
|
+
removeEmitterListener(stream, "close", onClose);
|
|
2904
|
+
};
|
|
2842
2905
|
const onAbort = () => {
|
|
2906
|
+
cleanup();
|
|
2843
2907
|
stream.destroy(new Error("Aborted"));
|
|
2844
2908
|
};
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
});
|
|
2909
|
+
const onClose = () => {
|
|
2910
|
+
cleanup();
|
|
2911
|
+
};
|
|
2912
|
+
signal.addEventListener("abort", onAbort);
|
|
2913
|
+
addEmitterListener(stream, "close", onClose, { once: true });
|
|
2850
2914
|
return stream;
|
|
2851
2915
|
}
|
|
2852
2916
|
/**
|
|
@@ -2855,60 +2919,68 @@ function addAbortSignal(signal, stream) {
|
|
|
2855
2919
|
function createDuplex(options) {
|
|
2856
2920
|
const readableObjectMode = options?.readableObjectMode ?? options?.objectMode;
|
|
2857
2921
|
const writableObjectMode = options?.writableObjectMode ?? options?.objectMode;
|
|
2922
|
+
const underlyingWritable = options?.writable;
|
|
2858
2923
|
const duplex = new Duplex({
|
|
2859
2924
|
allowHalfOpen: options?.allowHalfOpen,
|
|
2860
2925
|
readableHighWaterMark: options?.readableHighWaterMark,
|
|
2861
2926
|
writableHighWaterMark: options?.writableHighWaterMark,
|
|
2862
2927
|
readableObjectMode,
|
|
2863
|
-
writableObjectMode
|
|
2928
|
+
writableObjectMode,
|
|
2929
|
+
read: options?.read,
|
|
2930
|
+
write: options?.write ??
|
|
2931
|
+
(underlyingWritable
|
|
2932
|
+
? (chunk, encoding, callback) => {
|
|
2933
|
+
if (typeof underlyingWritable.write === "function") {
|
|
2934
|
+
underlyingWritable.write(chunk, encoding, callback);
|
|
2935
|
+
return;
|
|
2936
|
+
}
|
|
2937
|
+
// Best-effort sync sink
|
|
2938
|
+
try {
|
|
2939
|
+
underlyingWritable.write?.(chunk);
|
|
2940
|
+
callback(null);
|
|
2941
|
+
}
|
|
2942
|
+
catch (err) {
|
|
2943
|
+
callback(err);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
: undefined),
|
|
2947
|
+
final: options?.final ??
|
|
2948
|
+
(underlyingWritable
|
|
2949
|
+
? (callback) => {
|
|
2950
|
+
if (typeof underlyingWritable.end === "function") {
|
|
2951
|
+
underlyingWritable.end((err) => callback(err ?? null));
|
|
2952
|
+
}
|
|
2953
|
+
else {
|
|
2954
|
+
underlyingWritable.end?.();
|
|
2955
|
+
callback(null);
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
: undefined)
|
|
2864
2959
|
});
|
|
2865
|
-
// If
|
|
2960
|
+
// If an underlying readable is provided, forward it into the duplex readable side.
|
|
2866
2961
|
if (options?.readable) {
|
|
2867
2962
|
const readable = options.readable;
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
duplex.end = function (chunkOrCallback, encodingOrCallback, callback) {
|
|
2890
|
-
const cb = typeof chunkOrCallback === "function"
|
|
2891
|
-
? chunkOrCallback
|
|
2892
|
-
: typeof encodingOrCallback === "function"
|
|
2893
|
-
? encodingOrCallback
|
|
2894
|
-
: (callback ?? (() => { }));
|
|
2895
|
-
if (chunkOrCallback !== undefined && typeof chunkOrCallback !== "function") {
|
|
2896
|
-
duplex.write(chunkOrCallback);
|
|
2897
|
-
}
|
|
2898
|
-
// Call custom final handler
|
|
2899
|
-
options.final.call(duplex, (err) => {
|
|
2900
|
-
if (err) {
|
|
2901
|
-
duplex.emit("error", err);
|
|
2902
|
-
}
|
|
2903
|
-
else {
|
|
2904
|
-
duplex.emit("finish");
|
|
2905
|
-
}
|
|
2906
|
-
// Call original end to properly close writable side
|
|
2907
|
-
originalEnd();
|
|
2908
|
-
cb();
|
|
2909
|
-
});
|
|
2910
|
-
return duplex;
|
|
2911
|
-
};
|
|
2963
|
+
const sink = new Writable({
|
|
2964
|
+
objectMode: duplex.readableObjectMode,
|
|
2965
|
+
write(chunk, _encoding, callback) {
|
|
2966
|
+
duplex.push(chunk);
|
|
2967
|
+
callback(null);
|
|
2968
|
+
},
|
|
2969
|
+
final(callback) {
|
|
2970
|
+
duplex.push(null);
|
|
2971
|
+
callback(null);
|
|
2972
|
+
}
|
|
2973
|
+
});
|
|
2974
|
+
if (typeof readable?.on === "function") {
|
|
2975
|
+
const onError = (err) => {
|
|
2976
|
+
duplex.destroy(err);
|
|
2977
|
+
};
|
|
2978
|
+
const cleanupError = addEmitterListener(readable, "error", onError);
|
|
2979
|
+
addEmitterListener(readable, "end", cleanupError, { once: true });
|
|
2980
|
+
addEmitterListener(readable, "close", cleanupError, { once: true });
|
|
2981
|
+
addEmitterListener(sink, "finish", cleanupError, { once: true });
|
|
2982
|
+
}
|
|
2983
|
+
readable.pipe?.(sink);
|
|
2912
2984
|
}
|
|
2913
2985
|
if (options?.destroy) {
|
|
2914
2986
|
const originalDestroy = duplex.destroy.bind(duplex);
|
|
@@ -2932,20 +3004,7 @@ function createDuplex(options) {
|
|
|
2932
3004
|
*/
|
|
2933
3005
|
function createReadableFromGenerator(generator, options) {
|
|
2934
3006
|
const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
|
|
2935
|
-
(
|
|
2936
|
-
try {
|
|
2937
|
-
for await (const chunk of generator()) {
|
|
2938
|
-
if (!readable.push(chunk)) {
|
|
2939
|
-
// Backpressure
|
|
2940
|
-
await new Promise(resolve => setTimeout(resolve, 0));
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
readable.push(null);
|
|
2944
|
-
}
|
|
2945
|
-
catch (err) {
|
|
2946
|
-
readable.destroy(err);
|
|
2947
|
-
}
|
|
2948
|
-
})();
|
|
3007
|
+
pumpAsyncIterableToReadable(readable, generator());
|
|
2949
3008
|
return readable;
|
|
2950
3009
|
}
|
|
2951
3010
|
/**
|
|
@@ -2975,8 +3034,8 @@ function compose(...transforms) {
|
|
|
2975
3034
|
transform: chunk => chunk
|
|
2976
3035
|
});
|
|
2977
3036
|
}
|
|
2978
|
-
|
|
2979
|
-
if (len === 1
|
|
3037
|
+
// Preserve identity: compose(single) returns the same transform.
|
|
3038
|
+
if (len === 1) {
|
|
2980
3039
|
return transforms[0];
|
|
2981
3040
|
}
|
|
2982
3041
|
// Chain the transforms: first → second → ... → last
|
|
@@ -2986,74 +3045,118 @@ function compose(...transforms) {
|
|
|
2986
3045
|
for (let i = 0; i < len - 1; i++) {
|
|
2987
3046
|
transforms[i].pipe(transforms[i + 1]);
|
|
2988
3047
|
}
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
3048
|
+
// A lightweight Transform wrapper that delegates:
|
|
3049
|
+
// - writable side to `first`
|
|
3050
|
+
// - readable side to `last`
|
|
3051
|
+
// It forwards relevant events lazily to avoid per-chunk overhead when unused.
|
|
3052
|
+
const composed = new Transform({
|
|
3053
|
+
objectMode: first?.objectMode ?? true,
|
|
3054
|
+
transform: chunk => chunk
|
|
3055
|
+
});
|
|
3056
|
+
const registry = createListenerRegistry();
|
|
3057
|
+
// Always forward errors; they are critical for pipeline semantics.
|
|
3058
|
+
for (const t of transforms) {
|
|
3059
|
+
registry.add(t, "error", (err) => composed.emit("error", err));
|
|
3060
|
+
}
|
|
3061
|
+
// Forward writable-side backpressure/completion events from `first`.
|
|
3062
|
+
registry.add(first, "drain", () => composed.emit("drain"));
|
|
3063
|
+
registry.once(first, "finish", () => composed.emit("finish"));
|
|
3064
|
+
// Forward readable-side events from `last` lazily.
|
|
3065
|
+
let forwardData = false;
|
|
3066
|
+
let forwardEnd = false;
|
|
3067
|
+
let forwardReadable = false;
|
|
3068
|
+
const ensureDataForwarding = () => {
|
|
3069
|
+
if (forwardData) {
|
|
3070
|
+
return;
|
|
2994
3071
|
}
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
this._endForwarding = true;
|
|
3002
|
-
last.on("end", () => this.emit("end"));
|
|
3003
|
-
}
|
|
3004
|
-
return super.on(event, listener);
|
|
3072
|
+
forwardData = true;
|
|
3073
|
+
registry.add(last, "data", (chunk) => composed.emit("data", chunk));
|
|
3074
|
+
};
|
|
3075
|
+
const ensureEndForwarding = () => {
|
|
3076
|
+
if (forwardEnd) {
|
|
3077
|
+
return;
|
|
3005
3078
|
}
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3079
|
+
forwardEnd = true;
|
|
3080
|
+
registry.once(last, "end", () => composed.emit("end"));
|
|
3081
|
+
};
|
|
3082
|
+
const ensureReadableForwarding = () => {
|
|
3083
|
+
if (forwardReadable) {
|
|
3084
|
+
return;
|
|
3011
3085
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
}
|
|
3021
|
-
first.end(chunkOrCallback, encodingOrCallback, callback);
|
|
3022
|
-
return this;
|
|
3086
|
+
forwardReadable = true;
|
|
3087
|
+
registry.add(last, "readable", () => composed.emit("readable"));
|
|
3088
|
+
};
|
|
3089
|
+
const originalOn = composed.on.bind(composed);
|
|
3090
|
+
const originalOnce = composed.once.bind(composed);
|
|
3091
|
+
composed.on = (event, listener) => {
|
|
3092
|
+
if (event === "data") {
|
|
3093
|
+
ensureDataForwarding();
|
|
3023
3094
|
}
|
|
3024
|
-
|
|
3025
|
-
|
|
3095
|
+
else if (event === "end") {
|
|
3096
|
+
ensureEndForwarding();
|
|
3026
3097
|
}
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3098
|
+
else if (event === "readable") {
|
|
3099
|
+
ensureReadableForwarding();
|
|
3100
|
+
}
|
|
3101
|
+
return originalOn(event, listener);
|
|
3102
|
+
};
|
|
3103
|
+
composed.once = (event, listener) => {
|
|
3104
|
+
if (event === "data") {
|
|
3105
|
+
ensureDataForwarding();
|
|
3032
3106
|
}
|
|
3033
|
-
|
|
3034
|
-
|
|
3107
|
+
else if (event === "end") {
|
|
3108
|
+
ensureEndForwarding();
|
|
3035
3109
|
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3110
|
+
else if (event === "readable") {
|
|
3111
|
+
ensureReadableForwarding();
|
|
3112
|
+
}
|
|
3113
|
+
return originalOnce(event, listener);
|
|
3114
|
+
};
|
|
3115
|
+
// Delegate core stream methods
|
|
3116
|
+
const firstAny = first;
|
|
3117
|
+
const lastAny = last;
|
|
3118
|
+
composed.write = (chunk, encodingOrCallback, callback) => {
|
|
3119
|
+
if (typeof encodingOrCallback === "function") {
|
|
3120
|
+
return firstAny.write(chunk, encodingOrCallback);
|
|
3121
|
+
}
|
|
3122
|
+
return firstAny.write(chunk, encodingOrCallback, callback);
|
|
3123
|
+
};
|
|
3124
|
+
composed.end = (chunkOrCallback, encodingOrCallback, callback) => {
|
|
3125
|
+
if (typeof chunkOrCallback === "function") {
|
|
3126
|
+
firstAny.end(chunkOrCallback);
|
|
3127
|
+
return composed;
|
|
3128
|
+
}
|
|
3129
|
+
if (typeof encodingOrCallback === "function") {
|
|
3130
|
+
firstAny.end(chunkOrCallback, encodingOrCallback);
|
|
3131
|
+
return composed;
|
|
3132
|
+
}
|
|
3133
|
+
firstAny.end(chunkOrCallback, encodingOrCallback, callback);
|
|
3134
|
+
return composed;
|
|
3135
|
+
};
|
|
3136
|
+
composed.pipe = (destination) => {
|
|
3137
|
+
return lastAny.pipe(destination);
|
|
3138
|
+
};
|
|
3139
|
+
composed.read = (size) => {
|
|
3140
|
+
return typeof lastAny.read === "function" ? lastAny.read(size) : null;
|
|
3141
|
+
};
|
|
3142
|
+
composed[Symbol.asyncIterator] = async function* () {
|
|
3143
|
+
const it = lastAny?.[Symbol.asyncIterator]?.();
|
|
3144
|
+
if (it) {
|
|
3145
|
+
for await (const chunk of it) {
|
|
3146
|
+
yield chunk;
|
|
3043
3147
|
}
|
|
3044
|
-
|
|
3148
|
+
return;
|
|
3045
3149
|
}
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3150
|
+
yield* Transform.prototype[Symbol.asyncIterator].call(composed);
|
|
3151
|
+
};
|
|
3152
|
+
const originalDestroy = composed.destroy.bind(composed);
|
|
3153
|
+
composed.destroy = ((error) => {
|
|
3154
|
+
registry.cleanup();
|
|
3155
|
+
for (const t of transforms) {
|
|
3156
|
+
t.destroy(error);
|
|
3157
|
+
}
|
|
3158
|
+
originalDestroy(error);
|
|
3050
3159
|
});
|
|
3051
|
-
// Forward errors from any transform
|
|
3052
|
-
for (const t of transforms) {
|
|
3053
|
-
t.on("error", (err) => {
|
|
3054
|
-
composed.emit("error", err);
|
|
3055
|
-
});
|
|
3056
|
-
}
|
|
3057
3160
|
// Reflect underlying readability/writability like the previous duck-typed wrapper
|
|
3058
3161
|
Object.defineProperty(composed, "readable", {
|
|
3059
3162
|
get: () => last.readable
|
|
@@ -3299,77 +3402,54 @@ function duplexPair(options) {
|
|
|
3299
3402
|
async function collectStreamChunks(stream) {
|
|
3300
3403
|
const chunks = [];
|
|
3301
3404
|
let totalLength = 0;
|
|
3302
|
-
|
|
3303
|
-
if (isReadableStream(stream)) {
|
|
3304
|
-
iterable = Readable.fromWeb(stream);
|
|
3305
|
-
}
|
|
3306
|
-
else if (isAsyncIterable(stream)) {
|
|
3307
|
-
iterable = stream;
|
|
3308
|
-
}
|
|
3309
|
-
else {
|
|
3310
|
-
throw new Error("collectStreamChunks: unsupported stream type");
|
|
3311
|
-
}
|
|
3405
|
+
const iterable = toReadableAsyncIterable(stream, "collectStreamChunks");
|
|
3312
3406
|
for await (const chunk of iterable) {
|
|
3313
3407
|
chunks.push(chunk);
|
|
3314
3408
|
totalLength += chunk.length;
|
|
3315
3409
|
}
|
|
3316
|
-
return
|
|
3410
|
+
return [chunks, totalLength];
|
|
3317
3411
|
}
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
if (len === 0) {
|
|
3322
|
-
return new Uint8Array(0);
|
|
3323
|
-
}
|
|
3324
|
-
if (len === 1) {
|
|
3325
|
-
return chunks[0];
|
|
3412
|
+
function toReadableAsyncIterable(stream, name) {
|
|
3413
|
+
if ((0, type_guards_1.isReadableStream)(stream)) {
|
|
3414
|
+
return Readable.fromWeb(stream);
|
|
3326
3415
|
}
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
for (let i = 0; i < len; i++) {
|
|
3330
|
-
result.set(chunks[i], offset);
|
|
3331
|
-
offset += chunks[i].length;
|
|
3416
|
+
if ((0, type_guards_1.isAsyncIterable)(stream)) {
|
|
3417
|
+
return stream;
|
|
3332
3418
|
}
|
|
3333
|
-
|
|
3419
|
+
throw new Error(`${name}: unsupported stream type`);
|
|
3334
3420
|
}
|
|
3335
3421
|
exports.consumers = {
|
|
3336
3422
|
/**
|
|
3337
3423
|
* Consume entire stream as ArrayBuffer
|
|
3338
3424
|
*/
|
|
3339
3425
|
async arrayBuffer(stream) {
|
|
3340
|
-
const
|
|
3341
|
-
|
|
3342
|
-
return combined.buffer.slice(combined.byteOffset, combined.byteOffset + combined.byteLength);
|
|
3426
|
+
const bytes = await streamToUint8Array(stream);
|
|
3427
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
3343
3428
|
},
|
|
3344
3429
|
/**
|
|
3345
3430
|
* Consume entire stream as Blob
|
|
3346
3431
|
*/
|
|
3347
3432
|
async blob(stream, options) {
|
|
3348
|
-
const
|
|
3433
|
+
const [chunks] = await collectStreamChunks(stream);
|
|
3349
3434
|
return new Blob(chunks, options);
|
|
3350
3435
|
},
|
|
3351
3436
|
/**
|
|
3352
3437
|
* Consume entire stream as Buffer (Uint8Array in browser)
|
|
3353
3438
|
*/
|
|
3354
3439
|
async buffer(stream) {
|
|
3355
|
-
|
|
3356
|
-
return concatWithLength(chunks, totalLength);
|
|
3440
|
+
return streamToUint8Array(stream);
|
|
3357
3441
|
},
|
|
3358
3442
|
/**
|
|
3359
3443
|
* Consume entire stream as JSON
|
|
3360
3444
|
*/
|
|
3361
3445
|
async json(stream) {
|
|
3362
|
-
|
|
3363
|
-
return JSON.parse(text);
|
|
3446
|
+
return JSON.parse(await streamToString(stream));
|
|
3364
3447
|
},
|
|
3365
3448
|
/**
|
|
3366
3449
|
* Consume entire stream as text
|
|
3367
3450
|
*/
|
|
3368
3451
|
async text(stream, encoding) {
|
|
3369
|
-
|
|
3370
|
-
const combined = concatWithLength(chunks, totalLength);
|
|
3371
|
-
const decoder = encoding ? (0, shared_1.getTextDecoder)(encoding) : shared_1.textDecoder;
|
|
3372
|
-
return decoder.decode(combined);
|
|
3452
|
+
return streamToString(stream, encoding);
|
|
3373
3453
|
}
|
|
3374
3454
|
};
|
|
3375
3455
|
// =============================================================================
|