@cj-tech-master/excelts 4.2.1 → 4.2.2
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/worksheet.js +5 -2
- 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/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/xlsx.browser.js +3 -6
- 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/worksheet.js +5 -2
- 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/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/xlsx.browser.js +6 -9
- 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/worksheet.js +5 -2
- 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/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/xlsx.browser.js +3 -6
- 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 +6495 -4440
- 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/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
|
@@ -1,644 +0,0 @@
|
|
|
1
|
-
import { parseDosDateTimeUTC, resolveZipLastModifiedDateFromUnixSeconds } from "./utils/timestamps.js";
|
|
2
|
-
import { Duplex, PassThrough, Transform, concatUint8Arrays, pipeline, finished } from "../stream/index.browser.js";
|
|
3
|
-
import { parseTyped as parseBuffer } from "./utils/parse-buffer.js";
|
|
4
|
-
import { ByteQueue } from "./byte-queue.js";
|
|
5
|
-
import { indexOfUint8ArrayPattern } from "./utils/bytes.js";
|
|
6
|
-
import { readUint32LE, writeUint32LE } from "./utils/binary.js";
|
|
7
|
-
import { parseZipExtraFields } from "./utils/zip-extra-fields.js";
|
|
8
|
-
import { CENTRAL_DIR_HEADER_SIG, END_OF_CENTRAL_DIR_SIG, LOCAL_FILE_HEADER_SIG, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG, ZIP64_END_OF_CENTRAL_DIR_SIG } from "./zip-constants.js";
|
|
9
|
-
// Shared parseBuffer() formats
|
|
10
|
-
export const CRX_HEADER_FORMAT = [
|
|
11
|
-
["version", 4],
|
|
12
|
-
["pubKeyLength", 4],
|
|
13
|
-
["signatureLength", 4]
|
|
14
|
-
];
|
|
15
|
-
export const LOCAL_FILE_HEADER_FORMAT = [
|
|
16
|
-
["versionsNeededToExtract", 2],
|
|
17
|
-
["flags", 2],
|
|
18
|
-
["compressionMethod", 2],
|
|
19
|
-
["lastModifiedTime", 2],
|
|
20
|
-
["lastModifiedDate", 2],
|
|
21
|
-
["crc32", 4],
|
|
22
|
-
["compressedSize", 4],
|
|
23
|
-
["uncompressedSize", 4],
|
|
24
|
-
["fileNameLength", 2],
|
|
25
|
-
["extraFieldLength", 2]
|
|
26
|
-
];
|
|
27
|
-
export const DATA_DESCRIPTOR_FORMAT = [
|
|
28
|
-
["dataDescriptorSignature", 4],
|
|
29
|
-
["crc32", 4],
|
|
30
|
-
["compressedSize", 4],
|
|
31
|
-
["uncompressedSize", 4]
|
|
32
|
-
];
|
|
33
|
-
export const CENTRAL_DIRECTORY_FILE_HEADER_FORMAT = [
|
|
34
|
-
["versionMadeBy", 2],
|
|
35
|
-
["versionsNeededToExtract", 2],
|
|
36
|
-
["flags", 2],
|
|
37
|
-
["compressionMethod", 2],
|
|
38
|
-
["lastModifiedTime", 2],
|
|
39
|
-
["lastModifiedDate", 2],
|
|
40
|
-
["crc32", 4],
|
|
41
|
-
["compressedSize", 4],
|
|
42
|
-
["uncompressedSize", 4],
|
|
43
|
-
["fileNameLength", 2],
|
|
44
|
-
["extraFieldLength", 2],
|
|
45
|
-
["fileCommentLength", 2],
|
|
46
|
-
["diskNumber", 2],
|
|
47
|
-
["internalFileAttributes", 2],
|
|
48
|
-
["externalFileAttributes", 4],
|
|
49
|
-
["offsetToLocalFileHeader", 4]
|
|
50
|
-
];
|
|
51
|
-
export const END_OF_CENTRAL_DIRECTORY_FORMAT = [
|
|
52
|
-
["diskNumber", 2],
|
|
53
|
-
["diskStart", 2],
|
|
54
|
-
["numberOfRecordsOnDisk", 2],
|
|
55
|
-
["numberOfRecords", 2],
|
|
56
|
-
["sizeOfCentralDirectory", 4],
|
|
57
|
-
["offsetToStartOfCentralDirectory", 4],
|
|
58
|
-
["commentLength", 2]
|
|
59
|
-
];
|
|
60
|
-
const textDecoder = new TextDecoder();
|
|
61
|
-
const textEncoder = new TextEncoder();
|
|
62
|
-
export function decodeZipEntryPath(pathBuffer) {
|
|
63
|
-
return textDecoder.decode(pathBuffer);
|
|
64
|
-
}
|
|
65
|
-
export function isZipUnicodeFlag(flags) {
|
|
66
|
-
return ((flags || 0) & 0x800) !== 0;
|
|
67
|
-
}
|
|
68
|
-
export function isZipDirectoryPath(path) {
|
|
69
|
-
if (path.length === 0) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
const last = path.charCodeAt(path.length - 1);
|
|
73
|
-
return last === 47 || last === 92;
|
|
74
|
-
}
|
|
75
|
-
export function getZipEntryType(path, uncompressedSize) {
|
|
76
|
-
return uncompressedSize === 0 && isZipDirectoryPath(path) ? "Directory" : "File";
|
|
77
|
-
}
|
|
78
|
-
export function buildZipEntryProps(path, pathBuffer, flags) {
|
|
79
|
-
return {
|
|
80
|
-
path,
|
|
81
|
-
pathBuffer,
|
|
82
|
-
flags: {
|
|
83
|
-
isUnicode: isZipUnicodeFlag(flags)
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
export function resolveZipEntryLastModifiedDateTime(vars, extraFields) {
|
|
88
|
-
const dosDate = vars.lastModifiedDate || 0;
|
|
89
|
-
const dosTime = vars.lastModifiedTime || 0;
|
|
90
|
-
const dosDateTime = parseDosDateTimeUTC(dosDate, dosTime);
|
|
91
|
-
const unixSecondsMtime = extraFields.mtimeUnixSeconds;
|
|
92
|
-
if (unixSecondsMtime === undefined) {
|
|
93
|
-
return dosDateTime;
|
|
94
|
-
}
|
|
95
|
-
return resolveZipLastModifiedDateFromUnixSeconds(dosDate, dosTime, unixSecondsMtime);
|
|
96
|
-
}
|
|
97
|
-
export const parseExtraField = parseZipExtraFields;
|
|
98
|
-
export function hasDataDescriptorFlag(flags) {
|
|
99
|
-
return ((flags || 0) & 0x08) !== 0;
|
|
100
|
-
}
|
|
101
|
-
export function isFileSizeKnown(flags, compressedSize) {
|
|
102
|
-
return !hasDataDescriptorFlag(flags) || (compressedSize || 0) > 0;
|
|
103
|
-
}
|
|
104
|
-
export function autodrain(stream) {
|
|
105
|
-
const draining = stream.pipe(new Transform({
|
|
106
|
-
transform(_chunk, _encoding, callback) {
|
|
107
|
-
callback();
|
|
108
|
-
}
|
|
109
|
-
}));
|
|
110
|
-
draining.promise = () => new Promise((resolve, reject) => {
|
|
111
|
-
draining.on("finish", resolve);
|
|
112
|
-
draining.on("error", reject);
|
|
113
|
-
});
|
|
114
|
-
return draining;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Collects all data from a readable stream into a single Uint8Array.
|
|
118
|
-
*/
|
|
119
|
-
export function bufferStream(entry) {
|
|
120
|
-
return new Promise((resolve, reject) => {
|
|
121
|
-
const chunks = [];
|
|
122
|
-
const stream = new Transform({
|
|
123
|
-
transform(d, _encoding, callback) {
|
|
124
|
-
chunks.push(d);
|
|
125
|
-
callback();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
stream.on("finish", () => {
|
|
129
|
-
resolve(chunks.length === 1 ? chunks[0] : concatUint8Arrays(chunks));
|
|
130
|
-
});
|
|
131
|
-
stream.on("error", reject);
|
|
132
|
-
entry.on("error", reject).pipe(stream);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
const STR_FUNCTION = "function";
|
|
136
|
-
export class PullStream extends Duplex {
|
|
137
|
-
get buffer() {
|
|
138
|
-
return this._queue.view();
|
|
139
|
-
}
|
|
140
|
-
set buffer(value) {
|
|
141
|
-
this._queue.reset(value);
|
|
142
|
-
}
|
|
143
|
-
constructor() {
|
|
144
|
-
super({ decodeStrings: false, objectMode: true });
|
|
145
|
-
this._queue = new ByteQueue();
|
|
146
|
-
this.finished = false;
|
|
147
|
-
this.on("finish", () => {
|
|
148
|
-
this.finished = true;
|
|
149
|
-
this.emit("chunk", false);
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
_write(chunk, _encoding, callback) {
|
|
153
|
-
const data = typeof chunk === "string" ? textEncoder.encode(chunk) : chunk;
|
|
154
|
-
this._queue.append(data);
|
|
155
|
-
this.cb = callback;
|
|
156
|
-
this.emit("chunk");
|
|
157
|
-
}
|
|
158
|
-
_read() { }
|
|
159
|
-
_maybeReleaseWriteCallback() {
|
|
160
|
-
if (typeof this.cb === STR_FUNCTION) {
|
|
161
|
-
const callback = this.cb;
|
|
162
|
-
this.cb = undefined;
|
|
163
|
-
callback();
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* The `eof` parameter is interpreted as `file_length` if the type is number
|
|
168
|
-
* otherwise (i.e. Uint8Array) it is interpreted as a pattern signaling end of stream
|
|
169
|
-
*/
|
|
170
|
-
stream(eof, includeEof) {
|
|
171
|
-
const p = new PassThrough();
|
|
172
|
-
let done = false;
|
|
173
|
-
const cb = () => {
|
|
174
|
-
this._maybeReleaseWriteCallback();
|
|
175
|
-
};
|
|
176
|
-
const pull = () => {
|
|
177
|
-
let packet;
|
|
178
|
-
const available = this._queue.length;
|
|
179
|
-
if (available) {
|
|
180
|
-
if (typeof eof === "number") {
|
|
181
|
-
const toRead = Math.min(eof, available);
|
|
182
|
-
if (toRead > 0) {
|
|
183
|
-
packet = this._queue.read(toRead);
|
|
184
|
-
eof -= toRead;
|
|
185
|
-
}
|
|
186
|
-
done = done || eof === 0;
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
const view = this._queue.view();
|
|
190
|
-
let match = indexOfUint8ArrayPattern(view, eof);
|
|
191
|
-
if (match !== -1) {
|
|
192
|
-
// store signature match byte offset to allow us to reference
|
|
193
|
-
// this for zip64 offset
|
|
194
|
-
this.match = match;
|
|
195
|
-
if (includeEof) {
|
|
196
|
-
match = match + eof.length;
|
|
197
|
-
}
|
|
198
|
-
if (match > 0) {
|
|
199
|
-
packet = this._queue.read(match);
|
|
200
|
-
}
|
|
201
|
-
done = true;
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
const len = view.length - eof.length;
|
|
205
|
-
if (len <= 0) {
|
|
206
|
-
cb();
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
packet = this._queue.read(len);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
if (packet) {
|
|
214
|
-
p.write(packet, () => {
|
|
215
|
-
if (this._queue.length === 0 ||
|
|
216
|
-
(typeof eof !== "number" && eof.length && this._queue.length <= eof.length)) {
|
|
217
|
-
cb();
|
|
218
|
-
}
|
|
219
|
-
if (done) {
|
|
220
|
-
cb();
|
|
221
|
-
this.removeListener("chunk", pull);
|
|
222
|
-
p.end();
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
// Continue draining regardless of downstream read timing.
|
|
226
|
-
queueMicrotask(pull);
|
|
227
|
-
});
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
if (!done) {
|
|
232
|
-
if (this.finished) {
|
|
233
|
-
this.removeListener("chunk", pull);
|
|
234
|
-
cb();
|
|
235
|
-
p.destroy(new Error("FILE_ENDED"));
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
this.removeListener("chunk", pull);
|
|
241
|
-
cb();
|
|
242
|
-
p.end();
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
this.on("chunk", pull);
|
|
246
|
-
pull();
|
|
247
|
-
return p;
|
|
248
|
-
}
|
|
249
|
-
pull(eof, includeEof) {
|
|
250
|
-
if (eof === 0) {
|
|
251
|
-
return Promise.resolve(new Uint8Array(0));
|
|
252
|
-
}
|
|
253
|
-
// If we already have the required data in buffer
|
|
254
|
-
// we can resolve the request immediately
|
|
255
|
-
if (typeof eof === "number" && this._queue.length >= eof) {
|
|
256
|
-
const data = this._queue.read(eof);
|
|
257
|
-
// If we drained the internal buffer, allow the upstream writer to continue.
|
|
258
|
-
if (this._queue.length === 0) {
|
|
259
|
-
this._maybeReleaseWriteCallback();
|
|
260
|
-
}
|
|
261
|
-
return Promise.resolve(data);
|
|
262
|
-
}
|
|
263
|
-
// Otherwise we stream until we have it
|
|
264
|
-
const chunks = [];
|
|
265
|
-
const concatStream = new Transform({
|
|
266
|
-
transform(d, _encoding, cb) {
|
|
267
|
-
chunks.push(d);
|
|
268
|
-
cb();
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
let pullStreamRejectHandler;
|
|
272
|
-
return new Promise((resolve, reject) => {
|
|
273
|
-
pullStreamRejectHandler = (e) => {
|
|
274
|
-
this.__emittedError = e;
|
|
275
|
-
reject(e);
|
|
276
|
-
};
|
|
277
|
-
if (this.finished) {
|
|
278
|
-
return reject(new Error("FILE_ENDED"));
|
|
279
|
-
}
|
|
280
|
-
this.once("error", pullStreamRejectHandler); // reject any errors from pullstream itself
|
|
281
|
-
this.stream(eof, includeEof)
|
|
282
|
-
.on("error", reject)
|
|
283
|
-
.pipe(concatStream)
|
|
284
|
-
.on("finish", () => {
|
|
285
|
-
resolve(chunks.length === 1 ? chunks[0] : concatUint8Arrays(chunks));
|
|
286
|
-
})
|
|
287
|
-
.on("error", reject);
|
|
288
|
-
}).finally(() => {
|
|
289
|
-
this.removeListener("error", pullStreamRejectHandler);
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
pullUntil(pattern, includeEof) {
|
|
293
|
-
return this.pull(pattern, includeEof);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
export async function readCrxHeader(pull) {
|
|
297
|
-
const data = await pull(12);
|
|
298
|
-
const header = parseBuffer(data, CRX_HEADER_FORMAT);
|
|
299
|
-
const pubKeyLength = header.pubKeyLength || 0;
|
|
300
|
-
const signatureLength = header.signatureLength || 0;
|
|
301
|
-
const keyAndSig = await pull(pubKeyLength + signatureLength);
|
|
302
|
-
header.publicKey = keyAndSig.subarray(0, pubKeyLength);
|
|
303
|
-
header.signature = keyAndSig.subarray(pubKeyLength);
|
|
304
|
-
return header;
|
|
305
|
-
}
|
|
306
|
-
export async function readLocalFileHeader(pull) {
|
|
307
|
-
const data = await pull(26);
|
|
308
|
-
const vars = parseBuffer(data, LOCAL_FILE_HEADER_FORMAT);
|
|
309
|
-
const fileNameBuffer = await pull(vars.fileNameLength || 0);
|
|
310
|
-
const extraFieldData = await pull(vars.extraFieldLength || 0);
|
|
311
|
-
return { vars, fileNameBuffer, extraFieldData };
|
|
312
|
-
}
|
|
313
|
-
export async function readDataDescriptor(pull) {
|
|
314
|
-
const data = await pull(16);
|
|
315
|
-
return parseBuffer(data, DATA_DESCRIPTOR_FORMAT);
|
|
316
|
-
}
|
|
317
|
-
export async function consumeCentralDirectoryFileHeader(pull) {
|
|
318
|
-
const data = await pull(42);
|
|
319
|
-
const vars = parseBuffer(data, CENTRAL_DIRECTORY_FILE_HEADER_FORMAT);
|
|
320
|
-
await pull(vars.fileNameLength || 0);
|
|
321
|
-
await pull(vars.extraFieldLength || 0);
|
|
322
|
-
await pull(vars.fileCommentLength || 0);
|
|
323
|
-
}
|
|
324
|
-
export async function consumeEndOfCentralDirectoryRecord(pull) {
|
|
325
|
-
const data = await pull(18);
|
|
326
|
-
const vars = parseBuffer(data, END_OF_CENTRAL_DIRECTORY_FORMAT);
|
|
327
|
-
await pull(vars.commentLength || 0);
|
|
328
|
-
}
|
|
329
|
-
// =============================================================================
|
|
330
|
-
// Validated Data Descriptor Scan (shared by Node + Browser)
|
|
331
|
-
// =============================================================================
|
|
332
|
-
function isValidZipRecordSignature(sig) {
|
|
333
|
-
switch (sig) {
|
|
334
|
-
case LOCAL_FILE_HEADER_SIG:
|
|
335
|
-
case CENTRAL_DIR_HEADER_SIG:
|
|
336
|
-
case END_OF_CENTRAL_DIR_SIG:
|
|
337
|
-
case ZIP64_END_OF_CENTRAL_DIR_SIG:
|
|
338
|
-
case ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG:
|
|
339
|
-
return true;
|
|
340
|
-
default:
|
|
341
|
-
return false;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
function readUint32LEFromBytes(view, offset) {
|
|
345
|
-
return ((view[offset] |
|
|
346
|
-
0 |
|
|
347
|
-
((view[offset + 1] | 0) << 8) |
|
|
348
|
-
((view[offset + 2] | 0) << 16) |
|
|
349
|
-
((view[offset + 3] | 0) << 24)) >>>
|
|
350
|
-
0);
|
|
351
|
-
}
|
|
352
|
-
function indexOf4BytesPattern(buffer, pattern, startIndex) {
|
|
353
|
-
if (pattern.length !== 4) {
|
|
354
|
-
return indexOfUint8ArrayPattern(buffer, pattern, startIndex);
|
|
355
|
-
}
|
|
356
|
-
const b0 = pattern[0];
|
|
357
|
-
const b1 = pattern[1];
|
|
358
|
-
const b2 = pattern[2];
|
|
359
|
-
const b3 = pattern[3];
|
|
360
|
-
const bufLen = buffer.length;
|
|
361
|
-
let start = startIndex | 0;
|
|
362
|
-
if (start < 0) {
|
|
363
|
-
start = 0;
|
|
364
|
-
}
|
|
365
|
-
if (start > bufLen - 4) {
|
|
366
|
-
return -1;
|
|
367
|
-
}
|
|
368
|
-
for (let i = start; i <= bufLen - 4; i++) {
|
|
369
|
-
if (buffer[i] === b0 && buffer[i + 1] === b1 && buffer[i + 2] === b2 && buffer[i + 3] === b3) {
|
|
370
|
-
return i;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
return -1;
|
|
374
|
-
}
|
|
375
|
-
function initScanResult(out) {
|
|
376
|
-
if (out) {
|
|
377
|
-
return out;
|
|
378
|
-
}
|
|
379
|
-
return { foundIndex: -1, nextSearchFrom: 0 };
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Scan for a validated DATA_DESCRIPTOR record boundary.
|
|
383
|
-
*
|
|
384
|
-
* Scanning for the 4-byte signature alone is unsafe because it can appear inside
|
|
385
|
-
* compressed data. We validate a candidate by requiring:
|
|
386
|
-
* - the next 4 bytes after the 16-byte descriptor form a known ZIP record signature, and
|
|
387
|
-
* - the descriptor's compressedSize matches the number of compressed bytes emitted so far.
|
|
388
|
-
*/
|
|
389
|
-
export function scanValidatedDataDescriptor(view, dataDescriptorSignature, bytesEmitted, startIndex = 0, out) {
|
|
390
|
-
const result = initScanResult(out);
|
|
391
|
-
let searchFrom = startIndex | 0;
|
|
392
|
-
if (searchFrom < 0) {
|
|
393
|
-
searchFrom = 0;
|
|
394
|
-
}
|
|
395
|
-
if (searchFrom > view.length) {
|
|
396
|
-
searchFrom = view.length;
|
|
397
|
-
}
|
|
398
|
-
// To avoid missing a signature split across chunk boundaries, we may need
|
|
399
|
-
// to re-check the last (sigLen - 1) bytes on the next scan.
|
|
400
|
-
const sigLen = dataDescriptorSignature.length | 0;
|
|
401
|
-
const overlap = sigLen > 0 ? sigLen - 1 : 0;
|
|
402
|
-
while (searchFrom < view.length) {
|
|
403
|
-
const match = indexOf4BytesPattern(view, dataDescriptorSignature, searchFrom);
|
|
404
|
-
if (match === -1) {
|
|
405
|
-
result.foundIndex = -1;
|
|
406
|
-
result.nextSearchFrom = Math.max(searchFrom, Math.max(0, view.length - overlap));
|
|
407
|
-
return result;
|
|
408
|
-
}
|
|
409
|
-
const idx = match;
|
|
410
|
-
// Need 16 bytes for descriptor + 4 bytes for next record signature.
|
|
411
|
-
const nextSigOffset = idx + 16;
|
|
412
|
-
if (nextSigOffset + 4 <= view.length) {
|
|
413
|
-
const nextSig = readUint32LEFromBytes(view, nextSigOffset);
|
|
414
|
-
const descriptorCompressedSize = readUint32LEFromBytes(view, idx + 8);
|
|
415
|
-
const expectedCompressedSize = (bytesEmitted + idx) >>> 0;
|
|
416
|
-
if (isValidZipRecordSignature(nextSig) &&
|
|
417
|
-
descriptorCompressedSize === expectedCompressedSize) {
|
|
418
|
-
result.foundIndex = idx;
|
|
419
|
-
result.nextSearchFrom = idx;
|
|
420
|
-
return result;
|
|
421
|
-
}
|
|
422
|
-
searchFrom = idx + 1;
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
// Not enough bytes to validate yet. Re-check this candidate once more bytes arrive.
|
|
426
|
-
result.foundIndex = -1;
|
|
427
|
-
result.nextSearchFrom = idx;
|
|
428
|
-
return result;
|
|
429
|
-
}
|
|
430
|
-
result.foundIndex = -1;
|
|
431
|
-
result.nextSearchFrom = Math.max(searchFrom, Math.max(0, view.length - overlap));
|
|
432
|
-
return result;
|
|
433
|
-
}
|
|
434
|
-
/**
|
|
435
|
-
* Stream compressed file data until we reach a validated DATA_DESCRIPTOR boundary.
|
|
436
|
-
*
|
|
437
|
-
* This encapsulates the shared logic used by both Node and browser parsers.
|
|
438
|
-
*/
|
|
439
|
-
export function streamUntilValidatedDataDescriptor(options) {
|
|
440
|
-
const { source, dataDescriptorSignature } = options;
|
|
441
|
-
const keepTailBytes = options.keepTailBytes ?? 20;
|
|
442
|
-
const errorMessage = options.errorMessage ?? "FILE_ENDED: Data descriptor not found";
|
|
443
|
-
const output = new PassThrough();
|
|
444
|
-
let done = false;
|
|
445
|
-
// Total number of compressed bytes already emitted for this entry.
|
|
446
|
-
let bytesEmitted = 0;
|
|
447
|
-
let searchFrom = 0;
|
|
448
|
-
const scanResult = { foundIndex: -1, nextSearchFrom: 0 };
|
|
449
|
-
let unsubscribe;
|
|
450
|
-
const cleanup = () => {
|
|
451
|
-
if (unsubscribe) {
|
|
452
|
-
unsubscribe();
|
|
453
|
-
unsubscribe = undefined;
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
const pull = () => {
|
|
457
|
-
if (done) {
|
|
458
|
-
return;
|
|
459
|
-
}
|
|
460
|
-
while (source.getLength() > 0) {
|
|
461
|
-
const view = source.getView();
|
|
462
|
-
scanValidatedDataDescriptor(view, dataDescriptorSignature, bytesEmitted, searchFrom, scanResult);
|
|
463
|
-
const foundIndex = scanResult.foundIndex;
|
|
464
|
-
searchFrom = scanResult.nextSearchFrom;
|
|
465
|
-
if (foundIndex !== -1) {
|
|
466
|
-
if (foundIndex > 0) {
|
|
467
|
-
output.write(source.read(foundIndex));
|
|
468
|
-
bytesEmitted += foundIndex;
|
|
469
|
-
searchFrom = Math.max(0, searchFrom - foundIndex);
|
|
470
|
-
}
|
|
471
|
-
done = true;
|
|
472
|
-
source.maybeReleaseWriteCallback?.();
|
|
473
|
-
cleanup();
|
|
474
|
-
output.end();
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
// Flush most of the buffered data but keep a tail so a potential signature
|
|
478
|
-
// split across chunks can still be detected/validated.
|
|
479
|
-
const flushLen = Math.max(0, view.length - keepTailBytes);
|
|
480
|
-
if (flushLen > 0) {
|
|
481
|
-
output.write(source.read(flushLen));
|
|
482
|
-
bytesEmitted += flushLen;
|
|
483
|
-
searchFrom = Math.max(0, searchFrom - flushLen);
|
|
484
|
-
if (source.getLength() <= keepTailBytes) {
|
|
485
|
-
source.maybeReleaseWriteCallback?.();
|
|
486
|
-
}
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
// Need more data.
|
|
490
|
-
break;
|
|
491
|
-
}
|
|
492
|
-
if (!done && source.isFinished()) {
|
|
493
|
-
done = true;
|
|
494
|
-
cleanup();
|
|
495
|
-
output.destroy(new Error(errorMessage));
|
|
496
|
-
}
|
|
497
|
-
};
|
|
498
|
-
unsubscribe = source.onDataAvailable(pull);
|
|
499
|
-
queueMicrotask(pull);
|
|
500
|
-
return output;
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Default threshold for small file optimization (5MB).
|
|
504
|
-
*/
|
|
505
|
-
export const DEFAULT_PARSE_THRESHOLD_BYTES = 5 * 1024 * 1024;
|
|
506
|
-
const endDirectorySignature = writeUint32LE(END_OF_CENTRAL_DIR_SIG);
|
|
507
|
-
export async function runParseLoop(opts, io, emitter, inflateFactory, state, inflateRawSync) {
|
|
508
|
-
const thresholdBytes = opts.thresholdBytes ?? DEFAULT_PARSE_THRESHOLD_BYTES;
|
|
509
|
-
while (true) {
|
|
510
|
-
const sigBytes = await io.pull(4);
|
|
511
|
-
if (sigBytes.length === 0) {
|
|
512
|
-
emitter.emitClose();
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
const signature = readUint32LE(sigBytes, 0);
|
|
516
|
-
if (signature === 0x34327243) {
|
|
517
|
-
state.crxHeader = await readCrxHeader(async (length) => io.pull(length));
|
|
518
|
-
emitter.emitCrxHeader(state.crxHeader);
|
|
519
|
-
continue;
|
|
520
|
-
}
|
|
521
|
-
if (signature === LOCAL_FILE_HEADER_SIG) {
|
|
522
|
-
await readFileRecord(opts, io, emitter, inflateFactory, state, thresholdBytes, inflateRawSync);
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
if (signature === CENTRAL_DIR_HEADER_SIG) {
|
|
526
|
-
state.reachedCD = true;
|
|
527
|
-
await consumeCentralDirectoryFileHeader(async (length) => io.pull(length));
|
|
528
|
-
continue;
|
|
529
|
-
}
|
|
530
|
-
if (signature === END_OF_CENTRAL_DIR_SIG) {
|
|
531
|
-
await consumeEndOfCentralDirectoryRecord(async (length) => io.pull(length));
|
|
532
|
-
io.setDone();
|
|
533
|
-
emitter.emitClose();
|
|
534
|
-
return;
|
|
535
|
-
}
|
|
536
|
-
if (state.reachedCD) {
|
|
537
|
-
// We are in central directory trailing data; resync by scanning for EOCD signature.
|
|
538
|
-
// consumeEndOfCentralDirectoryRecord expects the EOCD signature to be consumed, so includeEof=true.
|
|
539
|
-
const includeEof = true;
|
|
540
|
-
await io.pullUntil(endDirectorySignature, includeEof);
|
|
541
|
-
await consumeEndOfCentralDirectoryRecord(async (length) => io.pull(length));
|
|
542
|
-
io.setDone();
|
|
543
|
-
emitter.emitClose();
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
emitter.emitError(new Error("invalid signature: 0x" + signature.toString(16)));
|
|
547
|
-
emitter.emitClose();
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
async function readFileRecord(opts, io, emitter, inflateFactory, state, thresholdBytes, inflateRawSync) {
|
|
552
|
-
const { vars: headerVars, fileNameBuffer, extraFieldData } = await readLocalFileHeader(async (l) => io.pull(l));
|
|
553
|
-
const vars = headerVars;
|
|
554
|
-
if (state.crxHeader) {
|
|
555
|
-
vars.crxHeader = state.crxHeader;
|
|
556
|
-
}
|
|
557
|
-
const fileName = decodeZipEntryPath(fileNameBuffer);
|
|
558
|
-
const entry = new PassThrough();
|
|
559
|
-
let autodraining = false;
|
|
560
|
-
entry.autodrain = function () {
|
|
561
|
-
autodraining = true;
|
|
562
|
-
entry.__autodraining = true;
|
|
563
|
-
return autodrain(entry);
|
|
564
|
-
};
|
|
565
|
-
entry.buffer = function () {
|
|
566
|
-
return bufferStream(entry);
|
|
567
|
-
};
|
|
568
|
-
entry.path = fileName;
|
|
569
|
-
entry.props = buildZipEntryProps(fileName, fileNameBuffer, vars.flags);
|
|
570
|
-
entry.type = getZipEntryType(fileName, vars.uncompressedSize || 0);
|
|
571
|
-
if (opts.verbose) {
|
|
572
|
-
if (entry.type === "Directory") {
|
|
573
|
-
console.log(" creating:", fileName);
|
|
574
|
-
}
|
|
575
|
-
else if (entry.type === "File") {
|
|
576
|
-
if (vars.compressionMethod === 0) {
|
|
577
|
-
console.log(" extracting:", fileName);
|
|
578
|
-
}
|
|
579
|
-
else {
|
|
580
|
-
console.log(" inflating:", fileName);
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
const extra = parseExtraField(extraFieldData, vars);
|
|
585
|
-
vars.lastModifiedDateTime = resolveZipEntryLastModifiedDateTime(vars, extra);
|
|
586
|
-
entry.vars = vars;
|
|
587
|
-
entry.extraFields = extra;
|
|
588
|
-
entry.__autodraining = autodraining;
|
|
589
|
-
const fileSizeKnown = isFileSizeKnown(vars.flags, vars.compressedSize);
|
|
590
|
-
if (fileSizeKnown) {
|
|
591
|
-
entry.size = vars.uncompressedSize || 0;
|
|
592
|
-
}
|
|
593
|
-
if (opts.forceStream) {
|
|
594
|
-
emitter.pushEntry(entry);
|
|
595
|
-
}
|
|
596
|
-
else {
|
|
597
|
-
emitter.emitEntry(entry);
|
|
598
|
-
emitter.pushEntryIfPiped(entry);
|
|
599
|
-
}
|
|
600
|
-
if (opts.verbose) {
|
|
601
|
-
console.log({
|
|
602
|
-
filename: fileName,
|
|
603
|
-
vars: vars,
|
|
604
|
-
extraFields: entry.extraFields
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
// Small file optimization: use sync decompression if:
|
|
608
|
-
// 1. Entry sizes are trusted (no data descriptor)
|
|
609
|
-
// 2. File size is known and below threshold
|
|
610
|
-
// 3. inflateRawSync is provided
|
|
611
|
-
// 4. File needs decompression (compressionMethod != 0)
|
|
612
|
-
// 5. Not autodraining
|
|
613
|
-
//
|
|
614
|
-
// We require BOTH compressedSize and uncompressedSize <= thresholdBytes.
|
|
615
|
-
// This prevents materializing large highly-compressible files in memory,
|
|
616
|
-
// which can cause massive peak RSS and negate streaming backpressure.
|
|
617
|
-
const sizesTrusted = !hasDataDescriptorFlag(vars.flags);
|
|
618
|
-
const compressedSize = vars.compressedSize || 0;
|
|
619
|
-
const uncompressedSize = vars.uncompressedSize || 0;
|
|
620
|
-
const useSmallFileOptimization = sizesTrusted &&
|
|
621
|
-
fileSizeKnown &&
|
|
622
|
-
inflateRawSync &&
|
|
623
|
-
vars.compressionMethod !== 0 &&
|
|
624
|
-
!autodraining &&
|
|
625
|
-
compressedSize <= thresholdBytes &&
|
|
626
|
-
uncompressedSize <= thresholdBytes;
|
|
627
|
-
if (useSmallFileOptimization) {
|
|
628
|
-
// Read compressed data directly and decompress synchronously
|
|
629
|
-
const compressedData = await io.pull(compressedSize);
|
|
630
|
-
const decompressedData = inflateRawSync(compressedData);
|
|
631
|
-
entry.end(decompressedData);
|
|
632
|
-
// Wait for entry stream write to complete (not for read/consume)
|
|
633
|
-
await finished(entry, { readable: false });
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
const inflater = vars.compressionMethod && !autodraining ? inflateFactory() : new PassThrough();
|
|
637
|
-
if (fileSizeKnown) {
|
|
638
|
-
await pipeline(io.stream(vars.compressedSize || 0), inflater, entry);
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
await pipeline(io.streamUntilDataDescriptor(), inflater, entry);
|
|
642
|
-
const dd = await readDataDescriptor(async (l) => io.pull(l));
|
|
643
|
-
entry.size = dd.uncompressedSize || 0;
|
|
644
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export declare function unixSecondsFromDate(date: Date): number;
|
|
2
|
-
/**
|
|
3
|
-
* Build Info-ZIP "Extended Timestamp" extra field (0x5455).
|
|
4
|
-
* We write only mtime (UTC, Unix seconds) to minimize size.
|
|
5
|
-
*
|
|
6
|
-
* Layout:
|
|
7
|
-
* - Header ID: 2 bytes (0x5455)
|
|
8
|
-
* - Data size: 2 bytes
|
|
9
|
-
* - Flags: 1 byte (bit0 = mtime)
|
|
10
|
-
* - mtime: 4 bytes (Unix seconds)
|
|
11
|
-
*/
|
|
12
|
-
export declare function buildExtendedTimestampExtraFieldFromUnixSeconds(unixSeconds: number): Uint8Array;
|
|
13
|
-
export declare function buildExtendedTimestampExtraFieldFromDate(date: Date): Uint8Array;
|
|
14
|
-
/**
|
|
15
|
-
* Parse Info-ZIP "Extended Timestamp" extra field (0x5455) and return mtime.
|
|
16
|
-
* Returns Unix seconds (UTC) if present.
|
|
17
|
-
*/
|
|
18
|
-
export declare function parseExtendedTimestampMtimeUnixSeconds(extraField: Uint8Array): number | undefined;
|