@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
@@ -134,6 +134,7 @@
134
134
  const BOOLEAN_TYPE = "boolean";
135
135
 
136
136
  const EMPTY_UINT8_ARRAY = new Uint8Array();
137
+ const SYMBOL_ASYNC_DISPOSE = Symbol.asyncDispose || Symbol();
137
138
 
138
139
  /*
139
140
  Copyright (c) 2022 Gildas Lormeau. All rights reserved.
@@ -178,6 +179,7 @@
178
179
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
179
180
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
180
181
  const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
182
+ const OPTION_CHECK_LOCAL_FILENAME = "checkLocalFilename";
181
183
  const OPTION_CHECK_SIGNATURE = "checkSignature";
182
184
  const OPTION_CHECK_CRC32 = "checkCrc32";
183
185
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -208,15 +210,20 @@
208
210
  const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
209
211
  const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
210
212
  const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
213
+ const OPTION_ENTRY = "entry";
211
214
  const TEXT_TYPE_FILENAME = "filename";
212
215
  const TEXT_TYPE_COMMENT = "comment";
213
216
  const STRICTNESS_STRICT = "strict";
214
217
  const STRICTNESS_BALANCED = "balanced";
215
218
  const STRICTNESS_TOLERANT = "tolerant";
219
+ const PASS_THROUGH_COMPRESSED = "compressed";
216
220
 
217
221
  const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
218
222
  const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
219
223
  const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
224
+ const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
225
+ const ERR_ABORTED = "The operation was aborted";
226
+ const ABORT_ERROR_NAME = "AbortError";
220
227
 
221
228
  function checkFunctionOption(value) {
222
229
  if (value && typeof value != FUNCTION_TYPE) {
@@ -232,12 +239,25 @@
232
239
  return signal || UNDEFINED_VALUE;
233
240
  }
234
241
 
242
+ function throwIfAborted(signal) {
243
+ if (signal && signal.aborted) {
244
+ throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
245
+ }
246
+ }
247
+
235
248
  function checkPasswordOption(password, rawPassword) {
236
249
  if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
237
250
  throw new Error(ERR_INVALID_PASSWORD_TYPE);
238
251
  }
239
252
  }
240
253
 
254
+ function checkPassThroughOption(passThrough) {
255
+ if (passThrough !== UNDEFINED_VALUE && typeof passThrough != BOOLEAN_TYPE && passThrough !== PASS_THROUGH_COMPRESSED) {
256
+ throw new Error(ERR_INVALID_PASS_THROUGH_VALUE);
257
+ }
258
+ return passThrough;
259
+ }
260
+
241
261
  function checkInteger(value, maxValue, errorMessage) {
242
262
  if (!Number.isInteger(value) || value < 0 || value > maxValue) {
243
263
  throw new Error(errorMessage);
@@ -287,6 +307,8 @@
287
307
  const MINIMUM_CHUNK_SIZE = 64;
288
308
  const MINIMUM_PROPERTY_VALUE = 1;
289
309
  const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
310
+ const ERR_INVALID_BASE_URI = "Invalid baseURI (must be a string)";
311
+ const ERR_INVALID_URI = "Invalid URI (must be a string or a function returning a string)";
290
312
  let maxWorkers = 2;
291
313
  try {
292
314
  if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
@@ -311,9 +333,9 @@
311
333
  };
312
334
 
313
335
  const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
336
+ const PROPERTY_NAME_BASE_URI = "baseURI";
314
337
 
315
- const STRING_PROPERTY_NAMES = [
316
- "baseURI",
338
+ const URI_PROPERTY_NAMES = [
317
339
  "wasmURI",
318
340
  "workerURI"
319
341
  ];
@@ -337,7 +359,8 @@
337
359
  "DecompressionStreamFallback"
338
360
  ];
339
361
  const CONFIGURABLE_PROPERTY_NAMES = [
340
- ...STRING_PROPERTY_NAMES,
362
+ PROPERTY_NAME_BASE_URI,
363
+ ...URI_PROPERTY_NAMES,
341
364
  ...BOOLEAN_PROPERTY_NAMES,
342
365
  ...NUMBER_PROPERTY_NAMES,
343
366
  ...FUNCTION_PROPERTY_NAMES
@@ -381,6 +404,14 @@
381
404
  }
382
405
  } else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
383
406
  checkFunctionOption(propertyValue);
407
+ } else if (propertyName == PROPERTY_NAME_BASE_URI) {
408
+ if (propertyValue && typeof propertyValue != STRING_TYPE) {
409
+ throw new Error(ERR_INVALID_BASE_URI);
410
+ }
411
+ } else if (URI_PROPERTY_NAMES.includes(propertyName)) {
412
+ if (propertyValue && typeof propertyValue != STRING_TYPE && typeof propertyValue != FUNCTION_TYPE) {
413
+ throw new Error(ERR_INVALID_URI);
414
+ }
384
415
  }
385
416
  return propertyValue;
386
417
  }
@@ -414,7 +445,7 @@
414
445
  Object.assign(config, DEFAULT_CONFIGURATION);
415
446
  }
416
447
 
417
- const o=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258],t=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],e=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],s=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],r=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],n=new Uint8Array(288);n.fill(8,0,144),n.fill(9,144,256),n.fill(7,256,280),n.fill(8,280,288);const i=new Uint8Array(30).fill(5);function A(o){const t=new Uint16Array(16);for(const e of o)t[e]++;t[0]=0;const e=new Uint16Array(17);for(let o=1;o<=15;o++)e[o+1]=e[o]+t[o];const s=new Uint16Array(o.length);for(let t=0;t<o.length;t++)o[t]&&(s[e[o[t]]++]=t);return {o:t,symbols:s}}const g$1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",c=(O=()=>function(g){let c=0,O=0,B=0,f=new Uint8Array(1024),C=0,u=0;for(;!u;){u=w(1);const o=w(2);if(0==o)m();else if(1==o)d(A(n),A(i));else {if(2!=o)throw new Error("invalid deflate block type");d(...p());}}return f.subarray(0,C);function q(){if(c>=g.length)throw new Error("unexpected end of deflate data");return g[c++]}function w(o){for(;B<o;)O|=q()<<B,B+=8;const t=O&(1<<o)-1;return O>>>=o,B-=o,t}function m(){O=0,B=0;const o=q()|q()<<8;c+=2,z(C+o);for(let t=0;t<o;t++)f[C++]=q();}function d(r,n){let i=F(r);for(;256!=i;){if(i<256)z(C+1),f[C++]=i;else {const r=i-257,A=o[r]+w(t[r]),g=F(n),c=e[g]+w(s[g]);z(C+A);const O=C-c;for(let o=0;o<A;o++)f[C++]=f[O+o];}i=F(r);}}function p(){const o=w(5)+257,t=w(5)+1,e=w(4)+4,s=new Uint8Array(19);for(let o=0;o<e;o++)s[r[o]]=w(3);const n=A(s),i=new Uint8Array(o+t);let g=0;for(;g<i.length;){const o=F(n);if(o<16)i[g++]=o;else if(16==o){const o=i[g-1];let t=w(2)+3;for(;t--;)i[g++]=o;}else g+=17==o?w(3)+3:w(7)+11;}return [A(i.subarray(0,o)),A(i.subarray(o))]}function F(o){const{o:t,symbols:e}=o;let s=0,r=0,n=0;for(let o=1;o<=15;o++){s|=w(1);const i=t[o];if(s-r<i)return e[n+(s-r)];n+=i,r=r+i<<1,s<<=1;}throw new Error("invalid huffman code")}function z(o){if(f.length<o){let t=2*f.length;for(;t<o;)t*=2;const e=new Uint8Array(t);e.set(f.subarray(0,C)),f=e;}}}(function(o){const t=(o=String(o).replace(/[^A-Za-z0-9+/=]/g,"")).length,e=[];for(let s=0;s<t;s+=4){const t=g$1.indexOf(o[s])<<18|g$1.indexOf(o[s+1])<<12|(63&g$1.indexOf(o[s+2]))<<6|63&g$1.indexOf(o[s+3]);e.push(t>>16&255),"="!==o[s+2]&&e.push(t>>8&255),"="!==o[s+3]&&e.push(255&t);}return new Uint8Array(e)}("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")),o=>o({workerURI:o=>{const t="text/javascript";let e=O();if("string"==typeof e&&(e=(new TextEncoder).encode(e)),o){const o=new Blob([e],{type:t});return URL.createObjectURL(o)}return "data:"+t+";base64,"+function(o){let t="";const e=o.length;let s=0;for(;s+2<e;s+=3){const e=o[s]<<16|o[s+1]<<8|o[s+2];t+=g$1[e>>18&63]+g$1[e>>12&63]+g$1[e>>6&63]+g$1[63&e];}const r=e-s;if(1===r){const e=o[s]<<16;t+=g$1[e>>18&63]+g$1[e>>12&63]+"==";}else if(2===r){const e=o[s]<<16|o[s+1]<<8;t+=g$1[e>>18&63]+g$1[e>>12&63]+g$1[e>>6&63]+"=";}return t}(e)}}));var O;
448
+ const r=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258],o=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],s=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],e=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],t=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],c=new Uint8Array(288);c.fill(8,0,144),c.fill(9,144,256),c.fill(7,256,280),c.fill(8,280,288);const n=new Uint8Array(30).fill(5);function B(r){const o=new Uint16Array(16);for(const s of r)o[s]++;o[0]=0;const s=new Uint16Array(17);for(let r=1;r<=15;r++)s[r+1]=s[r]+o[r];const e=new Uint16Array(r.length);for(let o=0;o<r.length;o++)r[o]&&(e[s[r[o]]++]=o);return {o:o,symbols:e}}const A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f=(w=()=>function(A){let f=0,w=0,K=0,g=new Uint8Array(1024),O=0,T=0;for(;!T;){T=W(1);const r=W(2);if(0==r)i();else if(1==r)z(B(c),B(n));else {if(2!=r)throw new Error("invalid deflate block type");z(...D());}}return g.subarray(0,O);function l(){if(f>=A.length)throw new Error("unexpected end of deflate data");return A[f++]}function W(r){for(;K<r;)w|=l()<<K,K+=8;const o=w&(1<<r)-1;return w>>>=r,K-=r,o}function i(){w=0,K=0;const r=l()|l()<<8;f+=2,u(O+r);for(let o=0;o<r;o++)g[O++]=l();}function z(t,c){let n=E(t);for(;256!=n;){if(n<256)u(O+1),g[O++]=n;else {const t=n-257,B=r[t]+W(o[t]),A=E(c),f=s[A]+W(e[A]);u(O+B);const w=O-f;for(let r=0;r<B;r++)g[O++]=g[w+r];}n=E(t);}}function D(){const r=W(5)+257,o=W(5)+1,s=W(4)+4,e=new Uint8Array(19);for(let r=0;r<s;r++)e[t[r]]=W(3);const c=B(e),n=new Uint8Array(r+o);let A=0;for(;A<n.length;){const r=E(c);if(r<16)n[A++]=r;else if(16==r){const r=n[A-1];let o=W(2)+3;for(;o--;)n[A++]=r;}else A+=17==r?W(3)+3:W(7)+11;}return [B(n.subarray(0,r)),B(n.subarray(r))]}function E(r){const{o:o,symbols:s}=r;let e=0,t=0,c=0;for(let r=1;r<=15;r++){e|=W(1);const n=o[r];if(e-t<n)return s[c+(e-t)];c+=n,t=t+n<<1,e<<=1;}throw new Error("invalid huffman code")}function u(r){if(g.length<r){let o=2*g.length;for(;o<r;)o*=2;const s=new Uint8Array(o);s.set(g.subarray(0,O)),g=s;}}}(function(r){const o=(r=String(r).replace(/[^A-Za-z0-9+/=]/g,"")).length,s=[];for(let e=0;e<o;e+=4){const o=A.indexOf(r[e])<<18|A.indexOf(r[e+1])<<12|(63&A.indexOf(r[e+2]))<<6|63&A.indexOf(r[e+3]);s.push(o>>16&255),"="!==r[e+2]&&s.push(o>>8&255),"="!==r[e+3]&&s.push(255&o);}return new Uint8Array(s)}("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")),r=>r({workerURI:r=>{const o="text/javascript";let s=w();if("string"==typeof s&&(s=(new TextEncoder).encode(s)),r){const r=new Blob([s],{type:o});return URL.createObjectURL(r)}return "data:"+o+";base64,"+function(r){let o="";const s=r.length;let e=0;for(;e+2<s;e+=3){const s=r[e]<<16|r[e+1]<<8|r[e+2];o+=A[s>>18&63]+A[s>>12&63]+A[s>>6&63]+A[63&s];}const t=s-e;if(1===t){const s=r[e]<<16;o+=A[s>>18&63]+A[s>>12&63]+"==";}else if(2===t){const s=r[e]<<16|r[e+1]<<8;o+=A[s>>18&63]+A[s>>12&63]+A[s>>6&63]+"=";}return o}(s)}}));var w;
418
449
 
419
450
  /*
420
451
  Copyright (c) 2026 Gildas Lormeau. All rights reserved.
@@ -2599,6 +2630,7 @@
2599
2630
  constructor(chunkSize) {
2600
2631
  const pendingChunks = [];
2601
2632
  let pendingLength = 0;
2633
+ let outputSize = 0;
2602
2634
  if (!Number.isFinite(chunkSize) || chunkSize < 1) {
2603
2635
  chunkSize = DEFAULT_CHUNK_SIZE;
2604
2636
  }
@@ -2607,15 +2639,20 @@
2607
2639
  pendingChunks.push(chunk);
2608
2640
  pendingLength += chunk.length;
2609
2641
  while (pendingLength > chunkSize) {
2642
+ outputSize += chunkSize;
2610
2643
  controller.enqueue(shiftChunk());
2611
2644
  }
2612
2645
  },
2613
2646
  flush(controller) {
2614
2647
  if (pendingLength) {
2648
+ outputSize += pendingLength;
2615
2649
  controller.enqueue(concatChunks(pendingChunks, pendingLength));
2616
2650
  }
2617
2651
  }
2618
2652
  });
2653
+ Object.defineProperty(this, "outputSize", {
2654
+ get: () => outputSize
2655
+ });
2619
2656
 
2620
2657
  function shiftChunk() {
2621
2658
  const result = new Uint8Array(chunkSize);
@@ -2816,7 +2853,7 @@
2816
2853
  }
2817
2854
 
2818
2855
  async function runWorker$1({ options, readable, writable, onTaskFinished }, config) {
2819
- let codecStream;
2856
+ let codecStream, chunkStream;
2820
2857
  try {
2821
2858
  if (options.compressed && !options.format) {
2822
2859
  const deflate = options.codecType.startsWith(CODEC_DEFLATE);
@@ -2839,9 +2876,10 @@
2839
2876
  }
2840
2877
  }
2841
2878
  codecStream = new CodecStream(options, config);
2879
+ chunkStream = new ChunkStream(getChunkSize(config));
2842
2880
  await readable
2843
2881
  .pipeThrough(codecStream)
2844
- .pipeThrough(new ChunkStream(getChunkSize(config)))
2882
+ .pipeThrough(chunkStream)
2845
2883
  .pipeTo(writable, { preventClose: true, preventAbort: true });
2846
2884
  const {
2847
2885
  crc32,
@@ -2855,7 +2893,7 @@
2855
2893
  };
2856
2894
  } catch (error) {
2857
2895
  if (codecStream) {
2858
- error.outputSize = codecStream.outputSize;
2896
+ error.outputSize = chunkStream ? chunkStream.outputSize : 0;
2859
2897
  }
2860
2898
  throw error;
2861
2899
  } finally {
@@ -2964,11 +3002,17 @@
2964
3002
  let resolveResult, rejectResult;
2965
3003
  const result = new Promise((resolve, reject) => {
2966
3004
  resolveResult = resolve;
2967
- rejectResult = reject;
3005
+ rejectResult = error => {
3006
+ if (error && error.outputSize === UNDEFINED_VALUE) {
3007
+ error.outputSize = workerData.outputSize;
3008
+ }
3009
+ reject(error);
3010
+ };
2968
3011
  });
2969
3012
  Object.assign(workerData, {
2970
3013
  reader: null,
2971
3014
  writer: null,
3015
+ outputSize: 0,
2972
3016
  resolveResult,
2973
3017
  rejectResult,
2974
3018
  result
@@ -3252,8 +3296,10 @@
3252
3296
  }
3253
3297
  }
3254
3298
  if (type == MESSAGE_DATA) {
3299
+ const chunk = new Uint8Array(value);
3255
3300
  await writer.ready;
3256
- await writer.write(new Uint8Array(value));
3301
+ await writer.write(chunk);
3302
+ workerData.outputSize += chunk.length;
3257
3303
  if (!stale()) {
3258
3304
  sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
3259
3305
  }
@@ -3561,10 +3607,13 @@
3561
3607
 
3562
3608
 
3563
3609
  const ERR_HTTP_STATUS = "HTTP error ";
3610
+ const MIN_SUCCESS_HTTP_STATUS = 200;
3611
+ const MAX_SUCCESS_HTTP_STATUS = 299;
3564
3612
  const ERR_HTTP_RANGE = "HTTP Range not supported";
3565
3613
  const ERR_HTTP_RESOURCE_CHANGED = "HTTP resource changed";
3566
3614
  const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
3567
3615
  const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
3616
+ const ERR_WRITER_SIZE_NOT_WRITABLE = "Invalid writer (size must be writable)";
3568
3617
 
3569
3618
  const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
3570
3619
  const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
@@ -3756,11 +3805,14 @@
3756
3805
  const reader = this;
3757
3806
  const { sourceBlob, size } = reader;
3758
3807
  const { offset = 0, size: readSize = size - offset } = options || {};
3759
- if (!offset && readSize >= size) {
3760
- return toCompatibleReadable(sourceBlob.stream());
3761
- }
3762
- if (blobSliceReliable) {
3763
- return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
3808
+ // deno-lint-ignore valid-typeof
3809
+ if (typeof sourceBlob.stream == FUNCTION_TYPE) {
3810
+ if (!offset && readSize >= size) {
3811
+ return toCompatibleReadable(sourceBlob.stream());
3812
+ }
3813
+ if (blobSliceReliable) {
3814
+ return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
3815
+ }
3764
3816
  }
3765
3817
  return super.createReadable(options);
3766
3818
  }
@@ -4160,7 +4212,7 @@
4160
4212
 
4161
4213
  async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
4162
4214
  const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
4163
- if (response.status < 400) {
4215
+ if (response.status >= MIN_SUCCESS_HTTP_STATUS && response.status <= MAX_SUCCESS_HTTP_STATUS) {
4164
4216
  return response;
4165
4217
  } else {
4166
4218
  throw response.status == 416 ? new Error(ERR_HTTP_RANGE) : new Error(ERR_HTTP_STATUS + (response.statusText || response.status));
@@ -4171,7 +4223,7 @@
4171
4223
  return new Promise((resolve, reject) => {
4172
4224
  const request = new XMLHttpRequest();
4173
4225
  request.addEventListener("load", () => {
4174
- if (request.status < 400) {
4226
+ if (request.status >= MIN_SUCCESS_HTTP_STATUS && request.status <= MAX_SUCCESS_HTTP_STATUS) {
4175
4227
  const headers = [];
4176
4228
  request.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(header => {
4177
4229
  const splitHeader = header.trim().split(/\s*:\s*/);
