@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.
Files changed (41) hide show
  1. package/BENCHMARKS.md +21 -11
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +217 -98
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +217 -98
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +217 -98
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +217 -98
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +217 -98
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +219 -100
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +219 -100
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +219 -100
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +219 -100
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip-web-worker-native.js +1 -1
  22. package/dist/zip-web-worker.js +1 -1
  23. package/dist/zip.js +219 -100
  24. package/dist/zip.min.js +1 -1
  25. package/index-native.cjs +219 -100
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +219 -100
  28. package/index.d.cts +46 -13
  29. package/index.d.ts +46 -13
  30. package/index.min.js +1 -1
  31. package/lib/core/codec-pool.js +35 -19
  32. package/lib/core/codec-worker.js +4 -2
  33. package/lib/core/io.js +3 -2
  34. package/lib/core/streams/zip-entry-stream.js +151 -66
  35. package/lib/core/util/decode-text.js +15 -1
  36. package/lib/core/version.js +1 -1
  37. package/lib/core/web-worker-inline-native.js +1 -1
  38. package/lib/core/web-worker-inline-wasm.js +1 -1
  39. package/lib/core/zip-reader.js +12 -10
  40. package/lib/core/zlib-streams-inline.js +1 -1
  41. package/package.json +1 -1
package/dist/zip-core.js CHANGED
@@ -1858,7 +1858,6 @@
1858
1858
  const GZIP_HEADER_LENGTH = 10;
1859
1859
  const GZIP_TRAILER_LENGTH = 8;
1860
1860
  const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
1861
- const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
1862
1861
 
1863
1862
  class DeflateStream extends TransformStream {
1864
1863
 
@@ -1869,8 +1868,8 @@
1869
1868
  let crc32Stream, encryptionStream, gzipCrc32Stream;
1870
1869
  let readable = super.readable;
1871
1870
  const codecStreams = format && getCodecStreams(format);
1872
- const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) &&
1873
- Boolean(useCompressionStream && CompressionStream);
1871
+ const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
1872
+ const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
1874
1873
  if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
1875
1874
  crc32Stream = new Crc32Stream();
1876
1875
  readable = pipeThrough(readable, crc32Stream);
@@ -1880,12 +1879,15 @@
1880
1879
  readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.CompressionStream, format, { level, chunkSize, compressionMethod, uncompressedSize: inputSize }));
