@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.
@@ -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;
@@ -1806,8 +1808,6 @@ function getInt32(number) {
1806
1808
  */
1807
1809
 
1808
1810
 
1809
- const HTTP_HEADER_CONTENT_TYPE = "Content-Type";
1810
-
1811
1811
  function toCompatibleReadable(readable) {
1812
1812
  if (readable instanceof ReadableStream) {
1813
1813
  return readable;
@@ -1830,12 +1830,9 @@ function toCompatibleReadable(readable) {
1830
1830
 
1831
1831
  function streamToBlob(readable, contentType) {
1832
1832
  readable = toCompatibleReadable(readable);
1833
+ const blobOptions = contentType ? { type: contentType } : {};
1833
1834
  if (responseSupportsGlobalReadable()) {
1834
- const options = {};
1835
- if (contentType) {
1836
- options.headers = [[HTTP_HEADER_CONTENT_TYPE, contentType]];
1837
- }
1838
- return new Response(readable, options).blob();
1835
+ return new Response(readable).blob().then(blob => contentType ? new Blob([blob], blobOptions) : blob);
1839
1836
  }
1840
1837
  const chunks = [];
1841
1838
  return readable
@@ -1844,7 +1841,7 @@ function streamToBlob(readable, contentType) {
1844
1841
  chunks.push(chunk);
1845
1842
  }
1846
1843
  }))
1847
- .then(() => new Blob(chunks, contentType ? { type: contentType } : {}));
1844
+ .then(() => new Blob(chunks, blobOptions));
1848
1845
  }
1849
1846
 
1850
1847
  function responseSupportsGlobalReadable() {
@@ -3379,8 +3376,10 @@ class Reader extends Stream {
3379
3376
  async pull(controller) {
3380
3377
  const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
3381
3378
  const data = await readUint8Array(reader, offset + chunkOffset, dataSize);
3382
- controller.enqueue(data);
3383
- if ((chunkOffset + chunkSize > size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3379
+ if (data.length) {
3380
+ controller.enqueue(data);
3381
+ }
3382
+ if ((chunkOffset + chunkSize >= size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
3384
3383
  controller.close();
3385
3384
  } else {
3386
3385
  chunkOffset += chunkSize;
@@ -3458,6 +3457,7 @@ class Data64URIWriter extends Writer {
3458
3457
  constructor(contentType) {
3459
3458
  super();
3460
3459
  Object.assign(this, {
3460
+ contentType,
3461
3461
  data: "data:" + (contentType || "") + ";base64,",
3462
3462
  pending: []
3463
3463
  });
@@ -3559,6 +3559,7 @@ class BlobWriter extends Stream {
3559
3559
  return transformStream.writable;
3560
3560
  }
3561
3561
  });
3562
+ writer.contentType = contentType;
3562
3563
  writer.blob = streamToBlob(transformStream.readable, contentType);
3563
3564
  writer.blob.catch(() => { });
3564
3565
  }
@@ -3575,6 +3576,26 @@ class TextReader extends BlobReader {
3575
3576
  }
3576
3577
  }
3577
3578
 
3579
+ function getTextSize(text) {
3580
+ let size = 0;
3581
+ for (let indexCharacter = 0; indexCharacter < text.length; indexCharacter++) {
3582
+ const characterCode = text.charCodeAt(indexCharacter);
3583
+ if (characterCode < 0x80) {
3584
+ size += 1;
3585
+ } else if (characterCode < 0x800) {
3586
+ size += 2;
3587
+ } else if (characterCode < 0xd800 || characterCode >= 0xe000) {
3588
+ size += 3;
3589
+ } else if (characterCode < 0xdc00 && (text.charCodeAt(indexCharacter + 1) & 0xfc00) == 0xdc00) {
3590
+ size += 4;
3591
+ indexCharacter++;
3592
+ } else {
3593
+ size += 3;
3594
+ }
3595
+ }
3596
+ return size;
3597
+ }
3598
+
3578
3599
  class TextWriter extends BlobWriter {
3579
3600
 
3580
3601
  constructor(encoding) {
@@ -4238,6 +4259,10 @@ class GenericWriter {
4238
4259
  }
4239
4260
  }
4240
4261
 
4262
+ function ownsWritable(writer) {
4263
+ return Boolean(writer && writer.getData);
4264
+ }
4265
+
4241
4266
  function isHttpFamily(url) {
4242
4267
  const { baseURI } = getConfiguration();
4243
4268
  const { protocol } = new URL(url, baseURI);
@@ -4382,6 +4407,8 @@ const PROPERTY_NAME_CREATION_DATE = "creationDate";
4382
4407
  const PROPERTY_NAME_RAW_CREATION_DATE = "rawCreationDate";
4383
4408
  const PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES = "internalFileAttributes";
4384
4409
  const PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttributes";
4410
+ const PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES = "internalFileAttribute";
4411
+ const PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES = "externalFileAttribute";
4385
4412
  const PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW = "msdosAttributesRaw";
4386
4413
  const PROPERTY_NAME_MSDOS_ATTRIBUTES = "msdosAttributes";
4387
4414
  const PROPERTY_NAME_MS_DOS_COMPATIBLE = "msDosCompatible";
@@ -4392,6 +4419,7 @@ const PROPERTY_NAME_VERSION_MADE_BY = "versionMadeBy";
4392
4419
  const PROPERTY_NAME_ZIPCRYPTO = "zipCrypto";
4393
4420
  const PROPERTY_NAME_DIRECTORY = "directory";
4394
4421
  const PROPERTY_NAME_EXECUTABLE = "executable";
4422
+ const PROPERTY_NAME_SYMLINK = "symlink";
4395
4423
  const PROPERTY_NAME_COMPRESSION_METHOD = "compressionMethod";
4396
4424
  const PROPERTY_NAME_SIGNATURE = "signature";
4397
4425
  const PROPERTY_NAME_CRC32 = "crc32";
@@ -4435,6 +4463,8 @@ const PROPERTY_NAMES = [
4435
4463
  PROPERTY_NAME_DISK_NUMBER_START,
4436
4464
  PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
4437
4465
  PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
4466
+ PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES,
4467
+ PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES,
4438
4468
  PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW,
4439
4469
  PROPERTY_NAME_MSDOS_ATTRIBUTES,
4440
4470
  PROPERTY_NAME_MS_DOS_COMPATIBLE,
@@ -4445,6 +4475,7 @@ const PROPERTY_NAMES = [
4445
4475
  PROPERTY_NAME_ZIPCRYPTO,
4446
4476
  PROPERTY_NAME_DIRECTORY,
4447
4477
  PROPERTY_NAME_EXECUTABLE,
4478
+ PROPERTY_NAME_SYMLINK,
4448
4479
  PROPERTY_NAME_COMPRESSION_METHOD,
4449
4480
  PROPERTY_NAME_SIGNATURE,
4450
4481
  PROPERTY_NAME_CRC32,
@@ -4907,15 +4938,18 @@ class ZipReader {
4907
4938
  const setuid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETUID_MASK);
4908
4939
  const setgid = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_SETGID_MASK);
4909
4940
  const sticky = Boolean(fileEntry.unixMode & FILE_ATTR_UNIX_STICKY_MASK);
4910
- const executable = (fileEntry.unixMode !== UNDEFINED_VALUE)
4941
+ const unixType = fileEntry.unixMode === UNDEFINED_VALUE ? unixExternalUpper : fileEntry.unixMode;
4942
+ const symlink = (unixType & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK;
4943
+ const executable = !symlink && ((fileEntry.unixMode !== UNDEFINED_VALUE)
4911
4944
  ? ((fileEntry.unixMode & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)
4912
- : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0));
4945
+ : (unixCompatible && ((unixExternalUpper & FILE_ATTR_UNIX_EXECUTABLE_MASK) != 0)));
4913
4946
  const modeIsDir = fileEntry.unixMode !== UNDEFINED_VALUE && ((fileEntry.unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4914
4947
  const upperIsDir = ((unixExternalUpper & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_DIR);
4915
4948
  Object.assign(fileEntry, {
4916
4949
  setuid,
4917
4950
  setgid,
4918
4951
  sticky,
4952
+ symlink,
4919
4953
  unixExternalUpper,
4920
4954
  internalFileAttribute: fileEntry.internalFileAttributes,
4921
4955
  externalFileAttribute: fileEntry.externalFileAttributes,
@@ -4981,6 +5015,10 @@ class ZipReader {
4981
5015
  }
4982
5016
 
4983
5017
  async close() {
5018
+ const { reader } = this;
5019
+ if (!reader.readUint8Array && reader.readable && !reader.readable.locked) {
5020
+ await reader.readable.cancel();
5021
+ }
4984
5022
  }
4985
5023
  }
4986
5024
 
@@ -5205,7 +5243,7 @@ let ZipEntry$1 = class ZipEntry {
5205
5243
  throw error;
5206
5244
  }
5207
5245
  } finally {
5208
- const preventClose = getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5246
+ const preventClose = !ownsWritable(writer) && getOptionValue$1(zipEntry, options, OPTION_PREVENT_CLOSE);
5209
5247
  if (!preventClose && writable && !writable.locked) {
5210
5248
  const writableWriter = writable.getWriter();
5211
5249
  if (abortError) {
@@ -5449,8 +5487,8 @@ function readExtraFieldUnixDates(extraField, directory) {
5449
5487
  return;
5450
5488
  }
5451
5489
  const extraFieldView = getDataView(extraField.data);
5452
- const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
5453
- const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
5490
+ const lastAccessDate = new Date((getUint32(extraFieldView, 0) | 0) * 1000);
5491
+ const lastModDate = new Date((getUint32(extraFieldView, 4) | 0) * 1000);
5454
5492
  const extraFieldData = { lastAccessDate, lastModDate };
5455
5493
  if (extraField.data.length >= 12) {
5456
5494
  extraFieldData.uid = getUint16(extraFieldView, 8);
@@ -5881,6 +5919,7 @@ const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
5881
5919
  const ERR_INVALID_VERSION = "Version exceeds 65535";
5882
5920
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
5883
5921
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
5922
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
5884
5923
  const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
5885
5924
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
5886
5925
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
@@ -5890,6 +5929,7 @@ const MIN_NTFS_TIME = BigInt(0);
5890
5929
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
5891
5930
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
5892
5931
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
5932
+ const ERR_UNDETERMINED_SIZE = "Undetermined size";
5893
5933
  const ERR_UNDEFINED_READER = "Undefined reader";
5894
5934
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
5895
5935
  const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
@@ -6097,7 +6137,7 @@ class ZipWriter {
6097
6137
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6098
6138
  }
6099
6139
  await closeFile(zipWriter, comment, options);
6100
- const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6140
+ const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6101
6141
  if (!preventClose) {
6102
6142
  await writable.getWriter().close();
6103
6143
  }
@@ -6256,7 +6296,7 @@ function resolveAttributes(zipWriter, name, options) {
6256
6296
  if (versionMadeBy > MAX_16_BITS) {
6257
6297
  throw new Error(ERR_INVALID_VERSION);
6258
6298
  }
6259
- let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
6299
+ let externalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES);
6260
6300
  const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
6261
6301
  if (!externalFileAttributesProvided) {
6262
6302
  externalFileAttributes = 0;
@@ -6304,7 +6344,9 @@ function resolveAttributes(zipWriter, name, options) {
6304
6344
  }
6305
6345
  if (!externalFileAttributesProvided || unixModeProvided) {
6306
6346
  if (directory) {
6307
- unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
6347
+ unixMode = (unixMode & ~FILE_ATTR_UNIX_TYPE_MASK) | FILE_ATTR_UNIX_TYPE_DIR;
6348
+ } else if (!(unixMode & FILE_ATTR_UNIX_TYPE_MASK)) {
6349
+ unixMode |= FILE_ATTR_UNIX_TYPE_FILE;
6308
6350
  }
6309
6351
  externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
6310
6352
  }
@@ -6357,15 +6399,12 @@ function resolveMetadata(zipWriter, name, options) {
6357
6399
  const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6358
6400
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6359
6401
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6360
- const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
6402
+ const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
6361
6403
  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
- }
6404
+ const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
6405
+ const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
6406
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
6407
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
6369
6408
  }
6370
6409
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
6371
6410
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
@@ -6478,14 +6517,24 @@ function serializeExtraField(extraField) {
6478
6517
  }
6479
6518
 
6480
6519
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
6520
+ if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
6521
+ throw new Error(ERR_UNDEFINED_READER);
6522
+ }
6523
+ let contentSize;
6524
+ if (reader) {
6525
+ reader = new GenericReader(reader);
6526
+ await initStream(reader);
6527
+ ({ size: contentSize } = reader);
6528
+ }
6529
+ return Object.assign({ reader }, resolveEntrySizes(zipWriter, Boolean(reader), contentSize, metadata, options));
6530
+ }
6531
+
6532
+ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
6481
6533
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
6482
6534
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
6483
6535
  let maximumCompressedSize = 0;
6484
6536
  let uncompressedSize = 0;
6485
- if (passThrough) {
6486
- if (!reader) {
6487
- throw new Error(ERR_UNDEFINED_READER);
6488
- }
6537
+ if (passThrough && hasContent) {
6489
6538
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
6490
6539
  if (uncompressedSize === UNDEFINED_VALUE) {
6491
6540
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -6493,29 +6542,30 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6493
6542
  }
6494
6543
  const zip64Enabled = zip64 === true;
6495
6544
  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) {
6545
+ if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
6546
+ throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
6547
+ }
6548
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
6549
+ if (!hasContent) {
6498
6550
  level = 0;
6499
6551
  compressionMethod = COMPRESSION_METHOD_STORE;
6500
6552
  }
6501
6553
  const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
6502
- if (reader) {
6503
- reader = new GenericReader(reader);
6504
- await initStream(reader);
6554
+ if (hasContent) {
6505
6555
  if (!passThrough) {
6506
- if (reader.size === UNDEFINED_VALUE) {
6556
+ if (contentSize === UNDEFINED_VALUE) {
6507
6557
  dataDescriptor = true;
6508
6558
  if (zip64 || zip64 === UNDEFINED_VALUE) {
6509
6559
  zip64 = true;
6510
6560
  uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
6511
6561
  }
6512
6562
  } else {
6513
- options.uncompressedSize = uncompressedSize = reader.size;
6514
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6563
+ options.uncompressedSize = uncompressedSize = contentSize;
6564
+ maximumCompressedSize = (isCompressed(compressionMethod, level) ? getMaximumCompressedSize(uncompressedSize) : uncompressedSize) + encryptionOverhead;
6515
6565
  }
6516
6566
  } else {
6517
6567
  options.uncompressedSize = uncompressedSize;
6518
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
6568
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
6519
6569
  }
6520
6570
  }
6521
6571
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
@@ -6529,7 +6579,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6529
6579
  }
6530
6580
  zip64 = zip64 || false;
6531
6581
  return {
6532
- reader,
6582
+ maximumCompressedSize,
6533
6583
  resolvedOptions: {
6534
6584
  dataDescriptor,
6535
6585
  zip64,
@@ -6543,6 +6593,78 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
6543
6593
  };
6544
6594
  }
6545
6595
 
6596
+ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
6597
+ const zipWriter = { options: writerOptions, config: getConfiguration() };
6598
+ if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
6599
+ throw new Error(ERR_UNDETERMINED_SIZE);
6600
+ }
6601
+ const commentLength = getLength(comment);
6602
+ if (commentLength > MAX_16_BITS) {
6603
+ throw new Error(ERR_INVALID_COMMENT);
6604
+ }
6605
+ const usdz = writerOptions[OPTION_USDZ];
6606
+ const files = new Map();
6607
+ let layoutDependsOnWriteOrder = Boolean(usdz);
6608
+ let offset = 0;
6609
+ for (const entry of entries) {
6610
+ let { name } = entry;
6611
+ const { size } = entry;
6612
+ const options = Object.assign({}, entry.options);
6613
+ name = name.trim();
6614
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6615
+ name += DIRECTORY_SIGNATURE;
6616
+ }
6617
+ const attributesInfo = resolveAttributes(zipWriter, name, options);
6618
+ ({ name } = attributesInfo);
6619
+ const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
6620
+ if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
6621
+ !metadata.passThrough && !(await supportsDeflate(zipWriter.config))) {
6622
+ metadata.level = 0;
6623
+ }
6624
+ const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
6625
+ if (hasContent && size === UNDEFINED_VALUE) {
6626
+ throw new Error(ERR_UNDETERMINED_SIZE);
6627
+ }
6628
+ const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
6629
+ if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
6630
+ throw new Error(ERR_UNDETERMINED_SIZE);
6631
+ }
6632
+ const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes);
6633
+ const headerInfo = getHeaderInfo(entryOptions);
6634
+ const dataDescriptorInfo = getDataDescriptorInfo(entryOptions);
6635
+ const entryInfo = {
6636
+ headerInfo,
6637
+ metadataSize: getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray)
6638
+ };
6639
+ if (usdz) {
6640
+ appendExtraFieldUSDZ(entryInfo, offset);
6641
+ }
6642
+ const compressedSize = hasContent ? maximumCompressedSize : 0;
6643
+ if (offset >= MAX_32_BITS) {
6644
+ layoutDependsOnWriteOrder = true;
6645
+ }
6646
+ files.set(name, Object.assign({}, entryOptions, headerInfo, {
6647
+ offset,
6648
+ diskNumberStart: 0,
6649
+ compressedSize
6650
+ }));
6651
+ offset += entryInfo.metadataSize + compressedSize;
6652
+ }
6653
+ if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
6654
+ throw new Error(ERR_UNDETERMINED_SIZE);
6655
+ }
6656
+ const directoryDataLength = createDirectoryRecords(files);
6657
+ let zip64 = getOptionValue(zipWriter, writerOptions, PROPERTY_NAME_ZIP64);
6658
+ if (offset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || files.size >= MAX_16_BITS) {
6659
+ if (zip64 === false) {
6660
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
6661
+ } else {
6662
+ zip64 = true;
6663
+ }
6664
+ }
6665
+ return offset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
6666
+ }
6667
+
6546
6668
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6547
6669
  const {
6548
6670
  files,
@@ -6914,9 +7036,7 @@ function getHeaderInfo(options) {
6914
7036
  crc32
6915
7037
  } = options;
6916
7038
  let { version, compressionMethod } = options;
6917
- const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
6918
- ? (level === UNDEFINED_VALUE || level > 0)
6919
- : compressionMethod !== COMPRESSION_METHOD_STORE);
7039
+ const compressed = !directory && isCompressed(compressionMethod, level);
6920
7040
  let rawLocalExtraFieldZip64;
6921
7041
  const uncompressedFile = passThrough || !compressed;
6922
7042
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
@@ -7603,6 +7723,16 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
7603
7723
  return result === UNDEFINED_VALUE ? defaultValue : result;
7604
7724
  }
7605
7725
 
7726
+ function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
7727
+ const value = getAliasedValue(options, name, deprecatedName);
7728
+ const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
7729
+ return result === UNDEFINED_VALUE ? defaultValue : result;
7730
+ }
7731
+
7732
+ function getAliasedValue(options, name, deprecatedName) {
7733
+ return options[name] === UNDEFINED_VALUE ? options[deprecatedName] : options[name];
7734
+ }
7735
+
7606
7736
  function getNumberOptionValue(zipWriter, options, name, defaultValue) {
7607
7737
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
7608
7738
  }
@@ -7615,6 +7745,12 @@ function getMaximumCompressedSize(uncompressedSize) {
7615
7745
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
7616
7746
  }
7617
7747
 
7748
+ function isCompressed(compressionMethod, level) {
7749
+ return compressionMethod === UNDEFINED_VALUE
7750
+ ? (level === UNDEFINED_VALUE || level > 0)
7751
+ : compressionMethod !== COMPRESSION_METHOD_STORE;
7752
+ }
7753
+
7618
7754
  function setUint8(view, offset, value) {
7619
7755
  view.setUint8(offset, value);
7620
7756
  }
@@ -8600,6 +8736,7 @@ configureExternalAssets();
8600
8736
 
8601
8737
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
8602
8738
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
8739
+ const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
8603
8740
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
8604
8741
  const ERR_ABORTED = "The operation was aborted";
8605
8742
  const ABORT_ERROR_NAME = "AbortError";
@@ -8637,6 +8774,7 @@ class ZipEntry {
8637
8774
  parent,
8638
8775
  children: [],
8639
8776
  uncompressedSize: params.uncompressedSize || 0,
8777
+ undeterminedSize: params.undeterminedSize || params.uncompressedSize === UNDEFINED_VALUE,
8640
8778
  passThrough: params.passThrough
8641
8779
  });
8642
8780
  if (parent || !fs.root) {
@@ -8704,16 +8842,17 @@ class ZipFileEntry extends ZipEntry {
8704
8842
 
8705
8843
  async getData(writer, options = {}) {
8706
8844
  const zipEntry = this;
8707
- if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data)) {
8845
+ if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data && keepsContentType(writer, zipEntry.data))) {
8708
8846
  return zipEntry.data;
8709
8847
  } else {
8710
8848
  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;
8849
+ const dataSize = zipEntry.uncompressedSize || reader.size;
8850
+ await Promise.all([initStream(reader), initStream(writer, dataSize)]);
8714
8851
  const { signal } = options;
8852
+ const readable = createProgressReadable(zipEntry, reader, options, signal);
8853
+ const preventClose = !ownsWritable(writer) && Boolean(options.preventClose);
8715
8854
  zipEntry.uncompressedSize = reader.size;
8716
- await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
8855
+ await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal, preventClose, preventAbort: preventClose });
8717
8856
  return writer.getData ? writer.getData() : writer.writable;
8718
8857
  }
8719
8858
  }
@@ -8844,7 +8983,7 @@ class ZipDirectoryEntry extends ZipEntry {
8844
8983
  Reader: TextReader,
8845
8984
  Writer: TextWriter,
8846
8985
  options,
8847
- uncompressedSize: text.length
8986
+ uncompressedSize: getTextSize(text)
8848
8987
  });
8849
8988
  }