@@ -4475,8 +4527,10 @@
4475
4527
  writable: toCompatibleWritable(writer)
4476
4528
  };
4477
4529
  }
4478
- if (writer.size === UNDEFINED_VALUE) {
4479
- writer.size = 0;
4530
+ try {
4531
+ writer.size = writer.size === UNDEFINED_VALUE ? 0 : writer.size;
4532
+ } catch {
4533
+ throw new Error(ERR_WRITER_SIZE_NOT_WRITABLE);
4480
4534
  }
4481
4535
  return writer;
4482
4536
  }
@@ -4524,6 +4578,45 @@
4524
4578
  }
4525
4579
  }
4526
4580
 
4581
+ /*
4582
+ Copyright (c) 2026 Gildas Lormeau. All rights reserved.
4583
+
4584
+ Redistribution and use in source and binary forms, with or without
4585
+ modification, are permitted provided that the following conditions are met:
4586
+
4587
+ 1. Redistributions of source code must retain the above copyright notice,
4588
+ this list of conditions and the following disclaimer.
4589
+
4590
+ 2. Redistributions in binary form must reproduce the above copyright
4591
+ notice, this list of conditions and the following disclaimer in
4592
+ the documentation and/or other materials provided with the distribution.
4593
+
4594
+ 3. The names of the authors may not be used to endorse or promote products
4595
+ derived from this software without specific prior written permission.
4596
+
4597
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
4598
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
4599
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
4600
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
4601
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
4602
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
4603
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
4604
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
4605
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
4606
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4607
+ */
4608
+
4609
+
4610
+ function addWarning(warnings, reason, filename) {
4611
+ if (!warnings.some(warning => warning.reason == reason)) {
4612
+ const warning = { reason };
4613
+ if (filename !== UNDEFINED_VALUE) {
4614
+ warning.filename = filename;
4615
+ }
4616
+ warnings.push(warning);
4617
+ }
4618
+ }
4619
+
4527
4620
  /*
4528
4621
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4529
4622
 
@@ -4552,6 +4645,7 @@
4552
4645
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4553
4646
  */
4554
4647
 
4648
+
4555
4649
  const PROPERTY_NAME_FILENAME = "filename";
4556
4650
  const PROPERTY_NAME_RAW_FILENAME = "rawFilename";
4557
4651
  const PROPERTY_NAME_COMMENT = "comment";
@@ -4676,6 +4770,38 @@
4676
4770
 
4677
4771
  }
4678
4772
 