1881
1880
  } else if (useGzipCrc32) {
1882
1881
  gzipCrc32Stream = new GzipToRawDeflateStream();
1883
- readable = pipeThroughBackpressured(readable, new CompressionStream(FORMAT_GZIP));
1882
+ readable = pipeThroughBackpressured(readable, new GzipCompressionStream(FORMAT_GZIP, { level, chunkSize }));
1884
1883
  readable = pipeThrough(readable, gzipCrc32Stream);
1885
1884
  } else {
1886
1885
  try {
1887
1886
  readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
1888
1887
  } catch (error) {
1888
+ if (!useCompressionStream && CompressionStreamFallback) {
1889
+ throw error;
1890
+ }
1889
1891
  let gzipStream;
1890
1892
  try {
1891
1893
  gzipStream = new CompressionStream(FORMAT_GZIP);
@@ -1954,82 +1956,144 @@
1954
1956
  }
1955
1957
  }
1956
1958
 
1957
- function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize) {
1958
- const crc32 = new Crc32();
1959
+ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
1960
+ const writer = gzipStream.writable.getWriter();
1961
+ const reader = gzipStream.readable.getReader();
1962
+ const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
1959
1963
  let outputLength = 0;
1960
1964
  let inputDone = false;
1961
- let watchdogTimeout;
1965
+ let trailerWritten = false;
1966
+ let idleCheckArmed = false;
1967
+ let readCount = 0;
1968
+ let readPending = false;
1962
1969
  let resolveTrailerReady, rejectTrailerReady;
1963
1970
  const trailerReady = new Promise((resolve, reject) => {
1964
1971
  resolveTrailerReady = resolve;
1965
1972
  rejectTrailerReady = reject;
1966
1973
  });
1967
1974
  trailerReady.catch(() => { });
1968
- if (!outputSize) {
1969
- resolveTrailerReady();
1970
- }
1971
- const gzipWrapStream = new TransformStream({
1972
- start(controller) {
1975
+ pump();
1976
+ return new ReadableStream({
1977
+ async pull(controller) {
1978
+ let result;
1979
+ try {
1980
+ result = await read();
1981
+ } catch (error) {
1982
+ throw trailerWritten ? getTrailerError(error) : error;
1983
+ }
1984
+ const { value, done } = result;
1985
+ if (done) {
1986
+ controller.close();
1987
+ } else {
1988
+ outputLength += value.length;
1989
+ if (outputLength > outputSize) {
1990
+ const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
1991
+ rejectTrailerReady(error);
1992
+ await cancel(reader, error);
1993
+ throw error;
1994
+ }
1995
+ if (outputCrc32) {
1996
+ outputCrc32.append(value);
1997
+ }
1998
+ controller.enqueue(value);
1999
+ }
2000
+ },
2001
+ cancel(reason) {
2002
+ rejectTrailerReady(reason);
2003
+ return reader.cancel(reason);
2004
+ }
2005
+ });
2006
+
2007
+ async function pump() {
2008
+ const inputReader = readable.getReader();
2009
+ try {
1973
2010
  const header = new Uint8Array(GZIP_HEADER_LENGTH);
1974
2011
  header.set(GZIP_HEADER_BYTES);
1975
- controller.enqueue(header);
1976
- },
1977
- transform(chunk, controller) {
1978
- controller.enqueue(chunk);
1979
- },
1980
- async flush(controller) {
2012
+ await writer.write(header);
2013
+ for (; ;) {
2014
+ await writer.ready;
2015
+ const { value, done } = await inputReader.read();
2016
+ if (done) {
2017
+ break;
2018
+ }
2019
+ await writer.write(value);
2020
+ }
1981
2021
  inputDone = true;
1982
- startWatchdog();
1983
- try {
2022
+ if (outputCrc32) {
2023
+ if (readPending) {
2024
+ armIdleCheck();
2025
+ }
1984
2026
  await trailerReady;
1985
- } finally {
1986
- stopWatchdog();
1987
2027
  }
1988
2028
  const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
1989
2029
  const dataView = getDataView(trailer);
1990
- dataView.setUint32(0, crc32.get(), true);
2030
+ dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
1991
2031
  dataView.setUint32(4, outputSize, true);
1992
- controller.enqueue(trailer);
1993
- },
1994
- cancel(reason) {
1995
- rejectTrailerReady(reason);
2032
+ trailerWritten = true;
2033
+ await writer.write(trailer);
2034
+ await writer.close();
2035
+ } catch (error) {
2036
+ await abort(writer, error);
2037
+ await cancel(inputReader, error);
1996
2038
  }
1997
- });
1998
- const outputStream = new TransformStream({
1999
- transform(chunk, controller) {
2000
- crc32.append(chunk);
2001
- outputLength += chunk.length;
2002
- if (outputLength >= outputSize) {
2003
- resolveTrailerReady();
2004
- } else if (inputDone) {
2005
- startWatchdog();
2006
- }
2007
- controller.enqueue(chunk);
2008
- },
2009
- cancel(reason) {
2010
- rejectTrailerReady(reason);
2039
+ }
2040
+
2041
+ function read() {
2042
+ readCount++;
2043
+ readPending = true;
2044
+ const result = reader.read();
2045
+ result.then(onReadSettled, onReadSettled);
2046
+ if (inputDone && outputCrc32) {
2047
+ armIdleCheck();
2011
2048
  }
2012
- });
2013
- readable = pipeThrough(readable, gzipWrapStream);
2014
- readable = pipeThroughBackpressured(readable, gzipStream);
2015
- return pipeThrough(readable, outputStream);
2049
+ return result;
2050
+ }
2016
2051
 
2017
- function startWatchdog() {
2018
- stopWatchdog();
2019
- watchdogTimeout = setTimeout(() => rejectTrailerReady(new Error(ERR_INVALID_UNCOMPRESSED_SIZE)), GZIP_OUTPUT_STALL_TIMEOUT);
2052
+ function onReadSettled() {
2053
+ readPending = false;
2054
+ }
2055
+
2056
+ async function armIdleCheck() {
2057
+ if (!idleCheckArmed) {
2058
+ idleCheckArmed = true;
2059
+ const count = readCount;
2060
+ await nextTask();
2061
+ idleCheckArmed = false;
2062
+ if (readPending) {
2063
+ if (readCount == count) {
2064
+ resolveTrailerReady();
2065
+ } else {
2066
+ armIdleCheck();
2067
+ }
2068
+ }
2069
+ }
2020
2070
  }
2021
2071
 
2022
- function stopWatchdog() {
2023
- clearTimeout(watchdogTimeout);
2072
+ function getTrailerError(error) {
2073
+ const trailerError = new Error(outputLength == outputSize ? ERR_INVALID_CRC32 : ERR_INVALID_UNCOMPRESSED_SIZE);
2074
+ trailerError.cause = error;
2075
+ return trailerError;
2024
2076
  }
2025
2077
  }
2026
2078
 
2079
+ function nextTask() {
2080
+ return new Promise(resolve => {
2081
+ const { port1, port2 } = new MessageChannel();
2082
+ port2.onmessage = () => {
2083
+ port1.close();
2084
+ port2.close();
2085
+ resolve();
2086
+ };
2087
+ port1.postMessage(UNDEFINED_VALUE);
2088
+ });
2089
+ }
2090
+
2027
2091
  class InflateStream extends TransformStream {
2028
2092
 
2029
2093
  constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
2030
2094
  super({});
2031
2095
  const { zipCrypto, encrypted, checkCrc32, crc32, compressed, useCompressionStream, deflate64, format, compressionMethod, rawBitFlag, outputSize } = options;
2032
- let crc32Stream, decryptionStream;
2096
+ let crc32Stream, decryptionStream, gzipCrc32;
2033
2097
  let readable = super.readable;
2034
2098
  if (encrypted) {
2035
2099
  if (zipCrypto) {
@@ -2044,31 +2108,44 @@
2044
2108
  if (codecStreams) {
2045
2109
  readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
2046
2110
  } else {
2047
- try {
2048
- readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
2049
- } catch (error) {
2050
- if (deflate64 || outputSize === UNDEFINED_VALUE) {
2051
- throw error;
2052
- }
2053
- let gzipStream;
2111
+ let gzipStream;
2112
+ const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
2113
+ if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
2054
2114
  try {
2055
- gzipStream = new DecompressionStream(FORMAT_GZIP);
2115
+ gzipStream = new GzipDecompressionStream(FORMAT_GZIP, { chunkSize });
2056
2116
  } catch {
2057
- throw error;
2117
+ gzipStream = UNDEFINED_VALUE;
2118
+ }
2119
+ }
2120
+ if (!gzipStream) {
2121
+ try {
2122
+ readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
2123
+ } catch (error) {
2124
+ if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
2125
+ throw error;
2126
+ }
2127
+ try {
2128
+ gzipStream = new DecompressionStream(FORMAT_GZIP);
2129
+ } catch {
2130
+ throw error;
2131
+ }
2058
2132
  }
2059
- readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize);
2133
+ }
2134
+ if (gzipStream) {
2135
+ gzipCrc32 = true;
2136
+ readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32);
2060
2137
  }
2061
2138
  }
2062
2139
  readable = mapInflateStreamError(readable);
2063
2140
  }
2064
- if (checkCrc32) {
2141
+ if (checkCrc32 && !gzipCrc32) {
2065
2142
  crc32Stream = new Crc32Stream();
2066
2143
  readable = pipeThrough(readable, crc32Stream);
2067
2144
  }
2068
2145
  setReadable(this, readable, () => {
2069
- if (checkCrc32) {
2070
- const computedCrc32View = new DataView(crc32Stream.value.buffer);
2071
- if (crc32 != computedCrc32View.getUint32(0, false)) {
2146
+ if (crc32Stream) {
2147
+ const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
2148
+ if (crc32 != computedCrc32) {
2072
2149
  throw new Error(ERR_INVALID_CRC32);
2073
2150
  }
2074
2151
  }
@@ -2124,6 +2201,14 @@
2124
2201
  return new CodecStreamClass(format, options);
2125
2202
  }
2126
2203
 
2204
+ function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
2205
+ if (useCompressionStream && CodecStreamNative) {
2206
+ return CodecStreamNative;
2207
+ } else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
2208
+ return CodecStreamFallback;
2209
+ }
2210
+ }
2211
+
2127
2212
  function pipeThroughCompressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamFallback) {
2128
2213
  const Stream = useCompressionStream && CompressionStreamNative ?
2129
2214
  CompressionStreamNative :
@@ -2492,10 +2577,12 @@
2492
2577
  workerData.terminated = true;
2493
2578
  worker.terminate();
2494
2579
  }
2495
- terminateResolvers.forEach(resolve => resolve());
2496
2580
  }
2497
2581
  workerData.busy = false;
2498
- onTaskFinished(workerData);
2582
+ const pendingTasks = onTaskFinished(workerData);
2583
+ if (terminateResolvers) {
2584
+ terminateResolvers.forEach(resolve => resolve(pendingTasks));
2585
+ }
2499
2586
  }
2500
2587
  }
2501
2588
  });