8850
8989
 
@@ -8973,10 +9112,16 @@ class ZipDirectoryEntry extends ZipEntry {
8973
9112
  }
8974
9113
 
8975
9114
  async importZip(reader, options = {}) {
8976
- await initStream(reader);
8977
- const zipReader = new ZipReader(reader, options);
9115
+ let zipReader;
9116
+ if (reader && typeof reader.getEntries == FUNCTION_TYPE) {
9117
+ zipReader = reader;
9118
+ options = Object.assign({}, zipReader.options, options);
9119
+ } else {
9120
+ await initStream(reader);
9121
+ zipReader = new ZipReader(reader, options);
9122
+ }
8978
9123
  const importedEntries = [];
8979
- const entries = await zipReader.getEntries();
9124
+ const entries = await zipReader.getEntries(options);
8980
9125
  for (const entry of entries) {
8981
9126
  let parent = this;
8982
9127
  try {
@@ -8998,7 +9143,7 @@ class ZipDirectoryEntry extends ZipEntry {
8998
9143
  importedEntries.push(addChild(parent, name, {
8999
9144
  data: entry,
9000
9145
  Reader: getZipBlobReader(Object.assign({}, options)),
9001
- uncompressedSize: entry.uncompressedSize,
9146
+ uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
9002
9147
  passThrough: options.passThrough
9003
9148
  }));
9004
9149
  } else {
@@ -9040,11 +9185,25 @@ class ZipDirectoryEntry extends ZipEntry {
9040
9185
  }
9041
9186
  const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
9042
9187
  const zipWriter = new ZipWriter(writer, options);
9043
- await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options, readers);
9044
- await zipWriter.close();
9188
+ await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
9189
+ await zipWriter.close(options.globalComment);
9045
9190
  return writer.getData ? writer.getData() : writer.writable;
9046
9191
  }
9047
9192
 
9193
+ getExportedSize(options = {}) {
9194
+ const zipEntry = this;
9195
+ options = Object.assign({}, options);
9196
+ if (options.bufferedWrite === UNDEFINED_VALUE) {
9197
+ options.bufferedWrite = true;
9198
+ }
9199
+ const writeOrderGuaranteed = !options.bufferedWrite ||
9200
+ (options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
9201
+ return getEntriesSize(options, Array.from(zipEntry.getChildren({ recursive: true }), child => {
9202
+ const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
9203
+ return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
9204
+ }), writeOrderGuaranteed, options.globalComment);
9205
+ }
9206
+
9048
9207
  getChildByName(name) {
9049
9208
  const children = this.children;
9050
9209
  for (let childIndex = 0; childIndex < children.length; childIndex++) {
@@ -9252,6 +9411,10 @@ class FS {
9252
9411
  return this.root.exportZip(writer, options);
9253
9412
  }
9254
9413
 
9414
+ getExportedSize(options) {
9415
+ return this.root.getExportedSize(options);
9416
+ }
9417
+
9255
9418
  isPasswordProtected() {
9256
9419
  return this.root.isPasswordProtected();
9257
9420
  }
@@ -9263,12 +9426,12 @@ class FS {
9263
9426
 
9264
9427
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
9265
9428
 
9266
- function getTotalSize(entries, propertyName) {
9429
+ function getTotalSize(entries, getEntrySize) {
9267
9430
  let size = 0;
9268
9431
  const pendingEntries = Array.from(entries);
9269
9432
  while (pendingEntries.length) {
9270
9433
  const entry = pendingEntries.pop();
9271
- size += entry[propertyName] || 0;
9434
+ size += getEntrySize(entry) || 0;
9272
9435
  for (const child of entry.children) {
9273
9436
  pendingEntries.push(child);
9274
9437
  }
@@ -9276,6 +9439,15 @@ function getTotalSize(entries, propertyName) {
9276
9439
  return size;
9277
9440
  }
9278
9441
 
9442
+ function getUncompressedSize(entry) {
9443
+ return entry.uncompressedSize;
9444
+ }
9445
+
9446
+ function getExtractedSize(entry, passThrough) {
9447
+ const { data } = entry;
9448
+ return passThrough && data instanceof Entry ? data.compressedSize : entry.uncompressedSize;
9449
+ }
9450
+
9279
9451
  function getReadableReader(readable) {
9280
9452
  let consumed;
9281
9453
  return function () {
@@ -9298,10 +9470,17 @@ function getZipBlobReader(options) {
9298
9470
 
9299
9471
  async init() {
9300
9472
  const zipBlobReader = this;
9301
- zipBlobReader.size = zipBlobReader.entry.uncompressedSize;
9302
- const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({}, options, zipBlobReader.options));
9473
+ const readerOptions = Object.assign({}, options, zipBlobReader.options);
9474
+ const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
9475
+ const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign(readerOptions, {
9476
+ checkPasswordOnly: false,
9477
+ checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
9478
+ checkOverlappingEntryOnly: false,
9479
+ preventClose: false
9480
+ }));
9303
9481
  zipBlobReader.data = data;
9304
9482
  zipBlobReader.blobReader = new BlobReader(data);
9483
+ zipBlobReader.size = data.size;
9305
9484
  super.init();
9306
9485
  }
9307
9486
 
@@ -9315,6 +9494,30 @@ function createReader(Reader, data, options) {
9315
9494
  return Reader.prototype ? new Reader(data, options) : Reader(data, options);
9316
9495
  }
9317
9496
 
9497
+ function keepsContentType(writer, data) {
9498
+ const { contentType } = writer;
9499
+ if (contentType === UNDEFINED_VALUE) {
9500
+ return true;
9501
+ } else if (writer.constructor == BlobWriter) {
9502
+ return data.type == contentType;
9503
+ } else if (writer.constructor == Data64URIWriter) {
9504
+ return data.startsWith(writer.data);
9505
+ } else {
9506
+ return true;
9507
+ }
9508
+ }
9509
+
9510
+ function createProgressReadable(zipEntry, reader, options, signal) {
9511
+ const { onstart, onprogress, onend } = options;
9512
+ const { readable } = reader;
9513
+ const coreReaderReportsProgress = zipEntry.data instanceof Entry;
9514
+ if (coreReaderReportsProgress || (!onstart && !onprogress && !onend)) {
9515
+ return readable;
9516
+ } else {
9517
+ return toCompatibleReadable(readable).pipeThrough(new ProgressWatcherStream({ onstart, onprogress, onend, size: reader.size }), { signal });
9518
+ }
9519
+ }
9520
+
9318
9521
  async function initReaders(entry, options) {
9319
9522
  const fileEntries = [];
9320
9523
  const pendingEntries = [entry];
@@ -9347,6 +9550,7 @@ async function initReaders(entry, options) {
9347
9550
  }
9348
9551
  if (reader.size !== UNDEFINED_VALUE) {
9349
9552
  child.uncompressedSize = reader.size;
9553
+ child.undeterminedSize = false;
9350
9554
  }
9351
9555
  }));
9352
9556
  return readers;
@@ -9396,6 +9600,90 @@ function aggregateEntryErrors(errors) {
9396
9600
  return error;
9397
9601
  }
9398
9602
 
9603
+ function getChildEntryOptions(child, selectedEntry, options) {
9604
+ const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
9605
+ const childOptions = child.options || {};
9606
+ let zipEntryMetadata = {};
9607
+ let passThroughOptions = {};
9608
+ if (child.data instanceof Entry) {
9609
+ const {
9610
+ externalFileAttributes,
9611
+ versionMadeBy,
9612
+ comment,
9613
+ lastModDate,
9614
+ creationDate,
9615
+ lastAccessDate,
9616
+ uncompressedSize,
9617
+ encrypted,
9618
+ zipCrypto,
9619
+ crc32,
9620
+ compressionMethod,
9621
+ extraFieldAES,
9622
+ internalFileAttributes,
9623
+ extraField,
9624
+ uid,
9625
+ gid
9626
+ } = child.data;
9627
+ zipEntryMetadata = {
9628
+ externalFileAttributes,
9629
+ versionMadeBy,
9630
+ comment,
9631
+ lastModDate,
9632
+ creationDate,
9633
+ lastAccessDate,
9634
+ internalFileAttributes
9635
+ };
9636
+ const userExtraField = getUserExtraField(extraField);
9637
+ if (userExtraField) {
9638
+ zipEntryMetadata.extraField = userExtraField;
9639
+ }
9640
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
9641
+ Object.assign(zipEntryMetadata, {
9642
+ uid,
9643
+ gid,
9644
+ unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
9645
+ });
9646
+ }
9647
+ if (isPassThrough(child, options)) {
9648
+ let level, encryptionStrength;
9649
+ if (compressionMethod === 0) {
9650
+ level = 0;
9651
+ }
9652
+ if (extraFieldAES) {
9653
+ encryptionStrength = extraFieldAES.strength;
9654
+ }
9655
+ passThroughOptions = {
9656
+ passThrough: true,
9657
+ encrypted,
9658
+ zipCrypto,
9659
+ crc32,
9660
+ uncompressedSize,
9661
+ level,
9662
+ encryptionStrength,
9663
+ compressionMethod
9664
+ };
9665
+ }
9666
+ }
9667
+ const entryOptions = Object.assign({}, zipEntryMetadata, options, passThroughOptions, childOptions, { directory: child.directory });
9668
+ if (!child.directory && entryOptions.passThrough && entryOptions.uncompressedSize === UNDEFINED_VALUE) {
9669
+ throw new Error(ERR_INVALID_PASS_THROUGH);
9670
+ }
9671
+ return { name, entryOptions };
9672
+ }
9673
+
9674
+ function getDeterminedSize(child, passThrough) {
9675
+ const { reader } = child;
9676
+ if (reader && reader.size !== UNDEFINED_VALUE) {
9677
+ return reader.size;
9678
+ }
9679
+ return child.undeterminedSize ? UNDEFINED_VALUE : getExtractedSize(child, passThrough);
9680
+ }
9681
+
9682
+ function isPassThrough(child, options) {
9683
+ const { readerOptions } = options;
9684
+ return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
9685
+ }
9686
+
9399
9687
  function getUserExtraField(extraField) {
9400
9688
  if (extraField) {
9401
9689
  const userExtraField = new Map();
@@ -9411,8 +9699,14 @@ function getUserExtraField(extraField) {
9411
9699
  }
9412
9700
 
9413
9701
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
9702
+ const { onstart, onprogress, onend, onentryprogress } = options;
9414
9703
  const selectedEntry = entry;
9415
- const entryOffsets = new Map();
9704
+ const totalEntries = getTotalSize(entry.children, () => 1);
9705
+ let writtenSize = 0;
9706
+ let writtenEntries = 0;
9707
+ if (onstart) {
9708
+ await callHandler(onstart, totalSize);
9709
+ }
9416
9710
  if (options.bufferedWrite) {
9417
9711
  await processChildren(entry);
9418
9712
  } else {
@@ -9420,6 +9714,9 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9420
9714
  await addChild(child);
9421
9715
  }
9422
9716
  }
9717
+ if (onend) {
9718
+ await callHandler(onend, writtenSize);
9719
+ }
9423
9720
 
9424
9721
  async function processChildren(entry) {
9425
9722
  const results = await Promise.allSettled(entry.children.map(async child => {
@@ -9433,81 +9730,23 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
9433
9730
  }
9434
9731
 
9435
9732
  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,
9733
+ const { name, entryOptions } = getChildEntryOptions(child, selectedEntry, options);
9734
+ let entryWrittenSize = 0;
9735
+ const entryMetadata = await zipWriter.add(name, readers.get(child), Object.assign(entryOptions, {
9736
+ onstart: UNDEFINED_VALUE,
9737
+ onend: UNDEFINED_VALUE,
9500
9738
  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
- }
9739
+ writtenSize += indexProgress - entryWrittenSize;
9740
+ entryWrittenSize = indexProgress;
9741
+ if (onprogress) {
9742
+ await callHandler(onprogress, writtenSize, totalSize);
9508
9743
  }
9509
9744
  }
9510
9745
  }));
9746
+ writtenEntries++;
9747
+ if (onentryprogress) {
9748
+ await callHandler(onentryprogress, writtenEntries, totalEntries, entryMetadata);
9749
+ }
9511
9750
  }
9512
9751
  }
9513
9752
 
@@ -9535,7 +9774,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
9535
9774
  })
9536
9775
  );
9537
9776
  } else if (handle.kind == "directory") {
9538
- const directoryEntry = parentEntry.addDirectory(handle.name);
9777
+ const directoryEntry = parentEntry.addDirectory(handle.name, options);
9539
9778
  addedEntries.push(directoryEntry);
9540
9779
  for await (const childHandle of handle.values()) {
9541
9780
  await addFile(directoryEntry, childHandle, addedEntries, entryName);
@@ -9557,15 +9796,29 @@ function addFileSystemHandle(zipEntry, handle, options) {
9557
9796
  }
9558
9797
 
9559
9798
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9560
- const totalSize = getTotalSize([zipEntry], "uncompressedSize");
9561
- const writtenSizes = new Map();
9799
+ const { onstart, onprogress, onend } = options;
9562
9800
  const abortController = new AbortController();
9563
9801
  const { signal } = abortController;
9564
9802
  const releaseSignal = forwardAbort(options.signal, abortController);
9803
+ const getDataOptions = Object.assign({}, options, options.readerOptions, {
9804
+ signal,
9805
+ onstart: UNDEFINED_VALUE,
9806
+ onprogress: UNDEFINED_VALUE,
9807
+ onend: UNDEFINED_VALUE,
9808
+ preventClose: false
9809
+ });
9810
+ const totalSize = getTotalSize([zipEntry], entry => getExtractedSize(entry, getDataOptions.passThrough));
9565
9811
  const exportedEntryNames = [];
9566
9812
  let exportAborted = false;
9813
+ let writtenSize = 0;
9567
9814
  try {
9815
+ if (onstart) {
9816
+ await callHandler(onstart, totalSize);
9817
+ }
9568
9818
  await exportChildren(zipEntry, directoryHandle);
9819
+ if (onend) {
9820
+ await callHandler(onend, writtenSize);
9821
+ }
9569
9822
  } catch (error) {
9570
9823
  try {
9571
9824
  error.exportedEntryNames = exportedEntryNames;
@@ -9578,6 +9831,25 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9578
9831
  }
9579
9832
  return directoryHandle;
9580
9833
 
9834
+ function createProgressWritable(writable) {
9835
+ const writer = writable.getWriter();
9836
+ return new WritableStream({
9837
+ async write(chunk) {
9838
+ await writer.write(chunk);
9839
+ writtenSize += chunk.length;
9840
+ if (onprogress) {
9841
+ await callHandler(onprogress, writtenSize, totalSize);
9842
+ }
9843
+ },
9844
+ close() {
9845
+ return writer.close();
9846
+ },
9847
+ abort(reason) {
9848
+ return writer.abort(reason);
9849
+ }
9850
+ });
9851
+ }
9852
+
9581
9853
  async function exportChildren(entry, parentHandle) {
9582
9854
  if (options.concurrent) {
9583
9855
  const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
@@ -9609,19 +9881,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
9609
9881
  const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
9610
9882
  const writable = await fileHandle.createWritable();
9611
9883
  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
- }));
9884
+ await child.getData({ writable: createProgressWritable(writable) }, getDataOptions);
9625
9885
  } catch (error) {
9626
9886
  throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
9627
9887
  }
@@ -9734,4 +9994,4 @@ function addChild(parent, name, params, directory) {
9734
9994
  }
9735
9995
  }
9736
9996
 
9737
- 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 };
9997
+ 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_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 };