@zip.js/zip.js 2.8.51 → 2.8.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +8 -3
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +241 -95
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +243 -94
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +564 -199
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +551 -194
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +564 -199
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +567 -198
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +567 -198
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +243 -94
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +243 -94
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip.js +243 -94
  22. package/dist/zip.min.js +1 -1
  23. package/eslint.config.mjs +1 -1
  24. package/index-native.cjs +567 -198
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +567 -198
  27. package/index.d.cts +551 -45
  28. package/index.d.ts +551 -45
  29. package/index.min.js +1 -1
  30. package/lib/core/codec-worker-web.js +13 -4
  31. package/lib/core/codec-worker.js +2 -0
  32. package/lib/core/constants.js +9 -0
  33. package/lib/core/io.js +43 -4
  34. package/lib/core/options.js +2 -0
  35. package/lib/core/util/compatible-streams.js +3 -8
  36. package/lib/core/zip-entry.js +16 -0
  37. package/lib/core/zip-fs.js +236 -107
  38. package/lib/core/zip-reader.js +106 -40
  39. package/lib/core/zip-writer.js +171 -41
  40. package/lib/zip-core-writer.js +3 -0
  41. package/package.json +9 -7
@@ -81,6 +81,8 @@ const FILE_ATTR_MSDOS_SYSTEM_MASK = 0x04;
81
81
  const FILE_ATTR_MSDOS_ARCHIVE_MASK = 0x20;
82
82
  const FILE_ATTR_UNIX_TYPE_MASK = 0o170000;
83
83
  const FILE_ATTR_UNIX_TYPE_DIR = 0o040000;
84
+ const FILE_ATTR_UNIX_TYPE_SYMLINK = 0o120000;
85
+ const FILE_ATTR_UNIX_TYPE_FILE = 0o100000;
84
86
  const FILE_ATTR_UNIX_EXECUTABLE_MASK = 0o111;
85
87
  const FILE_ATTR_UNIX_DEFAULT_MASK = 0o644;
86
88
  const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
@@ -91,6 +93,9 @@ const VERSION_DEFLATE = 0x14;
91
93
  const VERSION_ZIP64 = 0x2D;
92
94
  const VERSION_AES = 0x33;
93
95
 
96
+ const VERSION_MADE_BY_MSDOS = 0x0014;
97
+ const VERSION_MADE_BY_UNIX = 0x0300;
98
+
94
99
  const DIRECTORY_SIGNATURE = "/";
95
100
 
96
101
  const HEADER_SIZE = 30;
