@zip.js/zip.js 2.8.51 → 2.8.52

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.
package/index-native.cjs CHANGED
@@ -84,6 +84,8 @@ const FILE_ATTR_MSDOS_SYSTEM_MASK = 0x04;
84
84
  const FILE_ATTR_MSDOS_ARCHIVE_MASK = 0x20;
85
85
  const FILE_ATTR_UNIX_TYPE_MASK = 0o170000;
86
86
  const FILE_ATTR_UNIX_TYPE_DIR = 0o040000;
87
+ const FILE_ATTR_UNIX_TYPE_SYMLINK = 0o120000;
88
+ const FILE_ATTR_UNIX_TYPE_FILE = 0o100000;
87
89
  const FILE_ATTR_UNIX_EXECUTABLE_MASK = 0o111;
88
90
  const FILE_ATTR_UNIX_DEFAULT_MASK = 0o644;
89
91
  const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
@@ -1775,8 +1777,6 @@ function getInt32(number) {
1775
1777
  */
1776
1778
 
1777
1779
 
1778
- const HTTP_HEADER_CONTENT_TYPE = "Content-Type";
1779
-
1780
1780
  function toCompatibleReadable(readable) {
1781
1781
  if (readable instanceof ReadableStream) {
1782
1782
  return readable;
@@ -1799,12 +1799,9 @@ function toCompatibleReadable(readable) {
1799
1799
 
1800
1800
  function streamToBlob(readable, contentType) {
1801
1801
  readable = toCompatibleReadable(readable);
1802
+ const blobOptions = contentType ? { type: contentType } : {};
1802
1803
  if (responseSupportsGlobalReadable()) {
1803
- const options = {};
1804
- if (contentType) {
1805
- options.headers = [[HTTP_HEADER_CONTENT_TYPE, contentType]];
1806
- }
1807
- return new Response(readable, options).blob();
1804
+ return new Response(readable).blob().then(blob => contentType ? new Blob([blob], blobOptions) : blob);
1808
1805
  }
1809
1806
  const chunks = [];
1810
1807
  return readable
@@ -1813,7 +1810,7 @@ function streamToBlob(readable, contentType) {
1813
1810
  chunks.push(chunk);
1814
1811
  }
1815
1812
  }))
1816
- .then(() => new Blob(chunks, contentType ? { type: contentType } : {}));
1813
+ .then(() => new Blob(chunks, blobOptions));
1817
1814
  }
1818
1815
 
1819
1816
  function responseSupportsGlobalReadable() {
@@ -3344,8 +3341,10 @@ class Reader extends Stream {
3344
3341
  async pull(controller) {
3345
3342
  const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
3346
3343
  const data = await readUint8Array(reader, offset + chunkOffset, dataSize);
3347
- controller.enqueue(data);
3348
- if ((chunkOffset + chunkSize > size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3344
+ if (data.length) {
3345
+ controller.enqueue(data);
3346
+ }
3347
+ if ((chunkOffset + chunkSize >= size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3349
3348
  controller.close();
3350
3349
  } else {
3351
3350
  chunkOffset += chunkSize;
@@ -3423,6 +3422,7 @@ class Data64URIWriter extends Writer {
3423
3422
  constructor(contentType) {
3424
3423
  super();
3425
3424
  Object.assign(this, {
3425
+ contentType,
3426
3426
  data: "data:" + (contentType || "") + ";base64,",
3427
3427
  pending: []
3428
3428
  });
@@ -3524,6 +3524,7 @@ class BlobWriter extends Stream {
3524
3524
  return transformStream.writable;
3525
3525
  }
3526
3526
  });
3527
+ writer.contentType = contentType;
3527
3528
  writer.blob = streamToBlob(transformStream.readable, contentType);
3528
3529
  writer.blob.catch(() => { });
3529
3530
  }
@@ -3540,6 +3541,26 @@ class TextReader extends BlobReader {
3540
3541
  }
3541
3542
  }
3542
3543
 
3544
+ function getTextSize(text) {
3545
+ let size = 0;
3546
+ for (let indexCharacter = 0; indexCharacter < text.length; indexCharacter++) {
3547
+ const characterCode = text.charCodeAt(indexCharacter);
3548
+ if (characterCode < 0x80) {
3549
+ size += 1;
3550
+ } else if (characterCode < 0x800) {
3551
+ size += 2;
3552
+ } else if (characterCode < 0xd800 || characterCode >= 0xe000) {
3553
+ size += 3;
3554
+ } else if (characterCode < 0xdc00 && (text.charCodeAt(indexCharacter + 1) & 0xfc00) == 0xdc00) {
3555
+ size += 4;
3556
+ indexCharacter++;
3557
+ } else {
3558
+ size += 3;
3559
+ }
3560
+ }
3561
+ return size;
3562
+ }
3563
+
3543
3564
  class TextWriter extends BlobWriter {
3544
3565
 
3545
3566
  constructor(encoding) {
@@ -4203,6 +4224,10 @@ class GenericWriter {
4203
4224
  }
4204
4225
  }
4205
4226
 
4227
+ function ownsWritable(writer) {
4228
+ return Boolean(writer && writer.getData);
4229
+ }
4230
+
4206
4231
  function isHttpFamily(url) {
4207
4232
  const { baseURI } = getConfiguration();
4208
4233
  const { protocol } = new URL(url, baseURI);
@@ -4347,6 +4372,8 @@ const PROPERTY_NAME_CREATION_DATE = "creationDate";
4347
4372
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
4348
4373
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
4349
4374
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
4375
+ const PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES = "internalFileAttribute";
4376
+ const PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttribute";
4350
4377
  const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
4351
4378
  const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
4352
4379
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
@@ -4357,6 +4384,7 @@ const PROPERTY_NAME_VERSION_MADE_BY = "versionMadeBy";
4357
4384
  const PROPERTY_NAME_ZIPCRYPTO = "zipCrypto";
4358
4385
  const PROPERTY_NAME_DIRECTORY = "directory";
4359
4386
  const PROPERTY_NAME_EXECUTABLE = "executable";
4387
+ const PROPERTY_NAME_SYMLINK = "symlink";
4360
4388
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4361
4389
  const PROPERTY_NAME_SIGNATURE = "signature";
4362
4390
  const PROPERTY_NAME_CRC32 = "crc32";
@@ -4400,6 +4428,8 @@ const PROPERTY_NAMES = [
4400
4428
  PROPERTY_NAME_DISK_NUMBER_START,
4401
4429
  PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
4402
4430
  PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
4431
+ PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES,
4432
+ PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES,
4403
4433
  PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
4404
4434
  PROPERTY_NAME_MSDOS_ATTRIBUTES,
4405
4435
  PROPERTY_NAME_MS_DOS_COMPATIBLE,
@@ -4410,6 +4440,7 @@ const PROPERTY_NAMES = [
4410
4440
  PROPERTY_NAME_ZIPCRYPTO,
4411
4441
  PROPERTY_NAME_DIRECTORY,
4412
4442
  PROPERTY_NAME_EXECUTABLE,
4443
+ PROPERTY_NAME_SYMLINK,
4413
4444
  PROPERTY_NAME_COMPRESSION_METHOD,
4414
4445
  PROPERTY_NAME_SIGNATURE,
4415
4446
  PROPERTY_NAME_CRC32,
@@ -4872,15 +4903,18 @@ class ZipReader {
4872
4903
  const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4873
4904
  const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4874
4905
  const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4875
- const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
4906
+ const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
4907
+ const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
4908
+ const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
4876
4909
  ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
4877
- : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
4910
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
4878
4911
  const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4879
4912
  const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4880
4913
  Object.assign(fileEntry, {
4881
4914
  setuid,
4882
4915
  setgid,
4883
4916
  sticky,
4917
+ symlink,
4884
4918
  unixExternalUpper,
4885
4919
  internalFileAttribute: fileEntry.internalFileAttributes,
4886
4920
  externalFileAttribute: fileEntry.externalFileAttributes,
@@ -4946,6 +4980,10 @@ class ZipReader {
4946
4980
  }
4947
4981
 
4948
4982
  async close() {
4983
+ const { reader } = this;
4984
+ if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
4985
+ await reader.readable.cancel();
4986
+ }
4949
4987
  }
4950
4988
  }
4951
4989
 
@@ -5170,7 +5208,7 @@ let ZipEntry$1 = class ZipEntry {
5170
5208
  throw error;
5171
5209
  }
5172
5210
  } finally {
5173
- const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5211
+ const preventClose = !ownsWritable(writer) && getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5174
5212
  if (!preventClose && writable && !writable.locked) {
5175
5213
  const writableWriter = writable.getWriter();
5176
5214
  if (abortError) {
@@ -5414,8 +5452,8 @@ function readExtraFieldUnixDates(extraField, directory) {
5414
5452
  return;
5415
5453
  }
5416
5454
  const extraFieldView = getDataView(extraField.data);
5417
- const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5418
- const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5455
+ const lastAccessDate = new Date((getUint32(extraFieldView, 0) | 0) * 1000);
5456
+ const lastModDate = new Date((getUint32(extraFieldView, 4) | 0) * 1000);
5419
5457
  const extraFieldData = { lastAccessDate, lastModDate };
5420
5458
  if (extraField.data.length >= 12) {
5421
5459
  extraFieldData.uid = getUint16(extraFieldView, 8);
@@ -5846,6 +5884,7 @@ const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5846
5884
  const ERR_INVALID_VERSION = "Version exceeds 65535";
5847
5885
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
5848
5886
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
5887
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
5849
5888
  const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
5850
5889
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
5851
5890
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
@@ -5855,6 +5894,7 @@ const MIN_NTFS_TIME = BigInt(0);
5855
5894
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5856
5895
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5857
5896
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
5897
+ const ERR_UNDETERMINED_SIZE = "Undetermined size";
5858
5898
  const ERR_UNDEFINED_READER = "Undefined reader";
5859
5899
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
5860
5900
  const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
@@ -6062,7 +6102,7 @@ class ZipWriter {
6062
6102
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6063
6103
  }
6064
6104
  await closeFile(zipWriter, comment, options);
6065
- const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6105
+ const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6066
6106
  if (!preventClose) {
6067
6107
  await writable.getWriter().close();
6068
6108
  }
@@ -6221,7 +6261,7 @@ function resolveAttributes(zipWriter, name, options) {
6221
6261
  if (versionMadeBy > MAX_16_BITS) {
6222
6262
  throw new Error(ERR_INVALID_VERSION);
6223
6263
  }
6224
- let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
6264
+ let externalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES);
6225
6265
  const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
6226
6266
  if (!externalFileAttributesProvided) {
6227
6267
  externalFileAttributes = 0;
@@ -6269,7 +6309,9 @@ function resolveAttributes(zipWriter, name, options) {
6269
6309
  }
6270
6310
  if (!externalFileAttributesProvided || unixModeProvided) {
6271
6311
  if (directory) {
6272
- unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
6312
+ unixMode = (unixMode & ~FILE_ATTR_UNIX_TYPE_MASK) | FILE_ATTR_UNIX_TYPE_DIR;
6313
+ } else if (!(unixMode & FILE_ATTR_UNIX_TYPE_MASK)) {
6314
+ unixMode |= FILE_ATTR_UNIX_TYPE_FILE;
6273
6315
  }
6274
6316
  externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
6275
6317
  }
@@ -6322,15 +6364,12 @@ function resolveMetadata(zipWriter, name, options) {
6322
6364
  const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6323
6365
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6324
6366
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6325
- const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6367
+ const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
6326
6368
  const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
6327
- let password, rawPassword;
6328
- if (!passThrough) {
6329
- password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6330
- rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6331
- if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6332
- throw new Error(ERR_INVALID_PASSWORD_TYPE);
6333
- }
6369
+ const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6370
+ const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6371
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6372
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
6334
6373
  }
6335
6374
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
6336
6375
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
@@ -6443,14 +6482,24 @@ function serializeExtraField(extraField) {
6443
6482
  }
6444
6483
 
6445
6484
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6485
+ if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
6486
+ throw new Error(ERR_UNDEFINED_READER);
6487
+ }
6488
+ let contentSize;
6489
+ if (reader) {
6490
+ reader = new GenericReader(reader);
6491
+ await initStream(reader);
6492
+ ({ size: contentSize } = reader);
6493
+ }
6494
+ return Object.assign({ reader }, resolveEntrySizes(zipWriter, Boolean(reader), contentSize, metadata, options));
6495
+ }
6496
+
6497
+ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
6446
6498
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6447
6499
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
6448
6500
  let maximumCompressedSize = 0;
6449
6501
  let uncompressedSize = 0;
6450
- if (passThrough) {
6451
- if (!reader) {
6452
- throw new Error(ERR_UNDEFINED_READER);
6453
- }
6502
+ if (passThrough && hasContent) {
6454
6503
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
6455
6504
  if (uncompressedSize === UNDEFINED_VALUE) {
6456
6505
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -6458,29 +6507,30 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6458
6507
  }
6459
6508
  const zip64Enabled = zip64 === true;
6460
6509
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
6461
- const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6462
- if (!reader) {
6510
+ if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
6511
+ throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
6512
+ }
6513
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6514
+ if (!hasContent) {
6463
6515
  level = 0;
6464
6516
  compressionMethod = COMPRESSION_METHOD_STORE;
6465
6517
  }
6466
6518
  const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
6467
- if (reader) {
6468
- reader = new GenericReader(reader);
6469
- await initStream(reader);
6519
+ if (hasContent) {
6470
6520
  if (!passThrough) {
6471
- if (reader.size === UNDEFINED_VALUE) {
6521
+ if (contentSize === UNDEFINED_VALUE) {
6472
6522
  dataDescriptor = true;
6473
6523
  if (zip64 || zip64 === UNDEFINED_VALUE) {
6474
6524
  zip64 = true;
6475
6525
  uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
6476
6526
  }
6477
6527
  } else {
6478
- options.uncompressedSize = uncompressedSize = reader.size;
6479
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6528
+ options.uncompressedSize = uncompressedSize = contentSize;
6529
+ maximumCompressedSize = (isCompressed(compressionMethod, level) ? getMaximumCompressedSize(uncompressedSize) : uncompressedSize) + encryptionOverhead;
6480
6530
  }
6481
6531
  } else {
6482
6532
  options.uncompressedSize = uncompressedSize;
6483
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6533
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
6484
6534
  }
6485
6535
  }
6486
6536
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
@@ -6494,7 +6544,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6494
6544
  }
6495
6545
  zip64 = zip64 || false;
6496
6546
  return {
6497
- reader,
6547
+ maximumCompressedSize,
6498
6548
  resolvedOptions: {
6499
6549
  dataDescriptor,
6500
6550
  zip64,
@@ -6508,6 +6558,78 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6508
6558
  };
6509
6559
  }
6510
6560
 
6561
+ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
6562
+ const zipWriter = { options: writerOptions, config: getConfiguration() };
6563
+ if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6564
+ throw new Error(ERR_UNDETERMINED_SIZE);
6565
+ }
6566
+ const commentLength = getLength(comment);
6567
+ if (commentLength > MAX_16_BITS) {
6568
+ throw new Error(ERR_INVALID_COMMENT);
6569
+ }
6570
+ const usdz = writerOptions[OPTION_USDZ];
6571
+ const files = new Map();
6572
+ let layoutDependsOnWriteOrder = Boolean(usdz);
6573
+ let offset = 0;
6574
+ for (const entry of entries) {
6575
+ let { name } = entry;
6576
+ const { size } = entry;
6577
+ const options = Object.assign({}, entry.options);
6578
+ name = name.trim();
6579
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6580
+ name += DIRECTORY_SIGNATURE;
6581
+ }
6582
+ const attributesInfo = resolveAttributes(zipWriter, name, options);
6583
+ ({ name } = attributesInfo);
6584
+ const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
6585
+ if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
6586
+ !metadata.passThrough && !(await supportsDeflate(zipWriter.config))) {
6587
+ metadata.level = 0;
6588
+ }
6589
+ const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
6590
+ if (hasContent && size === UNDEFINED_VALUE) {
6591
+ throw new Error(ERR_UNDETERMINED_SIZE);
6592
+ }
6593
+ const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
6594
+ if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
6595
+ throw new Error(ERR_UNDETERMINED_SIZE);
6596
+ }
6597
+ const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes);
6598
+ const headerInfo = getHeaderInfo(entryOptions);
6599
+ const dataDescriptorInfo = getDataDescriptorInfo(entryOptions);
6600
+ const entryInfo = {
6601
+ headerInfo,
6602
+ metadataSize: getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray)
6603
+ };
6604
+ if (usdz) {
6605
+ appendExtraFieldUSDZ(entryInfo, offset);
6606
+ }
6607
+ const compressedSize = hasContent ? maximumCompressedSize : 0;
6608
+ if (offset >= MAX_32_BITS) {
6609
+ layoutDependsOnWriteOrder = true;
6610
+ }
6611
+ files.set(name, Object.assign({}, entryOptions, headerInfo, {
6612
+ offset,
6613
+ diskNumberStart: 0,
6614
+ compressedSize
6615
+ }));
6616
+ offset += entryInfo.metadataSize + compressedSize;
6617
+ }
6618
+ if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
6619
+ throw new Error(ERR_UNDETERMINED_SIZE);
6620
+ }
6621
+ const directoryDataLength = createDirectoryRecords(files);
6622
+ let zip64 = getOptionValue(zipWriter, writerOptions, PROPERTY_NAME_ZIP64);
6623
+ if (offset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || files.size >= MAX_16_BITS) {
6624
+ if (zip64 === false) {
6625
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
6626
+ } else {
6627
+ zip64 = true;
6628
+ }
6629
+ }
6630
+ return offset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
6631
+ }
6632
+
6511
6633
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6512
6634
  const {
6513
6635
  files,
@@ -6879,9 +7001,7 @@ function getHeaderInfo(options) {
6879
7001
  crc32
6880
7002
  } = options;
6881
7003
  let { version, compressionMethod } = options;
6882
- const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
6883
- ? (level === UNDEFINED_VALUE || level > 0)
6884
- : compressionMethod !== COMPRESSION_METHOD_STORE);
7004
+ const compressed = !directory && isCompressed(compressionMethod, level);
6885
7005
  let rawLocalExtraFieldZip64;
6886
7006
  const uncompressedFile = passThrough || !compressed;
6887
7007
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
@@ -7568,6 +7688,16 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
7568
7688
  return result === UNDEFINED_VALUE ? defaultValue : result;
7569
7689
  }
7570
7690
 
7691
+ function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
7692
+ const value = getAliasedValue(options, name, deprecatedName);
7693
+ const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
7694
+ return result === UNDEFINED_VALUE ? defaultValue : result;
7695
+ }
7696
+
7697
+ function getAliasedValue(options, name, deprecatedName) {
7698
+ return options[name] === UNDEFINED_VALUE ? options[deprecatedName] : options[name];
7699
+ }
7700
+
7571
7701
  function getNumberOptionValue(zipWriter, options, name, defaultValue) {
7572
7702
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
7573
7703
  }
@@ -7580,6 +7710,12 @@ function getMaximumCompressedSize(uncompressedSize) {
7580
7710
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
7581
7711
  }
7582
7712
 
7713
+ function isCompressed(compressionMethod, level) {
7714
+ return compressionMethod === UNDEFINED_VALUE
7715
+ ? (level === UNDEFINED_VALUE || level > 0)
7716
+ : compressionMethod !== COMPRESSION_METHOD_STORE;
7717
+ }
7718
+
7583
7719
  function setUint8(view, offset, value) {
7584
7720
  view.setUint8(offset, value);
7585
7721
  }
@@ -8228,6 +8364,7 @@ setDefaultConfiguration({
8228
8364
 
8229
8365
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
8230
8366
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
8367
+ const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
8231
8368
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
8232
8369
  const ERR_ABORTED = "The operation was aborted";
8233
8370
  const ABORT_ERROR_NAME = "AbortError";
@@ -8265,6 +8402,7 @@ class ZipEntry {
8265
8402
  parent,
8266
8403
  children: [],
8267
8404
  uncompressedSize: params.uncompressedSize || 0,
8405
+ undeterminedSize: params.undeterminedSize || params.uncompressedSize === UNDEFINED_VALUE,
8268
8406
  passThrough: params.passThrough
8269
8407
  });
8270
8408
  if (parent || !fs.root) {
@@ -8332,16 +8470,17 @@ class ZipFileEntry extends ZipEntry {
8332
8470
 
8333
8471
  async getData(writer, options = {}) {
8334
8472
  const zipEntry = this;
8335
- if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data)) {
8473
+ if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data && keepsContentType(writer, zipEntry.data))) {
8336
8474
  return zipEntry.data;
8337
8475
  } else {
8338
8476
  const reader = zipEntry.reader = createReader(zipEntry.Reader, zipEntry.data, options);
8339
- const uncompressedSize = zipEntry.data ? zipEntry.data.uncompressedSize : reader.size;
8340
- await Promise.all([initStream(reader), initStream(writer, uncompressedSize)]);
8341
- const { readable } = reader;
8477
+ const dataSize = zipEntry.uncompressedSize || reader.size;
8478
+ await Promise.all([initStream(reader), initStream(writer, dataSize)]);
8342
8479
  const { signal } = options;
8480
+ const readable = createProgressReadable(zipEntry, reader, options, signal);
8481
+ const preventClose = !ownsWritable(writer) && Boolean(options.preventClose);
8343
8482
  zipEntry.uncompressedSize = reader.size;
8344
- await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
8483
+ await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal, preventClose, preventAbort: preventClose });
8345
8484
  return writer.getData ? writer.getData() : writer.writable;
8346
8485
  }
8347
8486
  }
@@ -8472,7 +8611,7 @@ class ZipDirectoryEntry extends ZipEntry {
8472
8611
  Reader: TextReader,
8473
8612
  Writer: TextWriter,
8474
8613
  options,
8475
- uncompressedSize: text.length
8614
+ uncompressedSize: getTextSize(text)
8476
8615
  });
8477
8616
  }
8478
8617
 
@@ -8601,10 +8740,16 @@ class ZipDirectoryEntry extends ZipEntry {
8601
8740
  }
8602
8741
 
8603
8742
  async importZip(reader, options = {}) {
8604
- await initStream(reader);
8605
- const zipReader = new ZipReader(reader, options);
8743
+ let zipReader;
8744
+ if (reader && typeof reader.getEntries == FUNCTION_TYPE) {
8745
+ zipReader = reader;
8746
+ options = Object.assign({}, zipReader.options, options);
8747
+ } else {
8748
+ await initStream(reader);
8749
+ zipReader = new ZipReader(reader, options);
8750
+ }
8606
8751
  const importedEntries = [];
8607
- const entries = await zipReader.getEntries();
8752
+ const entries = await zipReader.getEntries(options);
8608
8753
  for (const entry of entries) {
8609
8754
  let parent = this;
8610
8755
  try {
@@ -8626,7 +8771,7 @@ class ZipDirectoryEntry extends ZipEntry {
8626
8771
  importedEntries.push(addChild(parent, name, {
8627
8772
  data: entry,
8628
8773
  Reader: getZipBlobReader(Object.assign({}, options)),
8629
- uncompressedSize: entry.uncompressedSize,
8774
+ uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
8630
8775
  passThrough: options.passThrough
8631
8776
  }));
8632
8777
  } else {
@@ -8668,11 +8813,25 @@ class ZipDirectoryEntry extends ZipEntry {
8668
8813
  }
8669
8814
  const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
8670
8815
  const zipWriter = new ZipWriter(writer, options);
8671
- await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options, readers);
8672
- await zipWriter.close();
8816
+ await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
8817
+ await zipWriter.close(options.globalComment);
8673
8818
  return writer.getData ? writer.getData() : writer.writable;
8674
8819
  }
8675
8820
 
8821
+ getExportedSize(options = {}) {
8822
+ const zipEntry = this;
8823
+ options = Object.assign({}, options);
8824
+ if (options.bufferedWrite === UNDEFINED_VALUE) {
8825
+ options.bufferedWrite = true;
8826
+ }
8827
+ const writeOrderGuaranteed = !options.bufferedWrite ||
8828
+ (options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
8829
+ return getEntriesSize(options, Array.from(zipEntry.getChildren({ recursive: true }), child => {
8830
+ const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
8831
+ return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
8832
+ }), writeOrderGuaranteed, options.globalComment);
8833
+ }
8834
+
8676
8835
  getChildByName(name) {
8677
8836
  const children = this.children;
8678
8837
  for (let childIndex = 0; childIndex < children.length; childIndex++) {
@@ -8880,6 +9039,10 @@ class FS {
8880
9039
  return this.root.exportZip(writer, options);
8881
9040
  }
8882
9041
 
9042
+ getExportedSize(options) {
9043
+ return this.root.getExportedSize(options);
9044
+ }
9045
+
8883
9046
  isPasswordProtected() {
8884
9047
  return this.root.isPasswordProtected();
8885
9048
  }
@@ -8891,12 +9054,12 @@ class FS {
8891
9054
 
8892
9055
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
8893
9056
 
8894
- function getTotalSize(entries, propertyName) {
9057
+ function getTotalSize(entries, getEntrySize) {
8895
9058
  let size = 0;
8896
9059
  const pendingEntries = Array.from(entries);
8897
9060
  while (pendingEntries.length) {
8898
9061
  const entry = pendingEntries.pop();
8899
- size += entry[propertyName] || 0;
9062
+ size += getEntrySize(entry) || 0;
8900
9063
  for (const child of entry.children) {
8901
9064
  pendingEntries.push(child);
8902
9065
  }
@@ -8904,6 +9067,15 @@ function getTotalSize(entries, propertyName) {
8904
9067
  return size;
8905
9068
  }
8906
9069
 
9070
+ function getUncompressedSize(entry) {
9071
+ return entry.uncompressedSize;
9072
+ }
9073
+
9074
+ function getExtractedSize(entry, passThrough) {
9075
+ const { data } = entry;
9076
+ return passThrough && data instanceof Entry ? data.compressedSize : entry.uncompressedSize;
9077
+ }
9078
+
8907
9079
  function getReadableReader(readable) {
8908
9080
  let consumed;
8909
9081
  return function () {
@@ -8926,10 +9098,17 @@ function getZipBlobReader(options) {
8926
9098
 
8927
9099
  async init() {
8928
9100
  const zipBlobReader = this;
8929
- zipBlobReader.size = zipBlobReader.entry.uncompressedSize;
8930
- const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({}, options, zipBlobReader.options));
9101
+ const readerOptions = Object.assign({}, options, zipBlobReader.options);
9102
+ const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
9103
+ const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign(readerOptions, {
9104
+ checkPasswordOnly: false,
9105
+ checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
9106
+ checkOverlappingEntryOnly: false,
9107
+ preventClose: false
9108
+ }));
8931
9109
  zipBlobReader.data = data;
8932
9110
  zipBlobReader.blobReader = new BlobReader(data);
9111
+ zipBlobReader.size = data.size;
8933
9112
  super.init();
8934
9113
  }
8935
9114
 
@@ -8943,6 +9122,30 @@ function createReader(Reader, data, options) {
8943
9122
  return Reader.prototype ? new Reader(data, options) : Reader(data, options);
8944
9123
  }
8945
9124
 
9125
+ function keepsContentType(writer, data) {
9126
+ const { contentType } = writer;
9127
+ if (contentType === UNDEFINED_VALUE) {
9128
+ return true;
9129
+ } else if (writer.constructor == BlobWriter) {
9130
+ return data.type == contentType;
9131
+ } else if (writer.constructor == Data64URIWriter) {
9132
+ return data.startsWith(writer.data);
9133
+ } else {
9134
+ return true;
9135
+ }
9136
+ }
9137
+
9138
+ function createProgressReadable(zipEntry, reader, options, signal) {
9139
+ const { onstart, onprogress, onend } = options;
9140
+ const { readable } = reader;
9141
+ const coreReaderReportsProgress = zipEntry.data instanceof Entry;
9142
+ if (coreReaderReportsProgress || (!onstart && !onprogress && !onend)) {
9143
+ return readable;
9144
+ } else {
9145
+ return toCompatibleReadable(readable).pipeThrough(new ProgressWatcherStream({ onstart, onprogress, onend, size: reader.size }), { signal });
9146
+ }
9147
+ }
9148
+
8946
9149
  async function initReaders(entry, options) {
8947
9150
  const fileEntries = [];
8948
9151
  const pendingEntries = [entry];
@@ -8975,6 +9178,7 @@ async function initReaders(entry, options) {
8975
9178
  }
8976
9179
  if (reader.size !== UNDEFINED_VALUE) {
8977
9180
  child.uncompressedSize = reader.size;
9181
+ child.undeterminedSize = false;
8978
9182
  }
8979
9183
  }));
8980
9184
  return readers;
@@ -9024,6 +9228,90 @@ function aggregateEntryErrors(errors) {
9024
9228
  return error;
9025
9229
  }
9026
9230
 
9231
+ function getChildEntryOptions(child, selectedEntry, options) {
9232
+ const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
9233
+ const childOptions = child.options || {};
9234
+ let zipEntryMetadata = {};
9235
+ let passThroughOptions = {};
9236
+ if (child.data instanceof Entry) {
9237
+ const {
9238
+ externalFileAttributes,
9239
+ versionMadeBy,
9240
+ comment,
9241
+ lastModDate,
9242
+ creationDate,
9243
+ lastAccessDate,
9244
+ uncompressedSize,
9245
+ encrypted,
9246
+ zipCrypto,
9247
+ crc32,
9248
+ compressionMethod,
9249
+ extraFieldAES,
9250
+ internalFileAttributes,
9251
+ extraField,
9252
+ uid,
9253
+ gid
9254
+ } = child.data;
9255
+ zipEntryMetadata = {
9256
+ externalFileAttributes,
9257
+ versionMadeBy,
9258
+ comment,
9259
+ lastModDate,
9260
+ creationDate,
9261
+ lastAccessDate,
9262
+ internalFileAttributes
9263
+ };
9264
+ const userExtraField = getUserExtraField(extraField);
9265
+ if (userExtraField) {
9266
+ zipEntryMetadata.extraField = userExtraField;
9267
+ }
9268
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
9269
+ Object.assign(zipEntryMetadata, {
9270
+ uid,
9271
+ gid,
9272
+ unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
9273
+ });
9274
+ }
9275
+ if (isPassThrough(child, options)) {
9276
+ let level, encryptionStrength;
9277
+ if (compressionMethod === 0) {
9278
+ level = 0;
9279
+ }
9280
+ if (extraFieldAES) {
9281
+ encryptionStrength = extraFieldAES.strength;
9282
+ }
9283
+ passThroughOptions = {
9284
+ passThrough: true,
9285
+ encrypted,
9286
+ zipCrypto,
9287
+ crc32,
9288
+ uncompressedSize,
9289
+ level,
9290
+ encryptionStrength,
9291
+ compressionMethod
9292
+ };
9293
+ }
9294
+ }
9295
+ const entryOptions = Object.assign({}, zipEntryMetadata, options, passThroughOptions, childOptions, { directory: child.directory });
9296
+ if (!child.directory && entryOptions.passThrough && entryOptions.uncompressedSize === UNDEFINED_VALUE) {
9297
+ throw new Error(ERR_INVALID_PASS_THROUGH);
9298
+ }
9299
+ return { name, entryOptions };
9300
+ }
9301
+
9302
+ function getDeterminedSize(child, passThrough) {
9303
+ const { reader } = child;
9304
+ if (reader && reader.size !== UNDEFINED_VALUE) {
9305
+ return reader.size;
9306
+ }
9307
+ return child.undeterminedSize ? UNDEFINED_VALUE : getExtractedSize(child, passThrough);
9308
+ }
9309
+
9310
+ function isPassThrough(child, options) {
9311
+ const { readerOptions } = options;
9312
+ return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
9313
+ }
9314
+
9027
9315
  function getUserExtraField(extraField) {
9028
9316
  if (extraField) {
9029
9317
  const userExtraField = new Map();
@@ -9039,8 +9327,14 @@ function getUserExtraField(extraField) {
9039
9327
  }
9040
9328
 
9041
9329
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
9330
+ const { onstart, onprogress, onend, onentryprogress } = options;
9042
9331
  const selectedEntry = entry;
9043
- const entryOffsets = new Map();
9332
+ const totalEntries = getTotalSize(entry.children, () => 1);
9333
+ let writtenSize = 0;
9334
+ let writtenEntries = 0;
9335
+ if (onstart) {
9336
+ await callHandler(onstart, totalSize);
9337
+ }
9044
9338
  if (options.bufferedWrite) {
9045
9339
  await processChildren(entry);
9046
9340
  } else {
@@ -9048,6 +9342,9 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9048
9342
  await addChild(child);
9049
9343
  }
9050
9344
  }
9345
+ if (onend) {
9346
+ await callHandler(onend, writtenSize);
9347
+ }
9051
9348
 
9052
9349
  async function processChildren(entry) {
9053
9350
  const results = await Promise.allSettled(entry.children.map(async child => {
@@ -9061,81 +9358,23 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9061
9358
  }
9062
9359
 
9063
9360
  async function addChild(child) {
9064
- const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
9065
- const childOptions = child.options || {};
9066
- let zipEntryOptions = {};
9067
- if (child.data instanceof Entry) {
9068
- const {
9069
- externalFileAttributes,
9070
- versionMadeBy,
9071
- comment,
9072
- lastModDate,
9073
- creationDate,
9074
- lastAccessDate,
9075
- uncompressedSize,
9076
- encrypted,
9077
- zipCrypto,
9078
- crc32,
9079
- compressionMethod,
9080
- extraFieldAES,
9081
- internalFileAttributes,
9082
- extraField,
9083
- uid,
9084
- gid
9085
- } = child.data;
9086
- zipEntryOptions = {
9087
- externalFileAttributes,
9088
- versionMadeBy,
9089
- comment,
9090
- lastModDate,
9091
- creationDate,
9092
- lastAccessDate,
9093
- internalFileAttributes
9094
- };
9095
- const userExtraField = getUserExtraField(extraField);
9096
- if (userExtraField) {
9097
- zipEntryOptions.extraField = userExtraField;
9098
- }
9099
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
9100
- Object.assign(zipEntryOptions, {
9101
- uid,
9102
- gid,
9103
- unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
9104
- });
9105
- }
9106
- if (child.passThrough) {
9107
- let level, encryptionStrength;
9108
- if (compressionMethod === 0) {
9109
- level = 0;
9110
- }
9111
- if (extraFieldAES) {
9112
- encryptionStrength = extraFieldAES.strength;
9113
- }
9114
- zipEntryOptions = Object.assign(zipEntryOptions, {
9115
- passThrough: true,
9116
- encrypted,
9117
- zipCrypto,
9118
- crc32,
9119
- uncompressedSize,
9120
- level,
9121
- encryptionStrength,
9122
- compressionMethod
9123
- });
9124
- }
9125
- }
9126
- await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
9127
- directory: child.directory,
9361
+ const { name, entryOptions } = getChildEntryOptions(child, selectedEntry, options);
9362
+ let entryWrittenSize = 0;
9363
+ const entryMetadata = await zipWriter.add(name, readers.get(child), Object.assign(entryOptions, {
9364
+ onstart: UNDEFINED_VALUE,
9365
+ onend: UNDEFINED_VALUE,
9128
9366
  onprogress: async indexProgress => {
9129
- if (options.onprogress) {
9130
- entryOffsets.set(name, indexProgress);
9131
- try {
9132
- await options.onprogress(Array.from(entryOffsets.values()).reduce((previousValue, currentValue) => previousValue + currentValue), totalSize);
9133
- } catch {
9134
- // ignored
9135
- }
9367
+ writtenSize += indexProgress - entryWrittenSize;
9368
+ entryWrittenSize = indexProgress;
9369
+ if (onprogress) {
9370
+ await callHandler(onprogress, writtenSize, totalSize);
9136
9371
  }
9137
9372
  }
9138
9373
  }));
9374
+ writtenEntries++;
9375
+ if (onentryprogress) {
9376
+ await callHandler(onentryprogress, writtenEntries, totalEntries, entryMetadata);
9377
+ }
9139
9378
  }
9140
9379
  }
9141
9380
 
@@ -9163,7 +9402,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
9163
9402
  })
9164
9403
  );
9165
9404
  } else if (handle.kind == "directory") {
9166
- const directoryEntry = parentEntry.addDirectory(handle.name);
9405
+ const directoryEntry = parentEntry.addDirectory(handle.name, options);
9167
9406
  addedEntries.push(directoryEntry);
9168
9407
  for await (const childHandle of handle.values()) {
9169
9408
  await addFile(directoryEntry, childHandle, addedEntries, entryName);
@@ -9185,15 +9424,29 @@ function addFileSystemHandle(zipEntry, handle, options) {
9185
9424
  }
9186
9425
 
9187
9426
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9188
- const totalSize = getTotalSize([zipEntry], "uncompressedSize");
9189
- const writtenSizes = new Map();
9427
+ const { onstart, onprogress, onend } = options;
9190
9428
  const abortController = new AbortController();
9191
9429
  const { signal } = abortController;
9192
9430
  const releaseSignal = forwardAbort(options.signal, abortController);
9431
+ const getDataOptions = Object.assign({}, options, options.readerOptions, {
9432
+ signal,
9433
+ onstart: UNDEFINED_VALUE,
9434
+ onprogress: UNDEFINED_VALUE,
9435
+ onend: UNDEFINED_VALUE,
9436
+ preventClose: false
9437
+ });
9438
+ const totalSize = getTotalSize([zipEntry], entry => getExtractedSize(entry, getDataOptions.passThrough));
9193
9439
  const exportedEntryNames = [];
9194
9440
  let exportAborted = false;
9441
+ let writtenSize = 0;
9195
9442
  try {
9443
+ if (onstart) {
9444
+ await callHandler(onstart, totalSize);
9445
+ }
9196
9446
  await exportChildren(zipEntry, directoryHandle);
9447
+ if (onend) {
9448
+ await callHandler(onend, writtenSize);
9449
+ }
9197
9450
  } catch (error) {
9198
9451
  try {
9199
9452
  error.exportedEntryNames = exportedEntryNames;
@@ -9206,6 +9459,25 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9206
9459
  }
9207
9460
  return directoryHandle;
9208
9461
 
9462
+ function createProgressWritable(writable) {
9463
+ const writer = writable.getWriter();
9464
+ return new WritableStream({
9465
+ async write(chunk) {
9466
+ await writer.write(chunk);
9467
+ writtenSize += chunk.length;
9468
+ if (onprogress) {
9469
+ await callHandler(onprogress, writtenSize, totalSize);
9470
+ }
9471
+ },
9472
+ close() {
9473
+ return writer.close();
9474
+ },
9475
+ abort(reason) {
9476
+ return writer.abort(reason);
9477
+ }
9478
+ });
9479
+ }
9480
+
9209
9481
  async function exportChildren(entry, parentHandle) {
9210
9482
  if (options.concurrent) {
9211
9483
  const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
@@ -9237,19 +9509,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9237
9509
  const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
9238
9510
  const writable = await fileHandle.createWritable();
9239
9511
  try {
9240
- await child.getData({ writable }, Object.assign({}, options, {
9241
- signal,
9242
- onprogress: async progress => {
9243
- if (options.onprogress) {
9244
- writtenSizes.set(child.id, progress);
9245
- try {
9246
- await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
9247
- } catch {
9248
- // ignored
9249
- }
9250
- }
9251
- }
9252
- }));
9512
+ await child.getData({ writable: createProgressWritable(writable) }, getDataOptions);
9253
9513
  } catch (error) {
9254
9514
  throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
9255
9515
  }
@@ -9493,6 +9753,7 @@ exports.ERR_INVALID_MSDOS_ATTRIBUTES = ERR_INVALID_MSDOS_ATTRIBUTES;
9493
9753
  exports.ERR_INVALID_MSDOS_DATA = ERR_INVALID_MSDOS_DATA;
9494
9754
  exports.ERR_INVALID_PASSWORD = ERR_INVALID_PASSWORD;
9495
9755
  exports.ERR_INVALID_PASSWORD_TYPE = ERR_INVALID_PASSWORD_TYPE;
9756
+ exports.ERR_INVALID_PASS_THROUGH = ERR_INVALID_PASS_THROUGH;
9496
9757
  exports.ERR_INVALID_SIGNATURE = ERR_INVALID_SIGNATURE;
9497
9758
  exports.ERR_INVALID_SIGNATURE_DATA = ERR_INVALID_SIGNATURE_DATA;
9498
9759
  exports.ERR_INVALID_STRICTNESS = ERR_INVALID_STRICTNESS;
@@ -9510,11 +9771,13 @@ exports.ERR_RESERVED_COMPRESSION_METHOD = ERR_RESERVED_COMPRESSION_METHOD;
9510
9771
  exports.ERR_SPLIT_ZIP_FILE = ERR_SPLIT_ZIP_FILE;
9511
9772
  exports.ERR_UNDEFINED_READER = ERR_UNDEFINED_READER;
9512
9773
  exports.ERR_UNDEFINED_UNCOMPRESSED_SIZE = ERR_UNDEFINED_UNCOMPRESSED_SIZE;
9774
+ exports.ERR_UNDETERMINED_SIZE = ERR_UNDETERMINED_SIZE;
9513
9775
  exports.ERR_UNSAFE_FILENAME = ERR_UNSAFE_FILENAME;
9514
9776
  exports.ERR_UNSUPPORTED_COMPRESSION = ERR_UNSUPPORTED_COMPRESSION$1;
9515
9777
  exports.ERR_UNSUPPORTED_CONTEXT = ERR_UNSUPPORTED_CONTEXT;
9516
9778
  exports.ERR_UNSUPPORTED_CRYPTO_API = ERR_UNSUPPORTED_CRYPTO_API;
9517
9779
  exports.ERR_UNSUPPORTED_ENCRYPTION = ERR_UNSUPPORTED_ENCRYPTION;
9780
+ exports.ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH;
9518
9781
  exports.ERR_UNSUPPORTED_ENCRYPTION_USDZ = ERR_UNSUPPORTED_ENCRYPTION_USDZ;
9519
9782
  exports.ERR_UNSUPPORTED_FORMAT = ERR_UNSUPPORTED_FORMAT;
9520
9783
  exports.ERR_WORKER_STARTUP_TIMEOUT = ERR_WORKER_STARTUP_TIMEOUT;