@zip.js/zip.js 2.11.3 → 2.12.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 (50) hide show
  1. package/deno.json +1 -1
  2. package/dist/zip-core-external.js +444 -114
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +454 -111
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +509 -236
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +522 -233
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +509 -236
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +524 -235
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +525 -236
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +456 -113
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +456 -113
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +457 -114
  23. package/dist/zip.min.js +1 -1
  24. package/index-native.cjs +524 -235
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +525 -236
  27. package/index.d.cts +480 -59
  28. package/index.d.ts +480 -59
  29. package/index.min.js +1 -1
  30. package/lib/core/codec-worker-web.js +10 -2
  31. package/lib/core/codec-worker.js +4 -3
  32. package/lib/core/configuration.js +20 -5
  33. package/lib/core/constants.js +2 -0
  34. package/lib/core/io.js +20 -10
  35. package/lib/core/options.js +29 -0
  36. package/lib/core/streams/codec-stream.js +6 -0
  37. package/lib/core/util/warnings.js +42 -0
  38. package/lib/core/version.js +1 -1
  39. package/lib/core/web-worker-base.js +4 -3
  40. package/lib/core/web-worker-inline-native.js +1 -1
  41. package/lib/core/web-worker-inline-wasm.js +1 -1
  42. package/lib/core/zip-entry.js +49 -1
  43. package/lib/core/zip-fs.js +43 -134
  44. package/lib/core/zip-reader.js +108 -47
  45. package/lib/core/zip-writer.js +238 -54
  46. package/lib/zip-core-base.js +9 -3
  47. package/lib/zip-core-reader.js +2 -0
  48. package/lib/zip-core-writer.js +6 -1
  49. package/lib/zip-module-wasm-base.js +2 -2
  50. package/package.json +5 -3
@@ -125,6 +125,7 @@ const NUMBER_TYPE = "number";
125
125
  const BOOLEAN_TYPE = "boolean";
126
126
 
127
127
  const EMPTY_UINT8_ARRAY = new Uint8Array();
128
+ const SYMBOL_ASYNC_DISPOSE = Symbol.asyncDispose || Symbol();
128
129
 
129
130
  /*
130
131
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
@@ -169,6 +170,7 @@ const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
169
170
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
170
171
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
171
172
  const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
173
+ const OPTION_CHECK_LOCAL_FILENAME = "checkLocalFilename";
172
174
  const OPTION_CHECK_SIGNATURE = "checkSignature";
173
175
  const OPTION_CHECK_CRC32 = "checkCrc32";
174
176
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -199,15 +201,20 @@ const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
199
201
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
200
202
  const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
201
203
  const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
204
+ const OPTION_ENTRY = "entry";
202
205
  const TEXT_TYPE_FILENAME = "filename";
203
206
  const TEXT_TYPE_COMMENT = "comment";
204
207
  const STRICTNESS_STRICT = "strict";
205
208
  const STRICTNESS_BALANCED = "balanced";
206
209
  const STRICTNESS_TOLERANT = "tolerant";
210
+ const PASS_THROUGH_COMPRESSED = "compressed";
207
211
 
208
212
  const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
209
213
  const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
210
214
  const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
215
+ const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
216
+ const ERR_ABORTED = "The operation was aborted";
217
+ const ABORT_ERROR_NAME = "AbortError";
211
218
 
212
219
  function checkFunctionOption(value) {
213
220
  if (value && typeof value != FUNCTION_TYPE) {
@@ -223,12 +230,25 @@ function checkSignalOption(signal) {
223
230
  return signal || UNDEFINED_VALUE;
224
231
  }
225
232
 
233
+ function throwIfAborted(signal) {
234
+ if (signal && signal.aborted) {
235
+ throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
236
+ }
237
+ }
238
+
226
239
  function checkPasswordOption(password, rawPassword) {
227
240
  if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
228
241
  throw new Error(ERR_INVALID_PASSWORD_TYPE);
229
242
  }
230
243
  }
231
244
 
245
+ function checkPassThroughOption(passThrough) {
246
+ if (passThrough !== UNDEFINED_VALUE && typeof passThrough != BOOLEAN_TYPE && passThrough !== PASS_THROUGH_COMPRESSED) {
247
+ throw new Error(ERR_INVALID_PASS_THROUGH_VALUE);
248
+ }
249
+ return passThrough;
250
+ }
251
+
232
252
  function checkInteger(value, maxValue, errorMessage) {
233
253
  if (!Number.isInteger(value) || value < 0 || value > maxValue) {
234
254
  throw new Error(errorMessage);
@@ -278,6 +298,8 @@ const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
278
298
  const MINIMUM_CHUNK_SIZE = 64;
279
299
  const MINIMUM_PROPERTY_VALUE = 1;
280
300
  const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
301
+ const ERR_INVALID_BASE_URI = "Invalid baseURI (must be a string)";
302
+ const ERR_INVALID_URI = "Invalid URI (must be a string or a function returning a string)";
281
303
  let maxWorkers = 2;
282
304
  try {
283
305
  if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
@@ -302,9 +324,9 @@ const DEFAULT_CONFIGURATION = {
302
324
  };
303
325
 
304
326
  const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
327
+ const PROPERTY_NAME_BASE_URI = "baseURI";
305
328
 
306
- const STRING_PROPERTY_NAMES = [
307
- "baseURI",
329
+ const URI_PROPERTY_NAMES = [
308
330
  "wasmURI",
309
331
  "workerURI"
310
332
  ];
@@ -328,7 +350,8 @@ const FUNCTION_PROPERTY_NAMES = [
328
350
  "DecompressionStreamFallback"
329
351
  ];
330
352
  const CONFIGURABLE_PROPERTY_NAMES = [
331
- ...STRING_PROPERTY_NAMES,
353
+ PROPERTY_NAME_BASE_URI,
354
+ ...URI_PROPERTY_NAMES,
332
355
  ...BOOLEAN_PROPERTY_NAMES,
333
356
  ...NUMBER_PROPERTY_NAMES,
334
357
  ...FUNCTION_PROPERTY_NAMES
@@ -372,6 +395,14 @@ function checkPropertyValue(propertyName, propertyValue) {
372
395
  }
373
396
  } else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
374
397
  checkFunctionOption(propertyValue);
398
+ } else if (propertyName == PROPERTY_NAME_BASE_URI) {
399
+ if (propertyValue && typeof propertyValue != STRING_TYPE) {
400
+ throw new Error(ERR_INVALID_BASE_URI);
401
+ }
402
+ } else if (URI_PROPERTY_NAMES.includes(propertyName)) {
403
+ if (propertyValue && typeof propertyValue != STRING_TYPE && typeof propertyValue != FUNCTION_TYPE) {
404
+ throw new Error(ERR_INVALID_URI);
405
+ }
375
406
  }
376
407
  return propertyValue;
377
408
  }
@@ -2624,6 +2655,7 @@ class ChunkStream extends TransformStream {
2624
2655
  constructor(chunkSize) {
2625
2656
  const pendingChunks = [];
2626
2657
  let pendingLength = 0;
2658
+ let outputSize = 0;
2627
2659
  if (!Number.isFinite(chunkSize) || chunkSize < 1) {
2628
2660
  chunkSize = DEFAULT_CHUNK_SIZE;
2629
2661
  }
@@ -2632,15 +2664,20 @@ class ChunkStream extends TransformStream {
2632
2664
  pendingChunks.push(chunk);
2633
2665
  pendingLength += chunk.length;
2634
2666
  while (pendingLength > chunkSize) {
2667
+ outputSize += chunkSize;
2635
2668
  controller.enqueue(shiftChunk());
2636
2669
  }
2637
2670
  },
2638
2671
  flush(controller) {
2639
2672
  if (pendingLength) {
2673
+ outputSize += pendingLength;
2640
2674
  controller.enqueue(concatChunks(pendingChunks, pendingLength));
2641
2675
  }
2642
2676
  }
2643
2677
  });
2678
+ Object.defineProperty(this, "outputSize", {
2679
+ get: () => outputSize
2680
+ });
2644
2681
 
2645
2682
  function shiftChunk() {
2646
2683
  const result = new Uint8Array(chunkSize);
@@ -2845,7 +2882,7 @@ function createWorkerInterface(workerData, config) {
2845
2882
  }
2846
2883
 
2847
2884
  async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
2848
- let codecStream;
2885
+ let codecStream, chunkStream;
2849
2886
  try {
2850
2887
  if (options.compressed && !options.format) {
2851
2888
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
@@ -2868,9 +2905,10 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
2868
2905
  }
2869
2906
  }
2870
2907
  codecStream = new CodecStream(options, config);
2908
+ chunkStream = new ChunkStream(getChunkSize(config));
2871
2909
  await readable
2872
2910
  .pipeThrough(codecStream)
2873
- .pipeThrough(new ChunkStream(getChunkSize(config)))
2911
+ .pipeThrough(chunkStream)
2874
2912
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2875
2913
  const {
2876
2914
  crc32,
@@ -2884,7 +2922,7 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
2884
2922
  };
2885
2923
  } catch (error) {
2886
2924
  if (codecStream) {
2887
- error.outputSize = codecStream.outputSize;
2925
+ error.outputSize = chunkStream ? chunkStream.outputSize : 0;
2888
2926
  }
2889
2927
  throw error;
2890
2928
  } finally {
@@ -2993,11 +3031,17 @@ async function runWebWorker(workerData, config) {
2993
3031
  let resolveResult, rejectResult;
2994
3032
  const result = new Promise((resolve, reject) => {
2995
3033
  resolveResult = resolve;
2996
- rejectResult = reject;
3034
+ rejectResult = error => {
3035
+ if (error && error.outputSize === UNDEFINED_VALUE) {
3036
+ error.outputSize = workerData.outputSize;
3037
+ }
3038
+ reject(error);
3039
+ };
2997
3040
  });
2998
3041
  Object.assign(workerData, {
2999
3042
  reader: null,
3000
3043
  writer: null,
3044
+ outputSize: 0,
3001
3045
  resolveResult,
3002
3046
  rejectResult,
3003
3047
  result
@@ -3281,8 +3325,10 @@ async function onMessage({ data }, workerData) {
3281
3325
  }
3282
3326
  }
3283
3327
  if (type == MESSAGE_DATA) {
3328
+ const chunk = new Uint8Array(value);
3284
3329
  await writer.ready;
3285
- await writer.write(new Uint8Array(value));
3330
+ await writer.write(chunk);
3331
+ workerData.outputSize += chunk.length;
3286
3332
  if (!stale()) {
3287
3333
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3288
3334
  }
@@ -3590,10 +3636,13 @@ function decode(value, encoding, ignoreBOM) {
3590
3636
 
3591
3637
 
3592
3638
  const ERR_HTTP_STATUS = "HTTP error ";
3639
+ const MIN_SUCCESS_HTTP_STATUS = 200;
3640
+ const MAX_SUCCESS_HTTP_STATUS = 299;
3593
3641
  const ERR_HTTP_RANGE = "HTTP Range not supported";
3594
3642
  const ERR_HTTP_RESOURCE_CHANGED = "HTTP resource changed";
3595
3643
  const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
3596
3644
  const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
3645
+ const ERR_WRITER_SIZE_NOT_WRITABLE = "Invalid writer (size must be writable)";
3597
3646
 
3598
3647
  const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
3599
3648
  const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
@@ -3785,11 +3834,14 @@ class BlobReader extends Reader {
3785
3834
  const reader = this;
3786
3835
  const { sourceBlob, size } = reader;
3787
3836
  const { offset = 0, size: readSize = size - offset } = options || {};
3788
- if (!offset && readSize >= size) {
3789
- return toCompatibleReadable(sourceBlob.stream());
3790
- }
3791
- if (blobSliceReliable) {
3792
- return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
3837
+ // deno-lint-ignore valid-typeof
3838
+ if (typeof sourceBlob.stream == FUNCTION_TYPE) {
3839
+ if (!offset && readSize >= size) {
3840
+ return toCompatibleReadable(sourceBlob.stream());
3841
+ }
3842
+ if (blobSliceReliable) {
3843
+ return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
3844
+ }
3793
3845
  }
3794
3846
  return super.createReadable(options);
3795
3847
  }
@@ -4189,7 +4241,7 @@ async function getContentLength(httpReader, sendRequest, getRequestData) {
4189
4241
 
4190
4242
  async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
4191
4243
  const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
4192
- if (response.status < 400) {
4244
+ if (response.status >= MIN_SUCCESS_HTTP_STATUS && response.status <= MAX_SUCCESS_HTTP_STATUS) {
4193
4245
  return response;
4194
4246
  } else {
4195
4247
  throw response.status == 416 ? new Error(ERR_HTTP_RANGE) : new Error(ERR_HTTP_STATUS + (response.statusText || response.status));
@@ -4200,7 +4252,7 @@ function sendXMLHttpRequest(method, { url }, headers) {
4200
4252
  return new Promise((resolve, reject) => {
4201
4253
  const request = new XMLHttpRequest();
4202
4254
  request.addEventListener("load", () => {
4203
- if (request.status < 400) {
4255
+ if (request.status >= MIN_SUCCESS_HTTP_STATUS && request.status <= MAX_SUCCESS_HTTP_STATUS) {
4204
4256
  const headers = [];
4205
4257
  request.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(header => {
4206
4258
  const splitHeader = header.trim().split(/\s*:\s*/);