@@ -1806,8 +1811,6 @@ function getInt32(number) {
1806
1811
  */
1807
1812
 
1808
1813
 
1809
- const HTTP_HEADER_CONTENT_TYPE = "Content-Type";
1810
-
1811
1814
  function toCompatibleReadable(readable) {
1812
1815
  if (readable instanceof ReadableStream) {
1813
1816
  return readable;
@@ -1830,12 +1833,9 @@ function toCompatibleReadable(readable) {
1830
1833
 
1831
1834
  function streamToBlob(readable, contentType) {
1832
1835
  readable = toCompatibleReadable(readable);
1836
+ const blobOptions = contentType ? { type: contentType } : {};
1833
1837
  if (responseSupportsGlobalReadable()) {
1834
- const options = {};
1835
- if (contentType) {
1836
- options.headers = [[HTTP_HEADER_CONTENT_TYPE, contentType]];
1837
- }
1838
- return new Response(readable, options).blob();
1838
+ return new Response(readable).blob().then(blob => contentType ? new Blob([blob], blobOptions) : blob);
1839
1839
  }
1840
1840
  const chunks = [];
1841
1841
  return readable
@@ -1844,7 +1844,7 @@ function streamToBlob(readable, contentType) {
1844
1844
  chunks.push(chunk);
1845
1845
  }
1846
1846
  }))
1847
- .then(() => new Blob(chunks, contentType ? { type: contentType } : {}));
1847
+ .then(() => new Blob(chunks, blobOptions));
1848
1848
  }
1849
1849
 
1850
1850
  function responseSupportsGlobalReadable() {
@@ -2790,6 +2790,7 @@ function createWebWorkerInterface(workerData, config) {
2790
2790
  worker,
2791
2791
  workerAlive: false,
2792
2792
  terminated: false,
2793
+ startupError: null,
2793
2794
  interface: {
2794
2795
  run: async () => {
2795
2796
  try {
@@ -2817,6 +2818,13 @@ function createWebWorkerInterface(workerData, config) {
2817
2818
  }
2818
2819
 
2819
2820
  async function runWebWorker(workerData, config) {
2821
+ if (!workerData.worker) {
2822
+ const { startupError } = workerData;
2823
+ workerData.startupError = null;
2824
+ const error = startupError || new Error(ERR_WORKER_STARTUP_TIMEOUT);
2825
+ error.workerStartupFailed = true;
2826
+ throw error;
2827
+ }
2820
2828
  let resolveResult, rejectResult;
2821
2829
  const result = new Promise((resolve, reject) => {
2822
2830
  resolveResult = resolve;
@@ -3030,11 +3038,12 @@ function onWorkerError(event, workerData) {
3030
3038
  if (!workerAlive) {
3031
3039
  workerData.worker = null;
3032
3040
  }
3041
+ let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3042
+ if (!workerAlive) {
3043
+ error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3044
+ workerData.startupError = error;
3045
+ }
3033
3046
  if (rejectResult) {
3034
- let error = event.error || new Error(event.message || ERROR_EVENT_TYPE);
3035
- if (!workerAlive) {
3036
- error = Object.assign(new Error(error.message || ERROR_EVENT_TYPE), { workerStartupFailed: true });
3037
- }
3038
3047
  rejectResult(error);
3039
3048
  if (writer) {
3040
3049
  writer.releaseLock();
@@ -3379,8 +3388,10 @@ class Reader extends Stream {
3379
3388
  async pull(controller) {
3380
3389
  const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
3381
3390
  const data = await readUint8Array(reader, offset + chunkOffset, dataSize);
3382
- controller.enqueue(data);
3383
- if ((chunkOffset + chunkSize > size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3391
+ if (data.length) {
3392
+ controller.enqueue(data);
3393
+ }
3394
+ if ((chunkOffset + chunkSize >= size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3384
3395
  controller.close();
3385
3396
  } else {
3386
3397
  chunkOffset += chunkSize;
@@ -3458,6 +3469,7 @@ class Data64URIWriter extends Writer {
3458
3469
  constructor(contentType) {
3459
3470
  super();
3460
3471
  Object.assign(this, {
3472
+ contentType,
3461
3473
  data: "data:" + (contentType || "") + ";base64,",
3462
3474
  pending: []
3463
3475
  });
@@ -3559,6 +3571,7 @@ class BlobWriter extends Stream {
3559
3571
  return transformStream.writable;
3560
3572
  }
3561
3573
  });
3574
+ writer.contentType = contentType;
3562
3575
  writer.blob = streamToBlob(transformStream.readable, contentType);
3563
3576
  writer.blob.catch(() => { });
3564
3577
  }
@@ -3575,6 +3588,26 @@ class TextReader extends BlobReader {
3575
3588
  }
3576
3589
  }
3577
3590
 
3591
+ function getTextSize(text) {
3592
+ let size = 0;
3593
+ for (let indexCharacter = 0; indexCharacter < text.length; indexCharacter++) {
3594
+ const characterCode = text.charCodeAt(indexCharacter);
3595
+ if (characterCode < 0x80) {
3596
+ size += 1;
3597
+ } else if (characterCode < 0x800) {
3598
+ size += 2;
3599
+ } else if (characterCode < 0xd800 || characterCode >= 0xe000) {
3600
+ size += 3;
3601
+ } else if (characterCode < 0xdc00 && (text.charCodeAt(indexCharacter + 1) & 0xfc00) == 0xdc00) {
3602
+ size += 4;
3603
+ indexCharacter++;
3604
+ } else {
3605
+ size += 3;
3606
+ }
3607
+ }
3608
+ return size;
3609
+ }
3610
+
3578
3611
  class TextWriter extends BlobWriter {
3579
3612
 
3580
3613
  constructor(encoding) {
@@ -4059,9 +4092,8 @@ class SplitDataReader extends Reader {
4059
4092
 
4060
4093
  async init() {
4061
4094
  const reader = this;
4062
- const { readers } = reader;
4063
4095
  reader.lastDiskNumber = 0;
4064
- await Promise.all(readers.map(diskReader => initStream(diskReader)));
4096
+ const readers = reader.readers = await Promise.all(reader.readers.map(initDiskReader));
4065
4097
  reader.diskOffsets = readers.map(diskReader => {
4066
4098
  const diskOffset = reader.size;
4067
4099
  reader.size += diskReader.size;
@@ -4238,6 +4270,10 @@ class GenericWriter {
4238
4270
  }
4239
4271
  }
4240
4272
 
4273
+ function ownsWritable(writer) {
4274
+ return Boolean(writer && writer.getData);
4275
+ }
4276
+
4241
4277
  function isHttpFamily(url) {
4242
4278
  const { baseURI } = getConfiguration();
4243
4279
  const { protocol } = new URL(url, baseURI);
@@ -4252,6 +4288,16 @@ async function initStream(stream, initSize) {
4252
4288
  }
4253
4289
  }
4254
4290
 
4291
+ async function initDiskReader(diskReader) {
4292
+ diskReader = new GenericReader(diskReader);
4293
+ await initStream(diskReader);
4294
+ if (diskReader.size === UNDEFINED_VALUE || !diskReader.readUint8Array) {
4295
+ diskReader = new BlobReader(await streamToBlob(diskReader.readable));
4296
+ await initStream(diskReader);
4297
+ }
4298
+ return diskReader;
4299
+ }
4300
+
4255
4301
  function readUint8Array(reader, offset, size) {
4256
4302
  return reader.readUint8Array(offset, size);
4257
4303
  }
@@ -4382,6 +4428,8 @@ const PROPERTY_NAME_CREATION_DATE = "creationDate";
4382
4428
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
4383
4429
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
4384
4430
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
4431
+ const PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES = "internalFileAttribute";
4432
+ const PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttribute";
4385
4433
  const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
4386
4434
  const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
4387
4435
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
@@ -4392,6 +4440,7 @@ const PROPERTY_NAME_VERSION_MADE_BY = "versionMadeBy";
4392
4440
  const PROPERTY_NAME_ZIPCRYPTO = "zipCrypto";
4393
4441
  const PROPERTY_NAME_DIRECTORY = "directory";
4394
4442
  const PROPERTY_NAME_EXECUTABLE = "executable";
4443
+ const PROPERTY_NAME_SYMLINK = "symlink";
4395
4444
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4396
4445
  const PROPERTY_NAME_SIGNATURE = "signature";
4397
4446
  const PROPERTY_NAME_CRC32 = "crc32";
@@ -4407,6 +4456,10 @@ const PROPERTY_NAME_SETUID = "setuid";
4407
4456
  const PROPERTY_NAME_SETGID = "setgid";
4408
4457
  const PROPERTY_NAME_STICKY = "sticky";
4409
4458
  const PROPERTY_NAME_BITFLAG = "bitFlag";
4459
+ const PROPERTY_NAME_RAW_BITFLAG = "rawBitFlag";
4460
+ const PROPERTY_NAME_FILENAME_LENGTH = "filenameLength";
4461
+ const PROPERTY_NAME_EXTRA_FIELD_LENGTH = "extraFieldLength";
4462
+ const PROPERTY_NAME_UNIX_EXTERNAL_UPPER = "unixExternalUpper";
4410
4463
  const PROPERTY_NAME_FILENAME_UTF8 = "filenameUTF8";
4411
4464
  const PROPERTY_NAME_COMMENT_UTF8 = "commentUTF8";
4412
4465
  const PROPERTY_NAME_RAW_EXTRA_FIELD = "rawExtraField";
@@ -4435,6 +4488,8 @@ const PROPERTY_NAMES = [
4435
4488
  PROPERTY_NAME_DISK_NUMBER_START,
4436
4489
  PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
4437
4490
  PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
4491
+ PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES,
4492
+ PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES,
4438
4493
  PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
4439
4494
  PROPERTY_NAME_MSDOS_ATTRIBUTES,
4440
4495
  PROPERTY_NAME_MS_DOS_COMPATIBLE,
@@ -4445,6 +4500,7 @@ const PROPERTY_NAMES = [
4445
4500
  PROPERTY_NAME_ZIPCRYPTO,
4446
4501
  PROPERTY_NAME_DIRECTORY,
4447
4502
  PROPERTY_NAME_EXECUTABLE,
4503
+ PROPERTY_NAME_SYMLINK,
4448
4504
  PROPERTY_NAME_COMPRESSION_METHOD,
4449
4505
  PROPERTY_NAME_SIGNATURE,
4450
4506
  PROPERTY_NAME_CRC32,
@@ -4456,10 +4512,14 @@ const PROPERTY_NAMES = [
4456
4512
  PROPERTY_NAME_UID,
4457
4513
  PROPERTY_NAME_GID,
4458
4514
  PROPERTY_NAME_UNIX_MODE,
4515
+ PROPERTY_NAME_UNIX_EXTERNAL_UPPER,
4459
4516
  PROPERTY_NAME_SETUID,
4460
4517
  PROPERTY_NAME_SETGID,
4461
4518
  PROPERTY_NAME_STICKY,
4462
4519
  PROPERTY_NAME_BITFLAG,
4520
+ PROPERTY_NAME_RAW_BITFLAG,
4521
+ PROPERTY_NAME_FILENAME_LENGTH,
4522
+ PROPERTY_NAME_EXTRA_FIELD_LENGTH,
4463
4523
  PROPERTY_NAME_FILENAME_UTF8,
4464
4524
  PROPERTY_NAME_COMMENT_UTF8,
4465
4525
  PROPERTY_NAME_RAW_EXTRA_FIELD,
@@ -4521,6 +4581,7 @@ const OPTION_CHECK_PASSWORD_ONLY = "checkPasswordOnly";
4521
4581
  const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
4522
4582
  const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
4523
4583
  const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
4584
+ const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
4524
4585
  const OPTION_CHECK_SIGNATURE = "checkSignature";
4525
4586
  const OPTION_CHECK_CRC32 = "checkCrc32";
4526
4587
  const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
@@ -4652,7 +4713,7 @@ class ZipReader {
4652
4713
  if (reader.size < END_OF_CENTRAL_DIR_LENGTH) {
4653
4714
  throw new Error(ERR_BAD_FORMAT);
4654
4715
  }
4655
- const strictness = getStrictness(getOptionValue$1(zipReader, options, OPTION_STRICTNESS), getOptionValue$1(zipReader, options, OPTION_CHECK_AMBIGUITY));
4716
+ const strictness = getStrictness(options, zipReader.options);
4656
4717
  const checkAmbiguity = strictness == STRICTNESS_STRICT;
4657
4718
  const rejectAmbiguousEndOfDirectory = strictness != STRICTNESS_TOLERANT;
4658
4719
  const maxAppendedDataSize = getMaxAppendedDataSize(getOptionValue$1(zipReader, options, OPTION_MAX_APPENDED_DATA_SIZE), strictness);
@@ -4874,6 +4935,7 @@ class ZipReader {
4874
4935
  index: indexFile,
4875
4936
  versionMadeBy,
4876
4937
  msDosCompatible,
4938
+ zip64: false,
4877
4939
  compressedSize: 0,
4878
4940
  uncompressedSize: 0,
4879
4941
  commentLength,
@@ -4907,15 +4969,18 @@ class ZipReader {
4907
4969
  const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4908
4970
  const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4909
4971
  const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4910
- const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
4972
+ const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
4973
+ const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
4974
+ const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
4911
4975
  ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
4912
- : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
4976
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
4913
4977
  const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4914
4978
  const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4915
4979
  Object.assign(fileEntry, {
4916
4980
  setuid,
4917
4981
  setgid,
4918
4982
  sticky,
4983
+ symlink,
4919
4984
  unixExternalUpper,
4920
4985
  internalFileAttribute: fileEntry.internalFileAttributes,
4921
4986
  externalFileAttribute: fileEntry.externalFileAttributes,
@@ -4981,6 +5046,10 @@ class ZipReader {
4981
5046
  }
4982
5047
 
4983
5048
  async close() {
5049
+ const { reader } = this;
5050
+ if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
5051
+ await reader.readable.cancel();
5052
+ }
4984
5053
  }
4985
5054
  }
4986
5055
 
@@ -5077,9 +5146,12 @@ let ZipEntry$1 = class ZipEntry {
5077
5146
  extraFieldLength,
5078
5147
  filenameLength
5079
5148
  } = localDirectory;
5080
- const checkAmbiguity = getStrictness(getOptionValue$1(zipEntry, options, OPTION_STRICTNESS), getOptionValue$1(zipEntry, options, OPTION_CHECK_AMBIGUITY)) == STRICTNESS_STRICT;
5149
+ const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5150
+ const entryStrictness = getStrictness(options, zipEntry.options);
5151
+ const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
5152
+ const checkLocalFilename = getCheckLocalFilename(checkLocalDirectoryOption, entryStrictness);
5081
5153
  let rawLocalFilename = EMPTY_UINT8_ARRAY;
5082
- if (checkAmbiguity && (filenameLength || extraFieldLength)) {
5154
+ if (checkLocalFilename && (filenameLength || extraFieldLength)) {
5083
5155
  const trailingDataArray = await readUint8Array(reader, localHeaderOffset + HEADER_SIZE, filenameLength + extraFieldLength);
5084
5156
  rawLocalFilename = trailingDataArray.subarray(0, filenameLength);
5085
5157
  localDirectory.rawExtraField = trailingDataArray.subarray(filenameLength);
@@ -5088,17 +5160,26 @@ let ZipEntry$1 = class ZipEntry {
5088
5160
  await readUint8Array(reader, localHeaderOffset + HEADER_SIZE + filenameLength, extraFieldLength) :
5089
5161
  EMPTY_UINT8_ARRAY;
5090
5162
  }
5163
+ if (checkLocalFilename) {
5164
+ localDirectory.rawFilename = rawLocalFilename;
5165
+ }
5091
5166
  readCommonFooter(zipEntry, localDirectory, dataView, 4, true);
5092
- if (checkAmbiguity) {
5093
- checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename);
5167
+ if (checkLocalDirectory) {
5168
+ validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename);
5094
5169
  }
5095
- const { lastAccessDate, creationDate } = localDirectory;
5170
+ const { lastAccessDate, creationDate, uid, gid } = localDirectory;
5096
5171
  if (lastAccessDate) {
5097
5172
  fileEntry.lastAccessDate = lastAccessDate;
5098
5173
  }
5099
5174
  if (creationDate) {
5100
5175
  fileEntry.creationDate = creationDate;
5101
5176
  }
5177
+ if (uid !== UNDEFINED_VALUE && fileEntry.uid === UNDEFINED_VALUE) {
5178
+ fileEntry.uid = uid;
5179
+ }
5180
+ if (gid !== UNDEFINED_VALUE && fileEntry.gid === UNDEFINED_VALUE) {
5181
+ fileEntry.gid = gid;
5182
+ }
5102
5183
  const encrypted = zipEntry.encrypted && localDirectory.encrypted && !passThrough;
5103
5184
  const zipCrypto = encrypted && !extraFieldAES;
5104
5185
  if (!passThrough) {
@@ -5205,7 +5286,7 @@ let ZipEntry$1 = class ZipEntry {
5205
5286
  throw error;
5206
5287
  }
5207
5288
  } finally {
5208
- const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5289
+ const preventClose = !ownsWritable(writer) && getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5209
5290
  if (!preventClose && writable && !writable.locked) {
5210
5291
  const writableWriter = writable.getWriter();
5211
5292
  if (abortError) {
@@ -5334,10 +5415,12 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
5334
5415
  directory.extraFieldNTFS = extraFieldNTFS;
5335
5416
  }
5336
5417
  const extraFieldUnix = extraField.get(EXTRAFIELD_TYPE_UNIX);
5418
+ let unixIdsRead;
5337
5419
  if (extraFieldUnix) {
5338
- readExtraFieldUnix(extraFieldUnix, directory, false);
5420
+ unixIdsRead = readExtraFieldUnix(extraFieldUnix, directory, false);
5339
5421
  directory.extraFieldUnix = extraFieldUnix;
5340
- } else {
5422
+ }
5423
+ if (!unixIdsRead) {
5341
5424
  const extraFieldInfoZip = extraField.get(EXTRAFIELD_TYPE_INFOZIP);
5342
5425
  if (extraFieldInfoZip) {
5343
5426
  readExtraFieldUnix(extraFieldInfoZip, directory, true);
@@ -5440,7 +5523,7 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
5440
5523
  const creationDate = getDateNTFS(rawCreationDate);
5441
5524
  const extraFieldData = { lastModDate, lastAccessDate, creationDate };
5442
5525
  Object.assign(extraFieldNTFS, extraFieldData);
5443
- Object.assign(directory, extraFieldData);
5526
+ Object.assign(directory, extraFieldData, { rawLastAccessDate, rawCreationDate });
5444
5527
  }
5445
5528
  }
5446
5529
 
@@ -5449,8 +5532,8 @@ function readExtraFieldUnixDates(extraField, directory) {
5449
5532
  return;
5450
5533
  }
5451
5534
  const extraFieldView = getDataView(extraField.data);
5452
- const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5453
- const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5535
+ const lastAccessDate = new Date((getUint32(extraFieldView, 0) | 0) * 1000);
5536
+ const lastModDate = new Date((getUint32(extraFieldView, 4) | 0) * 1000);
5454
5537
  const extraFieldData = { lastAccessDate, lastModDate };
5455
5538
  if (extraField.data.length >= 12) {
5456
5539
  extraFieldData.uid = getUint16(extraFieldView, 8);
@@ -5484,6 +5567,7 @@ function readExtraFieldUnix(extraField, directory, isInfoZip) {
5484
5567
  if (gid !== UNDEFINED_VALUE) {
5485
5568
  directory.gid = gid;
5486
5569
  }
5570
+ return uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE;
5487
5571
  } catch {
5488
5572
  // ignored
5489
5573
  }
@@ -5556,26 +5640,25 @@ async function detectOverlappingEntry({
5556
5640
  }
5557
5641
  if (dataDescriptorLength) {
5558
5642
  const dataDescriptorArray = await readUint8Array(reader, dataOffset + compressedSize, dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH);
5559
- const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5560
- getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5561
- if (dataDescriptorSignature) {
5562
- const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
5563
- let readCompressedSize;
5564
- let readUncompressedSize;
5565
- if (extraFieldZip64) {
5566
- readCompressedSize = getBigUint64(getDataView(dataDescriptorArray), 8);
5567
- readUncompressedSize = getBigUint64(getDataView(dataDescriptorArray), 16);
5568
- } else {
5569
- readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
5570
- readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
5571
- }
5572
- const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
5643
+ const dataDescriptorView = getDataView(dataDescriptorArray);
5644
+ let signature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
5645
+ getUint32(dataDescriptorView, 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
5646
+ if (signature) {
5647
+ const signedDataDescriptor = readDataDescriptor(dataDescriptorView, DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH, extraFieldZip64);
5648
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || signedDataDescriptor.crc32 == crc32;
5573
5649
  if (matchCrc32 &&
5574
- readCompressedSize == compressedSize &&
5575
- readUncompressedSize == uncompressedSize) {
5650
+ signedDataDescriptor.compressedSize == compressedSize &&
5651
+ signedDataDescriptor.uncompressedSize == uncompressedSize) {
5576
5652
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
5653
+ } else {
5654
+ signature = false;
5577
5655
  }
5578
5656
  }
5657
+ if (dataDescriptorArray.length >= dataDescriptorLength) {
5658
+ const localDataDescriptor = readDataDescriptor(dataDescriptorView, signature ? DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH : 0, extraFieldZip64);
5659
+ localDataDescriptor.signature = signature;
5660
+ fileEntry.localDirectory.dataDescriptor = localDataDescriptor;
5661
+ }
5579
5662
  }
5580
5663
  const range = {
5581
5664
  start: offset,
@@ -5592,6 +5675,20 @@ async function detectOverlappingEntry({
5592
5675
  readRanges.set(index, range);
5593
5676
  }
5594
5677
 
5678
+ function readDataDescriptor(dataDescriptorView, offset, extraFieldZip64) {
5679
+ const crc32 = getUint32(dataDescriptorView, offset);
5680
+ let compressedSize;
5681
+ let uncompressedSize;
5682
+ if (extraFieldZip64) {
5683
+ compressedSize = getBigUint64(dataDescriptorView, offset + 4);
5684
+ uncompressedSize = getBigUint64(dataDescriptorView, offset + 12);
5685
+ } else {
5686
+ compressedSize = getUint32(dataDescriptorView, offset + 4);
5687
+ uncompressedSize = getUint32(dataDescriptorView, offset + 8);
5688
+ }
5689
+ return { crc32, compressedSize, uncompressedSize };
5690
+ }
5691
+
5595
5692
  function getDiskOffset$1(reader, diskNumber) {
5596
5693
  return reader.getDiskOffset ? reader.getDiskOffset(diskNumber) : 0;
5597
5694
  }
@@ -5600,14 +5697,40 @@ function isStrictnessValue(value) {
5600
5697
  return value === STRICTNESS_STRICT || value === STRICTNESS_BALANCED || value === STRICTNESS_TOLERANT;
5601
5698
  }
5602
5699
 
5603
- function getStrictness(strictness, checkAmbiguity) {
5604
- if (strictness === UNDEFINED_VALUE) {
5605
- return checkAmbiguity ? STRICTNESS_STRICT : STRICTNESS_BALANCED;
5700
+ function getStrictness(options, inheritedOptions) {
5701
+ return resolveStrictness(options, resolveStrictness(inheritedOptions, STRICTNESS_BALANCED));
5702
+ }
5703
+
5704
+ function resolveStrictness(options, inheritedStrictness) {
5705
+ const strictness = options[OPTION_STRICTNESS];
5706
+ if (strictness !== UNDEFINED_VALUE) {
5707
+ if (!isStrictnessValue(strictness)) {
5708
+ throw new Error(ERR_INVALID_STRICTNESS);
5709
+ }
5710
+ return strictness;
5606
5711
  }
5607
- if (!isStrictnessValue(strictness)) {
5608
- throw new Error(ERR_INVALID_STRICTNESS);
5712
+ const checkAmbiguity = options[OPTION_CHECK_AMBIGUITY];
5713
+ if (checkAmbiguity === UNDEFINED_VALUE) {
5714
+ return inheritedStrictness;
5609
5715
  }
5610
- return strictness;
5716
+ if (checkAmbiguity) {
5717
+ return STRICTNESS_STRICT;
5718
+ }
5719
+ return inheritedStrictness == STRICTNESS_TOLERANT ? STRICTNESS_TOLERANT : STRICTNESS_BALANCED;
5720
+ }
5721
+
5722
+ function getCheckLocalDirectory(checkLocalDirectory, strictness) {
5723
+ if (checkLocalDirectory === UNDEFINED_VALUE) {
5724
+ return strictness != STRICTNESS_TOLERANT;
5725
+ }
5726
+ return Boolean(checkLocalDirectory);
5727
+ }
5728
+
5729
+ function getCheckLocalFilename(checkLocalFilename, strictness) {
5730
+ if (checkLocalFilename === UNDEFINED_VALUE) {
5731
+ return strictness == STRICTNESS_STRICT;
5732
+ }
5733
+ return Boolean(checkLocalFilename);
5611
5734
  }
5612
5735
 
5613
5736
  function getFilenameValidation(filenameValidation, strictness) {
@@ -5755,10 +5878,11 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
5755
5878
  return UNDEFINED_VALUE;
5756
5879
  }
5757
5880
 
5758
- function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
5881
+ function validateLocalDirectory(zipEntry, localDirectory, rawLocalFilename, checkLocalFilename) {
5759
5882
  const { rawFilename } = zipEntry;
5760
- if (rawLocalFilename.length != rawFilename.length ||
5761
- rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte])) {
5883
+ if (checkLocalFilename &&
5884
+ (rawLocalFilename.length != rawFilename.length ||
5885
+ rawLocalFilename.some((byteValue, indexByte) => byteValue != rawFilename[indexByte]))) {
5762
5886
  throwAmbiguousArchive("mismatched local file header (filename)");
5763
5887
  }
5764
5888
  if ((localDirectory.rawBitFlag & BITFLAG_AMBIGUITY_MASK) != (zipEntry.rawBitFlag & BITFLAG_AMBIGUITY_MASK)) {
@@ -5876,11 +6000,13 @@ var zipReader = /*#__PURE__*/Object.freeze({
5876
6000
 
5877
6001
  const ERR_DUPLICATED_NAME = "File already exists";
5878
6002
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
6003
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
5879
6004
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
5880
6005
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5881
6006
  const ERR_INVALID_VERSION = "Version exceeds 65535";
5882
6007
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
5883
6008
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
6009
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
5884
6010
  const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
5885
6011
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
5886
6012
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
@@ -5890,6 +6016,7 @@ const MIN_NTFS_TIME = BigInt(0);
5890
6016
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5891
6017
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5892
6018
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
6019
+ const ERR_UNDETERMINED_SIZE = "Undetermined size";
5893
6020
  const ERR_UNDEFINED_READER = "Undefined reader";
5894
6021
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
5895
6022
  const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
@@ -5942,6 +6069,10 @@ class ZipWriter {
5942
6069
  }
5943
6070
  reader = new GenericReader(reader);
5944
6071
  await initStream(reader);
6072
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6073
+ reader = new BlobReader(await streamToBlob(reader.readable));
6074
+ await initStream(reader);
6075
+ }
5945
6076
  const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
5946
6077
  const zipReader$1 = new ZipReader(reader.readable);
5947
6078
  const entries = await zipReader$1.getEntries();
@@ -6090,6 +6221,9 @@ class ZipWriter {
6090
6221
  const zipWriter = this;
6091
6222
  const { pendingAddFileCalls, writer } = this;
6092
6223
  const { writable } = writer;
6224
+ if (!(comment instanceof Uint8Array)) {
6225
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6226
+ }
6093
6227
  if (getLength(comment) > MAX_16_BITS) {
6094
6228
  throw new Error(ERR_INVALID_COMMENT);
6095
6229
  }
@@ -6097,7 +6231,7 @@ class ZipWriter {
6097
6231
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6098
6232
  }
6099
6233
  await closeFile(zipWriter, comment, options);
6100
- const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6234
+ const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6101
6235
  if (!preventClose) {
6102
6236
  await writable.getWriter().close();
6103
6237
  }
@@ -6186,8 +6320,6 @@ async function addFile(zipWriter, name, reader, options) {
6186
6320
  const diskOffset = getDiskOffset(zipWriter.writer);
6187
6321
  const diskNumber = getDiskNumber(zipWriter.writer);
6188
6322
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
6189
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
6190
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
6191
6323
  signature: options[PROPERTY_NAME_SIGNATURE],
6192
6324
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
6193
6325
  offset: zipWriter.offset - diskOffset,
@@ -6201,14 +6333,20 @@ async function addFile(zipWriter, name, reader, options) {
6201
6333
  zipWriter.files.delete(name);
6202
6334
  throw error;
6203
6335
  }
6204
- Object.assign(fileEntry, { name, comment, extraField });
6336
+ Object.assign(fileEntry, {
6337
+ name,
6338
+ comment,
6339
+ extraField,
6340
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
6341
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
6342
+ });
6205
6343
  return new Entry(fileEntry);
6206
6344
  }
6207
6345
 
6208
6346
  function resolveAttributes(zipWriter, name, options) {
6209
6347
  name = name.trim();
6210
6348
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
6211
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
6349
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
6212
6350
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
6213
6351
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
6214
6352
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -6242,7 +6380,7 @@ function resolveAttributes(zipWriter, name, options) {
6242
6380
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
6243
6381
  if (hasUnixMetadata) {
6244
6382
  msDosCompatible = false;
6245
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
6383
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
6246
6384
  } else if (hasMsDosProvided) {
6247
6385
  msDosCompatible = true;
6248
6386
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
@@ -6256,7 +6394,7 @@ function resolveAttributes(zipWriter, name, options) {
6256
6394
  if (versionMadeBy > MAX_16_BITS) {
6257
6395
  throw new Error(ERR_INVALID_VERSION);
6258
6396
  }
6259
- let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
6397
+ let externalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES);
6260
6398
  const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
6261
6399
  if (!externalFileAttributesProvided) {
6262
6400
  externalFileAttributes = 0;
@@ -6282,11 +6420,10 @@ function resolveAttributes(zipWriter, name, options) {
6282
6420
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
6283
6421
  }
6284
6422
  }
6285
- let unixExternalUpper;
6286
6423
  if (!msDosCompatible) {
6287
6424
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
6288
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6289
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
6425
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
6426
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
6290
6427
  if (setuid) {
6291
6428
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
6292
6429
  } else {
@@ -6304,7 +6441,9 @@ function resolveAttributes(zipWriter, name, options) {
6304
6441
  }
6305
6442
  if (!externalFileAttributesProvided || unixModeProvided) {
6306
6443
  if (directory) {
6307
- unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
6444
+ unixMode = (unixMode & ~FILE_ATTR_UNIX_TYPE_MASK) | FILE_ATTR_UNIX_TYPE_DIR;
6445
+ } else if (!(unixMode & FILE_ATTR_UNIX_TYPE_MASK)) {
6446
+ unixMode |= FILE_ATTR_UNIX_TYPE_FILE;
6308
6447
  }
6309
6448
  externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
6310
6449
  }
@@ -6313,17 +6452,20 @@ function resolveAttributes(zipWriter, name, options) {
6313
6452
  if (hasMsDosProvided) {
6314
6453
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
6315
6454
  }
6455
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
6456
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
6316
6457
  return {
6317
6458
  name,
6318
6459
  resolvedOptions: {
6319
6460
  versionMadeBy,
6320
- msDosCompatible,
6461
+ msDosCompatible: Boolean(msDosCompatible),
6321
6462
  externalFileAttributes,
6322
6463
  unixExternalUpper,
6323
6464
  uid,
6324
6465
  gid,
6325
6466
  unixMode,
6326
6467
  unixExtraFieldType,
6468
+ symlink,
6327
6469
  setuid,
6328
6470
  setgid,
6329
6471
  sticky,
@@ -6357,15 +6499,12 @@ function resolveMetadata(zipWriter, name, options) {
6357
6499
  const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6358
6500
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6359
6501
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6360
- const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6502
+ const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
6361
6503
  const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
6362
- let password, rawPassword;
6363
- if (!passThrough) {
6364
- password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6365
- rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6366
- if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6367
- throw new Error(ERR_INVALID_PASSWORD_TYPE);
6368
- }
6504
+ const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6505
+ const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6506
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6507
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
6369
6508
  }
6370
6509
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
6371
6510
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
@@ -6478,14 +6617,24 @@ function serializeExtraField(extraField) {
6478
6617
  }
6479
6618
 
6480
6619
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6620
+ if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
6621
+ throw new Error(ERR_UNDEFINED_READER);
6622
+ }
6623
+ let contentSize;
6624
+ if (reader) {
6625
+ reader = new GenericReader(reader);
6626
+ await initStream(reader);
6627
+ ({ size: contentSize } = reader);
6628
+ }
6629
+ return Object.assign({ reader }, resolveEntrySizes(zipWriter, Boolean(reader), contentSize, metadata, options));
6630
+ }
6631
+
6632
+ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
6481
6633
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6482
6634
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
6483
6635
  let maximumCompressedSize = 0;
6484
6636
  let uncompressedSize = 0;
6485
- if (passThrough) {
6486
- if (!reader) {
6487
- throw new Error(ERR_UNDEFINED_READER);
6488
- }
6637
+ if (passThrough && hasContent) {
6489
6638
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
6490
6639
  if (uncompressedSize === UNDEFINED_VALUE) {
6491
6640
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -6493,29 +6642,30 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6493
6642
  }
6494
6643
  const zip64Enabled = zip64 === true;
6495
6644
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
6496
- const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6497
- if (!reader) {
6645
+ if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
6646
+ throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
6647
+ }
6648
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6649
+ if (!hasContent) {
6498
6650
  level = 0;
6499
6651
  compressionMethod = COMPRESSION_METHOD_STORE;
6500
6652
  }
6501
6653
  const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
6502
- if (reader) {
6503
- reader = new GenericReader(reader);
6504
- await initStream(reader);
6654
+ if (hasContent) {
6505
6655
  if (!passThrough) {
6506
- if (reader.size === UNDEFINED_VALUE) {
6656
+ if (contentSize === UNDEFINED_VALUE) {
6507
6657
  dataDescriptor = true;
6508
6658
  if (zip64 || zip64 === UNDEFINED_VALUE) {
6509
6659
  zip64 = true;
6510
6660
  uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
6511
6661
  }
6512
6662
  } else {
6513
- options.uncompressedSize = uncompressedSize = reader.size;
6514
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6663
+ options.uncompressedSize = uncompressedSize = contentSize;
6664
+ maximumCompressedSize = (isCompressed(compressionMethod, level) ? getMaximumCompressedSize(uncompressedSize) : uncompressedSize) + encryptionOverhead;
6515
6665
  }
6516
6666
  } else {
6517
6667
  options.uncompressedSize = uncompressedSize;
6518
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6668
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
6519
6669
  }
6520
6670
  }
6521
6671
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
@@ -6529,7 +6679,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6529
6679
  }
6530
6680
  zip64 = zip64 || false;
6531
6681
  return {
6532
- reader,
6682
+ maximumCompressedSize,
6533
6683
  resolvedOptions: {
6534
6684
  dataDescriptor,
6535
6685
  zip64,
@@ -6543,6 +6693,81 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6543
6693
  };
6544
6694
  }
6545
6695
 
6696
+ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
6697
+ const zipWriter = { options: writerOptions, config: getConfiguration() };
6698
+ if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6699
+ throw new Error(ERR_UNDETERMINED_SIZE);
6700
+ }
6701
+ if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
6702
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
6703
+ }
6704
+ const commentLength = getLength(comment);
6705
+ if (commentLength > MAX_16_BITS) {
6706
+ throw new Error(ERR_INVALID_COMMENT);
6707
+ }
6708
+ const usdz = writerOptions[OPTION_USDZ];
6709
+ const files = new Map();
6710
+ let layoutDependsOnWriteOrder = Boolean(usdz);
6711
+ let offset = 0;
6712
+ for (const entry of entries) {
6713
+ let { name } = entry;
6714
+ const { size } = entry;
6715
+ const options = Object.assign({}, entry.options);
6716
+ name = name.trim();
6717
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6718
+ name += DIRECTORY_SIGNATURE;
6719
+ }
6720
+ const attributesInfo = resolveAttributes(zipWriter, name, options);
6721
+ ({ name } = attributesInfo);
6722
+ const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
6723
+ if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
6724
+ !metadata.passThrough && !(await supportsDeflate(zipWriter.config))) {
6725
+ metadata.level = 0;
6726
+ }
6727
+ const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
6728
+ if (hasContent && size === UNDEFINED_VALUE) {
6729
+ throw new Error(ERR_UNDETERMINED_SIZE);
6730
+ }
6731
+ const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
6732
+ if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
6733
+ throw new Error(ERR_UNDETERMINED_SIZE);
6734
+ }
6735
+ const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes);
6736
+ const headerInfo = getHeaderInfo(entryOptions);
6737
+ const dataDescriptorInfo = getDataDescriptorInfo(entryOptions);
6738
+ const entryInfo = {
6739
+ headerInfo,
6740
+ metadataSize: getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray)
6741
+ };
6742
+ if (usdz) {
6743
+ appendExtraFieldUSDZ(entryInfo, offset);
6744
+ }
6745
+ const compressedSize = hasContent ? maximumCompressedSize : 0;
6746
+ if (offset >= MAX_32_BITS) {
6747
+ layoutDependsOnWriteOrder = true;
6748
+ }
6749
+ files.set(name, Object.assign({}, entryOptions, headerInfo, {
6750
+ offset,
6751
+ diskNumberStart: 0,
6752
+ compressedSize
6753
+ }));
6754
+ offset += entryInfo.metadataSize + compressedSize;
6755
+ }
6756
+ if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
6757
+ throw new Error(ERR_UNDETERMINED_SIZE);
6758
+ }
6759
+ const directoryDataLength = createDirectoryRecords(files);
6760
+ let zip64 = getOptionValue(zipWriter, writerOptions, PROPERTY_NAME_ZIP64);
6761
+ if (offset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || files.size >= MAX_16_BITS) {
6762
+ if (zip64 === false) {
6763
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
6764
+ } else {
6765
+ zip64 = true;
6766
+ }
6767
+ }
6768
+ return offset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
6769
+ }
6770
+
6546
6771
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6547
6772
  const {
6548
6773
  files,
@@ -6757,6 +6982,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6757
6982
  uid,
6758
6983
  gid,
6759
6984
  unixMode,
6985
+ symlink,
6760
6986
  setuid,
6761
6987
  setgid,
6762
6988
  sticky,
@@ -6793,6 +7019,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6793
7019
  uid,
6794
7020
  gid,
6795
7021
  unixMode,
7022
+ symlink: Boolean(symlink),
6796
7023
  setuid,
6797
7024
  setgid,
6798
7025
  sticky,
@@ -6873,8 +7100,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
6873
7100
  rawLastModDate,
6874
7101
  creationDate,
6875
7102
  lastAccessDate,
6876
- encrypted,
6877
- zipCrypto,
7103
+ encrypted: Boolean(encrypted),
7104
+ zipCrypto: Boolean(zipCrypto),
6878
7105
  size: metadataSize + compressedSize,
6879
7106
  compressionMethod,
6880
7107
  version,
@@ -6914,9 +7141,7 @@ function getHeaderInfo(options) {
6914
7141
  crc32
6915
7142
  } = options;
6916
7143
  let { version, compressionMethod } = options;
6917
- const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
6918
- ? (level === UNDEFINED_VALUE || level > 0)
6919
- : compressionMethod !== COMPRESSION_METHOD_STORE);
7144
+ const compressed = !directory && isCompressed(compressionMethod, level);
6920
7145
  let rawLocalExtraFieldZip64;
6921
7146
  const uncompressedFile = passThrough || !compressed;
6922
7147
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
@@ -7603,6 +7828,16 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
7603
7828
  return result === UNDEFINED_VALUE ? defaultValue : result;
7604
7829
  }
7605
7830
 
7831
+ function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
7832
+ const value = getAliasedValue(options, name, deprecatedName);
7833
+ const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
7834
+ return result === UNDEFINED_VALUE ? defaultValue : result;
7835
+ }
7836
+
7837
+ function getAliasedValue(options, name, deprecatedName) {
7838
+ return options[name] === UNDEFINED_VALUE ? options[deprecatedName] : options[name];
7839
+ }
7840
+
7606
7841
  function getNumberOptionValue(zipWriter, options, name, defaultValue) {
7607
7842
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
7608
7843
  }
@@ -7615,6 +7850,12 @@ function getMaximumCompressedSize(uncompressedSize) {
7615
7850
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
7616
7851
  }
7617
7852
 
7853
+ function isCompressed(compressionMethod, level) {
7854
+ return compressionMethod === UNDEFINED_VALUE
7855
+ ? (level === UNDEFINED_VALUE || level > 0)
7856
+ : compressionMethod !== COMPRESSION_METHOD_STORE;
7857
+ }
7858
+
7618
7859
  function setUint8(view, offset, value) {
7619
7860
  view.setUint8(offset, value);
7620
7861
  }
@@ -8600,6 +8841,7 @@ configureExternalAssets();
8600
8841
 
8601
8842
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
8602
8843
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
8844
+ const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
8603
8845
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
8604
8846
  const ERR_ABORTED = "The operation was aborted";
8605
8847
  const ABORT_ERROR_NAME = "AbortError";
@@ -8637,6 +8879,7 @@ class ZipEntry {
8637
8879
  parent,
8638
8880
  children: [],
8639
8881
  uncompressedSize: params.uncompressedSize || 0,
8882
+ undeterminedSize: params.undeterminedSize || params.uncompressedSize === UNDEFINED_VALUE,
8640
8883
  passThrough: params.passThrough
8641
8884
  });
8642
8885
  if (parent || !fs.root) {
@@ -8704,16 +8947,17 @@ class ZipFileEntry extends ZipEntry {
8704
8947
 
8705
8948
  async getData(writer, options = {}) {
8706
8949
  const zipEntry = this;
8707
- if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data)) {
8950
+ if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data && keepsContentType(writer, zipEntry.data))) {
8708
8951
  return zipEntry.data;
8709
8952
  } else {
8710
8953
  const reader = zipEntry.reader = createReader(zipEntry.Reader, zipEntry.data, options);
8711
- const uncompressedSize = zipEntry.data ? zipEntry.data.uncompressedSize : reader.size;
8712
- await Promise.all([initStream(reader), initStream(writer, uncompressedSize)]);
8713
- const { readable } = reader;
8954
+ const dataSize = zipEntry.uncompressedSize || reader.size;
8955
+ await Promise.all([initStream(reader), initStream(writer, dataSize)]);
8714
8956
  const { signal } = options;
8957
+ const readable = createProgressReadable(zipEntry, reader, options, signal);
8958
+ const preventClose = !ownsWritable(writer) && Boolean(options.preventClose);
8715
8959
  zipEntry.uncompressedSize = reader.size;
8716
- await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
8960
+ await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal, preventClose, preventAbort: preventClose });
8717
8961
  return writer.getData ? writer.getData() : writer.writable;
8718
8962
  }
8719
8963
  }
@@ -8844,7 +9088,7 @@ class ZipDirectoryEntry extends ZipEntry {
8844
9088
  Reader: TextReader,
8845
9089
  Writer: TextWriter,
8846
9090
  options,
8847
- uncompressedSize: text.length
9091
+ uncompressedSize: getTextSize(text)
8848
9092
  });
8849
9093
  }
8850
9094
 
@@ -8973,10 +9217,16 @@ class ZipDirectoryEntry extends ZipEntry {
8973
9217
  }
8974
9218
 
8975
9219
  async importZip(reader, options = {}) {
8976
- await initStream(reader);
8977
- const zipReader = new ZipReader(reader, options);
9220
+ let zipReader;
9221
+ if (reader && typeof reader.getEntries == FUNCTION_TYPE) {
9222
+ zipReader = reader;
9223
+ options = Object.assign({}, zipReader.options, options);
9224
+ } else {
9225
+ await initStream(reader);
9226
+ zipReader = new ZipReader(reader, options);
9227
+ }
8978
9228
  const importedEntries = [];
8979
- const entries = await zipReader.getEntries();
9229
+ const entries = await zipReader.getEntries(options);
8980
9230
  for (const entry of entries) {
8981
9231
  let parent = this;
8982
9232
  try {
@@ -8998,7 +9248,7 @@ class ZipDirectoryEntry extends ZipEntry {
8998
9248
  importedEntries.push(addChild(parent, name, {
8999
9249
  data: entry,
9000
9250
  Reader: getZipBlobReader(Object.assign({}, options)),
9001
- uncompressedSize: entry.uncompressedSize,
9251
+ uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
9002
9252
  passThrough: options.passThrough
9003
9253
  }));
9004
9254
  } else {
@@ -9040,11 +9290,25 @@ class ZipDirectoryEntry extends ZipEntry {
9040
9290
  }
9041
9291
  const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
9042
9292
  const zipWriter = new ZipWriter(writer, options);
9043
- await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options, readers);
9044
- await zipWriter.close();
9293
+ await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
9294
+ await zipWriter.close(options.globalComment);
9045
9295
  return writer.getData ? writer.getData() : writer.writable;
9046
9296
  }
9047
9297
 
9298
+ getExportedSize(options = {}) {
9299
+ const zipEntry = this;
9300
+ options = Object.assign({}, options);
9301
+ if (options.bufferedWrite === UNDEFINED_VALUE) {
9302
+ options.bufferedWrite = true;
9303
+ }
9304
+ const writeOrderGuaranteed = !options.bufferedWrite ||
9305
+ (options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
9306
+ return getEntriesSize(options, Array.from(zipEntry.getChildren({ recursive: true }), child => {
9307
+ const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
9308
+ return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
9309
+ }), writeOrderGuaranteed, options.globalComment);
9310
+ }
9311
+
9048
9312
  getChildByName(name) {
9049
9313
  const children = this.children;
9050
9314
  for (let childIndex = 0; childIndex < children.length; childIndex++) {
@@ -9252,6 +9516,10 @@ class FS {
9252
9516
  return this.root.exportZip(writer, options);
9253
9517
  }
9254
9518
 
9519
+ getExportedSize(options) {
9520
+ return this.root.getExportedSize(options);
9521
+ }
9522
+
9255
9523
  isPasswordProtected() {
9256
9524
  return this.root.isPasswordProtected();
9257
9525
  }
@@ -9263,12 +9531,12 @@ class FS {
9263
9531
 
9264
9532
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
9265
9533
 
9266
- function getTotalSize(entries, propertyName) {
9534
+ function getTotalSize(entries, getEntrySize) {
9267
9535
  let size = 0;
9268
9536
  const pendingEntries = Array.from(entries);
9269
9537
  while (pendingEntries.length) {
9270
9538
  const entry = pendingEntries.pop();
9271
- size += entry[propertyName] || 0;
9539
+ size += getEntrySize(entry) || 0;
9272
9540
  for (const child of entry.children) {
9273
9541
  pendingEntries.push(child);
9274
9542
  }
@@ -9276,6 +9544,15 @@ function getTotalSize(entries, propertyName) {
9276
9544
  return size;
9277
9545
  }
9278
9546
 
9547
+ function getUncompressedSize(entry) {
9548
+ return entry.uncompressedSize;
9549
+ }
9550
+
9551
+ function getExtractedSize(entry, passThrough) {
9552
+ const { data } = entry;
9553
+ return passThrough && data instanceof Entry ? data.compressedSize : entry.uncompressedSize;
9554
+ }
9555
+
9279
9556
  function getReadableReader(readable) {
9280
9557
  let consumed;
9281
9558
  return function () {
@@ -9298,10 +9575,17 @@ function getZipBlobReader(options) {
9298
9575
 
9299
9576
  async init() {
9300
9577
  const zipBlobReader = this;
9301
- zipBlobReader.size = zipBlobReader.entry.uncompressedSize;
9302
- const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({}, options, zipBlobReader.options));
9578
+ const readerOptions = Object.assign({}, options, zipBlobReader.options);
9579
+ const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
9580
+ const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign(readerOptions, {
9581
+ checkPasswordOnly: false,
9582
+ checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
9583
+ checkOverlappingEntryOnly: false,
9584
+ preventClose: false
9585
+ }));
9303
9586
  zipBlobReader.data = data;
9304
9587
  zipBlobReader.blobReader = new BlobReader(data);
9588
+ zipBlobReader.size = data.size;
9305
9589
  super.init();
9306
9590
  }
9307
9591
 
@@ -9315,6 +9599,30 @@ function createReader(Reader, data, options) {
9315
9599
  return Reader.prototype ? new Reader(data, options) : Reader(data, options);
9316
9600
  }
9317
9601
 
9602
+ function keepsContentType(writer, data) {
9603
+ const { contentType } = writer;
9604
+ if (contentType === UNDEFINED_VALUE) {
9605
+ return true;
9606
+ } else if (writer.constructor == BlobWriter) {
9607
+ return data.type == contentType;
9608
+ } else if (writer.constructor == Data64URIWriter) {
9609
+ return data.startsWith(writer.data);
9610
+ } else {
9611
+ return true;
9612
+ }
9613
+ }
9614
+
9615
+ function createProgressReadable(zipEntry, reader, options, signal) {
9616
+ const { onstart, onprogress, onend } = options;
9617
+ const { readable } = reader;
9618
+ const coreReaderReportsProgress = zipEntry.data instanceof Entry;
9619
+ if (coreReaderReportsProgress || (!onstart && !onprogress && !onend)) {
9620
+ return readable;
9621
+ } else {
9622
+ return toCompatibleReadable(readable).pipeThrough(new ProgressWatcherStream({ onstart, onprogress, onend, size: reader.size }), { signal });
9623
+ }
9624
+ }
9625
+
9318
9626
  async function initReaders(entry, options) {
9319
9627
  const fileEntries = [];
9320
9628
  const pendingEntries = [entry];
@@ -9347,6 +9655,7 @@ async function initReaders(entry, options) {
9347
9655
  }
9348
9656
  if (reader.size !== UNDEFINED_VALUE) {
9349
9657
  child.uncompressedSize = reader.size;
9658
+ child.undeterminedSize = false;
9350
9659
  }
9351
9660
  }));
9352
9661
  return readers;
@@ -9396,6 +9705,90 @@ function aggregateEntryErrors(errors) {
9396
9705
  return error;
9397
9706
  }
9398
9707
 
9708
+ function getChildEntryOptions(child, selectedEntry, options) {
9709
+ const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
9710
+ const childOptions = child.options || {};
9711
+ let zipEntryMetadata = {};
9712
+ let passThroughOptions = {};
9713
+ if (child.data instanceof Entry) {
9714
+ const {
9715
+ externalFileAttributes,
9716
+ versionMadeBy,
9717
+ comment,
9718
+ lastModDate,
9719
+ creationDate,
9720
+ lastAccessDate,
9721
+ uncompressedSize,
9722
+ encrypted,
9723
+ zipCrypto,
9724
+ crc32,
9725
+ compressionMethod,
9726
+ extraFieldAES,
9727
+ internalFileAttributes,
9728
+ extraField,
9729
+ uid,
9730
+ gid
9731
+ } = child.data;
9732
+ zipEntryMetadata = {
9733
+ externalFileAttributes,
9734
+ versionMadeBy,
9735
+ comment,
9736
+ lastModDate,
9737
+ creationDate,
9738
+ lastAccessDate,
9739
+ internalFileAttributes
9740
+ };
9741
+ const userExtraField = getUserExtraField(extraField);
9742
+ if (userExtraField) {
9743
+ zipEntryMetadata.extraField = userExtraField;
9744
+ }
9745
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
9746
+ Object.assign(zipEntryMetadata, {
9747
+ uid,
9748
+ gid,
9749
+ unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
9750
+ });
9751
+ }
9752
+ if (isPassThrough(child, options)) {
9753
+ let level, encryptionStrength;
9754
+ if (compressionMethod === 0) {
9755
+ level = 0;
9756
+ }
9757
+ if (extraFieldAES) {
9758
+ encryptionStrength = extraFieldAES.strength;
9759
+ }
9760
+ passThroughOptions = {
9761
+ passThrough: true,
9762
+ encrypted,
9763
+ zipCrypto,
9764
+ crc32,
9765
+ uncompressedSize,
9766
+ level,
9767
+ encryptionStrength,
9768
+ compressionMethod
9769
+ };
9770
+ }
9771
+ }
9772
+ const entryOptions = Object.assign({}, zipEntryMetadata, options, passThroughOptions, childOptions, { directory: child.directory });
9773
+ if (!child.directory && entryOptions.passThrough && entryOptions.uncompressedSize === UNDEFINED_VALUE) {
9774
+ throw new Error(ERR_INVALID_PASS_THROUGH);
9775
+ }
9776
+ return { name, entryOptions };
9777
+ }
9778
+
9779
+ function getDeterminedSize(child, passThrough) {
9780
+ const { reader } = child;
9781
+ if (reader && reader.size !== UNDEFINED_VALUE) {
9782
+ return reader.size;
9783
+ }
9784
+ return child.undeterminedSize ? UNDEFINED_VALUE : getExtractedSize(child, passThrough);
9785
+ }
9786
+
9787
+ function isPassThrough(child, options) {
9788
+ const { readerOptions } = options;
9789
+ return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
9790
+ }
9791
+
9399
9792
  function getUserExtraField(extraField) {
9400
9793
  if (extraField) {
9401
9794
  const userExtraField = new Map();
@@ -9411,8 +9804,14 @@ function getUserExtraField(extraField) {
9411
9804
  }
9412
9805
 
9413
9806
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
9807
+ const { onstart, onprogress, onend, onentryprogress } = options;
9414
9808
  const selectedEntry = entry;
9415
- const entryOffsets = new Map();
9809
+ const totalEntries = getTotalSize(entry.children, () => 1);
9810
+ let writtenSize = 0;
9811
+ let writtenEntries = 0;
9812
+ if (onstart) {
9813
+ await callHandler(onstart, totalSize);
9814
+ }
9416
9815
  if (options.bufferedWrite) {
9417
9816
  await processChildren(entry);
9418
9817
  } else {
@@ -9420,6 +9819,9 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9420
9819
  await addChild(child);
9421
9820
  }
9422
9821
  }
9822
+ if (onend) {
9823
+ await callHandler(onend, writtenSize);
9824
+ }
9423
9825
 
9424
9826
  async function processChildren(entry) {
9425
9827
  const results = await Promise.allSettled(entry.children.map(async child => {
@@ -9433,81 +9835,23 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9433
9835
  }
9434
9836
 
9435
9837
  async function addChild(child) {
9436
- const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
9437
- const childOptions = child.options || {};
9438
- let zipEntryOptions = {};
9439
- if (child.data instanceof Entry) {
9440
- const {
9441
- externalFileAttributes,
9442
- versionMadeBy,
9443
- comment,
9444
- lastModDate,
9445
- creationDate,
9446
- lastAccessDate,
9447
- uncompressedSize,
9448
- encrypted,
9449
- zipCrypto,
9450
- crc32,
9451
- compressionMethod,
9452
- extraFieldAES,
9453
- internalFileAttributes,
9454
- extraField,
9455
- uid,
9456
- gid
9457
- } = child.data;
9458
- zipEntryOptions = {
9459
- externalFileAttributes,
9460
- versionMadeBy,
9461
- comment,
9462
- lastModDate,
9463
- creationDate,
9464
- lastAccessDate,
9465
- internalFileAttributes
9466
- };
9467
- const userExtraField = getUserExtraField(extraField);
9468
- if (userExtraField) {
9469
- zipEntryOptions.extraField = userExtraField;
9470
- }
9471
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
9472
- Object.assign(zipEntryOptions, {
9473
- uid,
9474
- gid,
9475
- unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
9476
- });
9477
- }
9478
- if (child.passThrough) {
9479
- let level, encryptionStrength;
9480
- if (compressionMethod === 0) {
9481
- level = 0;
9482
- }
9483
- if (extraFieldAES) {
9484
- encryptionStrength = extraFieldAES.strength;
9485
- }
9486
- zipEntryOptions = Object.assign(zipEntryOptions, {
9487
- passThrough: true,
9488
- encrypted,
9489
- zipCrypto,
9490
- crc32,
9491
- uncompressedSize,
9492
- level,
9493
- encryptionStrength,
9494
- compressionMethod
9495
- });
9496
- }
9497
- }
9498
- await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
9499
- directory: child.directory,
9838
+ const { name, entryOptions } = getChildEntryOptions(child, selectedEntry, options);
9839
+ let entryWrittenSize = 0;
9840
+ const entryMetadata = await zipWriter.add(name, readers.get(child), Object.assign(entryOptions, {
9841
+ onstart: UNDEFINED_VALUE,
9842
+ onend: UNDEFINED_VALUE,
9500
9843
  onprogress: async indexProgress => {
9501
- if (options.onprogress) {
9502
- entryOffsets.set(name, indexProgress);
9503
- try {
9504
- await options.onprogress(Array.from(entryOffsets.values()).reduce((previousValue, currentValue) => previousValue + currentValue), totalSize);
9505
- } catch {
9506
- // ignored
9507
- }
9844
+ writtenSize += indexProgress - entryWrittenSize;
9845
+ entryWrittenSize = indexProgress;
9846
+ if (onprogress) {
9847
+ await callHandler(onprogress, writtenSize, totalSize);
9508
9848
  }
9509
9849
  }
9510
9850
  }));
9851
+ writtenEntries++;
9852
+ if (onentryprogress) {
9853
+ await callHandler(onentryprogress, writtenEntries, totalEntries, entryMetadata);
9854
+ }
9511
9855
  }
9512
9856
  }
9513
9857
 
@@ -9535,7 +9879,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
9535
9879
  })
9536
9880
  );
9537
9881
  } else if (handle.kind == "directory") {
9538
- const directoryEntry = parentEntry.addDirectory(handle.name);
9882
+ const directoryEntry = parentEntry.addDirectory(handle.name, options);
9539
9883
  addedEntries.push(directoryEntry);
9540
9884
  for await (const childHandle of handle.values()) {
9541
9885
  await addFile(directoryEntry, childHandle, addedEntries, entryName);
@@ -9557,15 +9901,29 @@ function addFileSystemHandle(zipEntry, handle, options) {
9557
9901
  }
9558
9902
 
9559
9903
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9560
- const totalSize = getTotalSize([zipEntry], "uncompressedSize");
9561
- const writtenSizes = new Map();
9904
+ const { onstart, onprogress, onend } = options;
9562
9905
  const abortController = new AbortController();
9563
9906
  const { signal } = abortController;
9564
9907
  const releaseSignal = forwardAbort(options.signal, abortController);
9908
+ const getDataOptions = Object.assign({}, options, options.readerOptions, {
9909
+ signal,
9910
+ onstart: UNDEFINED_VALUE,
9911
+ onprogress: UNDEFINED_VALUE,
9912
+ onend: UNDEFINED_VALUE,
9913
+ preventClose: false
9914
+ });
9915
+ const totalSize = getTotalSize([zipEntry], entry => getExtractedSize(entry, getDataOptions.passThrough));
9565
9916
  const exportedEntryNames = [];
9566
9917
  let exportAborted = false;
9918
+ let writtenSize = 0;
9567
9919
  try {
9920
+ if (onstart) {
9921
+ await callHandler(onstart, totalSize);
9922
+ }
9568
9923
  await exportChildren(zipEntry, directoryHandle);
9924
+ if (onend) {
9925
+ await callHandler(onend, writtenSize);
9926
+ }
9569
9927
  } catch (error) {
9570
9928
  try {
9571
9929
  error.exportedEntryNames = exportedEntryNames;
@@ -9578,6 +9936,25 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9578
9936
  }
9579
9937
  return directoryHandle;
9580
9938
 
9939
+ function createProgressWritable(writable) {
9940
+ const writer = writable.getWriter();
9941
+ return new WritableStream({
9942
+ async write(chunk) {
9943
+ await writer.write(chunk);
9944
+ writtenSize += chunk.length;
9945
+ if (onprogress) {
9946
+ await callHandler(onprogress, writtenSize, totalSize);
9947
+ }
9948
+ },
9949
+ close() {
9950
+ return writer.close();
9951
+ },
9952
+ abort(reason) {
9953
+ return writer.abort(reason);
9954
+ }
9955
+ });
9956
+ }
9957
+
9581
9958
  async function exportChildren(entry, parentHandle) {
9582
9959
  if (options.concurrent) {
9583
9960
  const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
@@ -9609,19 +9986,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9609
9986
  const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
9610
9987
  const writable = await fileHandle.createWritable();
9611
9988
  try {
9612
- await child.getData({ writable }, Object.assign({}, options, {
9613
- signal,
9614
- onprogress: async progress => {
9615
- if (options.onprogress) {
9616
- writtenSizes.set(child.id, progress);
9617
- try {
9618
- await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
9619
- } catch {
9620
- // ignored
9621
- }
9622
- }
9623
- }
9624
- }));
9989
+ await child.getData({ writable: createProgressWritable(writable) }, getDataOptions);
9625
9990
  } catch (error) {
9626
9991
  throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
9627
9992
  }
@@ -9798,4 +10163,4 @@ function decodeMimeTypes(data) {
9798
10163
  return mimeTypes;
9799
10164
  }
9800
10165
 
9801
- export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, 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_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_SIGNATURE, 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_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION$1 as ERR_UNSUPPORTED_COMPRESSION, ERR_UNSUPPORTED_CONTEXT, ERR_UNSUPPORTED_CRYPTO_API, ERR_UNSUPPORTED_ENCRYPTION, ERR_UNSUPPORTED_ENCRYPTION_USDZ, ERR_UNSUPPORTED_FORMAT, ERR_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, Writer, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
10166
+ export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_ABORTED, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, 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_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_PASS_THROUGH, ERR_INVALID_SIGNATURE, 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_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION$1 as 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_WORKER_STARTUP_TIMEOUT, ERR_WRITER_NOT_INITIALIZED, ERR_ZIP_NOT_EMPTY, HttpRangeReader, HttpReader, Reader, SplitDataReader, SplitDataWriter, TextReader, TextWriter, Uint8ArrayReader, Uint8ArrayWriter, Writer, ZipReader, ZipReaderStream, ZipWriter, ZipWriterStream, configure, createBlobTempStream, createOPFSTempStream, createSyncAccessHandleTempStream, fs, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };