@zip.js/zip.js 2.14.1 → 2.15.0
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/BENCHMARKS.md +19 -11
- package/deno.json +1 -1
- package/dist/zip-core-external.js +82 -41
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +82 -41
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +82 -41
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +82 -41
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +82 -41
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +84 -43
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +84 -43
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +84 -43
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +84 -43
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +84 -43
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +84 -43
- package/index-native.min.js +1 -1
- package/index.cjs +84 -43
- package/index.d.cts +20 -13
- package/index.d.ts +20 -13
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +35 -19
- package/lib/core/codec-worker.js +4 -2
- package/lib/core/streams/zip-entry-stream.js +18 -10
- package/lib/core/util/decode-text.js +15 -1
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-reader.js +12 -10
- package/lib/core/zlib-streams-inline.js +1 -1
- package/package.json +1 -1
package/dist/zip-fs-external.js
CHANGED
|
@@ -1900,8 +1900,8 @@ class DeflateStream extends TransformStream {
|
|
|
1900
1900
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
1901
1901
|
let readable = super.readable;
|
|
1902
1902
|
const codecStreams = format && getCodecStreams(format);
|
|
1903
|
-
const
|
|
1904
|
-
|
|
1903
|
+
const GzipCompressionStream = getGzipCompressionStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
|
|
1904
|
+
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
|
|
1905
1905
|
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
1906
1906
|
crc32Stream = new Crc32Stream();
|
|
1907
1907
|
readable = pipeThrough(readable, crc32Stream);
|
|
@@ -1911,7 +1911,7 @@ class DeflateStream extends TransformStream {
|
|
|
1911
1911
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.CompressionStream, format, { level, chunkSize, compressionMethod, uncompressedSize: inputSize }));
|
|
1912
1912
|
} else if (useGzipCrc32) {
|
|
1913
1913
|
gzipCrc32Stream = new GzipToRawDeflateStream();
|
|
1914
|
-
readable = pipeThroughBackpressured(readable, new
|
|
1914
|
+
readable = pipeThroughBackpressured(readable, new GzipCompressionStream(FORMAT_GZIP$1, { level, chunkSize }));
|
|
1915
1915
|
readable = pipeThrough(readable, gzipCrc32Stream);
|
|
1916
1916
|
} else {
|
|
1917
1917
|
try {
|
|
@@ -1985,8 +1985,7 @@ class GzipToRawDeflateStream extends TransformStream {
|
|
|
1985
1985
|
}
|
|
1986
1986
|
}
|
|
1987
1987
|
|
|
1988
|
-
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize) {
|
|
1989
|
-
const crc32 = new Crc32();
|
|
1988
|
+
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
|
|
1990
1989
|
let outputLength = 0;
|
|
1991
1990
|
let inputDone = false;
|
|
1992
1991
|
let watchdogTimeout;
|
|
@@ -2060,7 +2059,7 @@ class InflateStream extends TransformStream {
|
|
|
2060
2059
|
constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
|
|
2061
2060
|
super({});
|
|
2062
2061
|
const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
|
|
2063
|
-
let crc32Stream, decryptionStream;
|
|
2062
|
+
let crc32Stream, decryptionStream, gzipCrc32;
|
|
2064
2063
|
let readable = super.readable;
|
|
2065
2064
|
if (encrypted) {
|
|
2066
2065
|
if (zipCrypto) {
|
|
@@ -2087,19 +2086,20 @@ class InflateStream extends TransformStream {
|
|
|
2087
2086
|
} catch {
|
|
2088
2087
|
throw error;
|
|
2089
2088
|
}
|
|
2090
|
-
|
|
2089
|
+
gzipCrc32 = new Crc32();
|
|
2090
|
+
readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, gzipCrc32);
|
|
2091
2091
|
}
|
|
2092
2092
|
}
|
|
2093
2093
|
readable = mapInflateStreamError(readable);
|
|
2094
2094
|
}
|
|
2095
|
-
if (checkCrc32) {
|
|
2095
|
+
if (checkCrc32 && !gzipCrc32) {
|
|
2096
2096
|
crc32Stream = new Crc32Stream();
|
|
2097
2097
|
readable = pipeThrough(readable, crc32Stream);
|
|
2098
2098
|
}
|
|
2099
2099
|
setReadable(this, readable, () => {
|
|
2100
2100
|
if (checkCrc32) {
|
|
2101
|
-
const
|
|
2102
|
-
if (crc32 !=
|
|
2101
|
+
const computedCrc32 = gzipCrc32 ? gzipCrc32.get() >>> 0 : new DataView(crc32Stream.value.buffer).getUint32(0, false);
|
|
2102
|
+
if (crc32 != computedCrc32) {
|
|
2103
2103
|
throw new Error(ERR_INVALID_CRC32);
|
|
2104
2104
|
}
|
|
2105
2105
|
}
|
|
@@ -2155,6 +2155,14 @@ function createCodecStream(CodecStreamClass, format, options) {
|
|
|
2155
2155
|
return new CodecStreamClass(format, options);
|
|
2156
2156
|
}
|
|
2157
2157
|
|
|
2158
|
+
function getGzipCompressionStream(useCompressionStream, CompressionStreamNative, CompressionStreamFallback) {
|
|
2159
|
+
if (useCompressionStream && CompressionStreamNative) {
|
|
2160
|
+
return CompressionStreamNative;
|
|
2161
|
+
} else if (CompressionStreamFallback && CompressionStreamFallback.requiresModule) {
|
|
2162
|
+
return CompressionStreamFallback;
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2158
2166
|
function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
|
|
2159
2167
|
const Stream = useCompressionStream && CompressionStreamNative ?
|
|
2160
2168
|
CompressionStreamNative :
|
|
@@ -2527,10 +2535,12 @@ class CodecWorker {
|
|
|
2527
2535
|
workerData.terminated = true;
|
|
2528
2536
|
worker.terminate();
|
|
2529
2537
|
}
|
|
2530
|
-
terminateResolvers.forEach(resolve => resolve());
|
|
2531
2538
|
}
|
|
2532
2539
|
workerData.busy = false;
|
|
2533
|
-
onTaskFinished(workerData);
|
|
2540
|
+
const pendingTasks = onTaskFinished(workerData);
|
|
2541
|
+
if (terminateResolvers) {
|
|
2542
|
+
terminateResolvers.forEach(resolve => resolve(pendingTasks));
|
|
2543
|
+
}
|
|
2534
2544
|
}
|
|
2535
2545
|
}
|
|
2536
2546
|
});
|
|
@@ -3215,7 +3225,10 @@ async function runWorker(stream, workerOptions) {
|
|
|
3215
3225
|
|
|
3216
3226
|
function onTaskFinished(workerData) {
|
|
3217
3227
|
clearStarvationTimeout();
|
|
3218
|
-
if (
|
|
3228
|
+
if (workerData.terminated) {
|
|
3229
|
+
workerData.terminated = false;
|
|
3230
|
+
return runPendingRequestsInline();
|
|
3231
|
+
} else if (pendingRequests.length) {
|
|
3219
3232
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
3220
3233
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
3221
3234
|
armStarvationTimeout();
|
|
@@ -3253,12 +3266,26 @@ function onWorkerStarvation() {
|
|
|
3253
3266
|
starvationTimeout = null;
|
|
3254
3267
|
if (pendingRequests.length) {
|
|
3255
3268
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
3256
|
-
|
|
3257
|
-
resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
|
|
3269
|
+
resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), onInlineTaskFinished));
|
|
3258
3270
|
armStarvationTimeout();
|
|
3259
3271
|
}
|
|
3260
3272
|
}
|
|
3261
3273
|
|
|
3274
|
+
function runPendingRequestsInline() {
|
|
3275
|
+
const tasks = pendingRequests.splice(0).map(({ resolve, stream, workerOptions }) => new Promise(resolveTask => {
|
|
3276
|
+
resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), () => {
|
|
3277
|
+
onInlineTaskFinished();
|
|
3278
|
+
resolveTask();
|
|
3279
|
+
}));
|
|
3280
|
+
}));
|
|
3281
|
+
clearStarvationTimeout();
|
|
3282
|
+
return Promise.all(tasks);
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
function getInlineWorkerOptions(workerOptions) {
|
|
3286
|
+
return Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3262
3289
|
function onInlineTaskFinished() {
|
|
3263
3290
|
clearStarvationTimeout();
|
|
3264
3291
|
armStarvationTimeout();
|
|
@@ -3268,18 +3295,14 @@ function terminateWorker(workerData, workerOptions) {
|
|
|
3268
3295
|
const { config } = workerOptions;
|
|
3269
3296
|
const { terminateWorkerTimeout } = config;
|
|
3270
3297
|
if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
// ignored
|
|
3280
|
-
}
|
|
3281
|
-
}, terminateWorkerTimeout);
|
|
3282
|
-
}
|
|
3298
|
+
workerData.terminateTimeout = setTimeout(async () => {
|
|
3299
|
+
pool = pool.filter(data => data != workerData);
|
|
3300
|
+
try {
|
|
3301
|
+
await workerData.terminate();
|
|
3302
|
+
} catch {
|
|
3303
|
+
// ignored
|
|
3304
|
+
}
|
|
3305
|
+
}, terminateWorkerTimeout);
|
|
3283
3306
|
}
|
|
3284
3307
|
}
|
|
3285
3308
|
|
|
@@ -3292,10 +3315,13 @@ function clearTerminateTimeout(workerData) {
|
|
|
3292
3315
|
}
|
|
3293
3316
|
|
|
3294
3317
|
async function terminateWorkers() {
|
|
3295
|
-
await Promise.allSettled(
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3318
|
+
await Promise.allSettled([
|
|
3319
|
+
runPendingRequestsInline(),
|
|
3320
|
+
...pool.map(workerData => {
|
|
3321
|
+
clearTerminateTimeout(workerData);
|
|
3322
|
+
return workerData.terminate();
|
|
3323
|
+
})
|
|
3324
|
+
]);
|
|
3299
3325
|
resetWebWorkerSupport();
|
|
3300
3326
|
}
|
|
3301
3327
|
|
|
@@ -3370,6 +3396,19 @@ function decodeText(value, encoding) {
|
|
|
3370
3396
|
return decode(value, encoding, true);
|
|
3371
3397
|
}
|
|
3372
3398
|
|
|
3399
|
+
function isUTF8Text(value) {
|
|
3400
|
+
if (value.some(byte => byte > 0x7f)) {
|
|
3401
|
+
try {
|
|
3402
|
+
new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
3403
|
+
return true;
|
|
3404
|
+
} catch {
|
|
3405
|
+
return false;
|
|
3406
|
+
}
|
|
3407
|
+
} else {
|
|
3408
|
+
return false;
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3373
3412
|
function decodeTextRemovingBOM(value, encoding) {
|
|
3374
3413
|
return decode(value, encoding, false);
|
|
3375
3414
|
}
|
|
@@ -4679,6 +4718,7 @@ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched loca
|
|
|
4679
4718
|
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
|
|
4680
4719
|
const MAX_KNOWN_VERSION = 63;
|
|
4681
4720
|
const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
|
|
4721
|
+
const PARENT_DIRECTORY_REGEXP = /(^|[\\/])\.\.([\\/]|$)/;
|
|
4682
4722
|
const CHARSET_UTF8 = "utf-8";
|
|
4683
4723
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4684
4724
|
const CHARSET_CP437 = "cp437";
|
|
@@ -4931,12 +4971,13 @@ class ZipReader {
|
|
|
4931
4971
|
const versionMadeBy = getUint16$1(directoryView, offset + 4);
|
|
4932
4972
|
const msDosCompatible = versionMadeBy >> 8 == 0;
|
|
4933
4973
|
const unixCompatible = versionMadeBy >> 8 == 3;
|
|
4934
|
-
const rawFilename = directoryArray.subarray(filenameOffset, extraFieldOffset);
|
|
4935
4974
|
const commentLength = getUint16$1(directoryView, offset + 32);
|
|
4936
4975
|
const endOffset = commentOffset + commentLength;
|
|
4937
|
-
const
|
|
4938
|
-
const
|
|
4939
|
-
const
|
|
4976
|
+
const rawEntryData = new Uint8Array(directoryArray.subarray(filenameOffset, endOffset));
|
|
4977
|
+
const rawFilename = rawEntryData.subarray(0, fileEntry.filenameLength);
|
|
4978
|
+
const rawComment = rawEntryData.subarray(fileEntry.filenameLength + fileEntry.extraFieldLength);
|
|
4979
|
+
const filenameUTF8 = languageEncodingFlag || (!filenameEncoding && isUTF8Text(rawFilename));
|
|
4980
|
+
const commentUTF8 = languageEncodingFlag || (!commentEncoding && isUTF8Text(rawComment));
|
|
4940
4981
|
const externalFileAttributes = getUint32$1(directoryView, offset + 38);
|
|
4941
4982
|
const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
|
|
4942
4983
|
const msdosAttributes = {
|
|
@@ -4987,7 +5028,7 @@ class ZipReader {
|
|
|
4987
5028
|
rawFilename,
|
|
4988
5029
|
filenameUTF8,
|
|
4989
5030
|
commentUTF8,
|
|
4990
|
-
rawExtraField:
|
|
5031
|
+
rawExtraField: rawEntryData.subarray(fileEntry.filenameLength, fileEntry.filenameLength + fileEntry.extraFieldLength),
|
|
4991
5032
|
rawComment,
|
|
4992
5033
|
filename,
|
|
4993
5034
|
comment
|
|
@@ -5495,7 +5536,7 @@ function readDigitalSignature(signatureRecordArray) {
|
|
|
5495
5536
|
if (getUint32$1(signatureRecordView, 0) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
|
|
5496
5537
|
const signatureDataLength = getUint16$1(signatureRecordView, 4);
|
|
5497
5538
|
if (6 + signatureDataLength <= signatureRecordArray.length) {
|
|
5498
|
-
return signatureRecordArray.subarray(6, 6 + signatureDataLength);
|
|
5539
|
+
return new Uint8Array(signatureRecordArray.subarray(6, 6 + signatureDataLength));
|
|
5499
5540
|
}
|
|
5500
5541
|
}
|
|
5501
5542
|
}
|
|
@@ -6018,10 +6059,10 @@ function isUnsafeFilename(filename, filenameValidation) {
|
|
|
6018
6059
|
if (pathParts.length > 1 && pathParts[pathParts.length - 1] === "") {
|
|
6019
6060
|
pathParts.pop();
|
|
6020
6061
|
}
|
|
6021
|
-
if (
|
|
6062
|
+
if (PARENT_DIRECTORY_REGEXP.test(filename) || filename.startsWith("/") || filename.startsWith("\\") || DRIVE_LETTER_REGEXP.test(filename)) {
|
|
6022
6063
|
return true;
|
|
6023
6064
|
}
|
|
6024
|
-
return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes(""));
|
|
6065
|
+
return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes("") || filename.includes("\0"));
|
|
6025
6066
|
}
|
|
6026
6067
|
|
|
6027
6068
|
function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
@@ -6107,7 +6148,7 @@ async function* scanEndOfCentralDirectory(reader, scanLength) {
|
|
|
6107
6148
|
}
|
|
6108
6149
|
|
|
6109
6150
|
function getEndOfCentralDirectoryInfo(scanArray, indexByte, offset) {
|
|
6110
|
-
return { offset, buffer: scanArray.
|
|
6151
|
+
return { offset, buffer: new Uint8Array(scanArray.subarray(indexByte, indexByte + END_OF_CENTRAL_DIR_LENGTH)).buffer };
|
|
6111
6152
|
}
|
|
6112
6153
|
|
|
6113
6154
|
async function getCentralDirectoryReachability(reader, view, anchoredOffset, indexByte, offset, size, remoteProbeBudget) {
|
|
@@ -8852,7 +8893,7 @@ function formatSupported(StreamClass, format) {
|
|
|
8852
8893
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8853
8894
|
*/
|
|
8854
8895
|
|
|
8855
|
-
const VERSION = "2.
|
|
8896
|
+
const VERSION = "2.15.0";
|
|
8856
8897
|
|
|
8857
8898
|
/*
|
|
8858
8899
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|