@@ -4504,8 +4556,10 @@ class GenericWriter {
4504
4556
  writable: toCompatibleWritable(writer)
4505
4557
  };
4506
4558
  }
4507
- if (writer.size === UNDEFINED_VALUE) {
4508
- writer.size = 0;
4559
+ try {
4560
+ writer.size = writer.size === UNDEFINED_VALUE ? 0 : writer.size;
4561
+ } catch {
4562
+ throw new Error(ERR_WRITER_SIZE_NOT_WRITABLE);
4509
4563
  }
4510
4564
  return writer;
4511
4565
  }
@@ -4553,6 +4607,45 @@ function createReadable(reader, options) {
4553
4607
  }
4554
4608
  }
4555
4609
 
4610
+ /*
4611
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
4612
+
4613
+ Redistribution and use in source and binary forms, with or without
4614
+ modification, are permitted provided that the following conditions are met:
4615
+
4616
+ 1. Redistributions of source code must retain the above copyright notice,
4617
+ this list of conditions and the following disclaimer.
4618
+
4619
+ 2. Redistributions in binary form must reproduce the above copyright
4620
+ notice, this list of conditions and the following disclaimer in
4621
+ the documentation and/or other materials provided with the distribution.
4622
+
4623
+ 3. The names of the authors may not be used to endorse or promote products
4624
+ derived from this software without specific prior written permission.
4625
+
4626
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
4627
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
4628
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
4629
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
4630
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4631
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
4632
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4633
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4634
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4635
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4636
+ */
4637
+
4638
+
4639
+ function addWarning(warnings, reason, filename) {
4640
+ if (!warnings.some(warning => warning.reason == reason)) {
4641
+ const warning = { reason };
4642
+ if (filename !== UNDEFINED_VALUE) {
4643
+ warning.filename = filename;
4644
+ }
4645
+ warnings.push(warning);
4646
+ }
4647
+ }
4648
+
4556
4649
  /*
4557
4650
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4558
4651
 
@@ -4581,6 +4674,7 @@ function createReadable(reader, options) {
4581
4674
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4582
4675
  */
4583
4676
 
4677
+
4584
4678
  const PROPERTY_NAME_FILENAME = "filename";
4585
4679
  const PROPERTY_NAME_RAW_FILENAME = "rawFilename";
4586
4680
  const PROPERTY_NAME_COMMENT = "comment";
@@ -4705,6 +4799,38 @@ class Entry {
4705
4799
 
4706
4800
  }
4707
4801
 
