@zip.js/zip.js 2.14.1 → 2.16.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 +21 -11
- package/deno.json +1 -1
- package/dist/zip-core-external.js +217 -98
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +217 -98
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +217 -98
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +217 -98
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +217 -98
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +219 -100
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +219 -100
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +219 -100
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +219 -100
- 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 +219 -100
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +219 -100
- package/index-native.min.js +1 -1
- package/index.cjs +219 -100
- package/index.d.cts +46 -13
- package/index.d.ts +46 -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/io.js +3 -2
- package/lib/core/streams/zip-entry-stream.js +151 -66
- 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
|
@@ -1889,7 +1889,6 @@ const FORMAT_GZIP$1 = "gzip";
|
|
|
1889
1889
|
const GZIP_HEADER_LENGTH = 10;
|
|
1890
1890
|
const GZIP_TRAILER_LENGTH = 8;
|
|
1891
1891
|
const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
|
|
1892
|
-
const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
|
|
1893
1892
|
|
|
1894
1893
|
class DeflateStream extends TransformStream {
|
|
1895
1894
|
|
|
@@ -1900,8 +1899,8 @@ class DeflateStream extends TransformStream {
|
|
|
1900
1899
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
1901
1900
|
let readable = super.readable;
|
|
1902
1901
|
const codecStreams = format && getCodecStreams(format);
|
|
1903
|
-
const
|
|
1904
|
-
|
|
1902
|
+
const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
|
|
1903
|
+
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
|
|
1905
1904
|
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
1906
1905
|
crc32Stream = new Crc32Stream();
|
|
1907
1906
|
readable = pipeThrough(readable, crc32Stream);
|
|
@@ -1911,12 +1910,15 @@ class DeflateStream extends TransformStream {
|
|
|
1911
1910
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.CompressionStream, format, { level, chunkSize, compressionMethod, uncompressedSize: inputSize }));
|
|
1912
1911
|
} else if (useGzipCrc32) {
|
|
1913
1912
|
gzipCrc32Stream = new GzipToRawDeflateStream();
|
|
1914
|
-
readable = pipeThroughBackpressured(readable, new
|
|
1913
|
+
readable = pipeThroughBackpressured(readable, new GzipCompressionStream(FORMAT_GZIP$1, { level, chunkSize }));
|
|
1915
1914
|
readable = pipeThrough(readable, gzipCrc32Stream);
|
|
1916
1915
|
} else {
|
|
1917
1916
|
try {
|
|
1918
1917
|
readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
|
|
1919
1918
|
} catch (error) {
|
|
1919
|
+
if (!useCompressionStream && CompressionStreamFallback) {
|
|
1920
|
+
throw error;
|
|
1921
|
+
}
|
|
1920
1922
|
let gzipStream;
|
|
1921
1923
|
try {
|
|
1922
1924
|
gzipStream = new CompressionStream(FORMAT_GZIP$1);
|
|
@@ -1985,82 +1987,144 @@ class GzipToRawDeflateStream extends TransformStream {
|
|
|
1985
1987
|
}
|
|
1986
1988
|
}
|
|
1987
1989
|
|
|
1988
|
-
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize) {
|
|
1989
|
-
const
|
|
1990
|
+
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
|
|
1991
|
+
const writer = gzipStream.writable.getWriter();
|
|
1992
|
+
const reader = gzipStream.readable.getReader();
|
|
1993
|
+
const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
|
|
1990
1994
|
let outputLength = 0;
|
|
1991
1995
|
let inputDone = false;
|
|
1992
|
-
let
|
|
1996
|
+
let trailerWritten = false;
|
|
1997
|
+
let idleCheckArmed = false;
|
|
1998
|
+
let readCount = 0;
|
|
1999
|
+
let readPending = false;
|
|
1993
2000
|
let resolveTrailerReady, rejectTrailerReady;
|
|
1994
2001
|
const trailerReady = new Promise((resolve, reject) => {
|
|
1995
2002
|
resolveTrailerReady = resolve;
|
|
1996
2003
|
rejectTrailerReady = reject;
|
|
1997
2004
|
});
|
|
1998
2005
|
trailerReady.catch(() => { });
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2006
|
+
pump();
|
|
2007
|
+
return new ReadableStream({
|
|
2008
|
+
async pull(controller) {
|
|
2009
|
+
let result;
|
|
2010
|
+
try {
|
|
2011
|
+
result = await read();
|
|
2012
|
+
} catch (error) {
|
|
2013
|
+
throw trailerWritten ? getTrailerError(error) : error;
|
|
2014
|
+
}
|
|
2015
|
+
const { value, done } = result;
|
|
2016
|
+
if (done) {
|
|
2017
|
+
controller.close();
|
|
2018
|
+
} else {
|
|
2019
|
+
outputLength += value.length;
|
|
2020
|
+
if (outputLength > outputSize) {
|
|
2021
|
+
const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2022
|
+
rejectTrailerReady(error);
|
|
2023
|
+
await cancel(reader, error);
|
|
2024
|
+
throw error;
|
|
2025
|
+
}
|
|
2026
|
+
if (outputCrc32) {
|
|
2027
|
+
outputCrc32.append(value);
|
|
2028
|
+
}
|
|
2029
|
+
controller.enqueue(value);
|
|
2030
|
+
}
|
|
2031
|
+
},
|
|
2032
|
+
cancel(reason) {
|
|
2033
|
+
rejectTrailerReady(reason);
|
|
2034
|
+
return reader.cancel(reason);
|
|
2035
|
+
}
|
|
2036
|
+
});
|
|
2037
|
+
|
|
2038
|
+
async function pump() {
|
|
2039
|
+
const inputReader = readable.getReader();
|
|
2040
|
+
try {
|
|
2004
2041
|
const header = new Uint8Array(GZIP_HEADER_LENGTH);
|
|
2005
2042
|
header.set(GZIP_HEADER_BYTES);
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2043
|
+
await writer.write(header);
|
|
2044
|
+
for (; ;) {
|
|
2045
|
+
await writer.ready;
|
|
2046
|
+
const { value, done } = await inputReader.read();
|
|
2047
|
+
if (done) {
|
|
2048
|
+
break;
|
|
2049
|
+
}
|
|
2050
|
+
await writer.write(value);
|
|
2051
|
+
}
|
|
2012
2052
|
inputDone = true;
|
|
2013
|
-
|
|
2014
|
-
|
|
2053
|
+
if (outputCrc32) {
|
|
2054
|
+
if (readPending) {
|
|
2055
|
+
armIdleCheck();
|
|
2056
|
+
}
|
|
2015
2057
|
await trailerReady;
|
|
2016
|
-
} finally {
|
|
2017
|
-
stopWatchdog();
|
|
2018
2058
|
}
|
|
2019
2059
|
const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
|
|
2020
2060
|
const dataView = getDataView(trailer);
|
|
2021
|
-
dataView.setUint32(0,
|
|
2061
|
+
dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
|
|
2022
2062
|
dataView.setUint32(4, outputSize, true);
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2063
|
+
trailerWritten = true;
|
|
2064
|
+
await writer.write(trailer);
|
|
2065
|
+
await writer.close();
|
|
2066
|
+
} catch (error) {
|
|
2067
|
+
await abort(writer, error);
|
|
2068
|
+
await cancel(inputReader, error);
|
|
2027
2069
|
}
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
}
|
|
2038
|
-
controller.enqueue(chunk);
|
|
2039
|
-
},
|
|
2040
|
-
cancel(reason) {
|
|
2041
|
-
rejectTrailerReady(reason);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
function read() {
|
|
2073
|
+
readCount++;
|
|
2074
|
+
readPending = true;
|
|
2075
|
+
const result = reader.read();
|
|
2076
|
+
result.then(onReadSettled, onReadSettled);
|
|
2077
|
+
if (inputDone && outputCrc32) {
|
|
2078
|
+
armIdleCheck();
|
|
2042
2079
|
}
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
readable = pipeThroughBackpressured(readable, gzipStream);
|
|
2046
|
-
return pipeThrough(readable, outputStream);
|
|
2080
|
+
return result;
|
|
2081
|
+
}
|
|
2047
2082
|
|
|
2048
|
-
function
|
|
2049
|
-
|
|
2050
|
-
watchdogTimeout = setTimeout(() => rejectTrailerReady(new Error(ERR_INVALID_UNCOMPRESSED_SIZE)), GZIP_OUTPUT_STALL_TIMEOUT);
|
|
2083
|
+
function onReadSettled() {
|
|
2084
|
+
readPending = false;
|
|
2051
2085
|
}
|
|
2052
2086
|
|
|
2053
|
-
function
|
|
2054
|
-
|
|
2087
|
+
async function armIdleCheck() {
|
|
2088
|
+
if (!idleCheckArmed) {
|
|
2089
|
+
idleCheckArmed = true;
|
|
2090
|
+
const count = readCount;
|
|
2091
|
+
await nextTask();
|
|
2092
|
+
idleCheckArmed = false;
|
|
2093
|
+
if (readPending) {
|
|
2094
|
+
if (readCount == count) {
|
|
2095
|
+
resolveTrailerReady();
|
|
2096
|
+
} else {
|
|
2097
|
+
armIdleCheck();
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
function getTrailerError(error) {
|
|
2104
|
+
const trailerError = new Error(outputLength == outputSize ? ERR_INVALID_CRC32 : ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2105
|
+
trailerError.cause = error;
|
|
2106
|
+
return trailerError;
|
|
2055
2107
|
}
|
|
2056
2108
|
}
|
|
2057
2109
|
|
|
2110
|
+
function nextTask() {
|
|
2111
|
+
return new Promise(resolve => {
|
|
2112
|
+
const { port1, port2 } = new MessageChannel();
|
|
2113
|
+
port2.onmessage = () => {
|
|
2114
|
+
port1.close();
|
|
2115
|
+
port2.close();
|
|
2116
|
+
resolve();
|
|
2117
|
+
};
|
|
2118
|
+
port1.postMessage(UNDEFINED_VALUE);
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2058
2122
|
class InflateStream extends TransformStream {
|
|
2059
2123
|
|
|
2060
2124
|
constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
|
|
2061
2125
|
super({});
|
|
2062
2126
|
const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
|
|
2063
|
-
let crc32Stream, decryptionStream;
|
|
2127
|
+
let crc32Stream, decryptionStream, gzipCrc32;
|
|
2064
2128
|
let readable = super.readable;
|
|
2065
2129
|
if (encrypted) {
|
|
2066
2130
|
if (zipCrypto) {
|
|
@@ -2075,31 +2139,44 @@ class InflateStream extends TransformStream {
|
|
|
2075
2139
|
if (codecStreams) {
|
|
2076
2140
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
|
|
2077
2141
|
} else {
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
if (deflate64 || outputSize === UNDEFINED_VALUE) {
|
|
2082
|
-
throw error;
|
|
2083
|
-
}
|
|
2084
|
-
let gzipStream;
|
|
2142
|
+
let gzipStream;
|
|
2143
|
+
const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
|
|
2144
|
+
if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
|
|
2085
2145
|
try {
|
|
2086
|
-
gzipStream = new
|
|
2146
|
+
gzipStream = new GzipDecompressionStream(FORMAT_GZIP$1, { chunkSize });
|
|
2087
2147
|
} catch {
|
|
2088
|
-
|
|
2148
|
+
gzipStream = UNDEFINED_VALUE;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
if (!gzipStream) {
|
|
2152
|
+
try {
|
|
2153
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
|
|
2154
|
+
} catch (error) {
|
|
2155
|
+
if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
|
|
2156
|
+
throw error;
|
|
2157
|
+
}
|
|
2158
|
+
try {
|
|
2159
|
+
gzipStream = new DecompressionStream(FORMAT_GZIP$1);
|
|
2160
|
+
} catch {
|
|
2161
|
+
throw error;
|
|
2162
|
+
}
|
|
2089
2163
|
}
|
|
2090
|
-
|
|
2164
|
+
}
|
|
2165
|
+
if (gzipStream) {
|
|
2166
|
+
gzipCrc32 = true;
|
|
2167
|
+
readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32);
|
|
2091
2168
|
}
|
|
2092
2169
|
}
|
|
2093
2170
|
readable = mapInflateStreamError(readable);
|
|
2094
2171
|
}
|
|
2095
|
-
if (checkCrc32) {
|
|
2172
|
+
if (checkCrc32 && !gzipCrc32) {
|
|
2096
2173
|
crc32Stream = new Crc32Stream();
|
|
2097
2174
|
readable = pipeThrough(readable, crc32Stream);
|
|
2098
2175
|
}
|
|
2099
2176
|
setReadable(this, readable, () => {
|
|
2100
|
-
if (
|
|
2101
|
-
const
|
|
2102
|
-
if (crc32 !=
|
|
2177
|
+
if (crc32Stream) {
|
|
2178
|
+
const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
|
|
2179
|
+
if (crc32 != computedCrc32) {
|
|
2103
2180
|
throw new Error(ERR_INVALID_CRC32);
|
|
2104
2181
|
}
|
|
2105
2182
|
}
|
|
@@ -2155,6 +2232,14 @@ function createCodecStream(CodecStreamClass, format, options) {
|
|
|
2155
2232
|
return new CodecStreamClass(format, options);
|
|
2156
2233
|
}
|
|
2157
2234
|
|
|
2235
|
+
function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
|
|
2236
|
+
if (useCompressionStream && CodecStreamNative) {
|
|
2237
|
+
return CodecStreamNative;
|
|
2238
|
+
} else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
|
|
2239
|
+
return CodecStreamFallback;
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2158
2243
|
function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
|
|
2159
2244
|
const Stream = useCompressionStream && CompressionStreamNative ?
|
|
2160
2245
|
CompressionStreamNative :
|
|
@@ -2527,10 +2612,12 @@ class CodecWorker {
|
|
|
2527
2612
|
workerData.terminated = true;
|
|
2528
2613
|
worker.terminate();
|
|
2529
2614
|
}
|
|
2530
|
-
terminateResolvers.forEach(resolve => resolve());
|
|
2531
2615
|
}
|
|
2532
2616
|
workerData.busy = false;
|
|
2533
|
-
onTaskFinished(workerData);
|
|
2617
|
+
const pendingTasks = onTaskFinished(workerData);
|
|
2618
|
+
if (terminateResolvers) {
|
|
2619
|
+
terminateResolvers.forEach(resolve => resolve(pendingTasks));
|
|
2620
|
+
}
|
|
2534
2621
|
}
|
|
2535
2622
|
}
|
|
2536
2623
|
});
|
|
@@ -3215,7 +3302,10 @@ async function runWorker(stream, workerOptions) {
|
|
|
3215
3302
|
|
|
3216
3303
|
function onTaskFinished(workerData) {
|
|
3217
3304
|
clearStarvationTimeout();
|
|
3218
|
-
if (
|
|
3305
|
+
if (workerData.terminated) {
|
|
3306
|
+
workerData.terminated = false;
|
|
3307
|
+
return runPendingRequestsInline();
|
|
3308
|
+
} else if (pendingRequests.length) {
|
|
3219
3309
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
3220
3310
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
3221
3311
|
armStarvationTimeout();
|
|
@@ -3253,12 +3343,26 @@ function onWorkerStarvation() {
|
|
|
3253
3343
|
starvationTimeout = null;
|
|
3254
3344
|
if (pendingRequests.length) {
|
|
3255
3345
|
const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
|
|
3256
|
-
|
|
3257
|
-
resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
|
|
3346
|
+
resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), onInlineTaskFinished));
|
|
3258
3347
|
armStarvationTimeout();
|
|
3259
3348
|
}
|
|
3260
3349
|
}
|
|
3261
3350
|
|
|
3351
|
+
function runPendingRequestsInline() {
|
|
3352
|
+
const tasks = pendingRequests.splice(0).map(({ resolve, stream, workerOptions }) => new Promise(resolveTask => {
|
|
3353
|
+
resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), () => {
|
|
3354
|
+
onInlineTaskFinished();
|
|
3355
|
+
resolveTask();
|
|
3356
|
+
}));
|
|
3357
|
+
}));
|
|
3358
|
+
clearStarvationTimeout();
|
|
3359
|
+
return Promise.all(tasks);
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
function getInlineWorkerOptions(workerOptions) {
|
|
3363
|
+
return Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3262
3366
|
function onInlineTaskFinished() {
|
|
3263
3367
|
clearStarvationTimeout();
|
|
3264
3368
|
armStarvationTimeout();
|
|
@@ -3268,18 +3372,14 @@ function terminateWorker(workerData, workerOptions) {
|
|
|
3268
3372
|
const { config } = workerOptions;
|
|
3269
3373
|
const { terminateWorkerTimeout } = config;
|
|
3270
3374
|
if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
// ignored
|
|
3280
|
-
}
|
|
3281
|
-
}, terminateWorkerTimeout);
|
|
3282
|
-
}
|
|
3375
|
+
workerData.terminateTimeout = setTimeout(async () => {
|
|
3376
|
+
pool = pool.filter(data => data != workerData);
|
|
3377
|
+
try {
|
|
3378
|
+
await workerData.terminate();
|
|
3379
|
+
} catch {
|
|
3380
|
+
// ignored
|
|
3381
|
+
}
|
|
3382
|
+
}, terminateWorkerTimeout);
|
|
3283
3383
|
}
|
|
3284
3384
|
}
|
|
3285
3385
|
|
|
@@ -3292,10 +3392,13 @@ function clearTerminateTimeout(workerData) {
|
|
|
3292
3392
|
}
|
|
3293
3393
|
|
|
3294
3394
|
async function terminateWorkers() {
|
|
3295
|
-
await Promise.allSettled(
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3395
|
+
await Promise.allSettled([
|
|
3396
|
+
runPendingRequestsInline(),
|
|
3397
|
+
...pool.map(workerData => {
|
|
3398
|
+
clearTerminateTimeout(workerData);
|
|
3399
|
+
return workerData.terminate();
|
|
3400
|
+
})
|
|
3401
|
+
]);
|
|
3299
3402
|
resetWebWorkerSupport();
|
|
3300
3403
|
}
|
|
3301
3404
|
|
|
@@ -3370,6 +3473,19 @@ function decodeText(value, encoding) {
|
|
|
3370
3473
|
return decode(value, encoding, true);
|
|
3371
3474
|
}
|
|
3372
3475
|
|
|
3476
|
+
function isUTF8Text(value) {
|
|
3477
|
+
if (value.some(byte => byte > 0x7f)) {
|
|
3478
|
+
try {
|
|
3479
|
+
new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
3480
|
+
return true;
|
|
3481
|
+
} catch {
|
|
3482
|
+
return false;
|
|
3483
|
+
}
|
|
3484
|
+
} else {
|
|
3485
|
+
return false;
|
|
3486
|
+
}
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3373
3489
|
function decodeTextRemovingBOM(value, encoding) {
|
|
3374
3490
|
return decode(value, encoding, false);
|
|
3375
3491
|
}
|
|
@@ -3722,10 +3838,11 @@ class FetchReader extends Reader {
|
|
|
3722
3838
|
|
|
3723
3839
|
createReadable(options) {
|
|
3724
3840
|
const reader = this;
|
|
3725
|
-
const { useRangeHeader, forceRangeRequests, size } = reader;
|
|
3841
|
+
const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
|
|
3726
3842
|
if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
|
|
3727
3843
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
3728
|
-
|
|
3844
|
+
const cached = eocdCache && offset >= size - eocdCache.length;
|
|
3845
|
+
if (readSize > 0 && offset < size && !cached) {
|
|
3729
3846
|
return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
|
|
3730
3847
|
}
|
|
3731
3848
|
}
|
|
@@ -4679,6 +4796,7 @@ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched loca
|
|
|
4679
4796
|
const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
|
|
4680
4797
|
const MAX_KNOWN_VERSION = 63;
|
|
4681
4798
|
const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
|
|
4799
|
+
const PARENT_DIRECTORY_REGEXP = /(^|[\\/])\.\.([\\/]|$)/;
|
|
4682
4800
|
const CHARSET_UTF8 = "utf-8";
|
|
4683
4801
|
const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
|
|
4684
4802
|
const CHARSET_CP437 = "cp437";
|
|
@@ -4931,12 +5049,13 @@ class ZipReader {
|
|
|
4931
5049
|
const versionMadeBy = getUint16$1(directoryView, offset + 4);
|
|
4932
5050
|
const msDosCompatible = versionMadeBy >> 8 == 0;
|
|
4933
5051
|
const unixCompatible = versionMadeBy >> 8 == 3;
|
|
4934
|
-
const rawFilename = directoryArray.subarray(filenameOffset, extraFieldOffset);
|
|
4935
5052
|
const commentLength = getUint16$1(directoryView, offset + 32);
|
|
4936
5053
|
const endOffset = commentOffset + commentLength;
|
|
4937
|
-
const
|
|
4938
|
-
const
|
|
4939
|
-
const
|
|
5054
|
+
const rawEntryData = new Uint8Array(directoryArray.subarray(filenameOffset, endOffset));
|
|
5055
|
+
const rawFilename = rawEntryData.subarray(0, fileEntry.filenameLength);
|
|
5056
|
+
const rawComment = rawEntryData.subarray(fileEntry.filenameLength + fileEntry.extraFieldLength);
|
|
5057
|
+
const filenameUTF8 = languageEncodingFlag || (!filenameEncoding && isUTF8Text(rawFilename));
|
|
5058
|
+
const commentUTF8 = languageEncodingFlag || (!commentEncoding && isUTF8Text(rawComment));
|
|
4940
5059
|
const externalFileAttributes = getUint32$1(directoryView, offset + 38);
|
|
4941
5060
|
const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
|
|
4942
5061
|
const msdosAttributes = {
|
|
@@ -4987,7 +5106,7 @@ class ZipReader {
|
|
|
4987
5106
|
rawFilename,
|
|
4988
5107
|
filenameUTF8,
|
|
4989
5108
|
commentUTF8,
|
|
4990
|
-
rawExtraField:
|
|
5109
|
+
rawExtraField: rawEntryData.subarray(fileEntry.filenameLength, fileEntry.filenameLength + fileEntry.extraFieldLength),
|
|
4991
5110
|
rawComment,
|
|
4992
5111
|
filename,
|
|
4993
5112
|
comment
|
|
@@ -5495,7 +5614,7 @@ function readDigitalSignature(signatureRecordArray) {
|
|
|
5495
5614
|
if (getUint32$1(signatureRecordView, 0) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
|
|
5496
5615
|
const signatureDataLength = getUint16$1(signatureRecordView, 4);
|
|
5497
5616
|
if (6 + signatureDataLength <= signatureRecordArray.length) {
|
|
5498
|
-
return signatureRecordArray.subarray(6, 6 + signatureDataLength);
|
|
5617
|
+
return new Uint8Array(signatureRecordArray.subarray(6, 6 + signatureDataLength));
|
|
5499
5618
|
}
|
|
5500
5619
|
}
|
|
5501
5620
|
}
|
|
@@ -6018,10 +6137,10 @@ function isUnsafeFilename(filename, filenameValidation) {
|
|
|
6018
6137
|
if (pathParts.length > 1 && pathParts[pathParts.length - 1] === "") {
|
|
6019
6138
|
pathParts.pop();
|
|
6020
6139
|
}
|
|
6021
|
-
if (
|
|
6140
|
+
if (PARENT_DIRECTORY_REGEXP.test(filename) || filename.startsWith("/") || filename.startsWith("\\") || DRIVE_LETTER_REGEXP.test(filename)) {
|
|
6022
6141
|
return true;
|
|
6023
6142
|
}
|
|
6024
|
-
return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes(""));
|
|
6143
|
+
return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes("") || filename.includes("\0"));
|
|
6025
6144
|
}
|
|
6026
6145
|
|
|
6027
6146
|
function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
@@ -6107,7 +6226,7 @@ async function* scanEndOfCentralDirectory(reader, scanLength) {
|
|
|
6107
6226
|
}
|
|
6108
6227
|
|
|
6109
6228
|
function getEndOfCentralDirectoryInfo(scanArray, indexByte, offset) {
|
|
6110
|
-
return { offset, buffer: scanArray.
|
|
6229
|
+
return { offset, buffer: new Uint8Array(scanArray.subarray(indexByte, indexByte + END_OF_CENTRAL_DIR_LENGTH)).buffer };
|
|
6111
6230
|
}
|
|
6112
6231
|
|
|
6113
6232
|
async function getCentralDirectoryReachability(reader, view, anchoredOffset, indexByte, offset, size, remoteProbeBudget) {
|
|
@@ -8852,7 +8971,7 @@ function formatSupported(StreamClass, format) {
|
|
|
8852
8971
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8853
8972
|
*/
|
|
8854
8973
|
|
|
8855
|
-
const VERSION = "2.
|
|
8974
|
+
const VERSION = "2.16.0";
|
|
8856
8975
|
|
|
8857
8976
|
/*
|
|
8858
8977
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|