@@ -3180,7 +3267,10 @@
3180
3267
 
3181
3268
  function onTaskFinished(workerData) {
3182
3269
  clearStarvationTimeout();
3183
- if (pendingRequests.length) {
3270
+ if (workerData.terminated) {
3271
+ workerData.terminated = false;
3272
+ return runPendingRequestsInline();
3273
+ } else if (pendingRequests.length) {
3184
3274
  const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
3185
3275
  resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
3186
3276
  armStarvationTimeout();
@@ -3218,12 +3308,26 @@
3218
3308
  starvationTimeout = null;
3219
3309
  if (pendingRequests.length) {
3220
3310
  const [{ resolve, stream, workerOptions }] = pendingRequests.splice(0, 1);
3221
- const inlineWorkerOptions = Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
3222
- resolve(new CodecWorker({}, stream, inlineWorkerOptions, onInlineTaskFinished));
3311
+ resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), onInlineTaskFinished));
3223
3312
  armStarvationTimeout();
3224
3313
  }
3225
3314
  }
3226
3315
 
3316
+ function runPendingRequestsInline() {
3317
+ const tasks = pendingRequests.splice(0).map(({ resolve, stream, workerOptions }) => new Promise(resolveTask => {
3318
+ resolve(new CodecWorker({}, stream, getInlineWorkerOptions(workerOptions), () => {
3319
+ onInlineTaskFinished();
3320
+ resolveTask();
3321
+ }));
3322
+ }));
3323
+ clearStarvationTimeout();
3324
+ return Promise.all(tasks);
3325
+ }
3326
+
3327
+ function getInlineWorkerOptions(workerOptions) {
3328
+ return Object.assign({}, workerOptions, { useWebWorkers: false, workerURI: UNDEFINED_VALUE, createWorker: UNDEFINED_VALUE });
3329
+ }
3330
+
3227
3331
  function onInlineTaskFinished() {
3228
3332
  clearStarvationTimeout();
3229
3333
  armStarvationTimeout();
@@ -3233,18 +3337,14 @@
3233
3337
  const { config } = workerOptions;
3234
3338
  const { terminateWorkerTimeout } = config;
3235
3339
  if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
3236
- if (workerData.terminated) {
3237
- workerData.terminated = false;
3238
- } else {
3239
- workerData.terminateTimeout = setTimeout(async () => {
3240
- pool = pool.filter(data => data != workerData);
3241
- try {
3242
- await workerData.terminate();
3243
- } catch {
3244
- // ignored
3245
- }
3246
- }, terminateWorkerTimeout);
3247
- }
3340
+ workerData.terminateTimeout = setTimeout(async () => {
3341
+ pool = pool.filter(data => data != workerData);
3342
+ try {
3343
+ await workerData.terminate();
3344
+ } catch {
3345
+ // ignored
3346
+ }
3347
+ }, terminateWorkerTimeout);
3248
3348
  }