4802
+ const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
4803
+ EXTRAFIELD_TYPE_ZIP64,
4804
+ EXTRAFIELD_TYPE_AES,
4805
+ EXTRAFIELD_TYPE_NTFS,
4806
+ EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
4807
+ EXTRAFIELD_TYPE_UNICODE_PATH,
4808
+ EXTRAFIELD_TYPE_UNICODE_COMMENT,
4809
+ EXTRAFIELD_TYPE_USDZ,
4810
+ EXTRAFIELD_TYPE_INFOZIP,
4811
+ EXTRAFIELD_TYPE_UNIX,
4812
+ EXTRAFIELD_TYPE_UNIX_TYPE1,
4813
+ EXTRAFIELD_TYPE_PKWARE_UNIX
4814
+ ]);
4815
+
4816
+ function getUserExtraField(extraField) {
4817
+ if (extraField) {
4818
+ const userExtraField = new Map();
4819
+ extraField.forEach((field, type) => {
4820
+ if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
4821
+ userExtraField.set(type, field.data);
4822
+ }
4823
+ });
4824
+ if (userExtraField.size) {
4825
+ return userExtraField;
4826
+ }
4827
+ }
4828
+ }
4829
+
4830
+ function getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength) {
4831
+ return encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
4832
+ }
4833
+
4708
4834
  /*
4709
4835
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4710
4836
 
@@ -4764,6 +4890,8 @@ const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
4764
4890
  const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
4765
4891
  const WARNING_DUPLICATE_FILENAME = "duplicate filename";
4766
4892
  const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
4893
+ const WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = "multiple end of central directory records";
4894
+ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME = "mismatched local file header (filename)";
4767
4895
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
4768
4896
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
4769
4897
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
@@ -4834,7 +4962,7 @@ class ZipReader {
4834
4962
  }
4835
4963
  }
4836
4964
  if (rejectAmbiguousEndOfDirectory && endOfDirectoryReachingEndCount > 1) {
4837
- throwAmbiguousArchive("multiple end of central directory records");
4965
+ throwAmbiguousArchive(WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY);
4838
4966
  }
4839
4967
  const endOfDirectoryView = getDataView(endOfDirectoryInfo);
4840
4968
  let directoryDataLength = getUint32$1(endOfDirectoryView, 12);
@@ -5132,7 +5260,8 @@ class ZipReader {
5132
5260
  const writer = new TransformStream();
5133
5261
  const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
5134
5262
  arrayBufferPromise.catch(() => { });
5135
- await fileEntry.getData(writer, entry, zipReader.readRanges, options);
5263
+ await fileEntry.getData(writer, entry, zipReader.readRanges,
5264
+ Object.assign({}, options, { preventClose: false }));
5136
5265
  return arrayBufferPromise;
5137
5266
  };
5138
5267
  offset = endOffset;
@@ -5213,48 +5342,101 @@ class ZipReader {
5213
5342
  await reader.readable.cancel();
5214
5343
  }
5215
5344
  }
5345
+
5346
+ [SYMBOL_ASYNC_DISPOSE]() {
5347
+ return this.close();
5348
+ }
5216
5349
  }
5217
5350
 
5218
5351
  class ZipReaderStream {
5219
5352
 
5220
5353
  constructor(options = {}) {
5221
- const { readable, writable } = new TransformStream();
5222
- const gen = new ZipReader(readable, options).getEntriesGenerator();
5354
+ let sourceController;
5355
+ const { readable, writable } = new TransformStream({
5356
+ start(controller) {
5357
+ sourceController = controller;
5358
+ }
5359
+ });
5360
+ const zipReader = new ZipReader(readable, options);
5361
+ const gen = zipReader.getEntriesGenerator();
5362
+ const pendingEntries = new Set();
5223
5363
  this.readable = new ReadableStream({
5224
5364
  async pull(controller) {
5225
5365
  const { done, value } = await gen.next();
5226
5366
  if (done)
5227
5367
  return controller.close();
5368
+ const entryStream = createEntryStream(value, pendingEntries);
5228
5369
  const chunk = {
5229
5370
  ...value,
5230
- readable: (function () {
5231
- const { readable, writable } = new TransformStream();
5232
- if (value.getData) {
5233
- getData();
5234
- return readable;
5235
- }
5236
-
5237
- async function getData() {
5238
- try {
5239
- await value.getData(writable);
5240
- } catch (error) {
5241
- try {
5242
- await writable.abort(error);
5243
- } catch {
5244
- // ignored
5245
- }
5246
- }
5247
- }
5248
- })()
5371
+ readable: entryStream.readable
5249
5372
  };
5250
5373
  delete chunk.getData;
5374
+ Object.defineProperties(chunk, {
5375
+ localDirectory: {
5376
+ get: () => value.localDirectory,
5377
+ enumerable: true
5378
+ },
5379
+ warnings: {
5380
+ get: () => value.warnings,
5381
+ enumerable: true
5382
+ }
5383
+ });
5251
5384
  controller.enqueue(chunk);
5385
+ },
5386
+ async cancel(reason) {
5387
+ const entryStreams = Array.from(pendingEntries);
5388
+ pendingEntries.clear();
5389
+ sourceController.error(reason);
5390
+ await Promise.allSettled(entryStreams.map(entryStream => entryStream.cancel(reason)));
5391
+ await Promise.allSettled([gen.return(), zipReader.close()]);
5252
5392
  }
5253
5393
  });
5254
5394
  this.writable = writable;
5255
5395
  }
5256
5396
  }
5257
5397
 
5398
+ function createEntryStream(entry, pendingEntries) {
5399
+ const { readable, writable } = new TransformStream();
5400
+ let dataReader;
5401
+ const entryStream = {
5402
+ cancel: async reason => {
5403
+ pendingEntries.delete(entryStream);
5404
+ await (dataReader ? dataReader.cancel(reason) : readable.cancel(reason));
5405
+ }
5406
+ };
5407
+ entryStream.readable = new ReadableStream({
5408
+ async pull(controller) {
5409
+ if (!dataReader) {
5410
+ dataReader = readable.getReader();
5411
+ pendingEntries.add(entryStream);
5412
+ getData();
5413
+ }
5414
+ const { done, value } = await dataReader.read();
5415
+ if (done) {
5416
+ controller.close();
5417
+ } else {
5418
+ controller.enqueue(value);
5419
+ }
5420
+ },
5421
+ cancel: reason => entryStream.cancel(reason)
5422
+ }, { highWaterMark: 0 });
5423
+ return entryStream;
5424
+
5425
+ async function getData() {
5426
+ try {
5427
+ await entry.getData(writable, { preventClose: false });
5428
+ } catch (error) {
5429
+ try {
5430
+ await writable.abort(error);
5431
+ } catch {
5432
+ // ignored
5433
+ }
5434
+ } finally {
5435
+ pendingEntries.delete(entryStream);
5436
+ }
5437
+ }
5438
+ }
5439
+
5258
5440
  async function isZipFile(reader, options = {}) {
5259
5441
  reader = new GenericReader(reader);
5260
5442
  await initStream(reader);
@@ -5314,7 +5496,9 @@ let ZipEntry$1 = class ZipEntry {
5314
5496
  const dataView = getDataView(dataArray);
5315
5497
  let password = getOptionValue$1(zipEntry, options, OPTION_PASSWORD);
5316
5498
  let rawPassword = getOptionValue$1(zipEntry, options, OPTION_RAW_PASSWORD);
5317
- const passThrough = getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH);
5499
+ const passThrough = checkPassThroughOption(getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH));
5500
+ const passThroughCompression = Boolean(passThrough);
5501
+ const passThroughEncryption = passThrough === true;
5318
5502
  checkPasswordOption(password, rawPassword);
5319
5503
  password = password && password.length && password;
5320
5504
  rawPassword = rawPassword && rawPassword.length && rawPassword;
@@ -5335,7 +5519,9 @@ let ZipEntry$1 = class ZipEntry {
5335
5519
  const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5336
5520
  const entryStrictness = getStrictness(options, zipEntry.options);
5337
5521
  const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5338
- const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5522
+ const checkLocalFilenameOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_FILENAME);
5523
+ const checkLocalFilename = getCheckLocalFilename(
5524
+ checkLocalFilenameOption === UNDEFINED_VALUE ? checkLocalDirectoryOption : checkLocalFilenameOption, entryStrictness);
5339
5525
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5340
5526
  if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5341
5527
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
@@ -5366,16 +5552,17 @@ let ZipEntry$1 = class ZipEntry {
5366
5552
  if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5367
5553
  fileEntry.gid = gid;
5368
5554
  }
5369
- const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5555
+ const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5556
+ const encrypted = zipEntry.encrypted && localDirectory.encrypted && (!passThroughEncryption || checkPasswordOnly);
5370
5557
  const zipCrypto = encrypted && !extraFieldAES;
5371
- if (!passThrough) {
5558
+ if (!passThroughEncryption) {
5372
5559
  fileEntry.zipCrypto = zipCrypto;
5373
5560
  }
5374
5561
  if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5375
5562
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
5376
5563
  }
5377
- const registeredCodec = passThrough ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
5378
- if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !passThrough) {
5564
+ const registeredCodec = passThroughCompression ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
5565
+ if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !passThroughCompression) {
5379
5566
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
5380
5567
  }
5381
5568
  if (encrypted) {
@@ -5391,15 +5578,17 @@ let ZipEntry$1 = class ZipEntry {
5391
5578
  const size = compressedSize;
5392
5579
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
5393
5580
  const signal = checkSignalOption(getOptionValue$1(zipEntry, options, OPTION_SIGNAL));
5394
- const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5581
+ throwIfAborted(signal);
5395
5582
  let checkOverlappingEntry = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
5396
5583
  const checkOverlappingEntryOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
5397
5584
  if (checkOverlappingEntryOnly) {
5398
5585
  checkOverlappingEntry = true;
5399
5586
  }
5400
5587
  const { onstart, onprogress, onend } = options;
5401
- const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
5402
- const outputSize = passThrough ? compressedSize : uncompressedSize;
5588
+ const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThroughCompression;
5589
+ const outputSize = passThroughCompression ?
5590
+ compressedSize - getEncryptionOverhead(encrypted, zipCrypto, extraFieldAES && extraFieldAES.strength) :
5591
+ uncompressedSize;
5403
5592
  const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
5404
5593
  let useCompressionStream = getOptionValue$1(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
5405
5594
  if (deflate64) {
@@ -5408,7 +5597,7 @@ let ZipEntry$1 = class ZipEntry {
5408
5597
  const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
5409
5598
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
5410
5599
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
5411
- checkCrc32Option) && !passThrough &&
5600
+ checkCrc32Option) && !passThroughCompression &&
5412
5601
  (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
5413
5602
  const workerOptions = {
5414
5603
  options: {
@@ -5462,10 +5651,10 @@ let ZipEntry$1 = class ZipEntry {
5462
5651
  await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
5463
5652
  ({ writable } = writer);
5464
5653
  const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
5465
- writer.size += writtenSize;
5466
5654
  if (writtenSize != outputSize) {
5467
- throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
5655
+ throw Object.assign(new Error(ERR_INVALID_UNCOMPRESSED_SIZE), { outputSize: writtenSize });
5468
5656
  }
5657
+ writer.size += writtenSize;
5469
5658
  }
5470
5659
  } catch (error) {
5471
5660
  if (error.outputSize !== UNDEFINED_VALUE) {
@@ -6131,7 +6320,7 @@ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, chec
6131
6320
  if (checkLocalFilename && !maskedLocalDirectory &&
6132
6321
  (rawLocalFilename.length != rawFilename.length ||
6133
6322
  rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
6134
- reportAmbiguity(reject, warnings, "mismatched local file header (filename)");
6323
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME);
6135
6324
  }
6136
6325
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
6137
6326
  reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
@@ -6156,16 +6345,6 @@ function reportAmbiguity(reject, warnings, reason) {
6156
6345
  }
6157
6346
  }
6158
6347
 
6159
- function addWarning(warnings, reason, filename) {
6160
- if (!warnings.some(warning => warning.reason == reason)) {
6161
- const warning = { reason };
6162
- if (filename !== UNDEFINED_VALUE) {
6163
- warning.filename = filename;
6164
- }
6165
- warnings.push(warning);
6166
- }
6167
- }
6168
-
6169
6348
  function throwAmbiguousArchive(reason) {
6170
6349
  const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
6171
6350
  error.reason = reason;
@@ -6245,7 +6424,9 @@ var zipReader = /*#__PURE__*/Object.freeze({
6245
6424
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
6246
6425
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
6247
6426
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES: WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES,
6427
+ WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME: WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME,
6248
6428
  WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY: WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
6429
+ WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY: WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
6249
6430
  WARNING_PREPENDED_CENTRAL_DIRECTORY: WARNING_PREPENDED_CENTRAL_DIRECTORY,
6250
6431
  WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
6251
6432
  WARNING_TRAILING_CENTRAL_DIRECTORY_DATA: WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
@@ -6298,7 +6479,7 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
6298
6479
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
6299
6480
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
6300
6481
  const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
6301
- const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
6482
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
6302
6483
  const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
6303
6484
  const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
6304
6485
  const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
@@ -6310,6 +6491,7 @@ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
6310
6491
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
6311
6492
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
6312
6493
  const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
6494
+ const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
6313
6495
  const ERR_UNDETERMINED_SIZE = "Undetermined size";
6314
6496
  const ERR_UNDEFINED_READER = "Undefined reader";
6315
6497
  const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
@@ -6323,14 +6505,21 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
6323
6505
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
6324
6506
  const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
6325
6507
  const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
6508
+ const ERR_INVALID_ENTRY = "Invalid entry option (must be an entry returned by ZipReader#getEntries())";
6509
+ const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
6510
+ const WARNING_COMPRESSION_UNAVAILABLE = "compression unavailable";
6511
+ const WARNING_CLAMPED_LAST_MODIFICATION_DATE = "clamped last modification date";
6326
6512
 
6327
6513
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
6328
6514
  const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
6329
6515
  const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
6330
6516
  const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
6517
+ const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
6518
+ const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
6331
6519
  const VENDOR_VERSION_AE_1 = 1;
6332
- const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
6520
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
6333
6521
  const UNIX_EXTRA_FIELD_TYPE = "unix";
6522
+ const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
6334
6523
  const MAX_LEVEL = 9;
6335
6524
 
6336
6525
  let workers = 0;
@@ -6357,9 +6546,11 @@ class ZipWriter {
6357
6546
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
6358
6547
  pendingAddFileCalls: new Set(),
6359
6548
  pendingErrors: [],
6549
+ warnings: [],
6360
6550
  bufferedWrites: 0,
6361
6551
  directWrites: 0,
6362
- lastFileEntry: UNDEFINED_VALUE
6552
+ lastFileEntry: UNDEFINED_VALUE,
6553
+ archiveClosed: false
6363
6554
  });
6364
6555
  }
