@zip.js/zip.js 2.11.4 → 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 +427 -110
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +437 -107
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +492 -230
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +505 -227
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +492 -230
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +507 -229
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +508 -230
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +439 -109
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +439 -109
  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 +440 -110
  23. package/dist/zip.min.js +1 -1
  24. package/index-native.cjs +507 -229
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +508 -230
  27. package/index.d.cts +468 -59
  28. package/index.d.ts +468 -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 +13 -5
  35. package/lib/core/options.js +16 -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 -132
  44. package/lib/core/zip-reader.js +106 -48
  45. package/lib/core/zip-writer.js +236 -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,18 @@ 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')";
211
216
  const ERR_ABORTED = "The operation was aborted";
212
217
  const ABORT_ERROR_NAME = "AbortError";
213
218
 
@@ -237,6 +242,13 @@ function checkPasswordOption(password, rawPassword) {
237
242
  }
238
243
  }
239
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
+
240
252
  function checkInteger(value, maxValue, errorMessage) {
241
253
  if (!Number.isInteger(value) || value < 0 || value > maxValue) {
242
254
  throw new Error(errorMessage);
@@ -286,6 +298,8 @@ const DEFAULT_CHUNK_SIZE$1 = 64 * 1024;
286
298
  const MINIMUM_CHUNK_SIZE = 64;
287
299
  const MINIMUM_PROPERTY_VALUE = 1;
288
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)";
289
303
  let maxWorkers = 2;
290
304
  try {
291
305
  if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
@@ -310,9 +324,9 @@ const DEFAULT_CONFIGURATION = {
310
324
  };
311
325
 
312
326
  const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
327
+ const PROPERTY_NAME_BASE_URI = "baseURI";
313
328
 
314
- const STRING_PROPERTY_NAMES = [
315
- "baseURI",
329
+ const URI_PROPERTY_NAMES = [
316
330
  "wasmURI",
317
331
  "workerURI"
318
332
  ];
@@ -336,7 +350,8 @@ const FUNCTION_PROPERTY_NAMES = [
336
350
  "DecompressionStreamFallback"
337
351
  ];
338
352
  const CONFIGURABLE_PROPERTY_NAMES = [
339
- ...STRING_PROPERTY_NAMES,
353
+ PROPERTY_NAME_BASE_URI,
354
+ ...URI_PROPERTY_NAMES,
340
355
  ...BOOLEAN_PROPERTY_NAMES,
341
356
  ...NUMBER_PROPERTY_NAMES,
342
357
  ...FUNCTION_PROPERTY_NAMES
@@ -380,6 +395,14 @@ function checkPropertyValue(propertyName, propertyValue) {
380
395
  }
381
396
  } else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
382
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
+ }
383
406
  }
384
407
  return propertyValue;
385
408
  }
@@ -2632,6 +2655,7 @@ class ChunkStream extends TransformStream {
2632
2655
  constructor(chunkSize) {
2633
2656
  const pendingChunks = [];
2634
2657
  let pendingLength = 0;
2658
+ let outputSize = 0;
2635
2659
  if (!Number.isFinite(chunkSize) || chunkSize < 1) {
2636
2660
  chunkSize = DEFAULT_CHUNK_SIZE;
2637
2661
  }
@@ -2640,15 +2664,20 @@ class ChunkStream extends TransformStream {
2640
2664
  pendingChunks.push(chunk);
2641
2665
  pendingLength += chunk.length;
2642
2666
  while (pendingLength > chunkSize) {
2667
+ outputSize += chunkSize;
2643
2668
  controller.enqueue(shiftChunk());
2644
2669
  }
2645
2670
  },
2646
2671
  flush(controller) {
2647
2672
  if (pendingLength) {
2673
+ outputSize += pendingLength;
2648
2674
  controller.enqueue(concatChunks(pendingChunks, pendingLength));
2649
2675
  }
2650
2676
  }
2651
2677
  });
2678
+ Object.defineProperty(this, "outputSize", {
2679
+ get: () => outputSize
2680
+ });
2652
2681
 
2653
2682
  function shiftChunk() {
2654
2683
  const result = new Uint8Array(chunkSize);
@@ -2853,7 +2882,7 @@ function createWorkerInterface(workerData, config) {
2853
2882
  }
2854
2883
 
2855
2884
  async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
2856
- let codecStream;
2885
+ let codecStream, chunkStream;
2857
2886
  try {
2858
2887
  if (options.compressed && !options.format) {
2859
2888
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
@@ -2876,9 +2905,10 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
2876
2905
  }
2877
2906
  }
2878
2907
  codecStream = new CodecStream(options, config);
2908
+ chunkStream = new ChunkStream(getChunkSize(config));
2879
2909
  await readable
2880
2910
  .pipeThrough(codecStream)
2881
- .pipeThrough(new ChunkStream(getChunkSize(config)))
2911
+ .pipeThrough(chunkStream)
2882
2912
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2883
2913
  const {
2884
2914
  crc32,
@@ -2892,7 +2922,7 @@ async function runWorker$1({ options, readable, writable, onTaskFinished }, conf
2892
2922
  };
2893
2923
  } catch (error) {
2894
2924
  if (codecStream) {
2895
- error.outputSize = codecStream.outputSize;
2925
+ error.outputSize = chunkStream ? chunkStream.outputSize : 0;
2896
2926
  }
2897
2927
  throw error;
2898
2928
  } finally {
@@ -3001,11 +3031,17 @@ async function runWebWorker(workerData, config) {
3001
3031
  let resolveResult, rejectResult;
3002
3032
  const result = new Promise((resolve, reject) => {
3003
3033
  resolveResult = resolve;
3004
- rejectResult = reject;
3034
+ rejectResult = error => {
3035
+ if (error && error.outputSize === UNDEFINED_VALUE) {
3036
+ error.outputSize = workerData.outputSize;
3037
+ }
3038
+ reject(error);
3039
+ };
3005
3040
  });
3006
3041
  Object.assign(workerData, {
3007
3042
  reader: null,
3008
3043
  writer: null,
3044
+ outputSize: 0,
3009
3045
  resolveResult,
3010
3046
  rejectResult,
3011
3047
  result
@@ -3289,8 +3325,10 @@ async function onMessage({ data }, workerData) {
3289
3325
  }
3290
3326
  }
3291
3327
  if (type == MESSAGE_DATA) {
3328
+ const chunk = new Uint8Array(value);
3292
3329
  await writer.ready;
3293
- await writer.write(new Uint8Array(value));
3330
+ await writer.write(chunk);
3331
+ workerData.outputSize += chunk.length;
3294
3332
  if (!stale()) {
3295
3333
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3296
3334
  }
@@ -3598,10 +3636,13 @@ function decode(value, encoding, ignoreBOM) {
3598
3636
 
3599
3637
 
3600
3638
  const ERR_HTTP_STATUS = "HTTP error ";
3639
+ const MIN_SUCCESS_HTTP_STATUS = 200;
3640
+ const MAX_SUCCESS_HTTP_STATUS = 299;
3601
3641
  const ERR_HTTP_RANGE = "HTTP Range not supported";
3602
3642
  const ERR_HTTP_RESOURCE_CHANGED = "HTTP resource changed";
3603
3643
  const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
3604
3644
  const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
3645
+ const ERR_WRITER_SIZE_NOT_WRITABLE = "Invalid writer (size must be writable)";
3605
3646
 
3606
3647
  const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
3607
3648
  const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
@@ -3793,6 +3834,7 @@ class BlobReader extends Reader {
3793
3834
  const reader = this;
3794
3835
  const { sourceBlob, size } = reader;
3795
3836
  const { offset = 0, size: readSize = size - offset } = options || {};
3837
+ // deno-lint-ignore valid-typeof
3796
3838
  if (typeof sourceBlob.stream == FUNCTION_TYPE) {
3797
3839
  if (!offset && readSize >= size) {
3798
3840
  return toCompatibleReadable(sourceBlob.stream());
@@ -4199,7 +4241,7 @@ async function getContentLength(httpReader, sendRequest, getRequestData) {
4199
4241
 
4200
4242
  async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
4201
4243
  const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
4202
- if (response.status < 400) {
4244
+ if (response.status >= MIN_SUCCESS_HTTP_STATUS && response.status <= MAX_SUCCESS_HTTP_STATUS) {
4203
4245
  return response;
4204
4246
  } else {
4205
4247
  throw response.status == 416 ? new Error(ERR_HTTP_RANGE) : new Error(ERR_HTTP_STATUS + (response.statusText || response.status));
@@ -4210,7 +4252,7 @@ function sendXMLHttpRequest(method, { url }, headers) {
4210
4252
  return new Promise((resolve, reject) => {
4211
4253
  const request = new XMLHttpRequest();
4212
4254
  request.addEventListener("load", () => {
4213
- if (request.status < 400) {
4255
+ if (request.status >= MIN_SUCCESS_HTTP_STATUS && request.status <= MAX_SUCCESS_HTTP_STATUS) {
4214
4256
  const headers = [];
4215
4257
  request.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(header => {
4216
4258
  const splitHeader = header.trim().split(/\s*:\s*/);
@@ -4514,8 +4556,10 @@ class GenericWriter {
4514
4556
  writable: toCompatibleWritable(writer)
4515
4557
  };
4516
4558
  }
4517
- if (writer.size === UNDEFINED_VALUE) {
4518
- 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);
4519
4563
  }
4520
4564
  return writer;
4521
4565
  }
@@ -4563,6 +4607,45 @@ function createReadable(reader, options) {
4563
4607
  }
4564
4608
  }
4565
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
+
4566
4649
  /*
4567
4650
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4568
4651
 
@@ -4591,6 +4674,7 @@ function createReadable(reader, options) {
4591
4674
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4592
4675
  */
4593
4676
 
4677
+
4594
4678
  const PROPERTY_NAME_FILENAME = "filename";
4595
4679
  const PROPERTY_NAME_RAW_FILENAME = "rawFilename";
4596
4680
  const PROPERTY_NAME_COMMENT = "comment";
@@ -4715,6 +4799,38 @@ class Entry {
4715
4799
 
4716
4800
  }
4717
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
+
4718
4834
  /*
4719
4835
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4720
4836
 
@@ -4774,6 +4890,8 @@ const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
4774
4890
  const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
4775
4891
  const WARNING_DUPLICATE_FILENAME = "duplicate filename";
4776
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)";
4777
4895
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
4778
4896
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
4779
4897
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
@@ -4844,7 +4962,7 @@ class ZipReader {
4844
4962
  }
4845
4963
  }
4846
4964
  if (rejectAmbiguousEndOfDirectory && endOfDirectoryReachingEndCount > 1) {
4847
- throwAmbiguousArchive("multiple end of central directory records");
4965
+ throwAmbiguousArchive(WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY);
4848
4966
  }
4849
4967
  const endOfDirectoryView = getDataView(endOfDirectoryInfo);
4850
4968
  let directoryDataLength = getUint32$1(endOfDirectoryView, 12);
@@ -5142,7 +5260,8 @@ class ZipReader {
5142
5260
  const writer = new TransformStream();
5143
5261
  const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
5144
5262
  arrayBufferPromise.catch(() => { });
5145
- await fileEntry.getData(writer, entry, zipReader.readRanges, options);
5263
+ await fileEntry.getData(writer, entry, zipReader.readRanges,
5264
+ Object.assign({}, options, { preventClose: false }));
5146
5265
  return arrayBufferPromise;
5147
5266
  };
5148
5267
  offset = endOffset;
@@ -5223,49 +5342,101 @@ class ZipReader {
5223
5342
  await reader.readable.cancel();
5224
5343
  }
5225
5344
  }
5345
+
5346
+ [SYMBOL_ASYNC_DISPOSE]() {
5347
+ return this.close();
5348
+ }
5226
5349
  }
5227
5350
 
5228
5351
  class ZipReaderStream {
5229
5352
 
5230
5353
  constructor(options = {}) {
5231
- const { readable, writable } = new TransformStream();
5232
- 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();
5233
5363
  this.readable = new ReadableStream({
5234
5364
  async pull(controller) {
5235
5365
  const { done, value } = await gen.next();
5236
5366
  if (done)
5237
5367
  return controller.close();
5238
- const entryReadable = (function () {
5239
- const { readable, writable } = new TransformStream();
5240
- if (value.getData) {
5241
- getData();
5242
- return readable;
5243
- }
5244
-
5245
- async function getData() {
5246
- try {
5247
- await value.getData(writable);
5248
- } catch (error) {
5249
- try {
5250
- await writable.abort(error);
5251
- } catch {
5252
- // ignored
5253
- }
5254
- }
5255
- }
5256
- })();
5368
+ const entryStream = createEntryStream(value, pendingEntries);
5257
5369
  const chunk = {
5258
5370
  ...value,
5259
- readable: entryReadable
5371
+ readable: entryStream.readable
5260
5372
  };
5261
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
+ });
5262
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()]);
5263
5392
  }
5264
5393
  });
5265
5394
  this.writable = writable;
5266
5395
  }
5267
5396
  }
5268
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
+
5269
5440
  async function isZipFile(reader, options = {}) {
5270
5441
  reader = new GenericReader(reader);
5271
5442
  await initStream(reader);
@@ -5325,7 +5496,9 @@ let ZipEntry$1 = class ZipEntry {
5325
5496
  const dataView = getDataView(dataArray);
5326
5497
  let password = getOptionValue$1(zipEntry, options, OPTION_PASSWORD);
5327
5498
  let rawPassword = getOptionValue$1(zipEntry, options, OPTION_RAW_PASSWORD);
5328
- 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;
5329
5502
  checkPasswordOption(password, rawPassword);
5330
5503
  password = password && password.length && password;
5331
5504
  rawPassword = rawPassword && rawPassword.length && rawPassword;
@@ -5346,7 +5519,9 @@ let ZipEntry$1 = class ZipEntry {
5346
5519
  const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5347
5520
  const entryStrictness = getStrictness(options, zipEntry.options);
5348
5521
  const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5349
- 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);
5350
5525
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5351
5526
  if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5352
5527
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
@@ -5377,16 +5552,17 @@ let ZipEntry$1 = class ZipEntry {
5377
5552
  if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5378
5553
  fileEntry.gid = gid;
5379
5554
  }
5380
- 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);
5381
5557
  const zipCrypto = encrypted && !extraFieldAES;
5382
- if (!passThrough) {
5558
+ if (!passThroughEncryption) {
5383
5559
  fileEntry.zipCrypto = zipCrypto;
5384
5560
  }
5385
5561
  if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5386
5562
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
5387
5563
  }
5388
- const registeredCodec = passThrough ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
5389
- 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) {
5390
5566
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
5391
5567
  }
5392
5568
  if (encrypted) {
@@ -5403,15 +5579,16 @@ let ZipEntry$1 = class ZipEntry {
5403
5579
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
5404
5580
  const signal = checkSignalOption(getOptionValue$1(zipEntry, options, OPTION_SIGNAL));
5405
5581
  throwIfAborted(signal);
5406
- const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5407
5582
  let checkOverlappingEntry = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
5408
5583
  const checkOverlappingEntryOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
5409
5584
  if (checkOverlappingEntryOnly) {
5410
5585
  checkOverlappingEntry = true;
5411
5586
  }
5412
5587
  const { onstart, onprogress, onend } = options;
5413
- const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
5414
- 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;
5415
5592
  const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
5416
5593
  let useCompressionStream = getOptionValue$1(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
5417
5594
  if (deflate64) {
@@ -5420,7 +5597,7 @@ let ZipEntry$1 = class ZipEntry {
5420
5597
  const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
5421
5598
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
5422
5599
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
5423
- checkCrc32Option) && !passThrough &&
5600
+ checkCrc32Option) && !passThroughCompression &&
5424
5601
  (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
5425
5602
  const workerOptions = {
5426
5603
  options: {
@@ -5474,10 +5651,10 @@ let ZipEntry$1 = class ZipEntry {
5474
5651
  await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
5475
5652
  ({ writable } = writer);
5476
5653
  const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
5477
- writer.size += writtenSize;
5478
5654
  if (writtenSize != outputSize) {
5479
- throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
5655
+ throw Object.assign(new Error(ERR_INVALID_UNCOMPRESSED_SIZE), { outputSize: writtenSize });
5480
5656
  }
5657
+ writer.size += writtenSize;
5481
5658
  }
5482
5659
  } catch (error) {
5483
5660
  if (error.outputSize !== UNDEFINED_VALUE) {
@@ -6143,7 +6320,7 @@ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, chec
6143
6320
  if (checkLocalFilename && !maskedLocalDirectory &&
6144
6321
  (rawLocalFilename.length != rawFilename.length ||
6145
6322
  rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
6146
- reportAmbiguity(reject, warnings, "mismatched local file header (filename)");
6323
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME);
6147
6324
  }
6148
6325
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
6149
6326
  reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
@@ -6168,16 +6345,6 @@ function reportAmbiguity(reject, warnings, reason) {
6168
6345
  }
6169
6346
  }
6170
6347
 
6171
- function addWarning(warnings, reason, filename) {
6172
- if (!warnings.some(warning => warning.reason == reason)) {
6173
- const warning = { reason };
6174
- if (filename !== UNDEFINED_VALUE) {
6175
- warning.filename = filename;
6176
- }
6177
- warnings.push(warning);
6178
- }
6179
- }
6180
-
6181
6348
  function throwAmbiguousArchive(reason) {
6182
6349
  const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
6183
6350
  error.reason = reason;
@@ -6257,7 +6424,9 @@ var zipReader = /*#__PURE__*/Object.freeze({
6257
6424
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
6258
6425
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
6259
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,
6260
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,
6261
6430
  WARNING_PREPENDED_CENTRAL_DIRECTORY: WARNING_PREPENDED_CENTRAL_DIRECTORY,
6262
6431
  WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
6263
6432
  WARNING_TRAILING_CENTRAL_DIRECTORY_DATA: WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
@@ -6310,7 +6479,7 @@ const ERR_INVALID_VERSION = "Version exceeds 65535";
6310
6479
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
6311
6480
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
6312
6481
  const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
6313
- 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)";
6314
6483
  const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
6315
6484
  const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
6316
6485
  const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
@@ -6322,6 +6491,7 @@ const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
6322
6491
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
6323
6492
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
6324
6493
  const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
6494
+ const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
6325
6495
  const ERR_UNDETERMINED_SIZE = "Undetermined size";
6326
6496
  const ERR_UNDEFINED_READER = "Undefined reader";
6327
6497
  const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
@@ -6335,14 +6505,21 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
6335
6505
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
6336
6506
  const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
6337
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";
6338
6512
 
6339
6513
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
6340
6514
  const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
6341
6515
  const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
6342
6516
  const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
6517
+ const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
6518
+ const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
6343
6519
  const VENDOR_VERSION_AE_1 = 1;
6344
- const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
6520
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
6345
6521
  const UNIX_EXTRA_FIELD_TYPE = "unix";
6522
+ const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
6346
6523
  const MAX_LEVEL = 9;
6347
6524
 
6348
6525
  let workers = 0;
@@ -6369,9 +6546,11 @@ class ZipWriter {
6369
6546
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
6370
6547
  pendingAddFileCalls: new Set(),
6371
6548
  pendingErrors: [],
6549
+ warnings: [],
6372
6550
  bufferedWrites: 0,
6373
6551
  directWrites: 0,
6374
- lastFileEntry: UNDEFINED_VALUE
6552
+ lastFileEntry: UNDEFINED_VALUE,
6553
+ archiveClosed: false
6375
6554
  });
6376
6555
  }
6377
6556
 
@@ -6536,6 +6715,9 @@ class ZipWriter {
6536
6715
  const zipWriter = this;
6537
6716
  const { pendingAddFileCalls, writer } = this;
6538
6717
  const { writable } = writer;
6718
+ if (zipWriter.archiveClosed) {
6719
+ return getWriterData(writer);
6720
+ }
6539
6721
  if (!(comment instanceof Uint8Array)) {
6540
6722
  throw new Error(ERR_INVALID_COMMENT_TYPE);
6541
6723
  }
@@ -6559,11 +6741,16 @@ class ZipWriter {
6559
6741
  throw error;
6560
6742
  }
6561
6743
  await closeFile(zipWriter, comment, options);
6744
+ zipWriter.archiveClosed = true;
6562
6745
  const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6563
6746
  if (!preventClose) {
6564
6747
  await writable.getWriter().close();
6565
6748
  }
6566
- return writer.getData ? writer.getData() : writable;
6749
+ return getWriterData(writer);
6750
+ }
6751
+
6752
+ [SYMBOL_ASYNC_DISPOSE]() {
6753
+ return this.close();
6567
6754
  }
6568
6755
  }
6569
6756
 
@@ -6642,6 +6829,10 @@ class WatchedPromise extends Promise {
6642
6829
  }
6643
6830
  }
6644
6831
 
6832
+ function getWriterData(writer) {
6833
+ return writer.getData ? writer.getData() : writer.writable;
6834
+ }
6835
+
6645
6836
  function watchPromiseError(zipWriter, promise) {
6646
6837
  const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6647
6838
  const watcher = {};
@@ -6660,6 +6851,14 @@ async function prependZipEntries(zipWriter, reader) {
6660
6851
 
6661
6852
  async function addFileEntry(zipWriter, name, reader, options) {
6662
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
+ }
6663
6862
  if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6664
6863
  name += DIRECTORY_SIGNATURE;
6665
6864
  }
@@ -6724,21 +6923,33 @@ async function addFile(zipWriter, name, reader, options) {
6724
6923
  try {
6725
6924
  const { resolvedOptions } = metadataInfo;
6726
6925
  if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
6727
- !resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
6926
+ !resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
6728
6927
  resolvedOptions.level = 0;
6928
+ addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
6729
6929
  }
6730
6930
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
6731
6931
  ({ reader } = sizesInfo);
6732
6932
  const diskOffset = getDiskOffset(zipWriter.writer);
6733
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
+ }
6734
6942
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6735
6943
  signature: options[PROPERTY_NAME_SIGNATURE],
6736
- crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6944
+ crc32,
6737
6945
  offset: zipWriter.offset - diskOffset,
6738
6946
  diskNumberStart: diskNumber,
6739
6947
  [OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
6740
6948
  });
6741
6949
  const headerInfo = getHeaderInfo(options);
6950
+ if (headerInfo.lastModDateClamped) {
6951
+ addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
6952
+ }
6742
6953
  const dataDescriptorInfo = getDataDescriptorInfo(options);
6743
6954
  const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
6744
6955
  fileEntry = await getFileEntry(zipWriter, name, reader, {
@@ -6765,6 +6976,95 @@ async function addFile(zipWriter, name, reader, options) {
6765
6976
  return new Entry(fileEntry);
6766
6977
  }
6767
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
+
6768
7068
  function resolveAttributes(zipWriter, name, options) {
6769
7069
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6770
7070
  let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
@@ -6779,7 +7079,7 @@ function resolveAttributes(zipWriter, name, options) {
6779
7079
  checkIntegerOption(uid, MAX_32_BITS, ERR_INVALID_UID);
6780
7080
  checkIntegerOption(gid, MAX_32_BITS, ERR_INVALID_GID);
6781
7081
  checkIntegerOption(unixMode, MAX_16_BITS, ERR_INVALID_UNIX_MODE);
6782
- 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) {
6783
7083
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
6784
7084
  }
6785
7085
  if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
@@ -6787,7 +7087,7 @@ function resolveAttributes(zipWriter, name, options) {
6787
7087
  throw new Error(ERR_INVALID_UNIX_ID_SIZE);
6788
7088
  }
6789
7089
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6790
- unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
7090
+ unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
6791
7091
  }
6792
7092
  let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
6793
7093
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
@@ -6918,7 +7218,9 @@ function resolveMetadata(zipWriter, name, options) {
6918
7218
  const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6919
7219
  const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6920
7220
  const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6921
- 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;
6922
7224
  const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6923
7225
  const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6924
7226
  checkPasswordOption(password, rawPassword);
@@ -6934,10 +7236,11 @@ function resolveMetadata(zipWriter, name, options) {
6934
7236
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
6935
7237
  const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
6936
7238
  throwIfAborted(signal);
6937
- const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
7239
+ const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
7240
+ !isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
6938
7241
  const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
6939
- const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
6940
- if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
7242
+ const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
7243
+ if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
6941
7244
  compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
6942
7245
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
6943
7246
  }
@@ -6951,15 +7254,15 @@ function resolveMetadata(zipWriter, name, options) {
6951
7254
  level = 0;
6952
7255
  }
6953
7256
  }
6954
- if (passThrough) {
6955
- level = UNDEFINED_VALUE;
7257
+ if (passThroughCompression) {
7258
+ level = toNumber(options[OPTION_LEVEL]);
6956
7259
  }
6957
7260
  let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
6958
7261
  let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
6959
7262
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
6960
7263
  dataDescriptor = false;
6961
7264
  }
6962
- if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThrough)) {
7265
+ if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
6963
7266
  dataDescriptor = true;
6964
7267
  }
6965
7268
  if (level !== UNDEFINED_VALUE && level != 6) {
@@ -6983,7 +7286,8 @@ function resolveMetadata(zipWriter, name, options) {
6983
7286
  lastAccessDate,
6984
7287
  creationDate,
6985
7288
  internalFileAttributes,
6986
- passThrough,
7289
+ passThroughCompression,
7290
+ passThroughEncryption,
6987
7291
  password,
6988
7292
  rawPassword,
6989
7293
  encryptionStrength,
@@ -7044,7 +7348,7 @@ function serializeExtraField(extraField) {
7044
7348
  }
7045
7349
 
7046
7350
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
7047
- if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7351
+ if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7048
7352
  throw new Error(ERR_UNDEFINED_READER);
7049
7353
  }
7050
7354
  let contentSize;
@@ -7060,12 +7364,12 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
7060
7364
  }
7061
7365
 
7062
7366
  function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
7063
- const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7367
+ const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7064
7368
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
7065
7369
  let maximumCompressedSize = 0;
7066
7370
  let uncompressedSize = 0;
7067
7371
  let unknownSize = false;
7068
- if (passThrough && hasContent) {
7372
+ if (passThroughCompression && hasContent) {
7069
7373
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
7070
7374
  if (uncompressedSize === UNDEFINED_VALUE) {
7071
7375
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -7076,17 +7380,17 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
7076
7380
  }
7077
7381
  const zip64Enabled = zip64 === true;
7078
7382
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
7079
- if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
7383
+ if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
7080
7384
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
7081
7385
  }
7082
- 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));
7083
7387
  if (!hasContent) {
7084
7388
  level = 0;
7085
7389
  compressionMethod = COMPRESSION_METHOD_STORE;
7086
7390
  }
7087
- const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7391
+ const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
7088
7392
  if (hasContent) {
7089
- if (!passThrough) {
7393
+ if (!passThroughCompression) {
7090
7394
  if (contentSize === UNDEFINED_VALUE) {
7091
7395
  dataDescriptor = true;
7092
7396
  if (zip64 || zip64 === UNDEFINED_VALUE) {
@@ -7099,10 +7403,12 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
7099
7403
  }
7100
7404
  } else {
7101
7405
  options.uncompressedSize = uncompressedSize;
7102
- maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
7406
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
7407
+ getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
7408
+ contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
7103
7409
  }
7104
7410
  }
7105
- const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThrough)) && !isCompressed(compressionMethod, level);
7411
+ const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
7106
7412
  if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7107
7413
  dataDescriptor = false;
7108
7414
  }
@@ -7151,6 +7457,8 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7151
7457
  const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
7152
7458
  let offset = initialOffset;
7153
7459
  let minimumEntrySize = INFINITY_VALUE;
7460
+ const entrySizes = [];
7461
+ const entriesAlreadyZip64 = new Set();
7154
7462
  for (const entry of entries) {
7155
7463
  let { name } = entry;
7156
7464
  const { size } = entry;
@@ -7162,7 +7470,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7162
7470
  ({ name } = attributesInfo);
7163
7471
  const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
7164
7472
  if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
7165
- !metadata.passThrough && !(await supportsDeflate(getConfiguration()))) {
7473
+ !metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
7166
7474
  metadata.level = 0;
7167
7475
  }
7168
7476
  const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
@@ -7170,7 +7478,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7170
7478
  throw new Error(ERR_UNDETERMINED_SIZE);
7171
7479
  }
7172
7480
  const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
7173
- if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
7481
+ if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
7174
7482
  throw new Error(ERR_UNDETERMINED_SIZE);
7175
7483
  }
7176
7484
  const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
@@ -7190,10 +7498,15 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7190
7498
  compressedSize
7191
7499
  }));
7192
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));
7193
7504
  minimumEntrySize = Math.min(minimumEntrySize, entrySize);
7194
7505
  offset += entrySize;
7195
7506
  }
7196
- 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))));
7197
7510
  if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
7198
7511
  throw new Error(ERR_UNDETERMINED_SIZE);
7199
7512
  }
@@ -7211,6 +7524,20 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
7211
7524
  return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
7212
7525
  }
7213
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
+
7214
7541
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
7215
7542
  const {
7216
7543
  fileEntries,
@@ -7386,6 +7713,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7386
7713
  localExtraFieldZip64Length,
7387
7714
  rawExtraFieldExtendedTimestamp,
7388
7715
  extraFieldExtendedTimestampFlag,
7716
+ extraFieldExtendedTimestampTime,
7389
7717
  rawExtraFieldNTFS,
7390
7718
  rawExtraFieldUnix,
7391
7719
  rawExtraFieldAES,
@@ -7398,6 +7726,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7398
7726
  password,
7399
7727
  rawPassword,
7400
7728
  level,
7729
+ useUnicodeFileNames,
7401
7730
  zip64,
7402
7731
  zip64Enabled,
7403
7732
  zip64UncompressedSize,
@@ -7432,7 +7761,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7432
7761
  msdosAttributesRaw,
7433
7762
  msdosAttributes,
7434
7763
  useCompressionStream,
7435
- passThrough,
7764
+ passThroughCompression,
7765
+ passThroughEncryption,
7436
7766
  format,
7437
7767
  codecURI
7438
7768
  } = options;
