@cj-tech-master/excelts 4.2.1-canary.20260111102127.f808a37 → 4.2.1
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 +31 -0
- package/dist/browser/index.browser.d.ts +0 -1
- package/dist/browser/index.browser.js +0 -12
- package/dist/browser/modules/archive/byte-queue.d.ts +18 -0
- package/dist/browser/modules/archive/byte-queue.js +125 -0
- package/dist/browser/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
- package/dist/browser/modules/archive/{compression/compress.browser.d.ts → compress.browser.d.ts} +8 -2
- package/dist/{esm/modules/archive/compression → browser/modules/archive}/compress.browser.js +11 -3
- package/dist/browser/modules/archive/{compression/compress.d.ts → compress.d.ts} +2 -2
- package/dist/{esm/modules/archive/compression → browser/modules/archive}/compress.js +1 -1
- package/dist/browser/modules/archive/{compression/crc32.browser.d.ts → crc32.browser.d.ts} +1 -1
- package/dist/browser/modules/archive/{compression/crc32.d.ts → crc32.d.ts} +1 -1
- package/dist/browser/modules/archive/{compression/crc32.js → crc32.js} +1 -1
- package/dist/browser/modules/archive/defaults.d.ts +0 -1
- package/dist/browser/modules/archive/defaults.js +3 -6
- package/dist/browser/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
- package/dist/browser/modules/archive/{unzip/extract.d.ts → extract.d.ts} +2 -2
- package/dist/browser/modules/archive/index.base.d.ts +4 -4
- package/dist/browser/modules/archive/index.base.js +6 -3
- package/dist/browser/modules/archive/index.browser.d.ts +4 -3
- package/dist/browser/modules/archive/index.browser.js +7 -3
- package/dist/browser/modules/archive/index.d.ts +4 -3
- package/dist/browser/modules/archive/index.js +5 -3
- package/dist/browser/modules/archive/{unzip/stream.base.d.ts → parse.base.d.ts} +2 -36
- package/dist/browser/modules/archive/parse.base.js +644 -0
- package/dist/browser/modules/archive/{unzip/stream.browser.d.ts → parse.browser.d.ts} +1 -1
- package/dist/{esm/modules/archive/unzip/stream.browser.js → browser/modules/archive/parse.browser.js} +110 -371
- package/dist/browser/modules/archive/{unzip/stream.d.ts → parse.d.ts} +2 -2
- package/dist/{esm/modules/archive/unzip/stream.js → browser/modules/archive/parse.js} +5 -6
- package/dist/browser/modules/archive/{compression/streaming-compress.browser.d.ts → streaming-compress.browser.d.ts} +2 -2
- package/dist/browser/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
- package/dist/browser/modules/archive/{compression/streaming-compress.d.ts → streaming-compress.d.ts} +2 -2
- package/dist/browser/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
- package/dist/browser/modules/archive/{zip/stream.d.ts → streaming-zip.d.ts} +5 -28
- package/dist/{esm/modules/archive/zip/stream.js → browser/modules/archive/streaming-zip.js} +48 -192
- package/dist/browser/modules/archive/utils/bytes.js +16 -16
- package/dist/browser/modules/archive/utils/parse-buffer.js +23 -21
- package/dist/browser/modules/archive/utils/timestamps.js +1 -62
- package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/browser/modules/archive/utils/zip-extra-fields.js +14 -26
- package/dist/browser/modules/archive/utils/zip-extra.d.ts +18 -0
- package/dist/browser/modules/archive/utils/zip-extra.js +68 -0
- package/dist/browser/modules/archive/zip-builder.d.ts +117 -0
- package/dist/browser/modules/archive/zip-builder.js +292 -0
- package/dist/browser/modules/archive/zip-constants.d.ts +18 -0
- package/dist/browser/modules/archive/zip-constants.js +23 -0
- package/dist/{esm/modules/archive/zip → browser/modules/archive}/zip-entry-metadata.js +3 -3
- package/dist/{types/modules/archive/unzip → browser/modules/archive}/zip-parser.d.ts +1 -1
- package/dist/{esm/modules/archive/unzip → browser/modules/archive}/zip-parser.js +24 -38
- package/dist/browser/modules/archive/{zip-spec/zip-records.d.ts → zip-records.d.ts} +0 -20
- package/dist/browser/modules/archive/zip-records.js +84 -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/xlsx/xlsx.browser.js +6 -3
- package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/browser/modules/stream/streams.browser.d.ts +30 -28
- package/dist/browser/modules/stream/streams.browser.js +710 -830
- package/dist/browser/modules/stream/streams.js +58 -140
- package/dist/cjs/modules/archive/byte-queue.js +129 -0
- package/dist/cjs/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
- package/dist/cjs/modules/archive/{compression/compress.browser.js → compress.browser.js} +11 -3
- package/dist/cjs/modules/archive/{compression/compress.js → compress.js} +1 -1
- package/dist/cjs/modules/archive/{compression/crc32.js → crc32.js} +1 -1
- package/dist/cjs/modules/archive/defaults.js +4 -7
- package/dist/cjs/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
- package/dist/cjs/modules/archive/index.base.js +19 -9
- package/dist/cjs/modules/archive/index.browser.js +10 -4
- package/dist/cjs/modules/archive/index.js +8 -4
- package/dist/cjs/modules/archive/parse.base.js +666 -0
- package/dist/cjs/modules/archive/{unzip/stream.browser.js → parse.browser.js} +111 -372
- package/dist/cjs/modules/archive/{unzip/stream.js → parse.js} +8 -9
- package/dist/cjs/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
- package/dist/cjs/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
- package/dist/cjs/modules/archive/{zip/stream.js → streaming-zip.js} +50 -194
- package/dist/cjs/modules/archive/utils/bytes.js +16 -16
- package/dist/cjs/modules/archive/utils/parse-buffer.js +23 -21
- package/dist/cjs/modules/archive/utils/timestamps.js +3 -64
- package/dist/cjs/modules/archive/utils/zip-extra-fields.js +14 -26
- package/dist/cjs/modules/archive/utils/zip-extra.js +74 -0
- package/dist/cjs/modules/archive/zip-builder.js +297 -0
- package/dist/cjs/modules/archive/zip-constants.js +26 -0
- package/dist/cjs/modules/archive/{zip/zip-entry-metadata.js → zip-entry-metadata.js} +5 -5
- package/dist/cjs/modules/archive/{unzip/zip-parser.js → zip-parser.js} +33 -47
- package/dist/cjs/modules/archive/zip-records.js +90 -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/xlsx/xlsx.browser.js +9 -6
- package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
- package/dist/cjs/modules/stream/streams.browser.js +710 -830
- package/dist/cjs/modules/stream/streams.js +58 -140
- package/dist/esm/index.browser.js +0 -12
- package/dist/esm/modules/archive/byte-queue.js +125 -0
- package/dist/esm/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
- package/dist/{browser/modules/archive/compression → esm/modules/archive}/compress.browser.js +11 -3
- package/dist/{browser/modules/archive/compression → esm/modules/archive}/compress.js +1 -1
- package/dist/esm/modules/archive/{compression/crc32.js → crc32.js} +1 -1
- package/dist/esm/modules/archive/defaults.js +3 -6
- package/dist/esm/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
- package/dist/esm/modules/archive/index.base.js +6 -3
- package/dist/esm/modules/archive/index.browser.js +7 -3
- package/dist/esm/modules/archive/index.js +5 -3
- package/dist/esm/modules/archive/parse.base.js +644 -0
- package/dist/{browser/modules/archive/unzip/stream.browser.js → esm/modules/archive/parse.browser.js} +110 -371
- package/dist/{browser/modules/archive/unzip/stream.js → esm/modules/archive/parse.js} +5 -6
- package/dist/esm/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
- package/dist/esm/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
- package/dist/{browser/modules/archive/zip/stream.js → esm/modules/archive/streaming-zip.js} +48 -192
- package/dist/esm/modules/archive/utils/bytes.js +16 -16
- package/dist/esm/modules/archive/utils/parse-buffer.js +23 -21
- package/dist/esm/modules/archive/utils/timestamps.js +1 -62
- package/dist/esm/modules/archive/utils/zip-extra-fields.js +14 -26
- package/dist/esm/modules/archive/utils/zip-extra.js +68 -0
- package/dist/esm/modules/archive/zip-builder.js +292 -0
- package/dist/esm/modules/archive/zip-constants.js +23 -0
- package/dist/{browser/modules/archive/zip → esm/modules/archive}/zip-entry-metadata.js +3 -3
- package/dist/{browser/modules/archive/unzip → esm/modules/archive}/zip-parser.js +24 -38
- package/dist/esm/modules/archive/zip-records.js +84 -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/xlsx/xlsx.browser.js +6 -3
- package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
- package/dist/esm/modules/stream/streams.browser.js +710 -830
- package/dist/esm/modules/stream/streams.js +58 -140
- package/dist/iife/THIRD_PARTY_NOTICES.md +31 -0
- package/dist/iife/excelts.iife.js +4425 -6215
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +31 -103
- package/dist/types/index.browser.d.ts +0 -1
- package/dist/types/modules/archive/byte-queue.d.ts +18 -0
- package/dist/types/modules/archive/{compression/compress.browser.d.ts → compress.browser.d.ts} +8 -2
- package/dist/types/modules/archive/defaults.d.ts +0 -1
- package/dist/types/modules/archive/index.base.d.ts +4 -4
- package/dist/types/modules/archive/index.browser.d.ts +4 -3
- package/dist/types/modules/archive/index.d.ts +4 -3
- package/dist/types/modules/archive/{unzip/stream.base.d.ts → parse.base.d.ts} +4 -38
- package/dist/types/modules/archive/{unzip/stream.browser.d.ts → parse.browser.d.ts} +2 -2
- package/dist/types/modules/archive/{unzip/stream.d.ts → parse.d.ts} +3 -3
- package/dist/types/modules/archive/{compression/streaming-compress.browser.d.ts → streaming-compress.browser.d.ts} +1 -1
- package/dist/types/modules/archive/{zip/stream.d.ts → streaming-zip.d.ts} +6 -29
- package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
- package/dist/types/modules/archive/utils/zip-extra.d.ts +18 -0
- package/dist/types/modules/archive/zip-builder.d.ts +117 -0
- package/dist/types/modules/archive/zip-constants.d.ts +18 -0
- package/dist/types/modules/archive/{zip/zip-entry-metadata.d.ts → zip-entry-metadata.d.ts} +1 -1
- package/dist/{browser/modules/archive/unzip → types/modules/archive}/zip-parser.d.ts +1 -1
- package/dist/types/modules/archive/{zip-spec/zip-records.d.ts → zip-records.d.ts} +0 -20
- package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
- package/dist/types/modules/stream/streams.browser.d.ts +30 -28
- package/package.json +1 -5
- package/dist/browser/modules/archive/internal/byte-queue.d.ts +0 -33
- package/dist/browser/modules/archive/internal/byte-queue.js +0 -407
- package/dist/browser/modules/archive/io/archive-sink.d.ts +0 -9
- package/dist/browser/modules/archive/io/archive-sink.js +0 -77
- package/dist/browser/modules/archive/io/archive-source.d.ts +0 -8
- package/dist/browser/modules/archive/io/archive-source.js +0 -107
- package/dist/browser/modules/archive/unzip/index.d.ts +0 -40
- package/dist/browser/modules/archive/unzip/index.js +0 -164
- package/dist/browser/modules/archive/unzip/stream.base.js +0 -1022
- package/dist/browser/modules/archive/utils/async-queue.d.ts +0 -7
- package/dist/browser/modules/archive/utils/async-queue.js +0 -103
- package/dist/browser/modules/archive/utils/compressibility.d.ts +0 -10
- package/dist/browser/modules/archive/utils/compressibility.js +0 -57
- package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +0 -21
- package/dist/browser/modules/archive/utils/pattern-scanner.js +0 -27
- package/dist/browser/modules/archive/zip/index.d.ts +0 -42
- package/dist/browser/modules/archive/zip/index.js +0 -157
- package/dist/browser/modules/archive/zip/zip-bytes.d.ts +0 -73
- package/dist/browser/modules/archive/zip/zip-bytes.js +0 -239
- package/dist/browser/modules/archive/zip-spec/zip-records.js +0 -126
- package/dist/cjs/modules/archive/internal/byte-queue.js +0 -411
- package/dist/cjs/modules/archive/io/archive-sink.js +0 -82
- package/dist/cjs/modules/archive/io/archive-source.js +0 -114
- package/dist/cjs/modules/archive/unzip/index.js +0 -170
- package/dist/cjs/modules/archive/unzip/stream.base.js +0 -1044
- package/dist/cjs/modules/archive/utils/async-queue.js +0 -106
- package/dist/cjs/modules/archive/utils/compressibility.js +0 -60
- package/dist/cjs/modules/archive/utils/pattern-scanner.js +0 -31
- package/dist/cjs/modules/archive/zip/index.js +0 -162
- package/dist/cjs/modules/archive/zip/zip-bytes.js +0 -242
- package/dist/cjs/modules/archive/zip-spec/zip-records.js +0 -136
- package/dist/esm/modules/archive/internal/byte-queue.js +0 -407
- package/dist/esm/modules/archive/io/archive-sink.js +0 -77
- package/dist/esm/modules/archive/io/archive-source.js +0 -107
- package/dist/esm/modules/archive/unzip/index.js +0 -164
- package/dist/esm/modules/archive/unzip/stream.base.js +0 -1022
- package/dist/esm/modules/archive/utils/async-queue.js +0 -103
- package/dist/esm/modules/archive/utils/compressibility.js +0 -57
- package/dist/esm/modules/archive/utils/pattern-scanner.js +0 -27
- package/dist/esm/modules/archive/zip/index.js +0 -157
- package/dist/esm/modules/archive/zip/zip-bytes.js +0 -239
- package/dist/esm/modules/archive/zip-spec/zip-records.js +0 -126
- package/dist/types/modules/archive/internal/byte-queue.d.ts +0 -33
- package/dist/types/modules/archive/io/archive-sink.d.ts +0 -9
- package/dist/types/modules/archive/io/archive-source.d.ts +0 -8
- package/dist/types/modules/archive/unzip/index.d.ts +0 -40
- package/dist/types/modules/archive/utils/async-queue.d.ts +0 -7
- package/dist/types/modules/archive/utils/compressibility.d.ts +0 -10
- package/dist/types/modules/archive/utils/pattern-scanner.d.ts +0 -21
- package/dist/types/modules/archive/zip/index.d.ts +0 -42
- package/dist/types/modules/archive/zip/zip-bytes.d.ts +0 -73
- /package/dist/browser/modules/archive/{compression/compress.base.d.ts → compress.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{compression/crc32.base.d.ts → crc32.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
- /package/dist/browser/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
- /package/dist/browser/modules/archive/{compression/deflate-fallback.d.ts → deflate-fallback.d.ts} +0 -0
- /package/dist/browser/modules/archive/{unzip/extract.js → extract.js} +0 -0
- /package/dist/browser/modules/archive/{compression/streaming-compress.base.d.ts → streaming-compress.base.d.ts} +0 -0
- /package/dist/browser/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
- /package/dist/browser/modules/archive/{zip-spec/zip-entry-info.d.ts → zip-entry-info.d.ts} +0 -0
- /package/dist/browser/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
- /package/dist/browser/modules/archive/{zip/zip-entry-metadata.d.ts → zip-entry-metadata.d.ts} +0 -0
- /package/dist/cjs/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
- /package/dist/cjs/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
- /package/dist/cjs/modules/archive/{unzip/extract.js → extract.js} +0 -0
- /package/dist/cjs/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
- /package/dist/cjs/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
- /package/dist/esm/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
- /package/dist/esm/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
- /package/dist/esm/modules/archive/{unzip/extract.js → extract.js} +0 -0
- /package/dist/esm/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
- /package/dist/esm/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
- /package/dist/types/modules/archive/{compression/compress.base.d.ts → compress.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/compress.d.ts → compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/crc32.base.d.ts → crc32.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/crc32.browser.d.ts → crc32.browser.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/crc32.d.ts → crc32.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/deflate-fallback.d.ts → deflate-fallback.d.ts} +0 -0
- /package/dist/types/modules/archive/{unzip/extract.d.ts → extract.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/streaming-compress.base.d.ts → streaming-compress.base.d.ts} +0 -0
- /package/dist/types/modules/archive/{compression/streaming-compress.d.ts → streaming-compress.d.ts} +0 -0
- /package/dist/types/modules/archive/{zip-spec/zip-entry-info.d.ts → zip-entry-info.d.ts} +0 -0
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* API compatible with Node.js version - supports .on("data"), .on("end"), .write(callback), .end()
|
|
8
8
|
*/
|
|
9
|
-
import { EventEmitter } from "
|
|
9
|
+
import { EventEmitter } from "../stream/index.js";
|
|
10
10
|
import { deflateRawCompressed, inflateRaw } from "./deflate-fallback.js";
|
|
11
11
|
import { hasDeflateRawWebStreams } from "./compress.base.js";
|
|
12
|
-
import { concatUint8Arrays } from "
|
|
13
|
-
import { DEFAULT_COMPRESS_LEVEL } from "
|
|
12
|
+
import { concatUint8Arrays } from "./utils/bytes.js";
|
|
13
|
+
import { DEFAULT_COMPRESS_LEVEL } from "./defaults.js";
|
|
14
14
|
import { asError } from "./streaming-compress.base.js";
|
|
15
15
|
/**
|
|
16
16
|
* Check if deflate-raw streaming compression is supported by this library.
|
package/dist/esm/modules/archive/{compression/streaming-compress.js → streaming-compress.js}
RENAMED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Each write() immediately produces compressed output without waiting for end().
|
|
6
6
|
*/
|
|
7
7
|
import { createDeflateRaw, createInflateRaw, constants } from "zlib";
|
|
8
|
-
import { Transform } from "
|
|
9
|
-
import { DEFAULT_COMPRESS_LEVEL } from "
|
|
8
|
+
import { Transform } from "../stream/index.js";
|
|
9
|
+
import { DEFAULT_COMPRESS_LEVEL } from "./defaults.js";
|
|
10
10
|
/**
|
|
11
11
|
* Wrapper around zlib DeflateRaw that flushes after every write
|
|
12
12
|
* This ensures true streaming behavior - data is emitted immediately, not buffered
|
|
@@ -2,16 +2,15 @@
|
|
|
2
2
|
* True Streaming ZIP creator - shared implementation.
|
|
3
3
|
*
|
|
4
4
|
* This module is intentionally platform-agnostic.
|
|
5
|
-
* - In Node builds it uses `./
|
|
5
|
+
* - In Node builds it uses `./crc32` + `./streaming-compress` (zlib-backed).
|
|
6
6
|
* - In browser builds the bundler aliases those imports to their browser variants.
|
|
7
7
|
*/
|
|
8
|
-
import { crc32Update, crc32Finalize } from "
|
|
9
|
-
import { createDeflateStream } from "
|
|
10
|
-
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "
|
|
11
|
-
import { buildZipEntryMetadata
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader, VERSION_MADE_BY, VERSION_NEEDED } from "../zip-spec/zip-records.js";
|
|
8
|
+
import { crc32Update, crc32Finalize } from "./crc32.js";
|
|
9
|
+
import { createDeflateStream } from "./streaming-compress.js";
|
|
10
|
+
import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "./defaults.js";
|
|
11
|
+
import { buildZipEntryMetadata } from "./zip-entry-metadata.js";
|
|
12
|
+
import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader } from "./zip-records.js";
|
|
13
|
+
import { VERSION_MADE_BY, VERSION_NEEDED } from "./zip-constants.js";
|
|
15
14
|
/**
|
|
16
15
|
* True Streaming ZIP File - compresses chunk by chunk
|
|
17
16
|
*/
|
|
@@ -24,15 +23,9 @@ export class ZipDeflateFile {
|
|
|
24
23
|
this._finalized = false;
|
|
25
24
|
this._headerEmitted = false;
|
|
26
25
|
this._ondata = null;
|
|
27
|
-
this._onerror = null;
|
|
28
26
|
this._centralDirEntryInfo = null;
|
|
29
27
|
this._pendingEnd = false;
|
|
30
28
|
this._emittedDataDescriptor = false;
|
|
31
|
-
this._localHeader = null;
|
|
32
|
-
// Smart STORE: delay method selection until we sample data.
|
|
33
|
-
this._deflateWanted = null;
|
|
34
|
-
this._pendingChunks = [];
|
|
35
|
-
this._sampleLen = 0;
|
|
36
29
|
// Promise resolution for completion (including data descriptor)
|
|
37
30
|
this._completeResolve = null;
|
|
38
31
|
this._completeReject = null;
|
|
@@ -41,70 +34,46 @@ export class ZipDeflateFile {
|
|
|
41
34
|
// Queue for incoming data before ondata is set
|
|
42
35
|
this._dataQueue = [];
|
|
43
36
|
this._finalQueued = false;
|
|
44
|
-
// Serialize push() calls so callers don't need to await to preserve ordering.
|
|
45
|
-
this._pushChain = Promise.resolve();
|
|
46
37
|
this.name = name;
|
|
47
38
|
const modTime = options?.modTime ?? new Date();
|
|
48
39
|
this._modTime = modTime;
|
|
49
40
|
this.level = options?.level ?? DEFAULT_ZIP_LEVEL;
|
|
50
|
-
this._smartStore = options?.smartStore ?? true;
|
|
51
|
-
this._sampleBuffer = this._smartStore ? new Uint8Array(64 * 1024) : new Uint8Array(0);
|
|
52
41
|
const metadata = buildZipEntryMetadata({
|
|
53
42
|
name,
|
|
54
|
-
comment:
|
|
43
|
+
comment: "",
|
|
55
44
|
modTime,
|
|
56
45
|
timestamps: options?.timestamps ?? DEFAULT_ZIP_TIMESTAMPS,
|
|
57
46
|
useDataDescriptor: true,
|
|
58
|
-
deflate:
|
|
47
|
+
deflate: this.level > 0
|
|
59
48
|
});
|
|
60
49
|
this.nameBytes = metadata.nameBytes;
|
|
61
|
-
this.commentBytes = metadata.commentBytes;
|
|
62
50
|
this.dosTime = metadata.dosTime;
|
|
63
51
|
this.dosDate = metadata.dosDate;
|
|
64
52
|
this.extraField = metadata.extraField;
|
|
65
53
|
this._flags = metadata.flags;
|
|
66
54
|
this._compressionMethod = metadata.compressionMethod;
|
|
67
|
-
//
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (this._deflate) {
|
|
88
|
-
return;
|
|
55
|
+
// Create deflate stream for compression
|
|
56
|
+
if (this.level > 0) {
|
|
57
|
+
this._deflate = createDeflateStream({ level: this.level });
|
|
58
|
+
this._deflate.on("error", (err) => {
|
|
59
|
+
this._rejectComplete(err);
|
|
60
|
+
});
|
|
61
|
+
// Handle compressed output - this is true streaming!
|
|
62
|
+
this._deflate.on("data", (chunk) => {
|
|
63
|
+
this._compressedSize += chunk.length;
|
|
64
|
+
this._enqueueData(chunk, false);
|
|
65
|
+
});
|
|
66
|
+
// Handle end - emit data descriptor
|
|
67
|
+
// IMPORTANT: Only use 'end' event, NOT 'finish'!
|
|
68
|
+
// Node.js zlib emits events in order: finish -> data -> end
|
|
69
|
+
this._deflate.on("end", () => {
|
|
70
|
+
if (this._pendingEnd && !this._emittedDataDescriptor) {
|
|
71
|
+
this._emittedDataDescriptor = true;
|
|
72
|
+
this._emitDataDescriptor();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
89
75
|
}
|
|
90
|
-
this.
|
|
91
|
-
this._deflate.on("error", (err) => {
|
|
92
|
-
this._rejectComplete(err);
|
|
93
|
-
});
|
|
94
|
-
// Handle compressed output - this is true streaming!
|
|
95
|
-
this._deflate.on("data", (chunk) => {
|
|
96
|
-
this._compressedSize += chunk.length;
|
|
97
|
-
this._enqueueData(chunk, false);
|
|
98
|
-
});
|
|
99
|
-
// Handle end - emit data descriptor
|
|
100
|
-
// IMPORTANT: Only use 'end' event, NOT 'finish'!
|
|
101
|
-
// Node.js zlib emits events in order: finish -> data -> end
|
|
102
|
-
this._deflate.on("end", () => {
|
|
103
|
-
if (this._pendingEnd && !this._emittedDataDescriptor) {
|
|
104
|
-
this._emittedDataDescriptor = true;
|
|
105
|
-
this._emitDataDescriptor();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
76
|
+
this._localHeader = this._buildLocalHeader();
|
|
108
77
|
}
|
|
109
78
|
_buildLocalHeader() {
|
|
110
79
|
// CRC + sizes are written via data descriptor for true streaming.
|
|
@@ -121,63 +90,6 @@ export class ZipDeflateFile {
|
|
|
121
90
|
versionNeeded: VERSION_NEEDED
|
|
122
91
|
});
|
|
123
92
|
}
|
|
124
|
-
_accumulateSample(data) {
|
|
125
|
-
if (this._deflateWanted !== null) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (this._sampleLen >= this._sampleBuffer.length) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const take = Math.min(this._sampleBuffer.length - this._sampleLen, data.length);
|
|
132
|
-
if (take <= 0) {
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
this._sampleBuffer.set(data.subarray(0, take), this._sampleLen);
|
|
136
|
-
this._sampleLen += take;
|
|
137
|
-
}
|
|
138
|
-
_shouldDecide(final) {
|
|
139
|
-
if (this._deflateWanted !== null) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
return final || this._sampleLen >= 16 * 1024;
|
|
143
|
-
}
|
|
144
|
-
_decideCompressionIfNeeded(final) {
|
|
145
|
-
if (this._deflateWanted !== null) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
// Match non-streaming builder semantics: empty files never need DEFLATE.
|
|
149
|
-
if (final && this._sampleLen === 0) {
|
|
150
|
-
this._deflateWanted = false;
|
|
151
|
-
this._compressionMethod = this._buildCompressionMethod(false);
|
|
152
|
-
this._localHeader = null;
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
// Default to DEFLATE unless heuristic says STORE.
|
|
156
|
-
const sample = this._sampleBuffer.subarray(0, this._sampleLen);
|
|
157
|
-
const store = isProbablyIncompressible(sample);
|
|
158
|
-
this._deflateWanted = !store;
|
|
159
|
-
this._compressionMethod = this._buildCompressionMethod(this._deflateWanted);
|
|
160
|
-
this._localHeader = null;
|
|
161
|
-
if (this._deflateWanted) {
|
|
162
|
-
this._initDeflateStream();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
_emitHeaderIfNeeded() {
|
|
166
|
-
if (this._headerEmitted) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
this._emitHeader();
|
|
170
|
-
this._headerEmitted = true;
|
|
171
|
-
}
|
|
172
|
-
async _flushPendingChunks() {
|
|
173
|
-
if (this._pendingChunks.length === 0) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
for (const chunk of this._pendingChunks) {
|
|
177
|
-
await this._writeData(chunk);
|
|
178
|
-
}
|
|
179
|
-
this._pendingChunks = [];
|
|
180
|
-
}
|
|
181
93
|
_enqueueData(data, final) {
|
|
182
94
|
if (this._ondata) {
|
|
183
95
|
this._ondata(data, final);
|
|
@@ -209,29 +121,13 @@ export class ZipDeflateFile {
|
|
|
209
121
|
// Flush any queued data
|
|
210
122
|
this._flushQueue();
|
|
211
123
|
}
|
|
212
|
-
get onerror() {
|
|
213
|
-
return this._onerror ?? undefined;
|
|
214
|
-
}
|
|
215
|
-
set onerror(cb) {
|
|
216
|
-
this._onerror = cb;
|
|
217
|
-
// If an error already occurred, surface it immediately.
|
|
218
|
-
if (this._completeError) {
|
|
219
|
-
cb(this._completeError);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
124
|
_resolveComplete() {
|
|
223
125
|
if (this._completeResolve) {
|
|
224
126
|
this._completeResolve();
|
|
225
127
|
}
|
|
226
128
|
}
|
|
227
129
|
_rejectComplete(err) {
|
|
228
|
-
if (this._completeError) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
130
|
this._completeError = err;
|
|
232
|
-
if (this._onerror) {
|
|
233
|
-
this._onerror(err);
|
|
234
|
-
}
|
|
235
131
|
if (this._completeReject) {
|
|
236
132
|
this._completeReject(err);
|
|
237
133
|
}
|
|
@@ -257,6 +153,13 @@ export class ZipDeflateFile {
|
|
|
257
153
|
}
|
|
258
154
|
promise.then(() => callback()).catch(err => callback(err));
|
|
259
155
|
}
|
|
156
|
+
_emitHeaderIfNeeded() {
|
|
157
|
+
if (this._headerEmitted) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this._emitHeader();
|
|
161
|
+
this._headerEmitted = true;
|
|
162
|
+
}
|
|
260
163
|
_writeData(data) {
|
|
261
164
|
if (data.length === 0) {
|
|
262
165
|
return Promise.resolve();
|
|
@@ -314,60 +217,27 @@ export class ZipDeflateFile {
|
|
|
314
217
|
this._emitDataDescriptor();
|
|
315
218
|
return completePromise;
|
|
316
219
|
}
|
|
317
|
-
|
|
220
|
+
/**
|
|
221
|
+
* Push data - immediately compresses and outputs
|
|
222
|
+
* Returns a Promise that resolves when the write is complete.
|
|
223
|
+
* If final=true, it resolves after the data descriptor is emitted.
|
|
224
|
+
*/
|
|
225
|
+
push(data, final = false, callback) {
|
|
318
226
|
if (this._finalized) {
|
|
319
227
|
const promise = Promise.reject(new Error("Cannot push to finalized ZipDeflateFile"));
|
|
320
228
|
this._tapCallback(promise, callback);
|
|
321
229
|
return promise;
|
|
322
230
|
}
|
|
323
|
-
if (this._deflateWanted === null) {
|
|
324
|
-
this._accumulateSample(data);
|
|
325
|
-
if (!this._shouldDecide(final)) {
|
|
326
|
-
if (data.length > 0) {
|
|
327
|
-
this._pendingChunks.push(data);
|
|
328
|
-
}
|
|
329
|
-
const promise = Promise.resolve();
|
|
330
|
-
this._tapCallback(promise, callback);
|
|
331
|
-
return promise;
|
|
332
|
-
}
|
|
333
|
-
this._decideCompressionIfNeeded(final);
|
|
334
|
-
this._emitHeaderIfNeeded();
|
|
335
|
-
const hadPendingChunks = this._pendingChunks.length > 0;
|
|
336
|
-
const flushPromise = this._flushPendingChunks();
|
|
337
|
-
let writePromise = flushPromise;
|
|
338
|
-
if (data.length > 0) {
|
|
339
|
-
writePromise = hadPendingChunks
|
|
340
|
-
? flushPromise.then(() => this._writeData(data))
|
|
341
|
-
: this._writeData(data);
|
|
342
|
-
}
|
|
343
|
-
const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
|
|
344
|
-
this._tapCallback(promise, callback);
|
|
345
|
-
return promise;
|
|
346
|
-
}
|
|
347
231
|
this._emitHeaderIfNeeded();
|
|
348
232
|
const writePromise = this._writeData(data);
|
|
349
233
|
const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
|
|
350
234
|
this._tapCallback(promise, callback);
|
|
351
235
|
return promise;
|
|
352
236
|
}
|
|
353
|
-
/**
|
|
354
|
-
* Push data - immediately compresses and outputs
|
|
355
|
-
* Returns a Promise that resolves when the write is complete.
|
|
356
|
-
* If final=true, it resolves after the data descriptor is emitted.
|
|
357
|
-
*/
|
|
358
|
-
push(data, final = false, callback) {
|
|
359
|
-
const promise = (this._pushChain = this._pushChain.then(() => this._pushUnchained(data, final, callback)));
|
|
360
|
-
// Prevent unhandled rejection when callers intentionally ignore the Promise.
|
|
361
|
-
promise.catch(() => { });
|
|
362
|
-
return promise;
|
|
363
|
-
}
|
|
364
237
|
/**
|
|
365
238
|
* Emit local file header with Data Descriptor flag
|
|
366
239
|
*/
|
|
367
240
|
_emitHeader() {
|
|
368
|
-
if (!this._localHeader) {
|
|
369
|
-
this._localHeader = this._buildLocalHeader();
|
|
370
|
-
}
|
|
371
241
|
this._enqueueData(this._localHeader, false);
|
|
372
242
|
}
|
|
373
243
|
/**
|
|
@@ -380,7 +250,6 @@ export class ZipDeflateFile {
|
|
|
380
250
|
this._centralDirEntryInfo = {
|
|
381
251
|
name: this.nameBytes,
|
|
382
252
|
extraField: this.extraField,
|
|
383
|
-
comment: this.commentBytes,
|
|
384
253
|
flags: this._flags,
|
|
385
254
|
crc: crcValue,
|
|
386
255
|
compressedSize: this._compressedSize,
|
|
@@ -419,7 +288,7 @@ export class ZipDeflateFile {
|
|
|
419
288
|
crc32: this._centralDirEntryInfo.crc,
|
|
420
289
|
lastModified: this._modTime,
|
|
421
290
|
localHeaderOffset: this._centralDirEntryInfo.offset,
|
|
422
|
-
comment:
|
|
291
|
+
comment: "",
|
|
423
292
|
externalAttributes: 0,
|
|
424
293
|
isEncrypted: false
|
|
425
294
|
};
|
|
@@ -436,7 +305,7 @@ export class ZipDeflateFile {
|
|
|
436
305
|
* Streaming ZIP Creator - processes files sequentially
|
|
437
306
|
*/
|
|
438
307
|
export class StreamingZip {
|
|
439
|
-
constructor(callback
|
|
308
|
+
constructor(callback) {
|
|
440
309
|
this.entries = [];
|
|
441
310
|
this.currentOffset = 0;
|
|
442
311
|
this.ended = false;
|
|
@@ -446,12 +315,10 @@ export class StreamingZip {
|
|
|
446
315
|
this.fileQueueIndex = 0;
|
|
447
316
|
this.activeFile = null;
|
|
448
317
|
this.callback = callback;
|
|
449
|
-
// Avoid per-instance TextEncoder allocations.
|
|
450
|
-
this.zipComment = options?.comment ? encodeUtf8(options.comment) : new Uint8Array(0);
|
|
451
318
|
}
|
|
452
319
|
add(file) {
|
|
453
320
|
if (this.ended) {
|
|
454
|
-
throw new Error("Cannot add files after calling end()
|
|
321
|
+
throw new Error("Cannot add files after calling end()");
|
|
455
322
|
}
|
|
456
323
|
this.fileQueue.push(file);
|
|
457
324
|
// If no active file, process this one
|
|
@@ -474,18 +341,7 @@ export class StreamingZip {
|
|
|
474
341
|
const file = this.fileQueue[this.fileQueueIndex++];
|
|
475
342
|
this.activeFile = file;
|
|
476
343
|
const startOffset = this.currentOffset;
|
|
477
|
-
const empty = new Uint8Array(0);
|
|
478
|
-
file.onerror = (err) => {
|
|
479
|
-
if (this.ended) {
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
this.ended = true;
|
|
483
|
-
this.callback(err, empty, true);
|
|
484
|
-
};
|
|
485
344
|
file.ondata = (data, final) => {
|
|
486
|
-
if (this.ended) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
345
|
this.currentOffset += data.length;
|
|
490
346
|
this.callback(null, data, false);
|
|
491
347
|
if (final) {
|
|
@@ -511,7 +367,7 @@ export class StreamingZip {
|
|
|
511
367
|
const header = buildCentralDirectoryHeader({
|
|
512
368
|
fileName: entry.name,
|
|
513
369
|
extraField: entry.extraField,
|
|
514
|
-
comment:
|
|
370
|
+
comment: empty,
|
|
515
371
|
flags: entry.flags,
|
|
516
372
|
compressionMethod: entry.compressionMethod,
|
|
517
373
|
dosTime: entry.dosTime,
|
|
@@ -530,7 +386,7 @@ export class StreamingZip {
|
|
|
530
386
|
entryCount: this.entries.length,
|
|
531
387
|
centralDirSize,
|
|
532
388
|
centralDirOffset,
|
|
533
|
-
comment:
|
|
389
|
+
comment: empty
|
|
534
390
|
});
|
|
535
391
|
this.callback(null, eocd, true);
|
|
536
392
|
}
|
|
@@ -45,18 +45,21 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
|
|
|
45
45
|
}
|
|
46
46
|
// Fast paths for small patterns (very common in ZIP parsing: 2/3/4-byte signatures).
|
|
47
47
|
if (patLen === 1) {
|
|
48
|
-
|
|
48
|
+
const p0 = pattern[0];
|
|
49
|
+
for (let i = start; i < bufLen; i++) {
|
|
50
|
+
if (buffer[i] === p0) {
|
|
51
|
+
return i;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return -1;
|
|
49
55
|
}
|
|
50
56
|
if (patLen === 2) {
|
|
51
57
|
const p0 = pattern[0];
|
|
52
58
|
const p1 = pattern[1];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
while (i !== -1 && i <= last) {
|
|
56
|
-
if (buffer[i + 1] === p1) {
|
|
59
|
+
for (let i = start; i <= bufLen - 2; i++) {
|
|
60
|
+
if (buffer[i] === p0 && buffer[i + 1] === p1) {
|
|
57
61
|
return i;
|
|
58
62
|
}
|
|
59
|
-
i = buffer.indexOf(p0, i + 1);
|
|
60
63
|
}
|
|
61
64
|
return -1;
|
|
62
65
|
}
|
|
@@ -64,13 +67,10 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
|
|
|
64
67
|
const p0 = pattern[0];
|
|
65
68
|
const p1 = pattern[1];
|
|
66
69
|
const p2 = pattern[2];
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
while (i !== -1 && i <= last) {
|
|
70
|
-
if (buffer[i + 1] === p1 && buffer[i + 2] === p2) {
|
|
70
|
+
for (let i = start; i <= bufLen - 3; i++) {
|
|
71
|
+
if (buffer[i] === p0 && buffer[i + 1] === p1 && buffer[i + 2] === p2) {
|
|
71
72
|
return i;
|
|
72
73
|
}
|
|
73
|
-
i = buffer.indexOf(p0, i + 1);
|
|
74
74
|
}
|
|
75
75
|
return -1;
|
|
76
76
|
}
|
|
@@ -79,13 +79,13 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
|
|
|
79
79
|
const p1 = pattern[1];
|
|
80
80
|
const p2 = pattern[2];
|
|
81
81
|
const p3 = pattern[3];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
for (let i = start; i <= bufLen - 4; i++) {
|
|
83
|
+
if (buffer[i] === p0 &&
|
|
84
|
+
buffer[i + 1] === p1 &&
|
|
85
|
+
buffer[i + 2] === p2 &&
|
|
86
|
+
buffer[i + 3] === p3) {
|
|
86
87
|
return i;
|
|
87
88
|
}
|
|
88
|
-
i = buffer.indexOf(p0, i + 1);
|
|
89
89
|
}
|
|
90
90
|
return -1;
|
|
91
91
|
}
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read unsigned little-endian integer from Uint8Array
|
|
3
|
+
*/
|
|
4
|
+
function readUIntLE(buffer, offset, size) {
|
|
5
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
6
|
+
switch (size) {
|
|
7
|
+
case 1:
|
|
8
|
+
return view.getUint8(offset);
|
|
9
|
+
case 2:
|
|
10
|
+
return view.getUint16(offset, true);
|
|
11
|
+
case 4:
|
|
12
|
+
return view.getUint32(offset, true);
|
|
13
|
+
case 8: {
|
|
14
|
+
// Read as BigUint64 and convert to Number
|
|
15
|
+
const low = view.getUint32(offset, true);
|
|
16
|
+
const high = view.getUint32(offset + 4, true);
|
|
17
|
+
return high * 0x100000000 + low;
|
|
18
|
+
}
|
|
19
|
+
default:
|
|
20
|
+
throw new Error("Unsupported UInt LE size!");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
1
23
|
/**
|
|
2
24
|
* Parses sequential unsigned little endian numbers from the head of the passed buffer according to
|
|
3
25
|
* the specified format passed. If the buffer is not large enough to satisfy the full format,
|
|
@@ -16,30 +38,10 @@
|
|
|
16
38
|
*/
|
|
17
39
|
export function parse(buffer, format) {
|
|
18
40
|
const result = {};
|
|
19
|
-
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
20
41
|
let offset = 0;
|
|
21
42
|
for (const [key, size] of format) {
|
|
22
43
|
if (buffer.length >= offset + size) {
|
|
23
|
-
|
|
24
|
-
case 1:
|
|
25
|
-
result[key] = view.getUint8(offset);
|
|
26
|
-
break;
|
|
27
|
-
case 2:
|
|
28
|
-
result[key] = view.getUint16(offset, true);
|
|
29
|
-
break;
|
|
30
|
-
case 4:
|
|
31
|
-
result[key] = view.getUint32(offset, true);
|
|
32
|
-
break;
|
|
33
|
-
case 8: {
|
|
34
|
-
// Keep behavior (Number) while avoiding BigInt costs.
|
|
35
|
-
const low = view.getUint32(offset, true);
|
|
36
|
-
const high = view.getUint32(offset + 4, true);
|
|
37
|
-
result[key] = high * 0x100000000 + low;
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
default:
|
|
41
|
-
throw new Error("Unsupported UInt LE size!");
|
|
42
|
-
}
|
|
44
|
+
result[key] = readUIntLE(buffer, offset, size);
|
|
43
45
|
}
|
|
44
46
|
else {
|
|
45
47
|
result[key] = null;
|
|
@@ -1,65 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
function clampUint32(value) {
|
|
3
|
-
if (!Number.isFinite(value)) {
|
|
4
|
-
return 0;
|
|
5
|
-
}
|
|
6
|
-
if (value <= 0) {
|
|
7
|
-
return 0;
|
|
8
|
-
}
|
|
9
|
-
// 0xFFFFFFFF fits JS safe integer.
|
|
10
|
-
if (value >= 0xffffffff) {
|
|
11
|
-
return 0xffffffff;
|
|
12
|
-
}
|
|
13
|
-
return value >>> 0;
|
|
14
|
-
}
|
|
15
|
-
function unixSecondsFromDate(date) {
|
|
16
|
-
return clampUint32(Math.floor(date.getTime() / 1000));
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Parse Info-ZIP "Extended Timestamp" extra field (0x5455) and return mtime.
|
|
20
|
-
* Returns Unix seconds (UTC) if present.
|
|
21
|
-
*/
|
|
22
|
-
function parseExtendedTimestampMtimeUnixSeconds(extraField) {
|
|
23
|
-
const view = new DataView(extraField.buffer, extraField.byteOffset, extraField.byteLength);
|
|
24
|
-
let offset = 0;
|
|
25
|
-
while (offset + 4 <= extraField.length) {
|
|
26
|
-
const headerId = view.getUint16(offset, true);
|
|
27
|
-
const dataSize = view.getUint16(offset + 2, true);
|
|
28
|
-
const dataStart = offset + 4;
|
|
29
|
-
const dataEnd = dataStart + dataSize;
|
|
30
|
-
if (dataEnd > extraField.length) {
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
if (headerId === EXTENDED_TIMESTAMP_ID && dataSize >= 1) {
|
|
34
|
-
const flags = extraField[dataStart];
|
|
35
|
-
if ((flags & 0x01) !== 0 && dataSize >= 5) {
|
|
36
|
-
// mtime is 4 bytes right after flags.
|
|
37
|
-
return view.getUint32(dataStart + 1, true) >>> 0;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
offset = dataEnd;
|
|
41
|
-
}
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Build Info-ZIP "Extended Timestamp" extra field (0x5455).
|
|
46
|
-
* We write only mtime (UTC, Unix seconds) to minimize size.
|
|
47
|
-
*/
|
|
48
|
-
function buildExtendedTimestampExtraFieldFromUnixSeconds(unixSeconds) {
|
|
49
|
-
const ts = clampUint32(unixSeconds);
|
|
50
|
-
// flags(1) + mtime(4)
|
|
51
|
-
const payloadSize = 5;
|
|
52
|
-
const out = new Uint8Array(4 + payloadSize);
|
|
53
|
-
const view = new DataView(out.buffer);
|
|
54
|
-
view.setUint16(0, EXTENDED_TIMESTAMP_ID, true);
|
|
55
|
-
view.setUint16(2, payloadSize, true);
|
|
56
|
-
out[4] = 0x01; // mtime present
|
|
57
|
-
view.setUint32(5, ts, true);
|
|
58
|
-
return out;
|
|
59
|
-
}
|
|
60
|
-
function buildExtendedTimestampExtraFieldFromDate(date) {
|
|
61
|
-
return buildExtendedTimestampExtraFieldFromUnixSeconds(unixSecondsFromDate(date));
|
|
62
|
-
}
|
|
1
|
+
import { buildExtendedTimestampExtraFieldFromDate, parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
|
|
63
2
|
/**
|
|
64
3
|
* DOS date/time helpers for ZIP files.
|
|
65
4
|
*/
|
|
@@ -1,31 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ZIP extra field parsing helpers.
|
|
3
3
|
*
|
|
4
|
-
* Kept standalone so both streaming parser (`
|
|
4
|
+
* Kept standalone so both streaming parser (`parse.base.ts`) and buffer parser
|
|
5
5
|
* (`zip-parser.ts`) can share ZIP64 + Info-ZIP timestamp handling.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
function parseExtendedTimestampMtimeUnixSeconds(extraField) {
|
|
9
|
-
const view = new DataView(extraField.buffer, extraField.byteOffset, extraField.byteLength);
|
|
10
|
-
let offset = 0;
|
|
11
|
-
while (offset + 4 <= extraField.length) {
|
|
12
|
-
const headerId = view.getUint16(offset, true);
|
|
13
|
-
const dataSize = view.getUint16(offset + 2, true);
|
|
14
|
-
const dataStart = offset + 4;
|
|
15
|
-
const dataEnd = dataStart + dataSize;
|
|
16
|
-
if (dataEnd > extraField.length) {
|
|
17
|
-
break;
|
|
18
|
-
}
|
|
19
|
-
if (headerId === EXTENDED_TIMESTAMP_ID && dataSize >= 1) {
|
|
20
|
-
const flags = extraField[dataStart];
|
|
21
|
-
if ((flags & 0x01) !== 0 && dataSize >= 5) {
|
|
22
|
-
return view.getUint32(dataStart + 1, true) >>> 0;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
offset = dataEnd;
|
|
26
|
-
}
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
7
|
+
import { parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
|
|
29
8
|
function readUint64LE(view, offset) {
|
|
30
9
|
// Convert to Number via 2x Uint32 to avoid BigInt requirements.
|
|
31
10
|
const low = view.getUint32(offset, true);
|
|
@@ -64,9 +43,18 @@ export function parseZipExtraFields(extraField, vars) {
|
|
|
64
43
|
}
|
|
65
44
|
}
|
|
66
45
|
else if (signature === 0x5455) {
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
46
|
+
// Fast-path parse for Info-ZIP extended timestamp (mtime only).
|
|
47
|
+
if (partSize >= 1) {
|
|
48
|
+
const flags = extraField[dataStart];
|
|
49
|
+
if ((flags & 0x01) !== 0 && partSize >= 5) {
|
|
50
|
+
extra.mtimeUnixSeconds = view.getUint32(dataStart + 1, true) >>> 0;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const unixSeconds = parseExtendedTimestampMtimeUnixSeconds(extraField.subarray(offset, dataEnd));
|
|
54
|
+
if (unixSeconds !== undefined) {
|
|
55
|
+
extra.mtimeUnixSeconds = unixSeconds;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
70
58
|
}
|
|
71
59
|
}
|
|
72
60
|
offset = dataEnd;
|