6365
6556
 
@@ -6524,6 +6715,9 @@ class ZipWriter {
6524
6715
  const zipWriter = this;
6525
6716
  const { pendingAddFileCalls, writer } = this;
6526
6717
  const { writable } = writer;
6718
+ if (zipWriter.archiveClosed) {
6719
+ return getWriterData(writer);
6720
+ }
6527
6721
  if (!(comment instanceof Uint8Array)) {
6528
6722
  throw new Error(ERR_INVALID_COMMENT_TYPE);
6529
6723
  }
@@ -6547,11 +6741,16 @@ class ZipWriter {
6547
6741
  throw error;
6548
6742
  }
6549
6743
  await closeFile(zipWriter, comment, options);
6744
+ zipWriter.archiveClosed = true;
6550
6745
  const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6551
6746
  if (!preventClose) {
6552
6747
  await writable.getWriter().close();
6553
6748
  }
6554
- return writer.getData ? writer.getData() : writable;
6749
+ return getWriterData(writer);
6750
+ }
6751
+
6752
+ [SYMBOL_ASYNC_DISPOSE]() {
6753
+ return this.close();
6555
6754
  }
6556
6755
  }
6557
6756
 
@@ -6630,6 +6829,10 @@ class WatchedPromise extends Promise {
6630
6829
  }
6631
6830
  }
6632
6831
 
6832
+ function getWriterData(writer) {
6833
+ return writer.getData ? writer.getData() : writer.writable;
6834
+ }
6835
+
6633
6836
  function watchPromiseError(zipWriter, promise) {
6634
6837
  const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6635
6838
  const watcher = {};
@@ -6648,6 +6851,14 @@ async function prependZipEntries(zipWriter, reader) {
6648
6851
 
6649
6852
  async function addFileEntry(zipWriter, name, reader, options) {
6650
6853
  options = Object.assign({}, options);
6854
+ const entry = options[OPTION_ENTRY];
6855
+ if (entry !== UNDEFINED_VALUE) {
6856
+ const { entryOptions, passThroughOptions } = getSourceEntryOptions(entry,
6857
+ checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH)),
6858
+ getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE));
6859
+ delete options[OPTION_ENTRY];
6860
+ options = Object.assign(entryOptions, passThroughOptions, options);
6861
+ }
6651
6862
  if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6652
6863
  name += DIRECTORY_SIGNATURE;
6653
6864
  }
@@ -6712,21 +6923,33 @@ async function addFile(zipWriter, name, reader, options) {
6712
6923
  try {
6713
6924
  const { resolvedOptions } = metadataInfo;
6714
6925
  if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
6715
- !resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
6926
+ !resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
6716
6927
  resolvedOptions.level = 0;
6928
+ addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
6717
6929
  }
6718
6930
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
6719
6931
  ({ reader } = sizesInfo);
6720
6932
  const diskOffset = getDiskOffset(zipWriter.writer);
6721
6933
  const diskNumber = getDiskNumber(zipWriter.writer);
6934
+ let crc32 = options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32;
6935
+ const storesAE2 = sizesInfo.resolvedOptions.encrypted && !resolvedOptions.zipCrypto;
6936
+ if (resolvedOptions.passThroughCompression && !resolvedOptions.passThroughEncryption && storesAE2) {
6937
+ crc32 = UNDEFINED_VALUE;
6938
+ }
6939
+ if (resolvedOptions.passThroughCompression && reader && !storesAE2 && crc32 === UNDEFINED_VALUE) {
6940
+ throw new Error(ERR_UNDEFINED_CRC32);
6941
+ }
6722
6942
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6723
6943
  signature: options[PROPERTY_NAME_SIGNATURE],
6724
- crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6944
+ crc32,
6725
6945
  offset: zipWriter.offset - diskOffset,
6726
6946
  diskNumberStart: diskNumber,
6727
6947
  [OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
6728
6948
  });
6729
6949
  const headerInfo = getHeaderInfo(options);
6950
+ if (headerInfo.lastModDateClamped) {
6951
+ addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
6952
+ }
6730
6953
  const dataDescriptorInfo = getDataDescriptorInfo(options);
6731
6954
  const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