3249
3349
  }
3250
3350
 
@@ -3257,10 +3357,13 @@
3257
3357
  }
3258
3358
 
3259
3359
  async function terminateWorkers() {
3260
- await Promise.allSettled(pool.map(workerData => {
3261
- clearTerminateTimeout(workerData);
3262
- return workerData.terminate();
3263
- }));
3360
+ await Promise.allSettled([
3361
+ runPendingRequestsInline(),
3362
+ ...pool.map(workerData => {
3363
+ clearTerminateTimeout(workerData);
3364
+ return workerData.terminate();
3365
+ })
3366
+ ]);
3264
3367
  resetWebWorkerSupport();
3265
3368
  }
3266
3369
 
@@ -3335,6 +3438,19 @@
3335
3438
  return decode(value, encoding, true);
3336
3439
  }
3337
3440
 
3441
+ function isUTF8Text(value) {
3442
+ if (value.some(byte => byte > 0x7f)) {
3443
+ try {
3444
+ new TextDecoder("utf-8", { fatal: true }).decode(value);
3445
+ return true;
3446
+ } catch {
3447
+ return false;
3448
+ }
3449
+ } else {
3450
+ return false;
3451
+ }
3452
+ }
3453
+
3338
3454
  function decodeTextRemovingBOM(value, encoding) {
3339
3455
  return decode(value, encoding, false);
3340
3456
  }