@@ -7443,9 +7773,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7443
7773
  zip64Enabled,
7444
7774
  directory: Boolean(directory),
7445
7775
  executable: Boolean(executable),
7446
- filenameUTF8: true,
7776
+ filenameUTF8: Boolean(useUnicodeFileNames),
7447
7777
  rawFilename,
7448
- commentUTF8: true,
7778
+ commentUTF8: Boolean(useUnicodeFileNames),
7449
7779
  rawComment,
7450
7780
  rawExtraFieldZip64,
7451
7781
  localExtraFieldZip64Length,
@@ -7476,7 +7806,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7476
7806
  uncompressedSize
7477
7807
  } = options;
7478
7808
  let compressedSize = 0;
7479
- if (!passThrough) {
7809
+ if (!passThroughCompression) {
7480
7810
  uncompressedSize = 0;
7481
7811
  }
7482
7812
  const { writable } = writer;
@@ -7493,9 +7823,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7493
7823
  encryptionStrength,
7494
7824
  zipCrypto: encrypted && zipCrypto,
7495
7825
  passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
7496
- computeCrc32: !passThrough,
7497
- compressed: compressed && !passThrough,
7498
- encrypted: encrypted && !passThrough,
7826
+ computeCrc32: !passThroughCompression,
7827
+ compressed: compressed && !passThroughCompression,
7828
+ encrypted: encrypted && !passThroughEncryption,
7499
7829
  useWebWorkers,
7500
7830
  useCompressionStream,
7501
7831
  transferStreams,
@@ -7510,7 +7840,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7510
7840
  const result = await runWorker({ readable, writable }, workerOptions);
7511
7841
  compressedSize = result.outputSize;
7512
7842
  writer.size += compressedSize;
7513
- if (!passThrough) {
7843
+ if (!passThroughCompression) {
7514
7844
  uncompressedSize = result.inputSize;
7515
7845
  if (!encrypted || zipCrypto) {
7516
7846
  crc32 = result.crc32;
@@ -7553,8 +7883,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry
7553
7883
  headerArray,
7554
7884
  headerView,
7555
7885
  signature: crc32,
7556
- crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
7886
+ crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
7557
7887
  extraFieldExtendedTimestampFlag,
7888
+ extraFieldExtendedTimestampTime,
7558
7889
  zip64UncompressedSize,
7559
7890
  zip64CompressedSize
7560
7891
  });
@@ -7579,7 +7910,7 @@ function getHeaderInfo(options) {
7579
7910
  encryptionStrength,
7580
7911
  extendedTimestamp,
7581
7912
  ntfsTimestamp,
7582
- passThrough,
7913
+ passThroughCompression,
7583
7914
  encrypted,
7584
7915
  zip64UncompressedSize,
7585
7916
  zip64CompressedSize,
@@ -7590,7 +7921,7 @@ function getHeaderInfo(options) {
7590
7921
  let { version, compressionMethod } = options;
7591
7922
  const compressed = !directory && isCompressed(compressionMethod, level);
7592
7923
  let rawLocalExtraFieldZip64;
7593
- const uncompressedFile = passThrough || !compressed;
7924
+ const uncompressedFile = passThroughCompression || !compressed;
7594
7925
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
7595
7926
  const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
7596
7927
  if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
@@ -7602,8 +7933,8 @@ function getHeaderInfo(options) {
7602
7933
  if (zip64ExtraFieldComplete) {
7603
7934
  extraFieldZip64.writeUint64(uncompressedSize);
7604
7935
  if (uncompressedFile) {
7605
- const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7606
- extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
7936
+ const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
7937
+ extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
7607
7938
  }
7608
7939
  }
7609
7940
  } else {
@@ -7622,6 +7953,7 @@ function getHeaderInfo(options) {
7622
7953
  let rawExtraFieldNTFS;
7623
7954
  let rawExtraFieldExtendedTimestamp;
7624
7955
  let extraFieldExtendedTimestampFlag;
7956
+ let extraFieldExtendedTimestampTime;
7625
7957
  if (extendedTimestamp) {
7626
7958
  const lastModTimeUnix = getTimeUnix(lastModDate);
7627
7959
  const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
@@ -7629,6 +7961,7 @@ function getHeaderInfo(options) {
7629
7961
  const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
7630
7962
  const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
7631
7963
  extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
7964
+ extraFieldExtendedTimestampTime = lastModTimeUnix;
7632
7965
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7633
7966
  extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
7634
7967
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
@@ -7671,7 +8004,7 @@ function getHeaderInfo(options) {
7671
8004
  let rawExtraFieldUnix;
7672
8005
  try {
7673
8006
  const { uid, gid, unixExtraFieldType } = options;
7674
- 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)) {
7675
8008
  const uidBytes = packUnixId(uid === UNDEFINED_VALUE ? 0 : uid);
7676
8009
  const gidBytes = packUnixId(gid === UNDEFINED_VALUE ? 0 : gid);
7677
8010
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
@@ -7712,7 +8045,7 @@ function getHeaderInfo(options) {
7712
8045
  }
7713
8046
  if (encrypted && !zipCrypto) {
7714
8047
  version = version > VERSION_AES ? version : VERSION_AES;
7715
- if (passThrough && crc32 !== UNDEFINED_VALUE) {
8048
+ if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
7716
8049
  rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
7717
8050
  }
7718
8051
  setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
@@ -7774,12 +8107,14 @@ function getHeaderInfo(options) {
7774
8107
  headerArray,
7775
8108
  headerView,
7776
8109
  lastModDate: storedLastModDate,
8110
+ lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
7777
8111
  rawLastModDate,
7778
8112
  encrypted,
7779
8113
  compressed,
7780
8114
  version,
7781
8115
  compressionMethod,
7782
8116
  extraFieldExtendedTimestampFlag,
8117
+ extraFieldExtendedTimestampTime,
7783
8118
  rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
7784
8119
  localExtraFieldZip64Length,
7785
8120
  rawExtraFieldExtendedTimestamp,
@@ -7882,7 +8217,7 @@ function setEntryInfo({
7882
8217
  }, {
7883
8218
  zip64,
7884
8219
  zipCrypto,
7885
- passThrough,
8220
+ passThroughCompression,
7886
8221
  dataDescriptor
7887
8222
  }) {
7888
8223
  const {
@@ -7893,7 +8228,7 @@ function setEntryInfo({
7893
8228
  dataDescriptorView,
7894
8229
  dataDescriptorOffset
7895
8230
  } = dataDescriptorInfo;
7896
- if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
8231
+ if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
7897
8232
  setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
7898
8233
  if (dataDescriptor) {
7899
8234
  setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
@@ -7924,9 +8259,9 @@ function updateLocalHeader({
7924
8259
  uncompressedSize,
7925
8260
  zip64UncompressedSize,
7926
8261
  zip64CompressedSize
7927
- }, localHeaderView, { dataDescriptor, passThrough }) {
8262
+ }, localHeaderView, { dataDescriptor, passThroughCompression }) {
7928
8263
  if (!dataDescriptor) {
7929
- if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
8264
+ if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
7930
8265
  setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
7931
8266
  }
7932
8267
  if (!zip64CompressedSize) {
@@ -7963,9 +8298,8 @@ function createDirectoryRecords(files) {
7963
8298
  rawExtraFieldUnix,
7964
8299
  rawExtraField,
7965
8300
  rawCentralExtraField,
7966
- extendedTimestamp,
7967
8301
  extraFieldExtendedTimestampFlag,
7968
- lastModDate,
8302
+ extraFieldExtendedTimestampTime,
7969
8303
  zip64Enabled,
7970
8304
  uncompressedSize,
7971
8305
  compressedSize
@@ -8008,16 +8342,15 @@ function createDirectoryRecords(files) {
8008
8342
  fileEntry.zip64Offset = zip64Offset;
8009
8343
  fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
8010
8344
  let rawExtraFieldTimestamp;
8011
- const lastModTimeUnix = getTimeUnix(lastModDate);
8012
- if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
8345
+ if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
8346
+ rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
8347
+ } else {
8013
8348
  const extraFieldTimestamp = createRecordWriter(9);
8014
8349
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
8015
8350
  extraFieldTimestamp.writeUint16(5);
8016
8351
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
8017
- extraFieldTimestamp.writeUint32(lastModTimeUnix);
8352
+ extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
8018
8353
  rawExtraFieldTimestamp = extraFieldTimestamp.array;
8019
- } else {
8020
- rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
8021
8354
  }
8022
8355
  fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
8023
8356
  const extraFieldLength = getLength(
@@ -8517,6 +8850,11 @@ function getHeaderArrayData({
8517
8850
  };
8518
8851
  }
8519
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
+
8520
8858
  function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
8521
8859
  let bitFlag = 0;
8522
8860
  if (useUnicodeFileNames) {
@@ -8678,7 +9016,7 @@ function formatSupported(StreamClass, format) {
8678
9016
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8679
9017
  */
8680
9018
 
8681
- const VERSION = "2.11.4";
9019
+ const VERSION = "2.12.0";
8682
9020
 
8683
9021
  /*
8684
9022
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9498,9 +9836,9 @@ setDefaultConfiguration({
9498
9836
  DecompressionStreamFallback: DecompressionStreamZlib
9499
9837
  });
9500
9838
 
9501
- function terminateWorkersAndModule() {
9839
+ async function terminateWorkersAndModule() {
9840
+ await terminateWorkers();
9502
9841
  modulePromise = null;
9503
- terminateWorkers();
9504
9842
  resetWasmModule();
9505
9843
  }
9506
9844
 
@@ -9541,7 +9879,10 @@ configureExternalAssets();
9541
9879
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
9542
9880
  const ERR_DUPLICATE_IMPORTED_ENTRY = "Duplicate entry filename in the imported zip file";
9543
9881
  const ERR_INVALID_DUPLICATES = "Invalid duplicates option (must be \"throw\", \"keep-first\" or \"keep-last\")";
9544
- 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";
9545
9886
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
9546
9887
  const DUPLICATES_THROW = "throw";
9547
9888
  const DUPLICATES_KEEP_FIRST = "keep-first";
@@ -9549,22 +9890,8 @@ const DUPLICATES_KEEP_LAST = "keep-last";
9549
9890
  const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPLICATES_KEEP_LAST]);
9550
9891
  const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
9551
9892
  const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
9552
- 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()";
9553
9894
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
9554
- const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
9555
- const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
9556
- EXTRAFIELD_TYPE_ZIP64,
9557
- EXTRAFIELD_TYPE_AES,
9558
- EXTRAFIELD_TYPE_NTFS,
9559
- EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
9560
- EXTRAFIELD_TYPE_UNICODE_PATH,
9561
- EXTRAFIELD_TYPE_UNICODE_COMMENT,
9562
- EXTRAFIELD_TYPE_USDZ,
9563
- EXTRAFIELD_TYPE_INFOZIP,
9564
- EXTRAFIELD_TYPE_UNIX,
9565
- EXTRAFIELD_TYPE_UNIX_TYPE1,
9566
- EXTRAFIELD_TYPE_PKWARE_UNIX
9567
- ]);
9568
9895
 
9569
9896
  class ZipEntry {
9570
9897
 
@@ -9936,6 +10263,7 @@ class ZipDirectoryEntry extends ZipEntry {
9936
10263
  await initStream(reader);
9937
10264
  zipReader = new ZipReader(reader, options);
9938
10265
  }
10266
+ checkPassThroughValue(options.passThrough);
9939
10267
  const duplicates = checkDuplicatesOption(options.duplicates);
9940
10268
  const importedEntries = [];
9941
10269
  const entries = await zipReader.getEntries(options);
@@ -10026,18 +10354,25 @@ class ZipDirectoryEntry extends ZipEntry {
10026
10354
 
10027
10355
  async exportZip(writer, options = {}) {
10028
10356
  const zipEntry = this;
10357
+ const zipWriterProvided = Boolean(writer) && typeof writer.add == FUNCTION_TYPE;
10029
10358
  options = Object.assign({}, options);
10030
- if (options.bufferedWrite === UNDEFINED_VALUE) {
10359
+ if (!zipWriterProvided && options.bufferedWrite === UNDEFINED_VALUE) {
10031
10360
  options.bufferedWrite = true;
10032
10361
  }
10033
- const [readers] = await Promise.all([initReaders(zipEntry, checkReaderOptions(options.readerOptions)), initStream(writer)]);
10034
- 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);
10035
10367
  await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
10368
+ if (zipWriterProvided) {
10369
+ return zipWriter;
10370
+ }
10036
10371
  await zipWriter.close(options.globalComment);
10037
10372
  return writer.getData ? writer.getData() : writer.writable;
10038
10373
  }
10039
10374
 
10040
- getExportedSize(options = {}) {
10375
+ async getExportedSize(options = {}) {
10041
10376
  const zipEntry = this;
10042
10377
  options = Object.assign({}, options);
10043
10378
  checkReaderOptions(options.readerOptions);
@@ -10052,7 +10387,7 @@ class ZipDirectoryEntry extends ZipEntry {
10052
10387
  const writeOrderGuaranteed = !options.bufferedWrite ||
10053
10388
  (entries.every(entry => entry.options.keepOrder !== false) &&
10054
10389
  children.every(child => isImplicitDirectory(child) || !child.children.length));
10055
- return getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
10390
+ return await getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
10056
10391
  }
10057
10392
 
10058
10393
  getChildByName(name) {
@@ -10113,7 +10448,7 @@ class ZipFS {
10113
10448
 
10114
10449
  move(entry, destination) {
10115
10450
  if (entry == this.root) {
10116
- throw new Error("Root directory cannot be moved");
10451
+ throw new Error(ERR_ROOT_DIRECTORY_NOT_MOVABLE);
10117
10452
  } else {
10118
10453
  if (destination.directory) {
10119
10454
  if (!destination.isDescendantOf(entry)) {
@@ -10134,7 +10469,7 @@ class ZipFS {
10134
10469
  throw new Error(ERR_ANCESTOR_ENTRY);
10135
10470
  }
10136
10471
  } else {
10137
- throw new Error("Target entry is not a directory");
10472
+ throw new Error(ERR_TARGET_NOT_DIRECTORY);
10138
10473
  }
10139
10474
  }
10140
10475
  }
@@ -10447,70 +10782,11 @@ function getChildEntryOptions(child, selectedEntry, options) {
10447
10782
  let zipEntryMetadata = {};
10448
10783
  let passThroughOptions = {};
10449
10784
  if (child.data instanceof Entry) {
10450
- const {
10451
- externalFileAttributes,
10452
- versionMadeBy,
10453
- comment,
10454
- lastModDate,
10455
- rawLastModDate,
10456
- creationDate,
10457
- lastAccessDate,
10458
- uncompressedSize,
10459
- encrypted,
10460
- zipCrypto,
10461
- crc32,
10462
- compressionMethod,
10463
- extraFieldAES,
10464
- internalFileAttributes,
10465
- extraField,
10466
- bitFlag,
10467
- uid,
10468
- gid
10469
- } = child.data;
10470
- zipEntryMetadata = {
10471
- externalFileAttributes,
10472
- versionMadeBy,
10473
- comment,
10474
- lastModDate,
10475
- creationDate,
10476
- lastAccessDate,
10477
- internalFileAttributes
10478
- };
10479
- const userExtraField = getUserExtraField(extraField);
10480
- if (userExtraField) {
10481
- zipEntryMetadata.extraField = userExtraField;
10482
- }
10483
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
10484
- Object.assign(zipEntryMetadata, {
10485
- uid,
10486
- gid,
10487
- unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
10488
- });
10489
- }
10490
- if (isPassThrough(child, options)) {
10491
- let encryptionStrength;
10492
- if (extraFieldAES) {
10493
- encryptionStrength = extraFieldAES.strength;
10494
- }
10495
- passThroughOptions = {
10496
- passThrough: true,
10497
- encrypted,
10498
- zipCrypto,
10499
- crc32,
10500
- uncompressedSize,
10501
- encryptionStrength,
10502
- compressionMethod
10503
- };
10504
- if (bitFlag) {
10505
- passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
10506
- }
10507
- const lastModDateOverride = childOptions.lastModDate === UNDEFINED_VALUE ? options.lastModDate : childOptions.lastModDate;
10508
- if (lastModDateOverride === UNDEFINED_VALUE) {
10509
- passThroughOptions.rawLastModDate = rawLastModDate;
10510
- } else if (zipCrypto && (!bitFlag || bitFlag.dataDescriptor) && lastModDateOverride instanceof Date &&
10511
- getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
10512
- throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
10513
- }
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;
10514
10790
  }
10515
10791
  }
10516
10792
  const entryOptions = Object.assign({ lastModDate: child.defaultLastModDate }, zipEntryMetadata, options, childOptions, passThroughOptions, { directory: child.directory });
@@ -10520,16 +10796,6 @@ function getChildEntryOptions(child, selectedEntry, options) {
10520
10796
  return { name, entryOptions };
10521
10797
  }
10522
10798
 
10523
- function getDosTimeHighByte(lastModDate) {
10524
- let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
10525
- if (dosLastModDate < MIN_DATE) {
10526
- dosLastModDate = MIN_DATE;
10527
- } else if (dosLastModDate > MAX_DATE) {
10528
- dosLastModDate = MAX_DATE;
10529
- }
10530
- return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
10531
- }
10532
-
10533
10799
  function getDeterminedSize(child, passThrough) {
10534
10800
  const { reader } = child;
10535
10801
  if (reader && reader.size !== UNDEFINED_VALUE) {
@@ -10542,9 +10808,18 @@ function checkReaderOptions(readerOptions) {
10542
10808
  if (readerOptions && (typeof readerOptions != OBJECT_TYPE || Array.isArray(readerOptions))) {
10543
10809
  throw new Error(ERR_INVALID_READER_OPTIONS);
10544
10810
  }
10811
+ if (readerOptions) {
10812
+ checkPassThroughValue(readerOptions.passThrough);
10813
+ }
10545
10814
  return readerOptions;
10546
10815
  }
10547
10816
 
10817
+ function checkPassThroughValue(passThrough) {
10818
+ if (checkPassThroughOption(passThrough) === PASS_THROUGH_COMPRESSED) {
10819
+ throw new Error(ERR_UNSUPPORTED_PASS_THROUGH_VALUE);
10820
+ }
10821
+ }
10822
+
10548
10823
  function replaceContent(zipEntry, params) {
10549
10824
  const { uncompressedSize } = params;
10550
10825
  Object.assign(zipEntry, params, {
@@ -10573,20 +10848,6 @@ function isImplicitDirectory(child) {
10573
10848
  return child.directory && child.data === null;
10574
10849
  }
10575
10850
 
10576
- function getUserExtraField(extraField) {
10577
- if (extraField) {
10578
- const userExtraField = new Map();
10579
- extraField.forEach((field, type) => {
10580
- if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
10581
- userExtraField.set(type, field.data);
10582
- }
10583
- });
10584
- if (userExtraField.size) {
10585
- return userExtraField;
10586
- }
10587
- }
10588
- }
10589
-
10590
10851
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
10591
10852
  const { onstart, onprogress, onend, onentryprogress } = options;
10592
10853
  const selectedEntry = entry;
@@ -10689,6 +10950,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
10689
10950
 
10690
10951
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
10691
10952
  const { onstart, onprogress, onend } = options;
10953
+ checkPassThroughValue(options.passThrough);
10692
10954
  const readerOptions = checkReaderOptions(options.readerOptions);
10693
10955
  const abortController = new AbortController();
10694
10956
  const { signal } = abortController;
@@ -10764,7 +11026,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
10764
11026
  if (exportAborted || isExportAborted(signal.reason)) {
10765
11027
  return;
10766
11028
  }
10767
- throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
11029
+ throwIfAborted(signal);
10768
11030
  }
10769
11031
  try {
10770
11032
  if (child.directory) {
@@ -10897,7 +11159,7 @@ function addChild(parent, name, params, directory) {
10897
11159
  }
10898
11160
  return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
10899
11161
  } else {
10900
- throw new Error("Parent entry is not a directory");
11162
+ throw new Error(ERR_PARENT_NOT_DIRECTORY);
10901
11163
  }
10902
11164
  }
10903
11165
 
@@ -10938,4 +11200,4 @@ function getPathParent(parent, path, movedEntry) {
10938
11200
  return parent;
10939
11201
  }
10940
11202
 
10941
- 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 };
11203
+ 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 };