6732
6955
  fileEntry = await getFileEntry(zipWriter, name, reader, {
@@ -6753,6 +6976,95 @@ async function addFile(zipWriter, name, reader, options) {
6753
6976
  return new Entry(fileEntry);
6754
6977
  }
6755
6978
 
6979
+ function getSourceEntryOptions(entry, passThrough, lastModDateOverride) {
6980
+ if (entry === null || typeof entry != OBJECT_TYPE || Array.isArray(entry)) {
6981
+ throw new Error(ERR_INVALID_ENTRY);
6982
+ }
6983
+ const {
6984
+ externalFileAttributes,
6985
+ versionMadeBy,
6986
+ comment,
6987
+ lastModDate,
6988
+ rawLastModDate,
6989
+ creationDate,
6990
+ lastAccessDate,
6991
+ uncompressedSize,
6992
+ encrypted,
6993
+ zipCrypto,
6994
+ crc32,
6995
+ compressionMethod,
6996
+ extraFieldAES,
6997
+ extraFieldUnix,
6998
+ internalFileAttributes,
6999
+ extraField,
7000
+ bitFlag,
7001
+ directory,
7002
+ uid,
7003
+ gid
7004
+ } = entry;
7005
+ const entryOptions = {
7006
+ externalFileAttributes,
7007
+ versionMadeBy,
7008
+ comment,
7009
+ lastModDate,
7010
+ creationDate,
7011
+ lastAccessDate,
7012
+ internalFileAttributes,
7013
+ directory
7014
+ };
7015
+ if (bitFlag && bitFlag.languageEncodingFlag) {
7016
+ entryOptions[OPTION_USE_UNICODE_FILE_NAMES] = true;
7017
+ }
7018
+ const userExtraField = getUserExtraField(extraField);
7019
+ if (userExtraField) {
7020
+ entryOptions[PROPERTY_NAME_EXTRA_FIELD] = userExtraField;
7021
+ }
7022
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
7023
+ Object.assign(entryOptions, {
7024
+ uid,
7025
+ gid,
7026
+ unixExtraFieldType: extraFieldUnix ? UNIX_EXTRA_FIELD_TYPE : INFOZIP_EXTRA_FIELD_TYPE
7027
+ });
7028
+ }
7029
+ const passThroughOptions = {};
7030
+ if (passThrough && !directory) {
7031
+ Object.assign(passThroughOptions, {
7032
+ uncompressedSize,
7033
+ crc32,
7034
+ compressionMethod
7035
+ });
7036
+ if (passThrough !== PASS_THROUGH_COMPRESSED) {
7037
+ Object.assign(passThroughOptions, {
7038
+ encrypted,
7039
+ zipCrypto,
7040
+ encryptionStrength: extraFieldAES ? extraFieldAES.strength : UNDEFINED_VALUE
7041
+ });
7042
+ }
7043
+ if (bitFlag) {
7044
+ passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
7045
+ passThroughOptions[OPTION_LEVEL] = LEVEL_BY_BITFLAG_LEVEL[bitFlag.level];
7046
+ }
7047
+ if (lastModDateOverride === UNDEFINED_VALUE) {
7048
+ passThroughOptions.rawLastModDate = rawLastModDate;
7049
+ } else if (passThrough !== PASS_THROUGH_COMPRESSED && zipCrypto && (!bitFlag || bitFlag.dataDescriptor) &&
7050
+ lastModDateOverride instanceof Date &&
7051
+ getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
7052
+ throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
7053
+ }
7054
+ }
7055
+ return { entryOptions, passThroughOptions };
7056
+ }
7057
+
7058
+ function getDosTimeHighByte(lastModDate) {
7059
+ let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
7060
+ if (dosLastModDate < MIN_DATE) {
7061
+ dosLastModDate = MIN_DATE;
7062
+ } else if (dosLastModDate > MAX_DATE) {
7063
+ dosLastModDate = MAX_DATE;
7064
+ }
7065
+ return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
7066
+ }
7067
+
6756
7068
  function resolveAttributes(zipWriter, name, options) {
6757
7069
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6758
7070
  let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
@@ -6767,7 +7079,7 @@ function resolveAttributes(zipWriter, name, options) {
6767
7079
  checkIntegerOption(uid, MAX_32_BITS, ERR_INVALID_UID);
6768
7080
  checkIntegerOption(gid, MAX_32_BITS, ERR_INVALID_GID);
6769
7081
  checkIntegerOption(unixMode, MAX_16_BITS, ERR_INVALID_UNIX_MODE);
6770
- if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
7082
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
6771
7083
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
6772
7084
  }
6773
7085
  if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
@@ -6775,7 +7087,7 @@ function resolveAttributes(zipWriter, name, options) {
6775
7087
  throw new Error(ERR_INVALID_UNIX_ID_SIZE);
6776
7088
  }
6777
7089
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6778
- unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
7090
+ unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
6779
7091
  }
6780
7092
  let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
6781
7093
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
@@ -6906,7 +7218,9 @@ function resolveMetadata(zipWriter, name, options) {
6906
7218
  const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6907
7219
  const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6908
7220
  const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6909
- const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
7221
+ const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
7222
+ const passThroughCompression = Boolean(passThrough);
7223
+ const passThroughEncryption = passThrough === true;
6910
7224
  const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6911
7225
  const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6912
7226
  checkPasswordOption(password, rawPassword);
@@ -6921,10 +7235,12 @@ function resolveMetadata(zipWriter, name, options) {
6921
7235
  const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
6922
7236
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
6923
7237
  const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
6924
- const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
7238
+ throwIfAborted(signal);
7239
+ const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
7240
+ !isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
6925
7241
  const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
6926
- const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
6927
- if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
7242
+ const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
7243
+ if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
6928
7244
  compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
6929
7245
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
6930
7246
  }
@@ -6938,15 +7254,15 @@ function resolveMetadata(zipWriter, name, options) {
6938
7254
  level = 0;
6939
7255
  }
6940
7256
  }
6941
- if (passThrough) {
6942
- level = UNDEFINED_VALUE;
7257
+ if (passThroughCompression) {
7258
+ level = toNumber(options[OPTION_LEVEL]);
6943
7259
  }
6944
7260
  let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
6945
7261
  let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
6946
7262
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
6947
7263
  dataDescriptor = false;
6948
7264
  }
6949
- if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThrough)) {
7265
+ if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
6950
7266
  dataDescriptor = true;
6951
7267
  }
6952
7268
  if (level !== UNDEFINED_VALUE && level != 6) {
@@ -6970,7 +7286,8 @@ function resolveMetadata(zipWriter, name, options) {
6970
7286
  lastAccessDate,
6971
7287
  creationDate,
6972
7288
  internalFileAttributes,
6973
- passThrough,
7289
+ passThroughCompression,
7290
+ passThroughEncryption,
6974
7291
  password,
6975
7292
  rawPassword,
6976
7293
  encryptionStrength,
@@ -7031,7 +7348,7 @@ function serializeExtraField(extraField) {
7031
7348
  }
7032
7349
 
7033
7350
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
7034
- if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7351
+ if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7035
7352
  throw new Error(ERR_UNDEFINED_READER);
7036
7353
  }
7037
7354
  let contentSize;
@@ -7047,12 +7364,12 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
7047
7364
  }
7048
7365
 
7049
7366
  function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
7050
- const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7367
+ const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7051
7368
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
7052
7369
  let maximumCompressedSize = 0;
7053
7370
  let uncompressedSize = 0;
7054
7371
  let unknownSize = false;
7055
- if (passThrough && hasContent) {
7372
+ if (passThroughCompression && hasContent) {
7056
7373
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
7057
7374
  if (uncompressedSize === UNDEFINED_VALUE) {
7058
7375
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -7063,17 +7380,17 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
7063
7380
  }
7064
7381
  const zip64Enabled = zip64 === true;
7065
7382
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
7066
- if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
7383
+ if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
7067
7384
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
7068
7385
  }
7069
- const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
7386
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
7070
7387
  if (!hasContent) {
7071
7388
  level = 0;
7072
7389
  compressionMethod = COMPRESSION_METHOD_STORE;
7073
7390
  }
7074
- const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7391
+ const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
7075
7392
  if (hasContent) {
7076
- if (!passThrough) {
7393
+ if (!passThroughCompression) {
7077
7394
  if (contentSize === UNDEFINED_VALUE) {
7078
7395
  dataDescriptor = true;
7079
7396
  if (zip64 || zip64 === UNDEFINED_VALUE) {
@@ -7086,10 +7403,12 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
7086
7403
  }
7087
7404
  } else {
7088
7405
  options.uncompressedSize = uncompressedSize;
7089
- maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
7406
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
7407
+ getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
7408
+ contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
7090
7409
  }
7091
7410
  }
7092
- const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThrough)) && !isCompressed(compressionMethod, level);
7411
+ const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
7093
7412
  if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7094
7413
  dataDescriptor = false;
7095
7414
  }
@@ -7138,6 +7457,8 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7138
7457
  const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
7139
7458
  let offset = initialOffset;
7140
7459
  let minimumEntrySize = INFINITY_VALUE;
7460
+ const entrySizes = [];
7461
+ const entriesAlreadyZip64 = new Set();
7141
7462
  for (const entry of entries) {
7142
7463
  let { name } = entry;
7143
7464
  const { size } = entry;
@@ -7149,7 +7470,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7149
7470
  ({ name } = attributesInfo);
7150
7471
  const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
7151
7472
  if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
7152
- !metadata.passThrough && !(await supportsDeflate(getConfiguration()))) {
7473
+ !metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
7153
7474
  metadata.level = 0;
7154
7475
  }
7155
7476
  const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
@@ -7157,7 +7478,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7157
7478
  throw new Error(ERR_UNDETERMINED_SIZE);
7158
7479
  }
7159
7480
  const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
7160
- if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
7481
+ if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
7161
7482
  throw new Error(ERR_UNDETERMINED_SIZE);
7162
7483
  }
7163
7484
  const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
@@ -7177,10 +7498,15 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7177
7498
  compressedSize
7178
7499
  }));
7179
7500
  const entrySize = entryInfo.metadataSize + compressedSize;
7501
+ entrySizes.push(entrySize);
7502
+ entriesAlreadyZip64.add(Boolean(entryOptions.zip64Enabled ||
7503
+ entryOptions.uncompressedSize >= MAX_32_BITS || compressedSize >= MAX_32_BITS));
7180
7504
  minimumEntrySize = Math.min(minimumEntrySize, entrySize);
7181
7505
  offset += entrySize;
7182
7506
  }
7183
- const layoutDependsOnWriteOrder = files.size > 1 && (usdz || offset - minimumEntrySize >= MAX_32_BITS);
7507
+ const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
7508
+ (offset - minimumEntrySize >= MAX_32_BITS &&
7509
+ (entriesAlreadyZip64.size > 1 || countEntriesBefore4GB(entrySizes, initialOffset, true) != countEntriesBefore4GB(entrySizes, initialOffset, false))));
7184
7510
  if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
7185
7511
  throw new Error(ERR_UNDETERMINED_SIZE);
7186
7512
  }
@@ -7198,6 +7524,20 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7198
7524
  return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
7199
7525
  }
7200
7526
 