4773
+ const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
4774
+ EXTRAFIELD_TYPE_ZIP64,
4775
+ EXTRAFIELD_TYPE_AES,
4776
+ EXTRAFIELD_TYPE_NTFS,
4777
+ EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
4778
+ EXTRAFIELD_TYPE_UNICODE_PATH,
4779
+ EXTRAFIELD_TYPE_UNICODE_COMMENT,
4780
+ EXTRAFIELD_TYPE_USDZ,
4781
+ EXTRAFIELD_TYPE_INFOZIP,
4782
+ EXTRAFIELD_TYPE_UNIX,
4783
+ EXTRAFIELD_TYPE_UNIX_TYPE1,
4784
+ EXTRAFIELD_TYPE_PKWARE_UNIX
4785
+ ]);
4786
+
4787
+ function getUserExtraField(extraField) {
4788
+ if (extraField) {
4789
+ const userExtraField = new Map();
4790
+ extraField.forEach((field, type) => {
4791
+ if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
4792
+ userExtraField.set(type, field.data);
4793
+ }
4794
+ });
4795
+ if (userExtraField.size) {
4796
+ return userExtraField;
4797
+ }
4798
+ }
4799
+ }
4800
+
4801
+ function getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength) {
4802
+ return encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
4803
+ }
4804
+
4679
4805
  /*
4680
4806
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
4681
4807
 
@@ -4735,6 +4861,8 @@
4735
4861
  const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
4736
4862
  const WARNING_DUPLICATE_FILENAME = "duplicate filename";
4737
4863
  const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
4864
+ const WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = "multiple end of central directory records";
4865
+ const WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME = "mismatched local file header (filename)";
4738
4866
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = "mismatched local file header (general purpose bit flag)";
4739
4867
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = "mismatched local file header (compression method)";
4740
4868
  const WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = "mismatched local file header (crc32 or sizes)";
@@ -4805,7 +4933,7 @@
4805
4933
  }
4806
4934
  }
4807
4935
  if (rejectAmbiguousEndOfDirectory && endOfDirectoryReachingEndCount > 1) {
4808
- throwAmbiguousArchive("multiple end of central directory records");
4936
+ throwAmbiguousArchive(WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY);
4809
4937
  }
4810
4938
  const endOfDirectoryView = getDataView(endOfDirectoryInfo);
4811
4939
  let directoryDataLength = getUint32$1(endOfDirectoryView, 12);
@@ -5103,7 +5231,8 @@
5103
5231
  const writer = new TransformStream();
5104
5232
  const arrayBufferPromise = streamToBlob(writer.readable).then(blob => blob.arrayBuffer());
5105
5233
  arrayBufferPromise.catch(() => { });
5106
- await fileEntry.getData(writer, entry, zipReader.readRanges, options);
5234
+ await fileEntry.getData(writer, entry, zipReader.readRanges,
5235
+ Object.assign({}, options, { preventClose: false }));
5107
5236
  return arrayBufferPromise;
5108
5237
  };
5109
5238
  offset = endOffset;
@@ -5184,48 +5313,101 @@
5184
5313
  await reader.readable.cancel();
5185
5314
  }
5186
5315
  }
5316
+
5317
+ [SYMBOL_ASYNC_DISPOSE]() {
5318
+ return this.close();
5319
+ }
5187
5320
  }
5188
5321
 
5189
5322
  class ZipReaderStream {
5190
5323
 
5191
5324
  constructor(options = {}) {
5192
- const { readable, writable } = new TransformStream();
5193
- const gen = new ZipReader(readable, options).getEntriesGenerator();
5325
+ let sourceController;
5326
+ const { readable, writable } = new TransformStream({
5327
+ start(controller) {
5328
+ sourceController = controller;
5329
+ }
5330
+ });
5331
+ const zipReader = new ZipReader(readable, options);
5332
+ const gen = zipReader.getEntriesGenerator();
5333
+ const pendingEntries = new Set();
5194
5334
  this.readable = new ReadableStream({
5195
5335
  async pull(controller) {
5196
5336
  const { done, value } = await gen.next();
5197
5337
  if (done)
5198
5338
  return controller.close();
5339
+ const entryStream = createEntryStream(value, pendingEntries);
5199
5340
  const chunk = {
5200
5341
  ...value,
5201
- readable: (function () {
5202
- const { readable, writable } = new TransformStream();
5203
- if (value.getData) {
5204
- getData();
5205
- return readable;
5206
- }
5207
-
5208
- async function getData() {
5209
- try {
5210
- await value.getData(writable);
5211
- } catch (error) {
5212
- try {
5213
- await writable.abort(error);
5214
- } catch {
5215
- // ignored
5216
- }
5217
- }
5218
- }
5219
- })()
5342
+ readable: entryStream.readable
5220
5343
  };
5221
5344
  delete chunk.getData;
5345
+ Object.defineProperties(chunk, {
5346
+ localDirectory: {
5347
+ get: () => value.localDirectory,
5348
+ enumerable: true
5349
+ },
5350
+ warnings: {
5351
+ get: () => value.warnings,
5352
+ enumerable: true
5353
+ }
5354
+ });
5222
5355
  controller.enqueue(chunk);
5356
+ },
5357
+ async cancel(reason) {
5358
+ const entryStreams = Array.from(pendingEntries);
5359
+ pendingEntries.clear();
5360
+ sourceController.error(reason);
5361
+ await Promise.allSettled(entryStreams.map(entryStream => entryStream.cancel(reason)));
5362
+ await Promise.allSettled([gen.return(), zipReader.close()]);
5223
5363
  }
5224
5364
  });
5225
5365
  this.writable = writable;
5226
5366
  }
5227
5367
  }
5228
5368
 
5369
+ function createEntryStream(entry, pendingEntries) {
5370
+ const { readable, writable } = new TransformStream();
5371
+ let dataReader;
5372
+ const entryStream = {
5373
+ cancel: async reason => {
5374
+ pendingEntries.delete(entryStream);
5375
+ await (dataReader ? dataReader.cancel(reason) : readable.cancel(reason));
5376
+ }
5377
+ };
5378
+ entryStream.readable = new ReadableStream({
5379
+ async pull(controller) {
5380
+ if (!dataReader) {
5381
+ dataReader = readable.getReader();
5382
+ pendingEntries.add(entryStream);
5383
+ getData();
5384
+ }
5385
+ const { done, value } = await dataReader.read();
5386
+ if (done) {
5387
+ controller.close();
5388
+ } else {
5389
+ controller.enqueue(value);
5390
+ }
5391
+ },
5392
+ cancel: reason => entryStream.cancel(reason)
5393
+ }, { highWaterMark: 0 });
5394
+ return entryStream;
5395
+
5396
+ async function getData() {
5397
+ try {
5398
+ await entry.getData(writable, { preventClose: false });
5399
+ } catch (error) {
5400
+ try {
5401
+ await writable.abort(error);
5402
+ } catch {
5403
+ // ignored
5404
+ }
5405
+ } finally {
5406
+ pendingEntries.delete(entryStream);
5407
+ }
5408
+ }
5409
+ }
5410
+
5229
5411
  async function isZipFile(reader, options = {}) {
5230
5412
  reader = new GenericReader(reader);
5231
5413
  await initStream(reader);
@@ -5285,7 +5467,9 @@
5285
5467
  const dataView = getDataView(dataArray);
5286
5468
  let password = getOptionValue$1(zipEntry, options, OPTION_PASSWORD);
5287
5469
  let rawPassword = getOptionValue$1(zipEntry, options, OPTION_RAW_PASSWORD);
5288
- const passThrough = getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH);
5470
+ const passThrough = checkPassThroughOption(getOptionValue$1(zipEntry, options, OPTION_PASS_THROUGH));
5471
+ const passThroughCompression = Boolean(passThrough);
5472
+ const passThroughEncryption = passThrough === true;
5289
5473
  checkPasswordOption(password, rawPassword);
5290
5474
  password = password && password.length && password;
5291
5475
  rawPassword = rawPassword && rawPassword.length && rawPassword;
@@ -5306,7 +5490,9 @@
5306
5490
  const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5307
5491
  const entryStrictness = getStrictness(options, zipEntry.options);
5308
5492
  const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5309
- const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5493
+ const checkLocalFilenameOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_FILENAME);
5494
+ const checkLocalFilename = getCheckLocalFilename(
5495
+ checkLocalFilenameOption === UNDEFINED_VALUE ? checkLocalDirectoryOption : checkLocalFilenameOption, entryStrictness);
5310
5496
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5311
5497
  if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5312
5498
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
@@ -5337,16 +5523,17 @@
5337
5523
  if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5338
5524
  fileEntry.gid = gid;
5339
5525
  }
5340
- const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5526
+ const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5527
+ const encrypted = zipEntry.encrypted && localDirectory.encrypted && (!passThroughEncryption || checkPasswordOnly);
5341
5528
  const zipCrypto = encrypted && !extraFieldAES;
5342
- if (!passThrough) {
5529
+ if (!passThroughEncryption) {
5343
5530
  fileEntry.zipCrypto = zipCrypto;
5344
5531
  }
5345
5532
  if (encrypted && (localDirectory.rawBitFlag & BITFLAG_STRONG_ENCRYPTION) == BITFLAG_STRONG_ENCRYPTION) {
5346
5533
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
5347
5534
  }
5348
- const registeredCodec = passThrough ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
5349
- if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !passThrough) {
5535
+ const registeredCodec = passThroughCompression ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
5536
+ if (compressionMethod != COMPRESSION_METHOD_STORE && compressionMethod != COMPRESSION_METHOD_DEFLATE && compressionMethod != COMPRESSION_METHOD_DEFLATE_64 && !registeredCodec && !passThroughCompression) {
5350
5537
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
5351
5538
  }
5352
5539
  if (encrypted) {
@@ -5362,15 +5549,17 @@
5362
5549
  const size = compressedSize;
5363
5550
  const readable = toCompatibleReadable(reader.createReadable({ offset: dataOffset, size }));
5364
5551
  const signal = checkSignalOption(getOptionValue$1(zipEntry, options, OPTION_SIGNAL));
5365
- const checkPasswordOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_PASSWORD_ONLY);
5552
+ throwIfAborted(signal);
5366
5553
  let checkOverlappingEntry = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY);
5367
5554
  const checkOverlappingEntryOnly = getOptionValue$1(zipEntry, options, OPTION_CHECK_OVERLAPPING_ENTRY_ONLY);
5368
5555
  if (checkOverlappingEntryOnly) {
5369
5556
  checkOverlappingEntry = true;
5370
5557
  }
5371
5558
  const { onstart, onprogress, onend } = options;
5372
- const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThrough;
5373
- const outputSize = passThrough ? compressedSize : uncompressedSize;
5559
+ const compressed = compressionMethod != COMPRESSION_METHOD_STORE && !passThroughCompression;
5560
+ const outputSize = passThroughCompression ?
5561
+ compressedSize - getEncryptionOverhead(encrypted, zipCrypto, extraFieldAES && extraFieldAES.strength) :
5562
+ uncompressedSize;
5374
5563
  const deflate64 = compressionMethod == COMPRESSION_METHOD_DEFLATE_64;
5375
5564
  let useCompressionStream = getOptionValue$1(zipEntry, options, OPTION_USE_COMPRESSION_STREAM);
5376
5565
  if (deflate64) {
@@ -5379,7 +5568,7 @@
5379
5568
  const checkCrc32Option = getOptionValue$1(zipEntry, options, OPTION_CHECK_CRC32);
5380
5569
  const checkCrc32 = (checkCrc32Option === UNDEFINED_VALUE ?
5381
5570
  getOptionValue$1(zipEntry, options, OPTION_CHECK_SIGNATURE) :
5382
- checkCrc32Option) && !passThrough &&
5571
+ checkCrc32Option) && !passThroughCompression &&
5383
5572
  (!encrypted || zipCrypto || (extraFieldAES && extraFieldAES.vendorVersion == VENDOR_VERSION_AE_1$1));
5384
5573
  const workerOptions = {
5385
5574
  options: {
@@ -5433,10 +5622,10 @@
5433
5622
  await initStream(writer, getDecodableOutputSize(outputSize, compressedSize, compressed));
5434
5623
  ({ writable } = writer);
5435
5624
  const { outputSize: writtenSize } = await runWorker({ readable, writable }, workerOptions);
5436
- writer.size += writtenSize;
5437
5625
  if (writtenSize != outputSize) {
5438
- throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
5626
+ throw Object.assign(new Error(ERR_INVALID_UNCOMPRESSED_SIZE), { outputSize: writtenSize });
5439
5627
  }
5628
+ writer.size += writtenSize;
5440
5629
  }
5441
5630
  } catch (error) {
5442
5631
  if (error.outputSize !== UNDEFINED_VALUE) {
@@ -6102,7 +6291,7 @@
6102
6291
  if (checkLocalFilename && !maskedLocalDirectory &&
6103
6292
  (rawLocalFilename.length != rawFilename.length ||
6104
6293
  rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
6105
- reportAmbiguity(reject, warnings, "mismatched local file header (filename)");
6294
+ reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME);
6106
6295
  }
6107
6296
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
6108
6297
  reportAmbiguity(reject, warnings, WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG);
@@ -6127,16 +6316,6 @@
6127
6316
  }
6128
6317
  }
6129
6318
 
6130
- function addWarning(warnings, reason, filename) {
6131
- if (!warnings.some(warning => warning.reason == reason)) {
6132
- const warning = { reason };
6133
- if (filename !== UNDEFINED_VALUE) {
6134
- warning.filename = filename;
6135
- }
6136
- warnings.push(warning);
6137
- }
6138
- }
6139
-
6140
6319
  function throwAmbiguousArchive(reason) {
6141
6320
  const error = new Error(ERR_AMBIGUOUS_ARCHIVE);
6142
6321
  error.reason = reason;
@@ -6216,7 +6395,9 @@
6216
6395
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG: WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG,
6217
6396
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD: WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD,
6218
6397
  WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES: WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES,
6398
+ WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME: WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME,
6219
6399
  WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY: WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
6400
+ WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY: WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY,
6220
6401
  WARNING_PREPENDED_CENTRAL_DIRECTORY: WARNING_PREPENDED_CENTRAL_DIRECTORY,
6221
6402
  WARNING_PREPENDED_DATA: WARNING_PREPENDED_DATA,
6222
6403
  WARNING_TRAILING_CENTRAL_DIRECTORY_DATA: WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
@@ -6269,7 +6450,7 @@
6269
6450
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
6270
6451
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
6271
6452
  const ERR_UNSUPPORTED_SPLIT_USDZ = "Split zip files are not supported in USDZ files";
6272
- const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
6453
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set to true (use 'compressed' instead)";
6273
6454
  const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
6274
6455
  const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
6275
6456
  const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
@@ -6281,6 +6462,7 @@
6281
6462
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
6282
6463
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
6283
6464
  const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
6465
+ const ERR_UNDEFINED_CRC32 = "Undefined CRC32";
6284
6466
  const ERR_UNDETERMINED_SIZE = "Undetermined size";
6285
6467
  const ERR_UNDEFINED_READER = "Undefined reader";
6286
6468
  const ERR_INVALID_READER = "Invalid reader (must be a Reader instance, a ReadableStream instance, or an object with a 'readable' property)";
@@ -6294,14 +6476,21 @@
6294
6476
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
6295
6477
  const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
6296
6478
  const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
6479
+ const ERR_INVALID_ENTRY = "Invalid entry option (must be an entry returned by ZipReader#getEntries())";
6480
+ const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
6481
+ const WARNING_COMPRESSION_UNAVAILABLE = "compression unavailable";
6482
+ const WARNING_CLAMPED_LAST_MODIFICATION_DATE = "clamped last modification date";
6297
6483
 
6298
6484
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
6299
6485
  const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
6300
6486
  const EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD = 9;
6301
6487
  const EXTRAFIELD_USDZ_MAX_LENGTH = 67;
6488
+ const MIN_PRINTABLE_ASCII_CHARACTER_CODE = 0x20;
6489
+ const MAX_PRINTABLE_ASCII_CHARACTER_CODE = 0x7e;
6302
6490
  const VENDOR_VERSION_AE_1 = 1;
6303
- const INFOZIP_EXTRA_FIELD_TYPE$1 = "infozip";
6491
+ const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
6304
6492
  const UNIX_EXTRA_FIELD_TYPE = "unix";
6493
+ const LEVEL_BY_BITFLAG_LEVEL = [8, 9, 5, 3];
6305
6494
  const MAX_LEVEL = 9;
6306
6495
 
6307
6496
  let workers = 0;
@@ -6328,9 +6517,11 @@
6328
6517
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
6329
6518
  pendingAddFileCalls: new Set(),
6330
6519
  pendingErrors: [],
6520
+ warnings: [],
6331
6521
  bufferedWrites: 0,
6332
6522
  directWrites: 0,
6333
- lastFileEntry: UNDEFINED_VALUE
6523
+ lastFileEntry: UNDEFINED_VALUE,
6524
+ archiveClosed: false
6334
6525
  });
6335
6526
  }
6336
6527
 
@@ -6495,6 +6686,9 @@
6495
6686
  const zipWriter = this;
6496
6687
  const { pendingAddFileCalls, writer } = this;
6497
6688
  const { writable } = writer;
6689
+ if (zipWriter.archiveClosed) {
6690
+ return getWriterData(writer);
6691
+ }
6498
6692
  if (!(comment instanceof Uint8Array)) {
6499
6693
  throw new Error(ERR_INVALID_COMMENT_TYPE);
6500
6694
  }
@@ -6518,11 +6712,16 @@
6518
6712
  throw error;
6519
6713
  }
6520
6714
  await closeFile(zipWriter, comment, options);
6715
+ zipWriter.archiveClosed = true;
6521
6716
  const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6522
6717
  if (!preventClose) {
6523
6718
  await writable.getWriter().close();
6524
6719
  }
6525
- return writer.getData ? writer.getData() : writable;
6720
+ return getWriterData(writer);
6721
+ }
6722
+
6723
+ [SYMBOL_ASYNC_DISPOSE]() {
6724
+ return this.close();
6526
6725
  }
6527
6726
  }
6528
6727
 
@@ -6601,6 +6800,10 @@
6601
6800
  }
6602
6801
  }
6603
6802
 
6803
+ function getWriterData(writer) {
6804
+ return writer.getData ? writer.getData() : writer.writable;
6805
+ }
6806
+
6604
6807
  function watchPromiseError(zipWriter, promise) {
6605
6808
  const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6606
6809
  const watcher = {};
@@ -6619,6 +6822,14 @@
6619
6822
 
6620
6823
  async function addFileEntry(zipWriter, name, reader, options) {
6621
6824
  options = Object.assign({}, options);
6825
+ const entry = options[OPTION_ENTRY];
6826
+ if (entry !== UNDEFINED_VALUE) {
6827
+ const { entryOptions, passThroughOptions } = getSourceEntryOptions(entry,
6828
+ checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH)),
6829
+ getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE));
6830
+ delete options[OPTION_ENTRY];
6831
+ options = Object.assign(entryOptions, passThroughOptions, options);
6832
+ }
6622
6833
  if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6623
6834
  name += DIRECTORY_SIGNATURE;
6624
6835
  }
@@ -6683,21 +6894,33 @@
6683
6894
  try {
6684
6895
  const { resolvedOptions } = metadataInfo;
6685
6896
  if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
6686
- !resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
6897
+ !resolvedOptions.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
6687
6898
  resolvedOptions.level = 0;
6899
+ addWarning(zipWriter.warnings, WARNING_COMPRESSION_UNAVAILABLE, name);
6688
6900
  }
6689
6901
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
6690
6902
  ({ reader } = sizesInfo);
6691
6903
  const diskOffset = getDiskOffset(zipWriter.writer);
6692
6904
  const diskNumber = getDiskNumber(zipWriter.writer);
6905
+ let crc32 = options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32;
6906
+ const storesAE2 = sizesInfo.resolvedOptions.encrypted && !resolvedOptions.zipCrypto;
6907
+ if (resolvedOptions.passThroughCompression && !resolvedOptions.passThroughEncryption && storesAE2) {
6908
+ crc32 = UNDEFINED_VALUE;
6909
+ }
6910
+ if (resolvedOptions.passThroughCompression && reader && !storesAE2 && crc32 === UNDEFINED_VALUE) {
6911
+ throw new Error(ERR_UNDEFINED_CRC32);
6912
+ }
6693
6913
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6694
6914
  signature: options[PROPERTY_NAME_SIGNATURE],
6695
- crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6915
+ crc32,
6696
6916
  offset: zipWriter.offset - diskOffset,
6697
6917
  diskNumberStart: diskNumber,
6698
6918
  [OPTION_USDZ]: zipWriter.options[OPTION_USDZ]
6699
6919
  });
6700
6920
  const headerInfo = getHeaderInfo(options);
6921
+ if (headerInfo.lastModDateClamped) {
6922
+ addWarning(zipWriter.warnings, WARNING_CLAMPED_LAST_MODIFICATION_DATE, name);
6923
+ }
6701
6924
  const dataDescriptorInfo = getDataDescriptorInfo(options);
6702
6925
  const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
6703
6926
  fileEntry = await getFileEntry(zipWriter, name, reader, {
@@ -6724,6 +6947,95 @@
6724
6947
  return new Entry(fileEntry);
6725
6948
  }
6726
6949
 
6950
+ function getSourceEntryOptions(entry, passThrough, lastModDateOverride) {
6951
+ if (entry === null || typeof entry != OBJECT_TYPE || Array.isArray(entry)) {
6952
+ throw new Error(ERR_INVALID_ENTRY);
6953
+ }
6954
+ const {
6955
+ externalFileAttributes,
6956
+ versionMadeBy,
6957
+ comment,
6958
+ lastModDate,
6959
+ rawLastModDate,
6960
+ creationDate,
6961
+ lastAccessDate,
6962
+ uncompressedSize,
6963
+ encrypted,
6964
+ zipCrypto,
6965
+ crc32,
6966
+ compressionMethod,
6967
+ extraFieldAES,
6968
+ extraFieldUnix,
6969
+ internalFileAttributes,
6970
+ extraField,
6971
+ bitFlag,
6972
+ directory,
6973
+ uid,
6974
+ gid
6975
+ } = entry;
6976
+ const entryOptions = {
6977
+ externalFileAttributes,
6978
+ versionMadeBy,
6979
+ comment,
6980
+ lastModDate,
6981
+ creationDate,
6982
+ lastAccessDate,
6983
+ internalFileAttributes,
6984
+ directory
6985
+ };
6986
+ if (bitFlag && bitFlag.languageEncodingFlag) {
6987
+ entryOptions[OPTION_USE_UNICODE_FILE_NAMES] = true;
6988
+ }
6989
+ const userExtraField = getUserExtraField(extraField);
6990
+ if (userExtraField) {
6991
+ entryOptions[PROPERTY_NAME_EXTRA_FIELD] = userExtraField;
6992
+ }
6993
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
6994
+ Object.assign(entryOptions, {
6995
+ uid,
6996
+ gid,
6997
+ unixExtraFieldType: extraFieldUnix ? UNIX_EXTRA_FIELD_TYPE : INFOZIP_EXTRA_FIELD_TYPE
6998
+ });
6999
+ }
7000
+ const passThroughOptions = {};
7001
+ if (passThrough && !directory) {
7002
+ Object.assign(passThroughOptions, {
7003
+ uncompressedSize,
7004
+ crc32,
7005
+ compressionMethod
7006
+ });
7007
+ if (passThrough !== PASS_THROUGH_COMPRESSED) {
7008
+ Object.assign(passThroughOptions, {
7009
+ encrypted,
7010
+ zipCrypto,
7011
+ encryptionStrength: extraFieldAES ? extraFieldAES.strength : UNDEFINED_VALUE
7012
+ });
7013
+ }
7014
+ if (bitFlag) {
7015
+ passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
7016
+ passThroughOptions[OPTION_LEVEL] = LEVEL_BY_BITFLAG_LEVEL[bitFlag.level];
7017
+ }
7018
+ if (lastModDateOverride === UNDEFINED_VALUE) {
7019
+ passThroughOptions.rawLastModDate = rawLastModDate;
7020
+ } else if (passThrough !== PASS_THROUGH_COMPRESSED && zipCrypto && (!bitFlag || bitFlag.dataDescriptor) &&
7021
+ lastModDateOverride instanceof Date &&
7022
+ getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
7023
+ throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
7024
+ }
7025
+ }
7026
+ return { entryOptions, passThroughOptions };
7027
+ }
7028
+
7029
+ function getDosTimeHighByte(lastModDate) {
7030
+ let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
7031
+ if (dosLastModDate < MIN_DATE) {
7032
+ dosLastModDate = MIN_DATE;
7033
+ } else if (dosLastModDate > MAX_DATE) {
7034
+ dosLastModDate = MAX_DATE;
7035
+ }
7036
+ return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
7037
+ }
7038
+
6727
7039
  function resolveAttributes(zipWriter, name, options) {
6728
7040
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6729
7041
  let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
@@ -6738,7 +7050,7 @@
6738
7050
  checkIntegerOption(uid, MAX_32_BITS, ERR_INVALID_UID);
6739
7051
  checkIntegerOption(gid, MAX_32_BITS, ERR_INVALID_GID);
6740
7052
  checkIntegerOption(unixMode, MAX_16_BITS, ERR_INVALID_UNIX_MODE);
6741
- if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE$1 && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
7053
+ if (unixExtraFieldType !== UNDEFINED_VALUE && unixExtraFieldType !== INFOZIP_EXTRA_FIELD_TYPE && unixExtraFieldType !== UNIX_EXTRA_FIELD_TYPE) {
6742
7054
  throw new Error(ERR_INVALID_UNIX_EXTRA_FIELD_TYPE);
6743
7055
  }
6744
7056
  if (unixExtraFieldType === UNIX_EXTRA_FIELD_TYPE &&
@@ -6746,7 +7058,7 @@
6746
7058
  throw new Error(ERR_INVALID_UNIX_ID_SIZE);
6747
7059
  }
6748
7060
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
6749
- unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE$1;
7061
+ unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
6750
7062
  }
6751
7063
  let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
6752
7064
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
@@ -6877,7 +7189,9 @@
6877
7189
  const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6878
7190
  const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6879
7191
  const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6880
- const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
7192
+ const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
7193
+ const passThroughCompression = Boolean(passThrough);
7194
+ const passThroughEncryption = passThrough === true;
6881
7195
  const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6882
7196
  const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6883
7197
  checkPasswordOption(password, rawPassword);
@@ -6892,10 +7206,12 @@
6892
7206
  const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
6893
7207
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
6894
7208
  const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
6895
- const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
7209
+ throwIfAborted(signal);
7210
+ const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES,
7211
+ !isPrintableASCIIText(rawFilename) || !isPrintableASCIIText(rawComment));
6896
7212
  const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
6897
- const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
6898
- if (!passThrough && compressionMethod !== UNDEFINED_VALUE &&
7213
+ const registeredCodec = passThroughCompression || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
7214
+ if (!passThroughCompression && compressionMethod !== UNDEFINED_VALUE &&
6899
7215
  compressionMethod !== COMPRESSION_METHOD_STORE && compressionMethod !== COMPRESSION_METHOD_DEFLATE && !registeredCodec) {
6900
7216
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
6901
7217
  }
@@ -6909,15 +7225,15 @@
6909
7225
  level = 0;
6910
7226
  }
6911
7227
  }
6912
- if (passThrough) {
6913
- level = UNDEFINED_VALUE;
7228
+ if (passThroughCompression) {
7229
+ level = toNumber(options[OPTION_LEVEL]);
6914
7230
  }
6915
7231
  let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
6916
7232
  let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
6917
7233
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
6918
7234
  dataDescriptor = false;
6919
7235
  }
6920
- if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThrough)) {
7236
+ if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThroughEncryption)) {
6921
7237
  dataDescriptor = true;
6922
7238
  }
6923
7239
  if (level !== UNDEFINED_VALUE && level != 6) {
@@ -6941,7 +7257,8 @@
6941
7257
  lastAccessDate,
6942
7258
  creationDate,
6943
7259
  internalFileAttributes,
6944
- passThrough,
7260
+ passThroughCompression,
7261
+ passThroughEncryption,
6945
7262
  password,
6946
7263
  rawPassword,
6947
7264
  encryptionStrength,
@@ -7002,7 +7319,7 @@
7002
7319
  }
7003
7320
 
7004
7321
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
7005
- if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7322
+ if (metadata.passThroughCompression && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
7006
7323
  throw new Error(ERR_UNDEFINED_READER);
7007
7324
  }
7008
7325
  let contentSize;
@@ -7018,12 +7335,12 @@
7018
7335
  }
7019
7336
 
7020
7337
  function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
7021
- const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7338
+ const { passThroughCompression, passThroughEncryption, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
7022
7339
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
7023
7340
  let maximumCompressedSize = 0;
7024
7341
  let uncompressedSize = 0;
7025
7342
  let unknownSize = false;
7026
- if (passThrough && hasContent) {
7343
+ if (passThroughCompression && hasContent) {
7027
7344
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
7028
7345
  if (uncompressedSize === UNDEFINED_VALUE) {
7029
7346
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -7034,17 +7351,17 @@
7034
7351
  }
7035
7352
  const zip64Enabled = zip64 === true;
7036
7353
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
7037
- if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
7354
+ if (hasContent && passThroughEncryption && !encrypted && getLength(password, rawPassword)) {
7038
7355
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
7039
7356
  }
7040
- const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
7357
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThroughEncryption && encrypted));
7041
7358
  if (!hasContent) {
7042
7359
  level = 0;
7043
7360
  compressionMethod = COMPRESSION_METHOD_STORE;
7044
7361
  }
7045
- const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7362
+ const encryptionOverhead = getEncryptionOverhead(encryptedEntry, zipCrypto, encryptionStrength);
7046
7363
  if (hasContent) {
7047
- if (!passThrough) {
7364
+ if (!passThroughCompression) {
7048
7365
  if (contentSize === UNDEFINED_VALUE) {
7049
7366
  dataDescriptor = true;
7050
7367
  if (zip64 || zip64 === UNDEFINED_VALUE) {
@@ -7057,10 +7374,12 @@
7057
7374
  }
7058
7375
  } else {
7059
7376
  options.uncompressedSize = uncompressedSize;
7060
- maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
7377
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ?
7378
+ getMaximumCompressedSize(uncompressedSize) + encryptionOverhead :
7379
+ contentSize + (passThroughEncryption ? 0 : encryptionOverhead);
7061
7380
  }
7062
7381
  }
7063
- const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThrough)) && !isCompressed(compressionMethod, level);
7382
+ const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThroughCompression)) && !isCompressed(compressionMethod, level);
7064
7383
  if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
7065
7384
  dataDescriptor = false;
7066
7385
  }
@@ -7109,6 +7428,8 @@
7109
7428
  const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
7110
7429
  let offset = initialOffset;
7111
7430
  let minimumEntrySize = INFINITY_VALUE;
7431
+ const entrySizes = [];
7432
+ const entriesAlreadyZip64 = new Set();
7112
7433
  for (const entry of entries) {
7113
7434
  let { name } = entry;
7114
7435
  const { size } = entry;
@@ -7120,7 +7441,7 @@
7120
7441
  ({ name } = attributesInfo);
7121
7442
  const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
7122
7443
  if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
7123
- !metadata.passThrough && !(await supportsDeflate(getConfiguration()))) {
7444
+ !metadata.passThroughCompression && !(await supportsDeflate(getConfiguration()))) {
7124
7445
  metadata.level = 0;
7125
7446
  }
7126
7447
  const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
@@ -7128,7 +7449,7 @@
7128
7449
  throw new Error(ERR_UNDETERMINED_SIZE);
7129
7450
  }
7130
7451
  const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
7131
- if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
7452
+ if (hasContent && !metadata.passThroughCompression && isCompressed(sizes.compressionMethod, sizes.level)) {
7132
7453
  throw new Error(ERR_UNDETERMINED_SIZE);
7133
7454
  }
7134
7455
  const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes, { [OPTION_USDZ]: usdz });
@@ -7148,10 +7469,15 @@
7148
7469
  compressedSize
7149
7470
  }));
7150
7471
  const entrySize = entryInfo.metadataSize + compressedSize;
7472
+ entrySizes.push(entrySize);
7473
+ entriesAlreadyZip64.add(Boolean(entryOptions.zip64Enabled ||
7474
+ entryOptions.uncompressedSize >= MAX_32_BITS || compressedSize >= MAX_32_BITS));
7151
7475
  minimumEntrySize = Math.min(minimumEntrySize, entrySize);
7152
7476
  offset += entrySize;
7153
7477
  }
7154
- const layoutDependsOnWriteOrder = files.size > 1 && (usdz || offset - minimumEntrySize >= MAX_32_BITS);
7478
+ const layoutDependsOnWriteOrder = files.size > 1 && (usdz ||
7479
+ (offset - minimumEntrySize >= MAX_32_BITS &&
7480
+ (entriesAlreadyZip64.size > 1 || countEntriesBefore4GB(entrySizes, initialOffset, true) != countEntriesBefore4GB(entrySizes, initialOffset, false))));
7155
7481
  if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
7156
7482
  throw new Error(ERR_UNDETERMINED_SIZE);
7157
7483
  }
@@ -7169,6 +7495,20 @@
7169
7495
  return offset - initialOffset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
7170
7496
  }
7171
7497
 
7498
+ function countEntriesBefore4GB(entrySizes, initialOffset, largestFirst) {
7499
+ const ordered = entrySizes.slice().sort((first, second) => largestFirst ? second - first : first - second);
7500
+ let position = initialOffset;
7501
+ let count = 0;
7502
+ for (const entrySize of ordered) {
7503
+ if (position >= MAX_32_BITS) {
7504
+ break;
7505
+ }
7506
+ position += entrySize;
7507
+ count++;
7508
+ }
7509
+ return count;
7510
+ }
7511
+
7172
7512
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
7173
7513
  const {
7174
7514
  fileEntries,
@@ -7344,6 +7684,7 @@
7344
7684
  localExtraFieldZip64Length,
7345
7685
  rawExtraFieldExtendedTimestamp,
7346
7686
  extraFieldExtendedTimestampFlag,
7687
+ extraFieldExtendedTimestampTime,
7347
7688
  rawExtraFieldNTFS,
7348
7689
  rawExtraFieldUnix,
7349
7690
  rawExtraFieldAES,
@@ -7356,6 +7697,7 @@
7356
7697
  password,
7357
7698
  rawPassword,
7358
7699
  level,
7700
+ useUnicodeFileNames,
7359
7701
  zip64,
7360
7702
  zip64Enabled,
7361
7703
  zip64UncompressedSize,
@@ -7390,7 +7732,8 @@
7390
7732
  msdosAttributesRaw,
7391
7733
  msdosAttributes,
7392
7734
  useCompressionStream,
7393
- passThrough,
7735
+ passThroughCompression,
7736
+ passThroughEncryption,
7394
7737
  format,
7395
7738
  codecURI
7396
7739
  } = options;
@@ -7401,9 +7744,9 @@
7401
7744
  zip64Enabled,
7402
7745
  directory: Boolean(directory),
7403
7746
  executable: Boolean(executable),
7404
- filenameUTF8: true,
7747
+ filenameUTF8: Boolean(useUnicodeFileNames),
7405
7748
  rawFilename,
7406
- commentUTF8: true,
7749
+ commentUTF8: Boolean(useUnicodeFileNames),
7407
7750
  rawComment,
7408
7751
  rawExtraFieldZip64,
7409
7752
  localExtraFieldZip64Length,
@@ -7434,7 +7777,7 @@
7434
7777
  uncompressedSize
7435
7778
  } = options;
7436
7779
  let compressedSize = 0;
7437
- if (!passThrough) {
7780
+ if (!passThroughCompression) {
7438
7781
  uncompressedSize = 0;
7439
7782
  }
7440
7783
  const { writable } = writer;
@@ -7451,9 +7794,9 @@
7451
7794
  encryptionStrength,
7452
7795
  zipCrypto: encrypted && zipCrypto,
7453
7796
  passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & MAX_8_BITS,
7454
- computeCrc32: !passThrough,
7455
- compressed: compressed && !passThrough,
7456
- encrypted: encrypted && !passThrough,
7797
+ computeCrc32: !passThroughCompression,
7798
+ compressed: compressed && !passThroughCompression,
7799
+ encrypted: encrypted && !passThroughEncryption,
7457
7800
  useWebWorkers,
7458
7801
  useCompressionStream,
7459
7802
  transferStreams,
@@ -7468,7 +7811,7 @@
7468
7811
  const result = await runWorker({ readable, writable }, workerOptions);
7469
7812
  compressedSize = result.outputSize;
7470
7813
  writer.size += compressedSize;
7471
- if (!passThrough) {
7814
+ if (!passThroughCompression) {
7472
7815
  uncompressedSize = result.inputSize;
7473
7816
  if (!encrypted || zipCrypto) {
7474
7817
  crc32 = result.crc32;
@@ -7511,8 +7854,9 @@
7511
7854
  headerArray,
7512
7855
  headerView,
7513
7856
  signature: crc32,
7514
- crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
7857
+ crc32: encrypted && !zipCrypto && !passThroughCompression ? UNDEFINED_VALUE : crc32,
7515
7858
  extraFieldExtendedTimestampFlag,
7859
+ extraFieldExtendedTimestampTime,
7516
7860
  zip64UncompressedSize,
7517
7861
  zip64CompressedSize
7518
7862
  });
@@ -7537,7 +7881,7 @@
7537
7881
  encryptionStrength,
7538
7882
  extendedTimestamp,
7539
7883
  ntfsTimestamp,
7540
- passThrough,
7884
+ passThroughCompression,
7541
7885
  encrypted,
7542
7886
  zip64UncompressedSize,
7543
7887
  zip64CompressedSize,
@@ -7548,7 +7892,7 @@
7548
7892
  let { version, compressionMethod } = options;
7549
7893
  const compressed = !directory && isCompressed(compressionMethod, level);
7550
7894
  let rawLocalExtraFieldZip64;
7551
- const uncompressedFile = passThrough || !compressed;
7895
+ const uncompressedFile = passThroughCompression || !compressed;
7552
7896
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || (uncompressedFile && !unknownSize)));
7553
7897
  const writeLocalExtraFieldZip64 = zip64ExtraFieldComplete || (zip64 && dataDescriptor && (zip64UncompressedSize || zip64CompressedSize));
7554
7898
  if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
@@ -7560,8 +7904,8 @@
7560
7904
  if (zip64ExtraFieldComplete) {
7561
7905
  extraFieldZip64.writeUint64(uncompressedSize);
7562
7906
  if (uncompressedFile) {
7563
- const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
7564
- extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
7907
+ const encryptionOverhead = getEncryptionOverhead(encrypted, zipCrypto, encryptionStrength);
7908
+ extraFieldZip64.writeUint64(passThroughCompression ? 0 : uncompressedSize + encryptionOverhead);
7565
7909
  }
7566
7910
  }
7567
7911
  } else {
@@ -7580,6 +7924,7 @@
7580
7924
  let rawExtraFieldNTFS;
7581
7925
  let rawExtraFieldExtendedTimestamp;
7582
7926
  let extraFieldExtendedTimestampFlag;
7927
+ let extraFieldExtendedTimestampTime;
7583
7928
  if (extendedTimestamp) {
7584
7929
  const lastModTimeUnix = getTimeUnix(lastModDate);
7585
7930
  const lastModTimeUnixInRange = inUnixTimeRange(lastModTimeUnix);
@@ -7587,6 +7932,7 @@
7587
7932
  const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
7588
7933
  const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
7589
7934
  extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
7935
+ extraFieldExtendedTimestampTime = lastModTimeUnix;
7590
7936
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7591
7937
  extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
7592
7938
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
@@ -7629,7 +7975,7 @@
7629
7975
  let rawExtraFieldUnix;
7630
7976
  try {
7631
7977
  const { uid, gid, unixExtraFieldType } = options;
7632
- if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE$1 && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
7978
+ if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
7633
7979
  const uidBytes = packUnixId(uid === UNDEFINED_VALUE ? 0 : uid);
7634
7980
  const gidBytes = packUnixId(gid === UNDEFINED_VALUE ? 0 : gid);
7635
7981
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
@@ -7670,7 +8016,7 @@
7670
8016
  }
7671
8017
  if (encrypted && !zipCrypto) {
7672
8018
  version = version > VERSION_AES ? version : VERSION_AES;
7673
- if (passThrough && crc32 !== UNDEFINED_VALUE) {
8019
+ if (passThroughCompression && crc32 !== UNDEFINED_VALUE) {
7674
8020
  rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
7675
8021
  }
7676
8022
  setUint16(getDataView(rawExtraFieldAES), EXTRAFIELD_OFFSET_AES_COMPRESSION_METHOD, compressionMethod);
@@ -7732,12 +8078,14 @@
7732
8078
  headerArray,
7733
8079
  headerView,
7734
8080
  lastModDate: storedLastModDate,
8081
+ lastModDateClamped: storedLastModDate === clampedLastModDate && dosLastModDate.getTime() != clampedLastModDate.getTime(),
7735
8082
  rawLastModDate,
7736
8083
  encrypted,
7737
8084
  compressed,
7738
8085
  version,
7739
8086
  compressionMethod,
7740
8087
  extraFieldExtendedTimestampFlag,
8088
+ extraFieldExtendedTimestampTime,
7741
8089
  rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
7742
8090
  localExtraFieldZip64Length,
7743
8091
  rawExtraFieldExtendedTimestamp,
@@ -7840,7 +8188,7 @@
7840
8188
  }, {
7841
8189
  zip64,
7842
8190
  zipCrypto,
7843
- passThrough,
8191
+ passThroughCompression,
7844
8192
  dataDescriptor
7845
8193
  }) {
7846
8194
  const {
@@ -7851,7 +8199,7 @@
7851
8199
  dataDescriptorView,
7852
8200
  dataDescriptorOffset
7853
8201
  } = dataDescriptorInfo;
7854
- if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
8202
+ if ((!encrypted || zipCrypto || passThroughCompression) && crc32 !== UNDEFINED_VALUE) {
7855
8203
  setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
7856
8204
  if (dataDescriptor) {
7857
8205
  setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
@@ -7882,9 +8230,9 @@
7882
8230
  uncompressedSize,
7883
8231
  zip64UncompressedSize,
7884
8232
  zip64CompressedSize
7885
- }, localHeaderView, { dataDescriptor, passThrough }) {
8233
+ }, localHeaderView, { dataDescriptor, passThroughCompression }) {
7886
8234
  if (!dataDescriptor) {
7887
- if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
8235
+ if (!encrypted || (passThroughCompression && crc32 !== UNDEFINED_VALUE)) {
7888
8236
  setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
7889
8237
  }
7890
8238
  if (!zip64CompressedSize) {
@@ -7921,9 +8269,8 @@
7921
8269
  rawExtraFieldUnix,
7922
8270
  rawExtraField,
7923
8271
  rawCentralExtraField,
7924
- extendedTimestamp,
7925
8272
  extraFieldExtendedTimestampFlag,
7926
- lastModDate,
8273
+ extraFieldExtendedTimestampTime,
7927
8274
  zip64Enabled,
7928
8275
  uncompressedSize,
7929
8276
  compressedSize
@@ -7966,16 +8313,15 @@
7966
8313
  fileEntry.zip64Offset = zip64Offset;
7967
8314
  fileEntry.zip64DiskNumberStart = zip64DiskNumberStart;
7968
8315
  let rawExtraFieldTimestamp;
7969
- const lastModTimeUnix = getTimeUnix(lastModDate);
7970
- if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
8316
+ if (extraFieldExtendedTimestampTime === UNDEFINED_VALUE) {
8317
+ rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
8318
+ } else {
7971
8319
  const extraFieldTimestamp = createRecordWriter(9);
7972
8320
  extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
7973
8321
  extraFieldTimestamp.writeUint16(5);
7974
8322
  extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
7975
- extraFieldTimestamp.writeUint32(lastModTimeUnix);
8323
+ extraFieldTimestamp.writeUint32(extraFieldExtendedTimestampTime);
7976
8324
  rawExtraFieldTimestamp = extraFieldTimestamp.array;
7977
- } else {
7978
- rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
7979
8325
  }
7980
8326
  fileEntry.rawExtraFieldExtendedTimestamp = rawExtraFieldTimestamp;
7981
8327
  const extraFieldLength = getLength(
@@ -8475,6 +8821,11 @@
8475
8821
  };
8476
8822
  }
8477
8823
 
8824
+ function isPrintableASCIIText(rawText) {
8825
+ return rawText.every(characterCode =>
8826
+ characterCode >= MIN_PRINTABLE_ASCII_CHARACTER_CODE && characterCode <= MAX_PRINTABLE_ASCII_CHARACTER_CODE);
8827
+ }
8828
+
8478
8829
  function getBitFlag(level, useUnicodeFileNames, dataDescriptor, encrypted, compressionMethod) {
8479
8830
  let bitFlag = 0;
8480
8831
  if (useUnicodeFileNames) {
@@ -8636,7 +8987,7 @@
8636
8987
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8637
8988
  */