@@ -3667,10 +3783,11 @@
3667
3783
 
3668
3784
  createReadable(options) {
3669
3785
  const reader = this;
3670
- const { useRangeHeader, forceRangeRequests, size } = reader;
3786
+ const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
3671
3787
  if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
3672
3788
  const { offset = 0, size: readSize = size - offset } = options || {};
3673
- if (readSize > 0 && offset < size) {
3789
+ const cached = eocdCache && offset >= size - eocdCache.length;
3790
+ if (readSize > 0 && offset < size && !cached) {
3674
3791
  return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
3675
3792
  }
3676
3793
  }
@@ -4624,6 +4741,7 @@
4624
4741
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
4625
4742
  const MAX_KNOWN_VERSION = 63;
4626
4743
  const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
4744
+ const PARENT_DIRECTORY_REGEXP = /(^|[\\/])\.\.([\\/]|$)/;
4627
4745
  const CHARSET_UTF8 = "utf-8";
4628
4746
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
4629
4747
  const CHARSET_CP437 = "cp437";
@@ -4876,12 +4994,13 @@
4876
4994
  const versionMadeBy = getUint16$1(directoryView, offset + 4);
4877
4995
  const msDosCompatible = versionMadeBy >> 8 == 0;
4878
4996
  const unixCompatible = versionMadeBy >> 8 == 3;
4879
- const rawFilename = directoryArray.subarray(filenameOffset, extraFieldOffset);
4880
4997
  const commentLength = getUint16$1(directoryView, offset + 32);
4881
4998
  const endOffset = commentOffset + commentLength;
4882
- const rawComment = directoryArray.subarray(commentOffset, endOffset);
4883
- const filenameUTF8 = languageEncodingFlag;
4884
- const commentUTF8 = languageEncodingFlag;
4999
+ const rawEntryData = new Uint8Array(directoryArray.subarray(filenameOffset, endOffset));
5000
+ const rawFilename = rawEntryData.subarray(0, fileEntry.filenameLength);
5001
+ const rawComment = rawEntryData.subarray(fileEntry.filenameLength + fileEntry.extraFieldLength);
5002
+ const filenameUTF8 = languageEncodingFlag || (!filenameEncoding && isUTF8Text(rawFilename));
5003
+ const commentUTF8 = languageEncodingFlag || (!commentEncoding && isUTF8Text(rawComment));
4885
5004
  const externalFileAttributes = getUint32$1(directoryView, offset + 38);
4886
5005
  const msdosAttributesRaw = externalFileAttributes & MAX_8_BITS;
4887
5006
  const msdosAttributes = {
@@ -4932,7 +5051,7 @@
4932
5051
  rawFilename,
4933
5052
  filenameUTF8,
4934
5053
  commentUTF8,
4935
- rawExtraField: directoryArray.subarray(extraFieldOffset, commentOffset),
5054
+ rawExtraField: rawEntryData.subarray(fileEntry.filenameLength, fileEntry.filenameLength + fileEntry.extraFieldLength),
4936
5055
  rawComment,
4937
5056
  filename,
4938
5057
  comment
@@ -5440,7 +5559,7 @@
5440
5559
  if (getUint32$1(signatureRecordView, 0) == DIGITAL_SIGNATURE_RECORD_SIGNATURE) {
5441
5560
  const signatureDataLength = getUint16$1(signatureRecordView, 4);
5442
5561
  if (6 + signatureDataLength <= signatureRecordArray.length) {
5443
- return signatureRecordArray.subarray(6, 6 + signatureDataLength);
5562
+ return new Uint8Array(signatureRecordArray.subarray(6, 6 + signatureDataLength));
5444
5563
  }
5445
5564
  }
5446
5565
  }
@@ -5963,10 +6082,10 @@
5963
6082
  if (pathParts.length > 1 && pathParts[pathParts.length - 1] === "") {
5964
6083
  pathParts.pop();
5965
6084
  }
5966
- if (pathParts.includes("..") || filename.startsWith("/") || filename.startsWith("\\\\") || DRIVE_LETTER_REGEXP.test(filename)) {
6085
+ if (PARENT_DIRECTORY_REGEXP.test(filename) || filename.startsWith("/") || filename.startsWith("\\") || DRIVE_LETTER_REGEXP.test(filename)) {
5967
6086
  return true;
5968
6087
  }
5969
- return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes(""));
6088
+ return filenameValidation == STRICTNESS_STRICT && (pathParts.includes(".") || pathParts.includes("") || filename.includes("\0"));
5970
6089
  }
5971
6090
 
5972
6091
  function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
@@ -6052,7 +6171,7 @@
6052
6171
  }
6053
6172
 
6054
6173
  function getEndOfCentralDirectoryInfo(scanArray, indexByte, offset) {
6055
- return { offset, buffer: scanArray.slice(indexByte, indexByte + END_OF_CENTRAL_DIR_LENGTH).buffer };
6174
+ return { offset, buffer: new Uint8Array(scanArray.subarray(indexByte, indexByte + END_OF_CENTRAL_DIR_LENGTH)).buffer };
6056
6175
  }
6057
6176
 
6058
6177
  async function getCentralDirectoryReachability(reader, view, anchoredOffset, indexByte, offset, size, remoteProbeBudget) {
@@ -8699,7 +8818,7 @@
8699
8818
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8700
8819
  */
8701
8820
 
8702
- const VERSION = "2.14.1";
8821
+ const VERSION = "2.16.0";
8703
8822
 
8704
8823
  /*
8705
8824
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.