7527
+ function countEntriesBefore4GB(entrySizes, initialOffset, largestFirst) {
7528
+ const ordered = entrySizes.slice().sort((first, second) => largestFirst ? second - first : first - second);
7529
+ let position = initialOffset;
7530
+ let count = 0;
7531
+ for (const entrySize of ordered) {
7532
+ if (position >= MAX_32_BITS) {
7533
+ break;
7534
+ }
7535
+ position += entrySize;
7536
+ count++;
7537
+ }
7538
+ return count;
7539
+ }
7540
+
7201
7541
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
7202
7542
  const {
7203
7543
  fileEntries,
@@ -7373,6 +7713,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7373
7713
  localExtraFieldZip64Length,
7374
7714
  rawExtraFieldExtendedTimestamp,
7375
7715
  extraFieldExtendedTimestampFlag,
7716
+ extraFieldExtendedTimestampTime,
7376
7717
  rawExtraFieldNTFS,
7377
7718
  rawExtraFieldUnix,
7378
7719
  rawExtraFieldAES,
@@ -7385,6 +7726,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7385
7726
  password,
7386
7727
  rawPassword,
7387
7728
  level,
7729
+ useUnicodeFileNames,
7388
7730
  zip64,
7389
7731
  zip64Enabled,
7390
7732
  zip64UncompressedSize,
@@ -7419,7 +7761,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7419
7761
  msdosAttributesRaw,
7420
7762
  msdosAttributes,
7421
7763
  useCompressionStream,
7422
- passThrough,
7764
+ passThroughCompression,
7765
+ passThroughEncryption,
7423
7766
  format,
7424
7767
  codecURI
7425
7768
  } = options;
@@ -7430,9 +7773,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7430
7773
  zip64Enabled,
7431
7774
  directory: Boolean(directory),
7432
7775
  executable: Boolean(executable),
7433
- filenameUTF8: true,
7776
+ filenameUTF8: Boolean(useUnicodeFileNames),
7434
7777
  rawFilename,
7435
- commentUTF8: true,
7778
+ commentUTF8: Boolean(useUnicodeFileNames),
7436
7779
  rawComment,
7437
7780
  rawExtraFieldZip64,
7438
7781
  localExtraFieldZip64Length,
@@ -7463,7 +7806,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7463
7806
  uncompressedSize
7464
7807
  } = options;
7465
7808
  let compressedSize = 0;