8638
8989
 
8639
- const VERSION = "2.11.3";
8990
+ const VERSION = "2.12.0";
8640
8991
 
8641
8992
  /*
8642
8993
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9155,7 +9506,10 @@
9155
9506
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
9156
9507
  const ERR_DUPLICATE_IMPORTED_ENTRY = "Duplicate entry filename in the imported zip file";
9157
9508
  const ERR_INVALID_DUPLICATES = "Invalid duplicates option (must be \"throw\", \"keep-first\" or \"keep-last\")";
9158
- const ERR_ANCESTOR_ENTRY = "Entry is a ancestor of target entry";
9509
+ const ERR_ANCESTOR_ENTRY = "Entry is an ancestor of target entry";
9510
+ const ERR_ROOT_DIRECTORY_NOT_MOVABLE = "Root directory cannot be moved";
9511
+ const ERR_TARGET_NOT_DIRECTORY = "Target entry is not a directory";
9512
+ const ERR_PARENT_NOT_DIRECTORY = "Parent entry is not a directory";
9159
9513
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
9160
9514
  const DUPLICATES_THROW = "throw";
9161
9515
  const DUPLICATES_KEEP_FIRST = "keep-first";
@@ -9163,24 +9517,8 @@
9163
9517
  const DUPLICATES_VALUES = new Set([DUPLICATES_THROW, DUPLICATES_KEEP_FIRST, DUPLICATES_KEEP_LAST]);
9164
9518
  const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
9165
9519
  const ERR_INVALID_READER_OPTIONS = "Invalid readerOptions (must be an object)";
9166
- const ERR_ZIP_CRYPTO_LAST_MOD_DATE = "The last modification date of an entry encrypted with ZipCrypto cannot be changed when passThrough is set";
9520
+ const ERR_UNSUPPORTED_PASS_THROUGH_VALUE = "The 'compressed' passThrough option is only supported by Entry#getData() and ZipWriter#add()";
9167
9521
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
9168
- const ERR_ABORTED = "The operation was aborted";
9169
- const ABORT_ERROR_NAME = "AbortError";
9170
- const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
9171
- const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
9172
- EXTRAFIELD_TYPE_ZIP64,
9173
- EXTRAFIELD_TYPE_AES,
9174
- EXTRAFIELD_TYPE_NTFS,
9175
- EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
9176
- EXTRAFIELD_TYPE_UNICODE_PATH,
9177
- EXTRAFIELD_TYPE_UNICODE_COMMENT,
9178
- EXTRAFIELD_TYPE_USDZ,
9179
- EXTRAFIELD_TYPE_INFOZIP,
9180
- EXTRAFIELD_TYPE_UNIX,
9181
- EXTRAFIELD_TYPE_UNIX_TYPE1,
9182
- EXTRAFIELD_TYPE_PKWARE_UNIX
9183
- ]);
9184
9522
 
9185
9523
  class ZipEntry {
9186
9524
 
@@ -9552,6 +9890,7 @@
9552
9890
  await initStream(reader);
9553
9891
  zipReader = new ZipReader(reader, options);
9554
9892
  }
9893
+ checkPassThroughValue(options.passThrough);
9555
9894
  const duplicates = checkDuplicatesOption(options.duplicates);
9556
9895
  const importedEntries = [];
9557
9896
  const entries = await zipReader.getEntries(options);
@@ -9642,18 +9981,25 @@
9642
9981
 
9643
9982
  async exportZip(writer, options = {}) {
9644
9983
  const zipEntry = this;
9984
+ const zipWriterProvided = Boolean(writer) && typeof writer.add == FUNCTION_TYPE;
9645
9985
  options = Object.assign({}, options);
9646
- if (options.bufferedWrite === UNDEFINED_VALUE) {
9986
+ if (!zipWriterProvided && options.bufferedWrite === UNDEFINED_VALUE) {
9647
9987
  options.bufferedWrite = true;
9648
9988
  }
9649
- const [readers] = await Promise.all([initReaders(zipEntry, checkReaderOptions(options.readerOptions)), initStream(writer)]);
9650
- const zipWriter = new ZipWriter(writer, options);
9989
+ const [readers] = await Promise.all([
9990
+ initReaders(zipEntry, checkReaderOptions(options.readerOptions)),
9991
+ zipWriterProvided ? UNDEFINED_VALUE : initStream(writer)
9992
+ ]);
9993
+ const zipWriter = zipWriterProvided ? writer : new ZipWriter(writer, options);
9651
9994
  await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
9995
+ if (zipWriterProvided) {
9996
+ return zipWriter;
9997
+ }
9652
9998
  await zipWriter.close(options.globalComment);
9653
9999
  return writer.getData ? writer.getData() : writer.writable;
9654
10000
  }
9655
10001
 
9656
- getExportedSize(options = {}) {
10002
+ async getExportedSize(options = {}) {
9657
10003
  const zipEntry = this;
9658
10004
  options = Object.assign({}, options);
9659
10005
  checkReaderOptions(options.readerOptions);
@@ -9668,7 +10014,7 @@
9668
10014
  const writeOrderGuaranteed = !options.bufferedWrite ||
9669
10015
  (entries.every(entry => entry.options.keepOrder !== false) &&
9670
10016
  children.every(child => isImplicitDirectory(child) || !child.children.length));
9671
- return getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
10017
+ return await getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
9672
10018
  }
9673
10019
 
9674
10020
  getChildByName(name) {
@@ -9729,7 +10075,7 @@
9729
10075
 
9730
10076
  move(entry, destination) {
9731
10077
  if (entry == this.root) {
9732
- throw new Error("Root directory cannot be moved");
10078
+ throw new Error(ERR_ROOT_DIRECTORY_NOT_MOVABLE);
9733
10079
  } else {
9734
10080
  if (destination.directory) {
9735
10081
  if (!destination.isDescendantOf(entry)) {
@@ -9750,7 +10096,7 @@
9750
10096
  throw new Error(ERR_ANCESTOR_ENTRY);
9751
10097
  }
9752
10098
  } else {
9753
- throw new Error("Target entry is not a directory");
10099
+ throw new Error(ERR_TARGET_NOT_DIRECTORY);
9754
10100
  }
9755
10101
  }
9756
10102
  }
@@ -10063,70 +10409,11 @@
10063
10409
  let zipEntryMetadata = {};
10064
10410
  let passThroughOptions = {};
10065
10411
  if (child.data instanceof Entry) {
10066
- const {
10067
- externalFileAttributes,
10068
- versionMadeBy,
10069
- comment,
10070
- lastModDate,
10071
- rawLastModDate,
10072
- creationDate,
10073
- lastAccessDate,
10074
- uncompressedSize,
10075
- encrypted,
10076
- zipCrypto,
10077
- crc32,
10078
- compressionMethod,
10079
- extraFieldAES,
10080
- internalFileAttributes,
10081
- extraField,
10082
- bitFlag,
10083
- uid,
10084
- gid
10085
- } = child.data;
10086
- zipEntryMetadata = {
10087
- externalFileAttributes,
10088
- versionMadeBy,
10089
- comment,
10090
- lastModDate,
10091
- creationDate,
10092
- lastAccessDate,
10093
- internalFileAttributes
10094
- };
10095
- const userExtraField = getUserExtraField(extraField);
10096
- if (userExtraField) {
10097
- zipEntryMetadata.extraField = userExtraField;
10098
- }
10099
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
10100
- Object.assign(zipEntryMetadata, {
10101
- uid,
10102
- gid,
10103
- unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
10104
- });
10105
- }
10106
- if (isPassThrough(child, options)) {
10107
- let encryptionStrength;
10108
- if (extraFieldAES) {
10109
- encryptionStrength = extraFieldAES.strength;
10110
- }
10111
- passThroughOptions = {
10112
- passThrough: true,
10113
- encrypted,
10114
- zipCrypto,
10115
- crc32,
10116
- uncompressedSize,
10117
- encryptionStrength,
10118
- compressionMethod
10119
- };
10120
- if (bitFlag) {
10121
- passThroughOptions.dataDescriptor = bitFlag.dataDescriptor;
10122
- }
10123
- const lastModDateOverride = childOptions.lastModDate === UNDEFINED_VALUE ? options.lastModDate : childOptions.lastModDate;
10124
- if (lastModDateOverride === UNDEFINED_VALUE) {
10125
- passThroughOptions.rawLastModDate = rawLastModDate;
10126
- } else if (zipCrypto && (!bitFlag || bitFlag.dataDescriptor) && lastModDateOverride instanceof Date &&
10127
- getDosTimeHighByte(lastModDateOverride) != ((rawLastModDate >>> 8) & MAX_8_BITS)) {
10128
- throw new Error(ERR_ZIP_CRYPTO_LAST_MOD_DATE);
10129
- }
10412
+ const passThrough = isPassThrough(child, options);
10413
+ const lastModDateOverride = childOptions.lastModDate === UNDEFINED_VALUE ? options.lastModDate : childOptions.lastModDate;
10414
+ ({ entryOptions: zipEntryMetadata, passThroughOptions } = getSourceEntryOptions(child.data, passThrough, lastModDateOverride));
10415
+ if (passThrough) {
10416
+ passThroughOptions.passThrough = true;
10130
10417
  }
10131
10418
  }
10132
10419
  const entryOptions = Object.assign({ lastModDate: child.defaultLastModDate }, zipEntryMetadata, options, childOptions, passThroughOptions, { directory: child.directory });
@@ -10136,16 +10423,6 @@
10136
10423
  return { name, entryOptions };
10137
10424
  }
10138
10425
 
10139
- function getDosTimeHighByte(lastModDate) {
10140
- let dosLastModDate = new Date(Math.ceil(Math.floor(lastModDate.getTime() / 1000) / 2) * 2000);
10141
- if (dosLastModDate < MIN_DATE) {
10142
- dosLastModDate = MIN_DATE;
10143
- } else if (dosLastModDate > MAX_DATE) {
10144
- dosLastModDate = MAX_DATE;
10145
- }
10146
- return ((dosLastModDate.getHours() << 3) | (dosLastModDate.getMinutes() >> 3)) & MAX_8_BITS;
10147
- }
10148
-
10149
10426
  function getDeterminedSize(child, passThrough) {
10150
10427
  const { reader } = child;
10151
10428
  if (reader && reader.size !== UNDEFINED_VALUE) {
@@ -10158,9 +10435,18 @@
10158
10435
  if (readerOptions && (typeof readerOptions != OBJECT_TYPE || Array.isArray(readerOptions))) {
10159
10436
  throw new Error(ERR_INVALID_READER_OPTIONS);
10160
10437
  }
10438
+ if (readerOptions) {
10439
+ checkPassThroughValue(readerOptions.passThrough);
10440
+ }
10161
10441
  return readerOptions;
10162
10442
  }
10163
10443
 
10444
+ function checkPassThroughValue(passThrough) {
10445
+ if (checkPassThroughOption(passThrough) === PASS_THROUGH_COMPRESSED) {
10446
+ throw new Error(ERR_UNSUPPORTED_PASS_THROUGH_VALUE);
10447
+ }
10448
+ }
10449
+
10164
10450
  function replaceContent(zipEntry, params) {
10165
10451
  const { uncompressedSize } = params;
10166
10452
  Object.assign(zipEntry, params, {
@@ -10189,20 +10475,6 @@
10189
10475
  return child.directory && child.data === null;
10190
10476
  }
10191
10477
 
10192
- function getUserExtraField(extraField) {
10193
- if (extraField) {
10194
- const userExtraField = new Map();
10195
- extraField.forEach((field, type) => {
10196
- if (!INTERPRETED_EXTRA_FIELD_TYPES.has(type)) {
10197
- userExtraField.set(type, field.data);
10198
- }
10199
- });
10200
- if (userExtraField.size) {
10201
- return userExtraField;
10202
- }
10203
- }
10204
- }
10205
-
10206
10478
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
10207
10479
  const { onstart, onprogress, onend, onentryprogress } = options;
10208
10480
  const selectedEntry = entry;
@@ -10305,6 +10577,7 @@
10305
10577
 
10306
10578
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
10307
10579
  const { onstart, onprogress, onend } = options;
10580
+ checkPassThroughValue(options.passThrough);
10308
10581
  const readerOptions = checkReaderOptions(options.readerOptions);
10309
10582
  const abortController = new AbortController();
10310
10583
  const { signal } = abortController;
@@ -10380,7 +10653,7 @@
10380
10653
  if (exportAborted || isExportAborted(signal.reason)) {
10381
10654
  return;
10382
10655
  }
10383
- throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
10656
+ throwIfAborted(signal);
10384
10657
  }
10385
10658
  try {
10386
10659
  if (child.directory) {
@@ -10513,7 +10786,7 @@
10513
10786
  }
10514
10787
  return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
10515
10788
  } else {
10516
- throw new Error("Parent entry is not a directory");
10789
+ throw new Error(ERR_PARENT_NOT_DIRECTORY);
10517
10790
  }
10518
10791
  }
10519
10792
 
@@ -10647,7 +10920,7 @@
10647
10920
  */
10648
10921
 
10649
10922
 
10650
- c(setDefaultConfiguration);
10923
+ f(setDefaultConfiguration);
10651
10924
 
10652
10925
  exports.BlobReader = BlobReader;
10653
10926
  exports.BlobWriter = BlobWriter;
@@ -10655,6 +10928,7 @@
10655
10928
  exports.Data64URIWriter = Data64URIWriter;
10656
10929
  exports.ERR_ABORTED = ERR_ABORTED;
10657
10930
  exports.ERR_AMBIGUOUS_ARCHIVE = ERR_AMBIGUOUS_ARCHIVE;
10931
+ exports.ERR_ANCESTOR_ENTRY = ERR_ANCESTOR_ENTRY;
10658
10932
  exports.ERR_BAD_FORMAT = ERR_BAD_FORMAT;
10659
10933
  exports.ERR_CENTRAL_DIRECTORY_NOT_FOUND = ERR_CENTRAL_DIRECTORY_NOT_FOUND;
10660
10934
  exports.ERR_DUPLICATED_NAME = ERR_DUPLICATED_NAME;
@@ -10668,7 +10942,9 @@
10668
10942
  exports.ERR_EXTRAFIELD_ZIP64_NOT_FOUND = ERR_EXTRAFIELD_ZIP64_NOT_FOUND;
10669
10943
  exports.ERR_HTTP_RANGE = ERR_HTTP_RANGE;
10670
10944
  exports.ERR_HTTP_RESOURCE_CHANGED = ERR_HTTP_RESOURCE_CHANGED;
10945
+ exports.ERR_HTTP_STATUS = ERR_HTTP_STATUS;
10671
10946
  exports.ERR_INVALID_AUTHENTICATION_CODE = ERR_INVALID_AUTHENTICATION_CODE;
10947
+ exports.ERR_INVALID_BASE_URI = ERR_INVALID_BASE_URI;
10672
10948
  exports.ERR_INVALID_CODEC_DEFINITION = ERR_INVALID_CODEC_DEFINITION;
10673
10949
  exports.ERR_INVALID_CODEC_MODULE = ERR_INVALID_CODEC_MODULE;
10674
10950
  exports.ERR_INVALID_COMMENT = ERR_INVALID_COMMENT;
@@ -10678,6 +10954,7 @@
10678
10954
  exports.ERR_INVALID_DATE = ERR_INVALID_DATE;
10679
10955
  exports.ERR_INVALID_DUPLICATES = ERR_INVALID_DUPLICATES;
10680
10956
  exports.ERR_INVALID_ENCRYPTION_STRENGTH = ERR_INVALID_ENCRYPTION_STRENGTH;
10957
+ exports.ERR_INVALID_ENTRY = ERR_INVALID_ENTRY;
10681
10958
  exports.ERR_INVALID_ENTRY_COMMENT = ERR_INVALID_ENTRY_COMMENT;
10682
10959
  exports.ERR_INVALID_ENTRY_COMMENT_TYPE = ERR_INVALID_ENTRY_COMMENT_TYPE;
10683
10960
  exports.ERR_INVALID_ENTRY_NAME = ERR_INVALID_ENTRY_NAME;
@@ -10696,6 +10973,7 @@
10696
10973
  exports.ERR_INVALID_PASSWORD = ERR_INVALID_PASSWORD;
10697
10974
  exports.ERR_INVALID_PASSWORD_TYPE = ERR_INVALID_PASSWORD_TYPE;
10698
10975
  exports.ERR_INVALID_PASS_THROUGH = ERR_INVALID_PASS_THROUGH;
10976
+ exports.ERR_INVALID_PASS_THROUGH_VALUE = ERR_INVALID_PASS_THROUGH_VALUE;
10699
10977
  exports.ERR_INVALID_READER = ERR_INVALID_READER;
10700
10978
  exports.ERR_INVALID_READER_OPTIONS = ERR_INVALID_READER_OPTIONS;
10701
10979
  exports.ERR_INVALID_SIGNAL = ERR_INVALID_SIGNAL;
@@ -10706,14 +10984,19 @@
10706
10984
  exports.ERR_INVALID_UNIX_EXTRA_FIELD_TYPE = ERR_INVALID_UNIX_EXTRA_FIELD_TYPE;
10707
10985
  exports.ERR_INVALID_UNIX_ID_SIZE = ERR_INVALID_UNIX_ID_SIZE;
10708
10986
  exports.ERR_INVALID_UNIX_MODE = ERR_INVALID_UNIX_MODE;
10987
+ exports.ERR_INVALID_URI = ERR_INVALID_URI;
10709
10988
  exports.ERR_INVALID_VERSION = ERR_INVALID_VERSION;
10710
10989
  exports.ERR_ITERATOR_COMPLETED_TOO_SOON = ERR_ITERATOR_COMPLETED_TOO_SOON;
10711
10990
  exports.ERR_LOCAL_FILE_HEADER_NOT_FOUND = ERR_LOCAL_FILE_HEADER_NOT_FOUND;
10712
10991
  exports.ERR_OVERLAPPING_ENTRY = ERR_OVERLAPPING_ENTRY;
10992
+ exports.ERR_PARENT_NOT_DIRECTORY = ERR_PARENT_NOT_DIRECTORY;
10713
10993
  exports.ERR_READABLE_CONSUMED = ERR_READABLE_CONSUMED;
10714
10994
  exports.ERR_RESERVED_COMPRESSION_METHOD = ERR_RESERVED_COMPRESSION_METHOD;
10995
+ exports.ERR_ROOT_DIRECTORY_NOT_MOVABLE = ERR_ROOT_DIRECTORY_NOT_MOVABLE;
10715
10996
  exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
10997
+ exports.ERR_TARGET_NOT_DIRECTORY = ERR_TARGET_NOT_DIRECTORY;
10716
10998
  exports.ERR_UNDEFINED_COMPRESSION_METHOD = ERR_UNDEFINED_COMPRESSION_METHOD;
10999
+ exports.ERR_UNDEFINED_CRC32 = ERR_UNDEFINED_CRC32;
10717
11000
  exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
10718
11001
  exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
10719
11002
  exports.ERR_UNDETERMINED_SIZE = ERR_UNDETERMINED_SIZE;
@@ -10725,10 +11008,12 @@
10725
11008
  exports.ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH;
10726
11009
  exports.ERR_UNSUPPORTED_ENCRYPTION_USDZ = ERR_UNSUPPORTED_ENCRYPTION_USDZ;
10727
11010
  exports.ERR_UNSUPPORTED_FORMAT = ERR_UNSUPPORTED_FORMAT;
11011
+ exports.ERR_UNSUPPORTED_PASS_THROUGH_VALUE = ERR_UNSUPPORTED_PASS_THROUGH_VALUE;
10728
11012
  exports.ERR_UNSUPPORTED_SPLIT_USDZ = ERR_UNSUPPORTED_SPLIT_USDZ;
10729
11013
  exports.ERR_UNSUPPORTED_UINT64 = ERR_UNSUPPORTED_UINT64;
10730
11014
  exports.ERR_WORKER_STARTUP_TIMEOUT = ERR_WORKER_STARTUP_TIMEOUT;
10731
11015
  exports.ERR_WRITER_NOT_INITIALIZED = ERR_WRITER_NOT_INITIALIZED;
11016
+ exports.ERR_WRITER_SIZE_NOT_WRITABLE = ERR_WRITER_SIZE_NOT_WRITABLE;
10732
11017
  exports.ERR_ZIP_CRYPTO_LAST_MOD_DATE = ERR_ZIP_CRYPTO_LAST_MOD_DATE;
10733
11018
  exports.ERR_ZIP_NOT_EMPTY = ERR_ZIP_NOT_EMPTY;
10734
11019
  exports.HttpRangeReader = HttpRangeReader;
@@ -10742,13 +11027,17 @@
10742
11027
  exports.Uint8ArrayWriter = Uint8ArrayWriter;
10743
11028
  exports.VERSION = VERSION;
10744
11029
  exports.WARNING_APPENDED_DATA = WARNING_APPENDED_DATA;
11030
+ exports.WARNING_CLAMPED_LAST_MODIFICATION_DATE = WARNING_CLAMPED_LAST_MODIFICATION_DATE;
10745
11031
  exports.WARNING_COMPRESSED_PATCHED_DATA = WARNING_COMPRESSED_PATCHED_DATA;
11032
+ exports.WARNING_COMPRESSION_UNAVAILABLE = WARNING_COMPRESSION_UNAVAILABLE;
10746
11033
  exports.WARNING_DUPLICATE_FILENAME = WARNING_DUPLICATE_FILENAME;
10747
11034
  exports.WARNING_MALFORMED_EXTRA_FIELD = WARNING_MALFORMED_EXTRA_FIELD;
10748
11035
  exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG = WARNING_MISMATCHED_LOCAL_FILE_HEADER_BIT_FLAG;
10749
11036
  exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD = WARNING_MISMATCHED_LOCAL_FILE_HEADER_COMPRESSION_METHOD;
10750
11037
  exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES = WARNING_MISMATCHED_LOCAL_FILE_HEADER_CRC32_OR_SIZES;
11038
+ exports.WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME = WARNING_MISMATCHED_LOCAL_FILE_HEADER_FILENAME;
10751
11039
  exports.WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY;
11040
+ exports.WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY = WARNING_MULTIPLE_END_OF_CENTRAL_DIRECTORY;
10752
11041
  exports.WARNING_PREPENDED_CENTRAL_DIRECTORY = WARNING_PREPENDED_CENTRAL_DIRECTORY;
10753
11042
  exports.WARNING_PREPENDED_DATA = WARNING_PREPENDED_DATA;
10754
11043
  exports.WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = WARNING_TRAILING_CENTRAL_DIRECTORY_DATA;