@zip.js/zip.js 2.8.56 → 2.8.58

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.
@@ -92,6 +92,7 @@ const FILE_ATTR_UNIX_SETUID_MASK = 0o4000;
92
92
  const FILE_ATTR_UNIX_SETGID_MASK = 0o2000;
93
93
  const FILE_ATTR_UNIX_STICKY_MASK = 0o1000;
94
94
 
95
+ const VERSION_STORE = 0x0A;
95
96
  const VERSION_DEFLATE = 0x14;
96
97
  const VERSION_ZIP64 = 0x2D;
97
98
  const VERSION_AES = 0x33;
@@ -4738,6 +4739,7 @@ const ERR_UNSAFE_FILENAME = "Unsafe filename";
4738
4739
  const ERR_INVALID_STRICTNESS = "Invalid strictness (must be 'strict', 'balanced' or 'tolerant')";
4739
4740
  const ERR_INVALID_FILENAME_VALIDATION = "Invalid filenameValidation (must be 'strict', 'balanced' or 'tolerant')";
4740
4741
  const ERR_INVALID_MAX_APPENDED_DATA_SIZE = "Invalid maxAppendedDataSize (must be a number greater than or equal to 0)";
4742
+ const ERR_UNSUPPORTED_UINT64 = "64-bit value exceeds Number.MAX_SAFE_INTEGER";
4741
4743
  const DRIVE_LETTER_REGEXP = /^[a-zA-Z]:/;
4742
4744
  const CHARSET_UTF8 = "utf-8";
4743
4745
  const PROPERTY_NAME_UTF8_SUFFIX = "UTF8";
@@ -4760,6 +4762,7 @@ const ZIP64_EXTRACTION = {
4760
4762
  bytes: 8
4761
4763
  }
4762
4764
  };
4765
+ const MAX_SAFE_UINT64 = BigInt(Number.MAX_SAFE_INTEGER);
4763
4766
  const MAX_END_OF_CENTRAL_DIR_PROBES = 64;
4764
4767
  const MAX_DEFLATE_EXPANSION_RATIO = 1032;
4765
4768
  const CENTRAL_DIRECTORY_UNREACHABLE = 0;
@@ -4855,7 +4858,7 @@ class ZipReader {
4855
4858
  zip64EndOfDirectoryVersion2 = getBigUint64(endOfDirectoryView, 4) > ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12;
4856
4859
  if (zip64EndOfDirectoryVersion2) {
4857
4860
  const extensibleDataLength = Math.min(
4858
- Number(getBigUint64(endOfDirectoryView, 4)) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
4861
+ getBigUint64(endOfDirectoryView, 4) - (ZIP64_END_OF_CENTRAL_DIR_LENGTH - 12),
4859
4862
  reader.size - directoryDataOffset - ZIP64_END_OF_CENTRAL_DIR_LENGTH);
4860
4863
  if (extensibleDataLength > 0) {
4861
4864
  zip64EndOfDirectoryLength += extensibleDataLength;
@@ -4955,6 +4958,10 @@ class ZipReader {
4955
4958
  const commentEncoding = getOptionValue$1(zipReader, options, OPTION_COMMENT_ENCODING);
4956
4959
  const filenames = checkAmbiguity ? new Set() : UNDEFINED_VALUE;
4957
4960
  let duplicateFilename;
4961
+ const recoverWrappedFilesLength = !checkAmbiguity && !zip64EndOfDirectory;
4962
+ if (!filesLength && recoverWrappedFilesLength) {
4963
+ filesLength = getWrappedFilesLength(directoryView, directoryArray, offset);
4964
+ }
4958
4965
  for (let indexFile = 0; indexFile < filesLength; indexFile++) {
4959
4966
  const fileEntry = new ZipEntry(reader, zipReader.options);
4960
4967
  if (offset + CENTRAL_FILE_HEADER_LENGTH > directoryArray.length || getUint32$1(directoryView, offset) != CENTRAL_FILE_HEADER_SIGNATURE) {
@@ -5064,7 +5071,7 @@ class ZipReader {
5064
5071
  internalFileAttribute: fileEntry.internalFileAttributes,
5065
5072
  externalFileAttribute: fileEntry.externalFileAttributes,
5066
5073
  executable,
5067
- directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || (fileEntry.filename.endsWith(DIRECTORY_SIGNATURE) && !fileEntry.uncompressedSize),
5074
+ directory: modeIsDir || upperIsDir || (msDosCompatible && msdosAttributes.directory) || fileEntry.filename.endsWith(DIRECTORY_SIGNATURE),
5068
5075
  zipCrypto: fileEntry.encrypted && !fileEntry.extraFieldAES
5069
5076
  });
5070
5077
  const entry = new Entry(fileEntry);
@@ -5077,6 +5084,9 @@ class ZipReader {
5077
5084
  return arrayBufferPromise;
5078
5085
  };
5079
5086
  offset = endOffset;
5087
+ if (indexFile == filesLength - 1 && recoverWrappedFilesLength) {
5088
+ filesLength += getWrappedFilesLength(directoryView, directoryArray, offset);
5089
+ }
5080
5090
  const { onprogress } = options;
5081
5091
  if (onprogress) {
5082
5092
  try {
@@ -5235,6 +5245,7 @@ class ZipEntry {
5235
5245
  extraFieldLength,
5236
5246
  filenameLength
5237
5247
  } = localDirectory;
5248
+ const dataOffset = localDirectory.dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
5238
5249
  const checkLocalDirectoryOption = getOptionValue$1(zipEntry, options, OPTION_CHECK_LOCAL_DIRECTORY);
5239
5250
  const entryStrictness = getStrictness(options, zipEntry.options);
5240
5251
  const checkLocalDirectory = getCheckLocalDirectory(checkLocalDirectoryOption, entryStrictness);
@@ -5288,7 +5299,6 @@ class ZipEntry {
5288
5299
  throw new Error(ERR_ENCRYPTED);
5289
5300
  }
5290
5301
  }
5291
- const dataOffset = localHeaderOffset + HEADER_SIZE + filenameLength + extraFieldLength;
5292
5302
  if (dataOffset + compressedSize > reader.size) {
5293
5303
  throw new Error(ERR_ENTRY_DATA_OUT_OF_BOUNDS);
5294
5304
  }
@@ -5408,6 +5418,16 @@ function detectEncryptedCentralDirectory(directoryView) {
5408
5418
  return false;
5409
5419
  }
5410
5420
 
5421
+ function getWrappedFilesLength(directoryView, directoryArray, offset) {
5422
+ let wrappedFilesLength = 0;
5423
+ while (offset + CENTRAL_FILE_HEADER_LENGTH <= directoryArray.length && getUint32$1(directoryView, offset) == CENTRAL_FILE_HEADER_SIGNATURE) {
5424
+ offset += CENTRAL_FILE_HEADER_LENGTH +
5425
+ getUint16$1(directoryView, offset + 28) + getUint16$1(directoryView, offset + 30) + getUint16$1(directoryView, offset + 32);
5426
+ wrappedFilesLength++;
5427
+ }
5428
+ return wrappedFilesLength % (MAX_16_BITS + 1) ? 0 : wrappedFilesLength;
5429
+ }
5430
+
5411
5431
  function readDigitalSignature(signatureRecordArray) {
5412
5432
  if (signatureRecordArray.length >= 6) {
5413
5433
  const signatureRecordView = getDataView(signatureRecordArray);
@@ -5436,8 +5456,8 @@ function getDirectoryEncryptionInfo(rawExtensibleData) {
5436
5456
  const hashDataLength = getUint16$1(extensibleDataView, 26);
5437
5457
  Object.assign(directoryEncryptionInfo, {
5438
5458
  compressionMethod: getUint16$1(extensibleDataView, 0),
5439
- compressedSize: Number(getBigUint64(extensibleDataView, 2)),
5440
- uncompressedSize: Number(getBigUint64(extensibleDataView, 10)),
5459
+ compressedSize: getBigUint64(extensibleDataView, 2),
5460
+ uncompressedSize: getBigUint64(extensibleDataView, 10),
5441
5461
  encryptionAlgorithm: getUint16$1(extensibleDataView, 18),
5442
5462
  bitLength: getUint16$1(extensibleDataView, 20),
5443
5463
  flags: getUint16$1(extensibleDataView, 22),
@@ -5580,10 +5600,11 @@ function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName,
5580
5600
  const computedCrc32View = getDataView(new Uint8Array(4));
5581
5601
  computedCrc32View.setUint32(0, computedCrc32.get(), true);
5582
5602
  const nameCrc32 = getUint32$1(extraFieldView, 1);
5603
+ const version = getUint8(extraFieldView, 0);
5583
5604
  Object.assign(extraFieldUnicode, {
5584
- version: getUint8(extraFieldView, 0),
5605
+ version,
5585
5606
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
5586
- valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32$1(computedCrc32View, 0)
5607
+ valid: version == 1 && !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32$1(computedCrc32View, 0)
5587
5608
  });
5588
5609
  if (extraFieldUnicode.valid) {
5589
5610
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -6052,7 +6073,8 @@ function getFunctionOptionValue$1(zipReader, options, name) {
6052
6073
 
6053
6074
  function getDate(timeRaw) {
6054
6075
  const date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & MAX_16_BITS;
6055
- return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
6076
+ const result = new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5, (time & 0x001F) * 2, 0);
6077
+ return result < MIN_DATE ? MIN_DATE : result;
6056
6078
  }
6057
6079
 
6058
6080
  function getDateNTFS(timeRaw) {
@@ -6072,7 +6094,11 @@ function getUint32$1(view, offset) {
6072
6094
  }
6073
6095
 
6074
6096
  function getBigUint64(view, offset) {
6075
- return Number(view.getBigUint64(offset, true));
6097
+ const value = view.getBigUint64(offset, true);
6098
+ if (value > MAX_SAFE_UINT64) {
6099
+ throw new Error(ERR_UNSUPPORTED_UINT64);
6100
+ }
6101
+ return Number(value);
6076
6102
  }
6077
6103
 
6078
6104
  var zipReader = /*#__PURE__*/Object.freeze({
@@ -6101,6 +6127,7 @@ var zipReader = /*#__PURE__*/Object.freeze({
6101
6127
  ERR_UNSAFE_FILENAME: ERR_UNSAFE_FILENAME,
6102
6128
  ERR_UNSUPPORTED_COMPRESSION: ERR_UNSUPPORTED_COMPRESSION$1,
6103
6129
  ERR_UNSUPPORTED_ENCRYPTION: ERR_UNSUPPORTED_ENCRYPTION,
6130
+ ERR_UNSUPPORTED_UINT64: ERR_UNSUPPORTED_UINT64,
6104
6131
  ERR_WORKER_STARTUP_TIMEOUT: ERR_WORKER_STARTUP_TIMEOUT,
6105
6132
  ZipReader: ZipReader,
6106
6133
  ZipReaderStream: ZipReaderStream
@@ -6200,153 +6227,150 @@ class ZipWriter {
6200
6227
  offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
6201
6228
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
6202
6229
  pendingAddFileCalls: new Set(),
6230
+ pendingErrors: [],
6203
6231
  bufferedWrites: 0,
6204
6232
  lastFileEntry: UNDEFINED_VALUE
6205
6233
  });
6206
6234
  }
6207
6235
 
6208
- async prependZip(reader) {
6209
- if (this.filenames.size) {
6210
- throw new Error(ERR_ZIP_NOT_EMPTY);
6211
- }
6212
- reader = new GenericReader(reader);
6213
- await initStream(reader);
6214
- if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6215
- reader = new BlobReader(await streamToBlob(reader.readable));
6216
- await initStream(reader);
6217
- }
6218
- const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
6219
- const zipReader$1 = new ZipReader(reader);
6220
- const entries = await zipReader$1.getEntries();
6221
- await zipReader$1.close();
6222
- await initStream(this.writer);
6223
- const { directoryOffset } = zipReader$1;
6224
- if (this.addSplitZipSignature) {
6225
- delete this.addSplitZipSignature;
6226
- if (!await startsWithSplitZipSignature(reader)) {
6227
- await writeData(this.writer, getSplitZipSignatureArray());
6228
- this.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
6229
- }
6230
- }
6231
- const entryPositions = await copyZipData(this, reader, entries, directoryOffset);
6232
- this.filenames = new Set(entries.map(entry => entry.filename));
6233
- this.fileEntries = new Map(entries.map(entry => {
6234
- const {
6235
- version,
6236
- rawLastModDate,
6237
- lastAccessDate,
6238
- creationDate,
6239
- rawFilename,
6240
- bitFlag,
6241
- encrypted,
6242
- uncompressedSize,
6243
- compressedSize,
6244
- zip64
6245
- } = entry;
6246
- let {
6247
- compressionMethod,
6248
- rawExtraFieldZip64,
6249
- rawExtraFieldAES,
6250
- rawExtraFieldExtendedTimestamp,
6251
- rawExtraFieldNTFS,
6252
- rawExtraFieldUnix,
6253
- rawExtraField,
6254
- } = entry;
6255
- const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
6256
- rawExtraFieldZip64 = rawExtraFieldZip64 || EMPTY_UINT8_ARRAY;
6257
- rawExtraFieldAES = rawExtraFieldAES || EMPTY_UINT8_ARRAY;
6258
- rawExtraFieldExtendedTimestamp = rawExtraFieldExtendedTimestamp || EMPTY_UINT8_ARRAY;
6259
- rawExtraFieldNTFS = rawExtraFieldNTFS || EMPTY_UINT8_ARRAY;
6260
- rawExtraFieldUnix = rawExtraFieldUnix || EMPTY_UINT8_ARRAY;
6261
- rawExtraField = rawExtraField || EMPTY_UINT8_ARRAY;
6262
- if (entry.extraFieldAES) {
6263
- compressionMethod = COMPRESSION_METHOD_AES;
6264
- }
6265
- const extraFieldLength = getLength(rawExtraFieldZip64, rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
6266
- const zip64UncompressedSize = zip64 && uncompressedSize >= MAX_32_BITS;
6267
- const zip64CompressedSize = zip64 && compressedSize >= MAX_32_BITS;
6268
- const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
6269
- const {
6270
- headerArray,
6271
- headerView
6272
- } = getHeaderArrayData({
6273
- version,
6274
- bitFlag: bitFlagValue,
6275
- compressionMethod,
6276
- uncompressedSize,
6277
- compressedSize,
6278
- rawLastModDate,
6279
- rawFilename,
6280
- zip64CompressedSize,
6281
- zip64UncompressedSize,
6282
- extraFieldLength
6283
- });
6284
- const { crc32 } = entry;
6285
- if (crc32 !== UNDEFINED_VALUE) {
6286
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6287
- }
6288
- const { offset, diskNumberStart } = entryPositions.get(entry);
6289
- Object.assign(entry, {
6290
- zip64UncompressedSize,
6291
- zip64CompressedSize,
6292
- offset,
6293
- diskNumberStart,
6294
- zip64DiskNumberStart: false,
6295
- rawExtraFieldZip64,
6296
- rawExtraFieldAES,
6297
- rawExtraFieldExtendedTimestamp,
6298
- rawExtraFieldNTFS,
6299
- rawExtraFieldUnix,
6300
- rawExtraField,
6301
- extendedTimestamp: rawExtraFieldExtendedTimestamp.length > 0 || rawExtraFieldNTFS.length > 0,
6302
- extraFieldExtendedTimestampFlag: 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0),
6303
- headerArray,
6304
- headerView
6305
- });
6306
- return [entry.filename, entry];
6307
- }));
6236
+ prependZip(reader) {
6237
+ return watchPromiseError(this, prependZipEntries(this, reader));
6238
+ }
6239
+
6240
+ appendZip(reader) {
6241
+ return watchPromiseError(this, this.appendZipEntries(reader));
6308
6242
  }
6309
6243
 
6310
- async add(name = "", reader, options = {}) {
6244
+ async appendZipEntries(reader) {
6311
6245
  const zipWriter = this;
6312
- options = Object.assign({}, options);
6313
- const { pendingAddFileCalls } = zipWriter;
6314
- if (workers < getConfiguration().maxWorkers) {
6315
- workers++;
6316
- } else {
6317
- await new Promise(resolve => pendingEntries.push(resolve));
6246
+ const { pendingAddFileCalls, filenames, fileEntries } = zipWriter;
6247
+ while (pendingAddFileCalls.size) {
6248
+ await Promise.allSettled(Array.from(pendingAddFileCalls));
6318
6249
  }
6319
- let promiseAddFile;
6320
- let nameAdded;
6250
+ let resolveAppendZip;
6251
+ const promiseAppendZip = new Promise(resolve => resolveAppendZip = resolve);
6252
+ pendingAddFileCalls.add(promiseAppendZip);
6253
+ const appendedFilenames = [];
6254
+ let releaseLockWriter;
6321
6255
  try {
6322
- name = name.trim();
6323
- if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6324
- name += DIRECTORY_SIGNATURE;
6325
- }
6326
- if (zipWriter.filenames.has(name)) {
6327
- throw new Error(ERR_DUPLICATED_NAME);
6328
- }
6329
- zipWriter.filenames.add(name);
6330
- nameAdded = true;
6331
- promiseAddFile = addFile(zipWriter, name, reader, options);
6332
- pendingAddFileCalls.add(promiseAddFile);
6333
- return await promiseAddFile;
6334
- } catch (error) {
6335
- if (nameAdded) {
6336
- zipWriter.filenames.delete(name);
6256
+ reader = new GenericReader(reader);
6257
+ await initStream(reader);
6258
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
6259
+ reader = new BlobReader(await streamToBlob(reader.readable));
6260
+ await initStream(reader);
6261
+ }
6262
+ const { ZipReader } = await Promise.resolve().then(function () { return zipReader; });
6263
+ const zipReader$1 = new ZipReader(reader);
6264
+ const entries = await zipReader$1.getEntries();
6265
+ await zipReader$1.close();
6266
+ await initStream(zipWriter.writer);
6267
+ const { directoryOffset } = zipReader$1;
6268
+ entries.forEach(({ filename }) => {
6269
+ if (filenames.has(filename)) {
6270
+ throw new Error(ERR_DUPLICATED_NAME);
6271
+ }
6272
+ filenames.add(filename);
6273
+ appendedFilenames.push(filename);
6274
+ });
6275
+ zipWriter.writerLocked = true;
6276
+ const { lockWriter } = zipWriter;
6277
+ zipWriter.lockWriter = new Promise(resolve => releaseLockWriter = () => {
6278
+ zipWriter.writerLocked = false;
6279
+ resolve();
6280
+ });
6281
+ await lockWriter;
6282
+ if (zipWriter.addSplitZipSignature) {
6283
+ delete zipWriter.addSplitZipSignature;
6284
+ if (!await startsWithSplitZipSignature(reader)) {
6285
+ await writeData(zipWriter.writer, getSplitZipSignatureArray());
6286
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
6287
+ }
6337
6288
  }
6289
+ const entryPositions = await copyZipData(zipWriter, reader, entries, directoryOffset);
6290
+ entries.forEach(entry => {
6291
+ const {
6292
+ version,
6293
+ rawLastModDate,
6294
+ rawFilename,
6295
+ bitFlag,
6296
+ encrypted,
6297
+ uncompressedSize,
6298
+ compressedSize,
6299
+ extraFieldZip64
6300
+ } = entry;
6301
+ let {
6302
+ compressionMethod,
6303
+ rawExtraField,
6304
+ } = entry;
6305
+ const { level, languageEncodingFlag, dataDescriptor } = bitFlag;
6306
+ rawExtraField = removeExtraFieldZip64(rawExtraField || EMPTY_UINT8_ARRAY);
6307
+ if (entry.extraFieldAES) {
6308
+ compressionMethod = COMPRESSION_METHOD_AES;
6309
+ }
6310
+ const extraFieldLength = getLength(rawExtraField);
6311
+ const zip64UncompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.uncompressedSize !== UNDEFINED_VALUE;
6312
+ const zip64CompressedSize = Boolean(extraFieldZip64) && extraFieldZip64.compressedSize !== UNDEFINED_VALUE;
6313
+ const bitFlagValue = (getBitFlag(level, languageEncodingFlag, dataDescriptor, encrypted, compressionMethod) & ~BITFLAG_LEVEL) | (level << 1);
6314
+ const {
6315
+ headerArray,
6316
+ headerView
6317
+ } = getHeaderArrayData({
6318
+ version,
6319
+ bitFlag: bitFlagValue,
6320
+ compressionMethod,
6321
+ uncompressedSize,
6322
+ compressedSize,
6323
+ rawLastModDate,
6324
+ rawFilename,
6325
+ zip64CompressedSize,
6326
+ zip64UncompressedSize,
6327
+ extraFieldLength
6328
+ });
6329
+ const { crc32 } = entry;
6330
+ if (crc32 !== UNDEFINED_VALUE) {
6331
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
6332
+ }
6333
+ const { offset, diskNumberStart } = entryPositions.get(entry);
6334
+ Object.assign(entry, {
6335
+ zip64UncompressedSize,
6336
+ zip64CompressedSize,
6337
+ offset,
6338
+ diskNumberStart,
6339
+ zip64DiskNumberStart: false,
6340
+ rawExtraFieldZip64: EMPTY_UINT8_ARRAY,
6341
+ rawExtraFieldAES: EMPTY_UINT8_ARRAY,
6342
+ rawExtraFieldExtendedTimestamp: EMPTY_UINT8_ARRAY,
6343
+ rawExtraFieldNTFS: EMPTY_UINT8_ARRAY,
6344
+ rawExtraFieldUnix: EMPTY_UINT8_ARRAY,
6345
+ rawExtraField,
6346
+ extendedTimestamp: false,
6347
+ headerArray,
6348
+ headerView
6349
+ });
6350
+ fileEntries.set(entry.filename, entry);
6351
+ });
6352
+ } catch (error) {
6353
+ appendedFilenames.forEach(filename => filenames.delete(filename));
6338
6354
  throw error;
6339
6355
  } finally {
6340
- pendingAddFileCalls.delete(promiseAddFile);
6341
- const pendingEntry = pendingEntries.shift();
6342
- if (pendingEntry) {
6343
- pendingEntry();
6344
- } else {
6345
- workers--;
6356
+ resolveAppendZip();
6357
+ pendingAddFileCalls.delete(promiseAppendZip);
6358
+ if (releaseLockWriter) {
6359
+ releaseLockWriter();
6346
6360
  }
6347
6361
  }
6348
6362
  }
6349
6363
 
6364
+ add(name = "", reader, options = {}) {
6365
+ const zipWriter = this;
6366
+ const { pendingAddFileCalls } = zipWriter;
6367
+ const promiseAddFile = addFileEntry(zipWriter, name, reader, options);
6368
+ pendingAddFileCalls.add(promiseAddFile);
6369
+ const deletePendingAddFileCall = () => pendingAddFileCalls.delete(promiseAddFile);
6370
+ Promise.prototype.then.call(promiseAddFile, deletePendingAddFileCall, deletePendingAddFileCall);
6371
+ return watchPromiseError(zipWriter, promiseAddFile);
6372
+ }
6373
+
6350
6374
  remove(entry) {
6351
6375
  const { filenames, fileEntries } = this;
6352
6376
  // deno-lint-ignore valid-typeof
@@ -6377,6 +6401,19 @@ class ZipWriter {
6377
6401
  while (pendingAddFileCalls.size) {
6378
6402
  await Promise.allSettled(Array.from(pendingAddFileCalls));
6379
6403
  }
6404
+ await Promise.allSettled(zipWriter.pendingErrors.map(watcher => watcher.recorded));
6405
+ const unobservedWatchers = zipWriter.pendingErrors.filter(watcher => watcher.error && !watcher.observed);
6406
+ if (unobservedWatchers.length) {
6407
+ const unobservedErrors = unobservedWatchers.map(watcher => watcher.error);
6408
+ unobservedWatchers.forEach(watcher => watcher.observed = true);
6409
+ const [error] = unobservedErrors;
6410
+ try {
6411
+ error.entryErrors = unobservedErrors;
6412
+ } catch {
6413
+ // ignored
6414
+ }
6415
+ throw error;
6416
+ }
6380
6417
  await closeFile(zipWriter, comment, options);
6381
6418
  const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
6382
6419
  if (!preventClose) {
@@ -6411,11 +6448,7 @@ class ZipWriterStream {
6411
6448
  try {
6412
6449
  await zipWriter.close();
6413
6450
  } catch (error) {
6414
- try {
6415
- await zipWriter.writer.writable.abort(error);
6416
- } catch {
6417
- // ignored
6418
- }
6451
+ await abortWritable(zipWriter, error);
6419
6452
  }
6420
6453
  }
6421
6454
  }
@@ -6432,8 +6465,90 @@ class ZipWriterStream {
6432
6465
  }
6433
6466
 
6434
6467
  async close(comment = UNDEFINED_VALUE, options = {}) {
6435
- await Promise.all(Array.from(this.pendingAddFileCalls));
6436
- return this.zipWriter.close(comment, options);
6468
+ const { zipWriter } = this;
6469
+ const results = await Promise.allSettled(Array.from(this.pendingAddFileCalls));
6470
+ const entryErrors = results.filter(result => result.status == "rejected").map(result => result.reason);
6471
+ if (entryErrors.length) {
6472
+ const [error] = entryErrors;
6473
+ try {
6474
+ error.entryErrors = entryErrors;
6475
+ } catch {
6476
+ // ignored
6477
+ }
6478
+ await abortWritable(zipWriter, error);
6479
+ throw error;
6480
+ }
6481
+ try {
6482
+ return await zipWriter.close(comment, options);
6483
+ } catch (error) {
6484
+ await abortWritable(zipWriter, error);
6485
+ throw error;
6486
+ }
6487
+ }
6488
+ }
6489
+
6490
+ class WatchedPromise extends Promise {
6491
+
6492
+ then(onFulfilled, onRejected) {
6493
+ const { watcher } = this;
6494
+ if (watcher) {
6495
+ watcher.observed = true;
6496
+ }
6497
+ return super.then(onFulfilled, onRejected);
6498
+ }
6499
+ }
6500
+
6501
+ function watchPromiseError(zipWriter, promise) {
6502
+ const watchedPromise = new WatchedPromise((resolve, reject) => Promise.prototype.then.call(promise, resolve, reject));
6503
+ const watcher = {};
6504
+ watchedPromise.watcher = watcher;
6505
+ watcher.recorded = Promise.prototype.then.call(watchedPromise, UNDEFINED_VALUE, error => watcher.error = error);
6506
+ zipWriter.pendingErrors.push(watcher);
6507
+ return watchedPromise;
6508
+ }
6509
+
6510
+ async function prependZipEntries(zipWriter, reader) {
6511
+ if (zipWriter.filenames.size) {
6512
+ throw new Error(ERR_ZIP_NOT_EMPTY);
6513
+ }
6514
+ await zipWriter.appendZipEntries(reader);
6515
+ }
6516
+
6517
+ async function addFileEntry(zipWriter, name, reader, options) {
6518
+ options = Object.assign({}, options);
6519
+ name = name.trim();
6520
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
6521
+ name += DIRECTORY_SIGNATURE;
6522
+ }
6523
+ if (zipWriter.filenames.has(name)) {
6524
+ throw new Error(ERR_DUPLICATED_NAME);
6525
+ }
6526
+ zipWriter.filenames.add(name);
6527
+ if (workers < getConfiguration().maxWorkers) {
6528
+ workers++;
6529
+ } else {
6530
+ await new Promise(resolve => pendingEntries.push(resolve));
6531
+ }
6532
+ try {
6533
+ return await addFile(zipWriter, name, reader, options);
6534
+ } catch (error) {
6535
+ zipWriter.filenames.delete(name);
6536
+ throw error;
6537
+ } finally {
6538
+ const pendingEntry = pendingEntries.shift();
6539
+ if (pendingEntry) {
6540
+ pendingEntry();
6541
+ } else {
6542
+ workers--;
6543
+ }
6544
+ }
6545
+ }
6546
+
6547
+ async function abortWritable(zipWriter, error) {
6548
+ try {
6549
+ await zipWriter.writer.writable.abort(error);
6550
+ } catch {
6551
+ // ignored
6437
6552
  }
6438
6553
  }
6439
6554
 
@@ -6636,11 +6751,12 @@ function resolveMetadata(zipWriter, name, options) {
6636
6751
  if (getLength(rawComment) > MAX_16_BITS) {
6637
6752
  throw new Error(ERR_INVALID_ENTRY_COMMENT);
6638
6753
  }
6639
- const version = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION, VERSION_DEFLATE);
6640
- if (version > MAX_16_BITS) {
6754
+ const version = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION);
6755
+ if (version !== UNDEFINED_VALUE && version > MAX_16_BITS) {
6641
6756
  throw new Error(ERR_INVALID_VERSION);
6642
6757
  }
6643
6758
  const lastModDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
6759
+ const rawLastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_RAW_LAST_MODIFICATION_DATE);
6644
6760
  const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
6645
6761
  const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
6646
6762
  const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
@@ -6684,7 +6800,7 @@ function resolveMetadata(zipWriter, name, options) {
6684
6800
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
6685
6801
  dataDescriptor = false;
6686
6802
  }
6687
- if (dataDescriptor === UNDEFINED_VALUE || zipCrypto) {
6803
+ if (dataDescriptor === UNDEFINED_VALUE || (zipCrypto && !passThrough)) {
6688
6804
  dataDescriptor = true;
6689
6805
  }
6690
6806
  if (level !== UNDEFINED_VALUE && level != 6) {
@@ -6703,6 +6819,7 @@ function resolveMetadata(zipWriter, name, options) {
6703
6819
  rawComment,
6704
6820
  version,
6705
6821
  lastModDate,
6822
+ rawLastModDate,
6706
6823
  lastAccessDate,
6707
6824
  creationDate,
6708
6825
  internalFileAttributes,
@@ -6820,6 +6937,10 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
6820
6937
  maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
6821
6938
  }
6822
6939
  }
6940
+ const emptyEntry = !encryptedEntry && (!hasContent || (contentSize === 0 && !passThrough)) && !isCompressed(compressionMethod, level);
6941
+ if (emptyEntry && !zipCrypto && getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR) === UNDEFINED_VALUE) {
6942
+ dataDescriptor = false;
6943
+ }
6823
6944
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
6824
6945
  const zip64CompressedSize = zip64Enabled || maximumCompressedSize >= MAX_32_BITS;
6825
6946
  if (zip64UncompressedSize || zip64CompressedSize) {
@@ -6834,6 +6955,7 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
6834
6955
  maximumCompressedSize,
6835
6956
  resolvedOptions: {
6836
6957
  dataDescriptor,
6958
+ emptyEntry,
6837
6959
  zip64,
6838
6960
  zip64UncompressedSize,
6839
6961
  zip64CompressedSize,
@@ -6853,6 +6975,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6853
6975
  const {
6854
6976
  keepOrder,
6855
6977
  dataDescriptor,
6978
+ emptyEntry,
6856
6979
  signal
6857
6980
  } = options;
6858
6981
  const {
@@ -6877,7 +7000,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6877
7000
  lockPreviousFileEntry = previousFileEntry && previousFileEntry.lockFileEntry;
6878
7001
  requestLockCurrentFileEntry();
6879
7002
  }
6880
- if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
7003
+ if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || (!dataDescriptor && !emptyEntry)) {
6881
7004
  bufferedWrite = true;
6882
7005
  zipWriter.bufferedWrites++;
6883
7006
  if (options.createTempStream) {
@@ -6893,10 +7016,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6893
7016
  }
6894
7017
  await initStream(fileWriter);
6895
7018
  const diskOffset = getDiskOffset(writer);
6896
- if (zipWriter.addSplitZipSignature) {
6897
- delete zipWriter.addSplitZipSignature;
6898
- await writeData(writer, getSplitZipSignatureArray());
6899
- zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
7019
+ if (zipWriter.addSplitZipSignature && !bufferedWrite) {
7020
+ await writeSplitZipSignature(zipWriter, writer);
6900
7021
  }
6901
7022
  if (usdz && !bufferedWrite) {
6902
7023
  appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
@@ -6923,6 +7044,9 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
6923
7044
  if (bufferedWrite) {
6924
7045
  await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
6925
7046
  await requestLockWriter();
7047
+ if (zipWriter.addSplitZipSignature) {
7048
+ await writeSplitZipSignature(zipWriter, writer);
7049
+ }
6926
7050
  writingBufferedEntryData = true;
6927
7051
  writerSizeBeforeEntry = writer.size;
6928
7052
  await skipDiskIfNeeded();
@@ -7194,6 +7318,7 @@ function getHeaderInfo(options) {
7194
7318
  const {
7195
7319
  rawFilename,
7196
7320
  lastModDate,
7321
+ rawLastModDate: rawLastModDateOption,
7197
7322
  lastAccessDate,
7198
7323
  creationDate,
7199
7324
  level,
@@ -7299,8 +7424,8 @@ function getHeaderInfo(options) {
7299
7424
  try {
7300
7425
  const { uid, gid, unixExtraFieldType } = options;
7301
7426
  if (unixExtraFieldType == INFOZIP_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
7302
- const uidBytes = packUnixId(uid);
7303
- const gidBytes = packUnixId(gid);
7427
+ const uidBytes = packUnixId(uid === UNDEFINED_VALUE ? 0 : uid);
7428
+ const gidBytes = packUnixId(gid === UNDEFINED_VALUE ? 0 : gid);
7304
7429
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
7305
7430
  const extraFieldUnix = createRecordWriter(4 + payloadLength);
7306
7431
  extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_INFOZIP);
@@ -7327,6 +7452,9 @@ function getHeaderInfo(options) {
7327
7452
  if (compressionMethod === UNDEFINED_VALUE) {
7328
7453
  compressionMethod = compressed ? COMPRESSION_METHOD_DEFLATE : COMPRESSION_METHOD_STORE;
7329
7454
  }
7455
+ if (version === UNDEFINED_VALUE) {
7456
+ version = compressionMethod == COMPRESSION_METHOD_STORE && !directory && !encrypted ? VERSION_STORE : VERSION_DEFLATE;
7457
+ }
7330
7458
  const { codecVersionNeeded } = options;
7331
7459
  if (compressed && codecVersionNeeded !== UNDEFINED_VALUE) {
7332
7460
  version = version > codecVersionNeeded ? version : codecVersionNeeded;
@@ -7359,6 +7487,7 @@ function getHeaderInfo(options) {
7359
7487
  compressionMethod,
7360
7488
  uncompressedSize,
7361
7489
  lastModDate: dosLastModDate < MIN_DATE ? MIN_DATE : dosLastModDate > MAX_DATE ? MAX_DATE : dosLastModDate,
7490
+ rawLastModDate: rawLastModDateOption,
7362
7491
  rawFilename,
7363
7492
  zip64CompressedSize,
7364
7493
  zip64UncompressedSize,
@@ -7431,18 +7560,14 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
7431
7560
  }
7432
7561
 
7433
7562
  function packUnixId(id) {
7434
- if (id === UNDEFINED_VALUE) {
7435
- return EMPTY_UINT8_ARRAY;
7436
- } else {
7437
- const dataArray = new Uint8Array(4);
7438
- const dataView = getDataView(dataArray);
7439
- dataView.setUint32(0, id, true);
7440
- let length = 4;
7441
- while (length > 1 && dataArray[length - 1] === 0) {
7442
- length--;
7443
- }
7444
- return dataArray.subarray(0, length);
7563
+ const dataArray = new Uint8Array(4);
7564
+ const dataView = getDataView(dataArray);
7565
+ dataView.setUint32(0, id, true);
7566
+ let length = 4;
7567
+ while (length > 1 && dataArray[length - 1] === 0) {
7568
+ length--;
7445
7569
  }
7570
+ return dataArray.subarray(0, length);
7446
7571
  }
7447
7572
 
7448
7573
  function normalizeMsdosAttributes(msdosAttributesRaw, msdosAttributes) {
@@ -7569,9 +7694,9 @@ function updateLocalHeader({
7569
7694
 
7570
7695
  async function closeFile(zipWriter, comment, options) {
7571
7696
  const directoryDataLength = createDirectoryRecords(zipWriter.fileEntries);
7572
- const { directoryStart, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7697
+ const { directoryStart, directoryEnd, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
7573
7698
  const signatureLength = await writeDigitalSignatureRecord(zipWriter, directoryArray, options);
7574
- await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength, signatureLength });
7699
+ await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryEnd, directoryDataLength, signatureLength });
7575
7700
  }
7576
7701
 
7577
7702
  function createDirectoryRecords(files) {
@@ -7655,6 +7780,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7655
7780
  let directoryDiskOffset = 0;
7656
7781
  let directoryStartDiskNumber = getDiskNumber(writer);
7657
7782
  let directoryStartDiskOffset = getDiskOffset(writer);
7783
+ let directoryEndDiskEntriesLength = 0;
7658
7784
  for (const [indexFileEntry, fileEntry] of Array.from(fileEntries.values()).entries()) {
7659
7785
  const {
7660
7786
  offset: fileEntryOffset,
@@ -7684,6 +7810,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7684
7810
  if (exceedsAvailableSize(writer, offset + directoryRecordLength - directoryDiskOffset)) {
7685
7811
  await writeData(writer, directoryArray.slice(directoryDiskOffset, offset));
7686
7812
  directoryDiskOffset = offset;
7813
+ directoryEndDiskEntriesLength = 0;
7687
7814
  await writer.closeDisk();
7688
7815
  }
7689
7816
  if (indexFileEntry == 0) {
@@ -7719,6 +7846,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7719
7846
  directoryRecord.writeBytes(rawComment);
7720
7847
  arraySet(directoryArray, directoryRecord.array, offset);
7721
7848
  offset += directoryRecordLength;
7849
+ directoryEndDiskEntriesLength++;
7722
7850
  if (options.onprogress) {
7723
7851
  try {
7724
7852
  await options.onprogress(indexFileEntry + 1, fileEntries.size, new Entry(fileEntry));
@@ -7730,6 +7858,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
7730
7858
  await writeData(writer, directoryDiskOffset ? directoryArray.slice(directoryDiskOffset) : directoryArray);
7731
7859
  return {
7732
7860
  directoryStart: { diskNumber: directoryStartDiskNumber, diskOffset: directoryStartDiskOffset },
7861
+ directoryEnd: { diskNumber: getDiskNumber(writer), entriesLength: directoryEndDiskEntriesLength },
7733
7862
  directoryArray
7734
7863
  };
7735
7864
  }
@@ -7758,16 +7887,20 @@ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
7758
7887
 
7759
7888
  async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7760
7889
  const { writer } = zipWriter;
7761
- const { directoryStart, signatureLength } = cdInfo;
7890
+ const { directoryStart, directoryEnd, signatureLength } = cdInfo;
7762
7891
  let { directoryDataLength } = cdInfo;
7763
7892
  let fileEntriesLength = zipWriter.fileEntries.size;
7764
7893
  let diskNumber = directoryStart.diskNumber;
7765
7894
  let directoryOffset = getSegmentOffset(zipWriter, directoryStart);
7895
+ const commentLength = getLength(comment);
7896
+ if (commentLength > MAX_16_BITS) {
7897
+ throw new Error(ERR_INVALID_COMMENT);
7898
+ }
7899
+ let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
7766
7900
  let lastDiskNumber = getDiskNumber(writer);
7767
- if (exceedsAvailableSize(writer, END_OF_CENTRAL_DIR_LENGTH)) {
7901
+ if (exceedsAvailableSize(writer, (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH) + commentLength)) {
7768
7902
  lastDiskNumber++;
7769
7903
  }
7770
- let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
7771
7904
  if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || fileEntriesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
7772
7905
  if (zip64 === false) {
7773
7906
  throw new Error(ERR_UNSUPPORTED_FORMAT);
@@ -7775,15 +7908,12 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7775
7908
  zip64 = true;
7776
7909
  }
7777
7910
  }
7778
- const commentLength = getLength(comment);
7779
- if (commentLength > MAX_16_BITS) {
7780
- throw new Error(ERR_INVALID_COMMENT);
7781
- }
7782
7911
  const endOfdirectoryRecord = createRecordWriter(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
7783
7912
  if (exceedsAvailableSize(writer, getLength(endOfdirectoryRecord.array) + commentLength)) {
7784
7913
  await writer.closeDisk();
7785
7914
  }
7786
7915
  lastDiskNumber = getDiskNumber(writer);
7916
+ let diskFileEntriesLength = lastDiskNumber == directoryEnd.diskNumber ? directoryEnd.entriesLength : 0;
7787
7917
  if (zip64) {
7788
7918
  endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
7789
7919
  endOfdirectoryRecord.writeUint64(44);
@@ -7791,7 +7921,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7791
7921
  endOfdirectoryRecord.writeUint16(45);
7792
7922
  endOfdirectoryRecord.writeUint32(lastDiskNumber);
7793
7923
  endOfdirectoryRecord.writeUint32(diskNumber);
7794
- endOfdirectoryRecord.writeUint64(fileEntriesLength);
7924
+ endOfdirectoryRecord.writeUint64(diskFileEntriesLength);
7795
7925
  endOfdirectoryRecord.writeUint64(fileEntriesLength);
7796
7926
  endOfdirectoryRecord.writeUint64(directoryDataLength);
7797
7927
  endOfdirectoryRecord.writeUint64(directoryOffset);
@@ -7804,6 +7934,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7804
7934
  lastDiskNumber = MAX_16_BITS;
7805
7935
  diskNumber = MAX_16_BITS;
7806
7936
  }
7937
+ diskFileEntriesLength = MAX_16_BITS;
7807
7938
  fileEntriesLength = MAX_16_BITS;
7808
7939
  directoryOffset = MAX_32_BITS;
7809
7940
  directoryDataLength = MAX_32_BITS;
@@ -7811,7 +7942,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
7811
7942
  endOfdirectoryRecord.writeUint32(END_OF_CENTRAL_DIR_SIGNATURE);
7812
7943
  endOfdirectoryRecord.writeUint16(lastDiskNumber);
7813
7944
  endOfdirectoryRecord.writeUint16(diskNumber);
7814
- endOfdirectoryRecord.writeUint16(fileEntriesLength);
7945
+ endOfdirectoryRecord.writeUint16(diskFileEntriesLength);
7815
7946
  endOfdirectoryRecord.writeUint16(fileEntriesLength);
7816
7947
  endOfdirectoryRecord.writeUint32(directoryDataLength);
7817
7948
  endOfdirectoryRecord.writeUint32(directoryOffset);
@@ -7861,6 +7992,21 @@ async function startsWithSplitZipSignature(reader) {
7861
7992
  return getUint32(getDataView(signatureArray), 0) == SPLIT_ZIP_FILE_SIGNATURE;
7862
7993
  }
7863
7994
 
7995
+ function removeExtraFieldZip64(rawExtraField) {
7996
+ const rawExtraFieldView = getDataView(rawExtraField);
7997
+ let offsetExtraField = 0;
7998
+ while (offsetExtraField + 4 <= getLength(rawExtraField)) {
7999
+ const size = 4 + getUint16(rawExtraFieldView, offsetExtraField + 2);
8000
+ if (getUint16(rawExtraFieldView, offsetExtraField) == EXTRAFIELD_TYPE_ZIP64) {
8001
+ return removeExtraFieldZip64(concat(
8002
+ rawExtraField.subarray(0, offsetExtraField),
8003
+ rawExtraField.subarray(Math.min(offsetExtraField + size, getLength(rawExtraField)))));
8004
+ }
8005
+ offsetExtraField += size;
8006
+ }
8007
+ return rawExtraField;
8008
+ }
8009
+
7864
8010
  async function copyZipData(zipWriter, reader, entries, directoryOffset) {
7865
8011
  const { writer } = zipWriter;
7866
8012
  const entryPositions = new Map();
@@ -7895,9 +8041,21 @@ async function copyZipData(zipWriter, reader, entries, directoryOffset) {
7895
8041
  async function copyData(zipWriter, reader, offset, size) {
7896
8042
  if (size > 0) {
7897
8043
  const { writer } = zipWriter;
7898
- await createReadable(reader, { offset, size }).pipeTo(writer.writable, { preventClose: true, preventAbort: true });
7899
- writer.size += size;
7900
- zipWriter.offset += size;
8044
+ let copiedLength = 0;
8045
+ try {
8046
+ await flushBufferedData(createReadable(reader, { offset, size }), writer, UNDEFINED_VALUE, chunkLength => copiedLength += chunkLength);
8047
+ } catch (error) {
8048
+ zipWriter.hasCorruptedEntries = true;
8049
+ try {
8050
+ error.corruptedEntry = true;
8051
+ } catch {
8052
+ // ignored
8053
+ }
8054
+ throw error;
8055
+ } finally {
8056
+ writer.size += copiedLength;
8057
+ zipWriter.offset += copiedLength;
8058
+ }
7901
8059
  }
7902
8060
  }
7903
8061
 
@@ -7922,6 +8080,12 @@ function getSplitZipSignatureArray() {
7922
8080
  return signatureArray;
7923
8081
  }
7924
8082
 
8083
+ async function writeSplitZipSignature(zipWriter, writer) {
8084
+ delete zipWriter.addSplitZipSignature;
8085
+ await writeData(writer, getSplitZipSignatureArray());
8086
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
8087
+ }
8088
+
7925
8089
  async function writeData(writer, array) {
7926
8090
  const { writable } = writer;
7927
8091
  const streamWriter = writable.getWriter();
@@ -8975,4 +9139,4 @@ function terminateWorkersAndModule() {
8975
9139
 
8976
9140
  configureExternalAssets();
8977
9141
 
8978
- export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_SIGNAL, 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_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION$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, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };
9142
+ export { BlobReader, BlobWriter, Data64URIReader, Data64URIWriter, ERR_AMBIGUOUS_ARCHIVE, ERR_BAD_FORMAT, ERR_CENTRAL_DIRECTORY_NOT_FOUND, ERR_DUPLICATED_NAME, ERR_ENCRYPTED, ERR_ENCRYPTED_CENTRAL_DIRECTORY, ERR_ENTRY_DATA_OUT_OF_BOUNDS, ERR_EOCDR_LOCATOR_ZIP64_NOT_FOUND, ERR_EOCDR_NOT_FOUND, ERR_EXTRAFIELD_ZIP64_NOT_FOUND, ERR_HTTP_RANGE, ERR_HTTP_RESOURCE_CHANGED, ERR_INVALID_AUTHENTICATION_CODE, ERR_INVALID_CODEC_DEFINITION, ERR_INVALID_CODEC_MODULE, ERR_INVALID_COMMENT, ERR_INVALID_COMMENT_TYPE, ERR_INVALID_COMPRESSED_DATA, ERR_INVALID_CRC32, ERR_INVALID_DATE, ERR_INVALID_ENCRYPTION_STRENGTH, ERR_INVALID_ENTRY_COMMENT, ERR_INVALID_ENTRY_COMMENT_TYPE, ERR_INVALID_ENTRY_NAME, ERR_INVALID_EXTRAFIELD, ERR_INVALID_EXTRAFIELD_DATA, ERR_INVALID_EXTRAFIELD_DATA_TYPE, ERR_INVALID_EXTRAFIELD_TYPE, ERR_INVALID_FILENAME_VALIDATION, ERR_INVALID_FUNCTION_OPTION, ERR_INVALID_GID, ERR_INVALID_LEVEL, ERR_INVALID_MAX_APPENDED_DATA_SIZE, ERR_INVALID_MAX_WORKERS, ERR_INVALID_MSDOS_ATTRIBUTES, ERR_INVALID_MSDOS_DATA, ERR_INVALID_PASSWORD, ERR_INVALID_PASSWORD_TYPE, ERR_INVALID_SIGNAL, 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_RESERVED_COMPRESSION_METHOD, ERR_SPLIT_ZIP_FILE, ERR_UNDEFINED_COMPRESSION_METHOD, ERR_UNDEFINED_READER, ERR_UNDEFINED_UNCOMPRESSED_SIZE, ERR_UNDETERMINED_SIZE, ERR_UNSAFE_FILENAME, ERR_UNSUPPORTED_COMPRESSION$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_UNSUPPORTED_UINT64, 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, getMimeType, registerCodec, resetConfiguration, terminateWorkersAndModule as terminateWorkers, unregisterCodec };