7466
- if (!passThrough) {
7809
+ if (!passThroughCompression) {
7467
7810
  uncompressedSize = 0;
7468
7811
  }
7469
7812
  const { writable } = writer;
@@ -7480,9 +7823,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7480
7823
  encryptionStrength,
7481
7824
  zipCrypto: encrypted && zipCrypto,
7482
7825
  passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
7483
- computeCrc32: !passThrough,
7484
- compressed: compressed && !passThrough,
7485
- encrypted: encrypted && !passThrough,
7826
+ computeCrc32: !passThroughCompression,
7827
+ compressed: compressed && !passThroughCompression,
7828
+ encrypted: encrypted && !passThroughEncryption,
7486
7829
  useWebWorkers,
7487
7830
  useCompressionStream,
7488
7831
  transferStreams,
@@ -7497,7 +7840,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7497
7840
  const result = await runWorker({ readable, writable }, workerOptions);
7498
7841
  compressedSize = result.outputSize;
7499
7842
  writer.size += compressedSize;
7500
- if (!passThrough) {
7843
+ if (!passThroughCompression) {
7501
7844
  uncompressedSize = result.inputSize;
7502
7845
  if (!encrypted || zipCrypto) {
7503
7846
  crc32 = result.crc32;
@@ -7540,8 +7883,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7540
7883
  headerArray,
7541
7884
  headerView,
7542
7885
  signature: crc32,
7543
- crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
7886
+ crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
7544
7887
  extraFieldExtendedTimestampFlag,
7888
+ extraFieldExtendedTimestampTime,
7545
7889
  zip64UncompressedSize,
7546
7890
  zip64CompressedSize
7547
7891
  });
@@ -7566,7 +7910,7 @@ function getHeaderInfo(options) {
7566
7910
  encryptionStrength,
7567
7911
  extendedTimestamp,
7568
7912
  ntfsTimestamp,
7569
- passThrough,
7913
+ passThroughCompression,
7570
7914
  encrypted,
7571
7915
  zip64UncompressedSize,
7572
7916
  zip64CompressedSize,
@@ -7577,7 +7921,7 @@ function getHeaderInfo(options) {
7577
7921
  let { version, compressionMethod } = options;
7578
7922
  const compressed = !directory && isCompressed(compressionMethod, level);
7579
7923
  let rawLocalExtraFieldZip64;
7580
- const uncompressedFile = passThrough || !compressed;
7924
+ const uncompressedFile = passThroughCompression || !compressed;
7581
7925
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
7582
7926
  const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
7583
7927
  if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
@@ -7589,8 +7933,8 @@ function getHeaderInfo(options) {
7589
7933
  if (zip64ExtraFieldComplete) {
7590
7934
  extraFieldZip64.writeUint64(uncompressedSize);
7591
7935
  if (uncompressedFile) {
7592
- const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7593
- extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
7936
+ const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
7937
+ extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
7594
7938
  }
7595
7939
  }
7596
7940
  } else {
@@ -7609,6 +7953,7 @@ function getHeaderInfo(options) {
7609
7953
  let rawExtraFieldNTFS;
7610
7954
  let rawExtraFieldExtendedTimestamp;
7611
7955
  let extraFieldExtendedTimestampFlag;
7956
+ let extraFieldExtendedTimestampTime;
7612
7957
  if (extendedTimestamp) {
7613
7958
  const lastModTimeUnix = getTimeUnix(lastModDate);
7614
7959
  const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
@@ -7616,6 +7961,7 @@ function getHeaderInfo(options) {
7616
7961
  const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
7617
7962
  const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
7618
7963
  extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
7964
+ extraFieldExtendedTimestampTime = lastModTimeUnix;
7619
7965
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7620
7966
  extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
7621
7967
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
@@ -7658,7 +8004,7 @@ function getHeaderInfo(options) {
7658
8004
  let rawExtraFieldUnix;
7659
8005
  try {
7660
8006
  const { uid, gid, unixExtraFieldType } = options;
7661
- if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE$1 && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
8007
+ if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
7662
8008
  const uidBytes = packUnixId(uid === UNDEFINED_VALUE ? 0 : uid);
7663
8009
  const gidBytes = packUnixId(gid === UNDEFINED_VALUE ? 0 : gid);
7664
8010
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
@@ -7699,7 +8045,7 @@ function getHeaderInfo(options) {
7699
8045
  }
7700
8046
  if (encrypted && !zipCrypto) {
7701
8047
  version = version > VERSION_AES ? version : VERSION_AES;
7702
- if (passThrough && crc32 !== UNDEFINED_VALUE) {
8048
+ if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
7703
8049
  rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
7704
8050
  }
7705
8051
  setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
@@ -7761,12 +8107,14 @@ function getHeaderInfo(options) {
7761
8107
  headerArray,
7762
8108
  headerView,
7763
8109
  lastModDate: storedLastModDate,
8110
+ lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
7764
8111
  rawLastModDate,
7765
8112
  encrypted,
7766
8113
  compressed,
7767
8114
  version,
7768
8115
  compressionMethod,
7769
8116
  extraFieldExtendedTimestampFlag,
8117
+ extraFieldExtendedTimestampTime,
7770
8118
  rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
7771
8119
  localExtraFieldZip64Length,
7772
8120
  rawExtraFieldExtendedTimestamp,
@@ -7869,7 +8217,7 @@ function setEntryInfo({
7869
8217
  }, {
7870
8218
  zip64,
7871
8219
  zipCrypto,
7872
- passThrough,
8220
+ passThroughCompression,
7873
8221
  dataDescriptor
7874
8222
  }) {
7875
8223
  const {
@@ -7880,7 +8228,7 @@ function setEntryInfo({
7880
8228
  dataDescriptorView,
7881
8229
  dataDescriptorOffset
7882
8230
  } = dataDescriptorInfo;
7883
- if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
8231
+ if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
7884
8232
  setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
7885
8233
  if (dataDescriptor) {
7886
8234
  setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
@@ -7911,9 +8259,9 @@ function updateLocalHeader({
7911
8259
  uncompressedSize,
7912
8260
  zip64UncompressedSize,
7913
8261
  zip64CompressedSize
7914
- }, localHeaderView, { dataDescriptor, passThrough }) {
8262
+ }, localHeaderView, { dataDescriptor, passThroughCompression }) {
7915
8263
  if (!dataDescriptor) {
7916
- if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
8264
+ if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
7917
8265
  setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
7918
8266
  }
7919
8267
  if (!zip64CompressedSize) {
@@ -7950,9 +8298,8 @@ function createDirectoryRecords(files) {
7950
8298
  rawExtraFieldUnix,
7951
8299
  rawExtraField,
7952
8300
  rawCentralExtraField,
7953
- extendedTimestamp,
7954
8301
  extraFieldExtendedTimestampFlag,
7955
- lastModDate,
8302
+ extraFieldExtendedTimestampTime,
7956
8303
  zip64Enabled,
7957
8304
  uncompressedSize,
7958
8305
  compressedSize
@@ -7995,16 +8342,15 @@ function createDirectoryRecords(files) {
7995
8342
  fileEntry.zip64Offset = zip64Offset;
7996
8343
  fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
7997
8344
  let rawExtraFieldTimestamp;
7998
- const lastModTimeUnix = getTimeUnix(lastModDate);
7999
- if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
8345
+ if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
8346
+ rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
8347
+ } else {
8000
8348
  const extraFieldTimestamp = createRecordWriter(9);
8001
8349
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
8002
8350
  extraFieldTimestamp.writeUint16(5);
8003
8351
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
8004
- extraFieldTimestamp.writeUint32(lastModTimeUnix);
8352
+ extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
8005
8353
  rawExtraFieldTimestamp = extraFieldTimestamp.array;
8006
- } else {
8007
- rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
8008
8354
  }
8009
8355
  fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
8010
8356
  const extraFieldLength = getLength(
@@ -8504,6 +8850,11 @@ function getHeaderArrayData({
8504
8850
  };
8505
8851
  }
8506
8852
 
8853
+ function isPrintableASCIIText(rawText) {
8854
+ return rawText.every(characterCode =>
8855
+ characterCode >= MIN_PRINTABLE_ASCII_CHARACTER_CODE && characterCode <= MAX_PRINTABLE_ASCII_CHARACTER_CODE);
8856
+ }
8857
+
8507
8858
  function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
8508
8859
  let bitFlag = 0;
8509
8860
  if (useUnicodeFileNames) {
@@ -8665,7 +9016,7 @@ function formatSupported(StreamClass, format) {
8665
9016
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8666
9017
  */
8667
9018
 
8668
- const VERSION = "2.11.3";
9019
+ const VERSION = "2.12.0";
8669
9020
 
8670
9021
  /*
8671
9022
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9485,9 +9836,9 @@ setDefaultConfiguration({
9485
9836
  DecompressionStreamFallback: DecompressionStreamZlib
9486
9837
  });
9487
9838
 
9488
- function terminateWorkersAndModule() {
9839
+ async function terminateWorkersAndModule() {
9840
+ await terminateWorkers();
9489
9841
  modulePromise = null;
9490
- terminateWorkers();
9491
9842
  resetWasmModule();
9492
9843
  }
9493
9844
 
@@ -9528,7 +9879,10 @@ configureExternalAssets();
9528
9879
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
9529
9880
  const ERR_DUPLICATE_IMPORTED_ENTRY = "Duplicate entry filename in the imported zip file";
9530
9881
  const ERR_INVALID_DUPLICATES = "Invalid duplicates option (must be \"throw\", \"keep-first\" or \"keep-last\")";
9531
- const ERR_ANCESTOR_ENTRY = "Entry is a ancestor of target entry";
9882
+ const ERR_ANCESTOR_ENTRY = "Entry is an ancestor of target entry";
9883
+ const ERR_ROOT_DIRECTORY_NOT_MOVABLE = "Root directory cannot be moved";
9884
+ const ERR_TARGET_NOT_DIRECTORY = "Target entry is not a directory";
9885
+ const ERR_PARENT_NOT_DIRECTORY = "Parent entry is not a directory";
9532
9886
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
9533
9887
  const DUPLICATES_THROW = "throw";
9534
9888
  const DUPLICATES_KEEP_FIRST = "keep-first";
@@ -9536,24 +9890,8 @@ const DUPLICATES_KEEP_LAST = "keep-last";
9536
9890
  const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPLICATES_KEEP_LAST]);
9537
9891
  const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
9538
9892
  const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
9539
- const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
9893
+ const ERR_UNSUPPORTED_PASS_THROUGH_VALUE = "The 'compressed' passThrough option is only supported by Entry#getData() and ZipWriter#add()";
9540
9894
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
9541
- const ERR_ABORTED = "The operation was aborted";
9542
- const ABORT_ERROR_NAME = "AbortError";
9543
- const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
9544
- const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
9545
- EXTRAFIELD_TYPE_ZIP64,
9546
- EXTRAFIELD_TYPE_AES,
9547
- EXTRAFIELD_TYPE_NTFS,
9548
- EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
9549
- EXTRAFIELD_TYPE_UNICODE_PATH,
9550
- EXTRAFIELD_TYPE_UNICODE_COMMENT,
9551
- EXTRAFIELD_TYPE_USDZ,
9552
- EXTRAFIELD_TYPE_INFOZIP,
9553
- EXTRAFIELD_TYPE_UNIX,
9554
- EXTRAFIELD_TYPE_UNIX_TYPE1,
9555
- EXTRAFIELD_TYPE_PKWARE_UNIX
9556
- ]);
9557
9895
 
9558
9896
  class ZipEntry {
9559
9897
 
@@ -9925,6 +10263,7 @@ class ZipDirectoryEntry extends ZipEntry {
9925
10263
  await initStream(reader);
9926
10264
  zipReader = new ZipReader(reader, options);
9927
10265
  }
10266
+ checkPassThroughValue(options.passThrough);
9928
10267
  const duplicates = checkDuplicatesOption(options.duplicates);
9929
10268
  const importedEntries = [];
9930
10269
  const entries = await zipReader.getEntries(options);
@@ -10015,18 +10354,25 @@ class ZipDirectoryEntry extends ZipEntry {
10015
10354
 
10016
10355
  async exportZip(writer, options = {}) {
10017
10356
  const zipEntry = this;
10357
+ const zipWriterProvided = Boolean(writer) && typeof writer.add == FUNCTION_TYPE;
10018
10358
  options = Object.assign({}, options);
10019
- if (options.bufferedWrite === UNDEFINED_VALUE) {
10359
+ if (!zipWriterProvided && options.bufferedWrite === UNDEFINED_VALUE) {
10020
10360
  options.bufferedWrite = true;
10021
10361
  }
10022
- const [readers] = await Promise.all([initReaders(zipEntry, checkReaderOptions(options.readerOptions)), initStream(writer)]);
10023
- const zipWriter = new ZipWriter(writer, options);
10362
+ const [readers] = await Promise.all([
10363
+ initReaders(zipEntry, checkReaderOptions(options.readerOptions)),
10364
+ zipWriterProvided ? UNDEFINED_VALUE : initStream(writer)
10365
+ ]);
10366
+ const zipWriter = zipWriterProvided ? writer : new ZipWriter(writer, options);
10024
10367
  await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
10368
+ if (zipWriterProvided) {
10369
+ return zipWriter;
10370
+ }
10025
10371
  await zipWriter.close(options.globalComment);
10026
10372
  return writer.getData ? writer.getData() : writer.writable;
10027
10373
  }
10028
10374
 
10029
- getExportedSize(options = {}) {
10375
+ async getExportedSize(options = {}) {
10030
10376
  const zipEntry = this;
10031
10377
  options = Object.assign({}, options);
10032
10378
  checkReaderOptions(options.readerOptions);
@@ -10041,7 +10387,7 @@ class ZipDirectoryEntry extends ZipEntry {
10041
10387
  const writeOrderGuaranteed = !options.bufferedWrite ||
10042
10388
  (entries.every(entry => entry.options.keepOrder !== false) &&
10043
10389
  children.every(child => isImplicitDirectory(child) || !child.children.length));
10044
- return getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
10390
+ return await getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
10045
10391
  }
10046
10392
 
10047
10393
  getChildByName(name) {
@@ -10102,7 +10448,7 @@ class ZipFS {
10102
10448
 
10103
10449
  move(entry, destination) {
10104
10450
  if (entry == this.root) {
10105
- throw new Error("Root directory cannot be moved");
10451
+ throw new Error(ERR_ROOT_DIRECTORY_NOT_MOVABLE);
10106
10452
  } else {
10107
10453
  if (destination.directory) {
10108
10454
  if (!destination.isDescendantOf(entry)) {
@@ -10123,7 +10469,7 @@ class ZipFS {
10123
10469
  throw new Error(ERR_ANCESTOR_ENTRY);
10124
10470
  }
10125
10471
  } else {
10126
- throw new Error("Target entry is not a directory");
10472
+ throw new Error(ERR_TARGET_NOT_DIRECTORY);
10127
10473
  }
10128
10474
  }
10129
10475
  }
@@ -10436,70 +10782,11 @@ function getChildEntryOptions(child, selectedEntry, options) {
10436
10782
  let zipEntryMetadata = {};
10437
10783
  let passThroughOptions = {};
10438
10784
  if (child.data instanceof Entry) {
10439
- const {
10440
- externalFileAttributes,
10441
- versionMadeBy,
10442
- comment,
10443
- lastModDate,
10444
- rawLastModDate,
10445
- creationDate,
10446
- lastAccessDate,
10447
- uncompressedSize,
10448
- encrypted,
10449
- zipCrypto,
10450
- crc32,
10451
- compressionMethod,
10452
- extraFieldAES,
10453
- internalFileAttributes,
10454
- extraField,
10455
- bitFlag,
10456
- uid,
10457
- gid
10458
- } = child.data;
10459
- zipEntryMetadata = {
10460
- externalFileAttributes,
10461
- versionMadeBy,
10462
- comment,
10463
- lastModDate,
10464
- creationDate,
10465
- lastAccessDate,
10466
- internalFileAttributes
10467
- };
10468
- const userExtraField = getUserExtraField(extraField);
10469
- if (userExtraField) {
10470
- zipEntryMetadata.extraField = userExtraField;
10471
- }
10472
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
10473
- Object.assign(zipEntryMetadata, {
10474
- uid,
10475
- gid,
10476
- unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
10477
- });
10478
- }
10479
- if (isPassThrough(child, options)) {
10480
- let encryptionStrength;
10481
- if (extraFieldAES) {
10482
- encryptionStrength = extraFieldAES.strength;
10483
- }
10484
- passThroughOptions = {
10485
- passThrough: true,
10486
- encrypted,
10487
- zipCrypto,
10488
- crc32,
10489
- uncompressedSize,
10490
- encryptionStrength,
10491
- compressionMethod
10492
- };
10493
- if (bitFlag) {
10494
- passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
10495
- }
10496
- const lastModDateOverride = childOptions.lastModDate === UNDEFINED_VALUE ? options.lastModDate : childOptions.lastModDate;
10497
- if (lastModDateOverride === UNDEFINED_VALUE) {
10498
- passThroughOptions.rawLastModDate = rawLastModDate;
10499
- } else if (zipCrypto && (!bitFlag || bitFlag.dataDescriptor) && lastModDateOverride instanceof Date &&
10500
- getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
10501
- throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
10502
- }
10785
+ const passThrough = isPassThrough(child, options);
10786
+ const lastModDateOverride = childOptions.lastModDate === UNDEFINED_VALUE ? options.lastModDate : childOptions.lastModDate;
10787
+ ({ entryOptions: zipEntryMetadata, passThroughOptions } = getSourceEntryOptions(child.data, passThrough, lastModDateOverride));
10788
+ if (passThrough) {
10789
+ passThroughOptions.passThrough = true;
10503
10790
  }
10504
10791
  }
10505
10792
  const entryOptions = Object.assign({ lastModDate: child.defaultLastModDate }, zipEntryMetadata, options, childOptions, passThroughOptions, { directory: child.directory });
@@ -10509,16 +10796,6 @@ function getChildEntryOptions(child, selectedEntry, options) {
10509
10796
  return { name, entryOptions };
10510
10797
  }
10511
10798
 
10512
- function getDosTimeHighByte(lastModDate) {
10513
- let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
10514
- if (dosLastModDate < MIN_DATE) {
10515
- dosLastModDate = MIN_DATE;
10516
- } else if (dosLastModDate > MAX_DATE) {
10517
- dosLastModDate = MAX_DATE;
10518
- }
10519
- return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
10520
- }
10521
-
10522
10799
  function getDeterminedSize(child, passThrough) {
10523
10800
  const { reader } = child;
10524
10801
  if (reader && reader.size !== UNDEFINED_VALUE) {
@@ -10531,9 +10808,18 @@ function checkReaderOptions(readerOptions) {
10531
10808
  if (readerOptions && (typeof readerOptions != OBJECT_TYPE || Array.isArray(readerOptions))) {
10532
10809
  throw new Error(ERR_INVALID_READER_OPTIONS);
10533
10810
  }
10811
+ if (readerOptions) {
10812
+ checkPassThroughValue(readerOptions.passThrough);
10813
+ }
10534
10814
  return readerOptions;
10535
10815
  }
10536
10816
 
10817
+ function checkPassThroughValue(passThrough) {
10818
+ if (checkPassThroughOption(passThrough) === PASS_THROUGH_COMPRESSED) {
10819
+ throw new Error(ERR_UNSUPPORTED_PASS_THROUGH_VALUE);
10820
+ }
10821
+ }
10822
+
10537
10823
  function replaceContent(zipEntry, params) {
10538
10824
  const { uncompressedSize } = params;
10539
10825
  Object.assign(zipEntry, params, {
@@ -10562,20 +10848,6 @@ function isImplicitDirectory(child) {
10562
10848
  return child.directory && child.data === null;
10563
10849
  }
10564
10850
 
10565
- function getUserExtraField(extraField) {
10566
- if (extraField) {
10567
- const userExtraField = new Map();
10568
- extraField.forEach((field, type) => {
10569
- if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
10570
- userExtraField.set(type, field.data);
10571
- }
10572
- });
10573
- if (userExtraField.size) {
10574
- return userExtraField;
10575
- }
10576
- }
10577
- }
10578
-
10579
10851
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
10580
10852
  const { onstart, onprogress, onend, onentryprogress } = options;
10581
10853
  const selectedEntry = entry;
@@ -10678,6 +10950,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
10678
10950
 
10679
10951
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
10680
10952
  const { onstart, onprogress, onend } = options;
10953
+ checkPassThroughValue(options.passThrough);
10681
10954
  const readerOptions = checkReaderOptions(options.readerOptions);
10682
10955
  const abortController = new AbortController();
10683
10956
  const { signal } = abortController;
@@ -10753,7 +11026,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
10753
11026
  if (exportAborted || isExportAborted(signal.reason)) {
10754
11027
  return;
10755
11028
  }
10756
- throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
11029
+ throwIfAborted(signal);
10757
11030
  }
10758
11031
  try {
10759
11032
  if (child.directory) {
@@ -10886,7 +11159,7 @@ function addChild(parent, name, params, directory) {
10886
11159
  }
10887
11160
  return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
10888
11161
  } else {
10889
- throw new Error("Parent entry is not a directory");
11162
+ throw new Error(ERR_PARENT_NOT_DIRECTORY);
10890
11163
  }
10891
11164
  }
10892
11165
 
@@ -10991,4 +11264,4 @@ function decodeMimeTypes(data) {
10991
11264
  return mimeTypes;
10992
11265
  }
10993
11266
 
10994
- export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_ENTRY_EXISTS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_DUPLICATES, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_PASS_THROUGH, ERR_INVALID_READER, ERR_INVALID_READER_OPTIONS, ERR_INVALID_SIGNAL, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, ERR_INVALID_UID, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_UNIX_EXTRA_FIELD_TYPE, ERR_INVALID_UNIX_ID_SIZE, ERR_INVALID_UNIX_MODE, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_READABLE_CONSUMED, ERR_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_SPLIT_USDZ, ERR_UNSUPPORTED_UINT64, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, VERSION, WARNING_APPENDED_DATA, WARNING_COMPRESSED_PATCHED_DATA, WARNING_DUPLICATE_FILENAME, WARNING_MALFORMED_EXTRA_FIELD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY, WARNING_PREPENDED_CENTRAL_DIRECTORY, WARNING_PREPENDED_DATA, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA, WARNING_UNKNOWN_VERSION, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA, WARNING_UNSORTED_CENTRAL_DIRECTORY, WARNING_WRAPPED_ENTRIES_COUNT, Writer, ZipDirectoryEntry, ZipEntry, ZipFS, ZipFileEntry, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, isZipFile, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
11267
+ export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_ANCESTOR_ENTRY, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_DUPLICATE_IMPORTED_ENTRY, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_ENTRY_EXISTS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_HTTP_STATUS, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_BASE_URI, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_DUPLICATES, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_PASS_THROUGH, ERR_INVALID_PASS_THROUGH_VALUE, ERR_INVALID_READER, ERR_INVALID_READER_OPTIONS, ERR_INVALID_SIGNAL, ERR_INVALID_SIGNATURE_DATA, ERR_INVALID_STRICTNESS, ERR_INVALID_UID, ERR_INVALID_UNCOMPRESSED_SIZE, ERR_INVALID_UNIX_EXTRA_FIELD_TYPE, ERR_INVALID_UNIX_ID_SIZE, ERR_INVALID_UNIX_MODE, ERR_INVALID_URI, ERR_INVALID_VERSION, ERR_ITERATOR_COMPLETED_TOO_SOON, ERR_LOCAL_FILE_HEADER_NOT_FOUND, ERR_OVERLAPPING_ENTRY, ERR_PARENT_NOT_DIRECTORY, ERR_READABLE_CONSUMED, ERR_RESERVED_COMPRESSION_METHOD, ERR_ROOT_DIRECTORY_NOT_MOVABLE, ERR_SPLIT_ZIP_FILE, ERR_TARGET_NOT_DIRECTORY, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_CRC32, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_UNSUPPORTED_PASS_THROUGH_VALUE, ERR_UNSUPPORTED_SPLIT_USDZ, ERR_UNSUPPORTED_UINT64, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_WRITER_SIZE_NOT_WRITABLE, ERR_ZIP_CRYPTO_LAST_MOD_DATE, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, VERSION, WARNING_APPENDED_DATA, WARNING_CLAMPED_LAST_MODIFICATION_DATE, WARNING_COMPRESSED_PATCHED_DATA, WARNING_COMPRESSION_UNAVAILABLE, WARNING_DUPLICATE_FILENAME, WARNING_MALFORMED_EXTRA_FIELD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG, WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD, WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME, WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY, WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY, WARNING_PREPENDED_CENTRAL_DIRECTORY, WARNING_PREPENDED_DATA, WARNING_TRAILING_CENTRAL_DIRECTORY_DATA, WARNING_UNKNOWN_VERSION, WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA, WARNING_UNSORTED_CENTRAL_DIRECTORY, WARNING_WRAPPED_ENTRIES_COUNT, Writer, ZipDirectoryEntry, ZipEntry, ZipFS, ZipFileEntry, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, getRegisteredCodecs, getSupportedCompressionMethods, isZipFile, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };