@zip.js/zip.js 2.8.53 → 2.8.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +1 -1
  2. package/deno.json +2 -1
  3. package/dist/zip-core-external.js +737 -491
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +745 -490
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +776 -525
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +738 -510
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +776 -525
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +790 -525
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +791 -526
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +746 -491
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +746 -491
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip-web-worker-native.js +1 -1
  22. package/dist/zip-web-worker.js +1 -1
  23. package/dist/zip.js +747 -492
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +1 -0
  26. package/index-native.cjs +790 -525
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +791 -526
  29. package/index.d.cts +422 -49
  30. package/index.d.ts +422 -49
  31. package/index.min.js +1 -1
  32. package/lib/core/configuration.js +62 -21
  33. package/lib/core/constants.js +13 -1
  34. package/lib/core/io.js +33 -27
  35. package/lib/core/options.js +44 -2
  36. package/lib/core/streams/aes-crypto-stream.js +12 -12
  37. package/lib/core/util/decode-text.js +11 -2
  38. package/lib/core/web-worker-base.js +3 -2
  39. package/lib/core/web-worker-inline-native.js +1 -1
  40. package/lib/core/web-worker-inline-wasm.js +1 -1
  41. package/lib/core/zip-fs.js +39 -32
  42. package/lib/core/zip-reader.js +100 -38
  43. package/lib/core/zip-writer.js +301 -177
  44. package/lib/core/zlib-streams-inline.js +1 -1
  45. package/lib/zip-core-base.js +6 -1
  46. package/lib/zip-core-reader.js +1 -0
  47. package/lib/zip-core-writer.js +5 -0
  48. package/package.json +8 -2
@@ -53,10 +53,10 @@
53
53
  *
54
54
  * Scheduling:
55
55
  * - The central directory order (i.e. the order in which entries are listed by getEntries()) is
56
- * the insertion order of the `files` map. addFile() reserves each entry's slot synchronously in
56
+ * the insertion order of the `fileEntries` map. addFile() reserves each entry's slot synchronously in
57
57
  * add() call order, before initializing the reader, so concurrent entries whose readers
58
58
  * initialize at different speeds are still listed in call order.
59
- * - `fileEntry.lock` chains every entry to the previous one to reach getFileEntry(); awaiting it
59
+ * - `fileEntry.lockFileEntry` chains every entry to the previous one to reach getFileEntry(); awaiting it
60
60
  * serializes the physical writes when `keepOrder` is set. The physical layout therefore follows
61
61
  * the order in which the readers finish initializing, not necessarily the central directory
62
62
  * order; each entry records its own `offset`, so the archive stays consistent either way.
@@ -86,6 +86,7 @@ import {
86
86
  COMPRESSION_METHOD_STORE,
87
87
  COMPRESSION_METHOD_AES,
88
88
  SPLIT_ZIP_FILE_SIGNATURE,
89
+ SPLIT_ZIP_FILE_SIGNATURE_LENGTH,
89
90
  LOCAL_FILE_HEADER_SIGNATURE,
90
91
  DATA_DESCRIPTOR_RECORD_SIGNATURE,
91
92
  DIGITAL_SIGNATURE_RECORD_SIGNATURE,
@@ -139,6 +140,8 @@ import {
139
140
  HEADER_OFFSET_SIGNATURE,
140
141
  HEADER_OFFSET_COMPRESSED_SIZE,
141
142
  HEADER_OFFSET_UNCOMPRESSED_SIZE,
143
+ HEADER_OFFSET_FILENAME_LENGTH,
144
+ HEADER_OFFSET_EXTRAFIELD_LENGTH,
142
145
  LOCAL_HEADER_COMMON_OFFSET,
143
146
  MIN_DATE,
144
147
  MAX_DATE,
@@ -146,6 +149,7 @@ import {
146
149
  INFINITY_VALUE,
147
150
  OBJECT_TYPE,
148
151
  STRING_TYPE,
152
+ FUNCTION_TYPE,
149
153
  EMPTY_UINT8_ARRAY
150
154
  } from "./constants.js";
151
155
  import { getConfiguration } from "./configuration.js";
@@ -158,6 +162,8 @@ import {
158
162
  } from "./codec-pool.js";
159
163
  import {
160
164
  initStream,
165
+ createReadable,
166
+ readUint8Array,
161
167
  GenericWriter,
162
168
  GenericReader,
163
169
  BlobReader,
@@ -224,19 +230,28 @@ import {
224
230
  OPTION_LOCAL_EXTRA_FIELD,
225
231
  OPTION_SIGN_CENTRAL_DIRECTORY,
226
232
  TEXT_TYPE_FILENAME,
227
- TEXT_TYPE_COMMENT
233
+ TEXT_TYPE_COMMENT,
234
+ ERR_INVALID_PASSWORD_TYPE,
235
+ checkFunctionOption,
236
+ checkSignalOption,
237
+ checkPasswordOption,
238
+ toNumber
228
239
  } from "./options.js";
229
240
 
230
241
  const ERR_DUPLICATED_NAME = "File already exists";
231
242
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
232
243
  const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
233
244
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
245
+ const ERR_INVALID_ENTRY_COMMENT_TYPE = "Invalid file entry comment (must be a string)";
246
+ const ERR_INVALID_DATE = "Invalid date (must be a valid Date instance)";
234
247
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
235
248
  const ERR_INVALID_VERSION = "Version exceeds 65535";
236
249
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
237
250
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
238
251
  const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
239
- const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
252
+ const ERR_INVALID_EXTRAFIELD = "Invalid extra field (must be a Map)";
253
+ const ERR_INVALID_EXTRAFIELD_TYPE = "Invalid extra field type (must be integer 0..65535)";
254
+ const ERR_INVALID_EXTRAFIELD_DATA_TYPE = "Invalid extra field data (must be a Uint8Array)";
240
255
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
241
256
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
242
257
  const MIN_UNIX_TIME = -2147483648;
@@ -245,6 +260,7 @@ const MIN_NTFS_TIME = BigInt(0);
245
260
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
246
261
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
247
262
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
263
+ const ERR_UNDEFINED_COMPRESSION_METHOD = "Undefined compression method";
248
264
  const ERR_UNDETERMINED_SIZE = "Undetermined size";
249
265
  const ERR_UNDEFINED_READER = "Undefined reader";
250
266
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
@@ -256,7 +272,6 @@ const ERR_INVALID_UNIX_ID_SIZE = "uid/gid must be 0..65535 for unixExtraFieldTyp
256
272
  const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be integer 0..255)";
257
273
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
258
274
  const ERR_INVALID_LEVEL = "Invalid level (must be integer 0..9)";
259
- const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
260
275
  const ERR_INVALID_SIGNATURE_DATA = "Signature data exceeds 64KB";
261
276
 
262
277
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
@@ -281,8 +296,7 @@ class ZipWriter {
281
296
  writer,
282
297
  addSplitZipSignature,
283
298
  options,
284
- config: getConfiguration(),
285
- files: new Map(),
299
+ fileEntries: new Map(),
286
300
  filenames: new Set(),
287
301
  offset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? writer.size || writer.writable.size || 0 : options[OPTION_OFFSET],
288
302
  initialOffset: options[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : options[OPTION_OFFSET] - (writer.size || writer.writable.size || 0),
@@ -303,14 +317,23 @@ class ZipWriter {
303
317
  await initStream(reader);
304
318
  }
305
319
  const { ZipReader } = await import("./zip-reader.js");
306
- const zipReader = new ZipReader(reader.readable);
320
+ const zipReader = new ZipReader(reader);
307
321
  const entries = await zipReader.getEntries();
308
322
  await zipReader.close();
309
323
  await initStream(this.writer);
310
- await reader.readable.pipeTo(this.writer.writable, { preventClose: true, preventAbort: true });
311
- this.writer.size = this.offset = reader.size;
324
+ const { directoryOffset } = zipReader;
325
+ let splitZipSignatureLength = 0;
326
+ if (this.addSplitZipSignature) {
327
+ delete this.addSplitZipSignature;
328
+ if (!await startsWithSplitZipSignature(reader)) {
329
+ await writeData(this.writer, getSplitZipSignatureArray());
330
+ splitZipSignatureLength = SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
331
+ this.offset += splitZipSignatureLength;
332
+ }
333
+ }
334
+ const entryPositions = await copyZipData(this, reader, entries, directoryOffset, splitZipSignatureLength);
312
335
  this.filenames = new Set(entries.map(entry => entry.filename));
313
- this.files = new Map(entries.map(entry => {
336
+ this.fileEntries = new Map(entries.map(entry => {
314
337
  const {
315
338
  version,
316
339
  rawLastModDate,
@@ -365,11 +388,12 @@ class ZipWriter {
365
388
  if (crc32 !== UNDEFINED_VALUE) {
366
389
  setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
367
390
  }
391
+ const { offset, diskNumberStart } = entryPositions.get(entry);
368
392
  Object.assign(entry, {
369
393
  zip64UncompressedSize,
370
394
  zip64CompressedSize,
371
- zip64Offset: zip64 && entry.offset >= MAX_32_BITS,
372
- diskNumberStart: 0,
395
+ offset,
396
+ diskNumberStart,
373
397
  zip64DiskNumberStart: false,
374
398
  rawExtraFieldZip64,
375
399
  rawExtraFieldAES,
@@ -389,11 +413,8 @@ class ZipWriter {
389
413
  async add(name = "", reader, options = {}) {
390
414
  const zipWriter = this;
391
415
  options = Object.assign({}, options);
392
- const {
393
- pendingAddFileCalls,
394
- config
395
- } = zipWriter;
396
- if (workers < config.maxWorkers) {
416
+ const { pendingAddFileCalls } = zipWriter;
417
+ if (workers < getConfiguration().maxWorkers) {
397
418
  workers++;
398
419
  } else {
399
420
  await new Promise(resolve => pendingEntries.push(resolve));
@@ -430,16 +451,16 @@ class ZipWriter {
430
451
  }
431
452
 
432
453
  remove(entry) {
433
- const { filenames, files } = this;
454
+ const { filenames, fileEntries } = this;
434
455
  // deno-lint-ignore valid-typeof
435
456
  if (typeof entry == STRING_TYPE) {
436
- entry = files.get(entry);
457
+ entry = fileEntries.get(entry);
437
458
  }
438
459
  if (entry && entry.filename !== UNDEFINED_VALUE) {
439
460
  const { filename } = entry;
440
- if (filenames.has(filename) && files.has(filename)) {
461
+ if (filenames.has(filename) && fileEntries.has(filename)) {
441
462
  filenames.delete(filename);
442
- files.delete(filename);
463
+ fileEntries.delete(filename);
443
464
  return true;
444
465
  }
445
466
  }
@@ -539,14 +560,19 @@ export {
539
560
  ERR_INVALID_COMMENT_TYPE,
540
561
  ERR_INVALID_ENTRY_NAME,
541
562
  ERR_INVALID_ENTRY_COMMENT,
563
+ ERR_INVALID_ENTRY_COMMENT_TYPE,
564
+ ERR_INVALID_DATE,
542
565
  ERR_INVALID_VERSION,
566
+ ERR_INVALID_EXTRAFIELD,
543
567
  ERR_INVALID_EXTRAFIELD_TYPE,
568
+ ERR_INVALID_EXTRAFIELD_DATA_TYPE,
544
569
  ERR_INVALID_EXTRAFIELD_DATA,
545
570
  ERR_INVALID_ENCRYPTION_STRENGTH,
546
571
  ERR_UNSUPPORTED_ENCRYPTION_USDZ,
547
572
  ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH,
548
573
  ERR_UNSUPPORTED_FORMAT,
549
574
  ERR_UNDEFINED_UNCOMPRESSED_SIZE,
575
+ ERR_UNDEFINED_COMPRESSION_METHOD,
550
576
  ERR_UNDETERMINED_SIZE,
551
577
  ERR_UNDEFINED_READER,
552
578
  ERR_ZIP_NOT_EMPTY,
@@ -569,12 +595,12 @@ async function addFile(zipWriter, name, reader, options) {
569
595
  const metadataInfo = resolveMetadata(zipWriter, name, options);
570
596
  const { comment } = metadataInfo;
571
597
  const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
572
- zipWriter.files.set(name, UNDEFINED_VALUE);
598
+ zipWriter.fileEntries.set(name, UNDEFINED_VALUE);
573
599
  let fileEntry;
574
600
  try {
575
601
  const { resolvedOptions } = metadataInfo;
576
602
  if (resolvedOptions.level != 0 && resolvedOptions.compressionMethod === UNDEFINED_VALUE &&
577
- !resolvedOptions.passThrough && !(await supportsDeflate(zipWriter.config))) {
603
+ !resolvedOptions.passThrough && !(await supportsDeflate(getConfiguration()))) {
578
604
  resolvedOptions.level = 0;
579
605
  }
580
606
  const sizesInfo = await resolveSizes(zipWriter, reader, metadataInfo, options);
@@ -592,7 +618,7 @@ async function addFile(zipWriter, name, reader, options) {
592
618
  const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
593
619
  fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo, metadataSize }, options);
594
620
  } catch (error) {
595
- zipWriter.files.delete(name);
621
+ zipWriter.fileEntries.delete(name);
596
622
  throw error;
597
623
  }
598
624
  Object.assign(fileEntry, {
@@ -636,9 +662,9 @@ function resolveAttributes(zipWriter, name, options) {
636
662
  if (unixExtraFieldType === UNDEFINED_VALUE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
637
663
  unixExtraFieldType = INFOZIP_EXTRA_FIELD_TYPE;
638
664
  }
639
- let msdosAttributesRaw = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
665
+ let msdosAttributesRaw = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES_RAW);
640
666
  let msdosAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_MSDOS_ATTRIBUTES);
641
- const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType;
667
+ const hasUnixMetadata = uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE || unixMode !== UNDEFINED_VALUE || unixExtraFieldType || executable;
642
668
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
643
669
  if (hasUnixMetadata) {
644
670
  msDosCompatible = false;
@@ -647,10 +673,10 @@ function resolveAttributes(zipWriter, name, options) {
647
673
  msDosCompatible = true;
648
674
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
649
675
  }
650
- if (msdosAttributesRaw !== UNDEFINED_VALUE && (msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
676
+ if (msdosAttributesRaw !== UNDEFINED_VALUE && (!Number.isInteger(msdosAttributesRaw) || msdosAttributesRaw < 0 || msdosAttributesRaw > MAX_8_BITS)) {
651
677
  throw new Error(ERR_INVALID_MSDOS_ATTRIBUTES);
652
678
  }
653
- if (msdosAttributes && typeof msdosAttributes !== OBJECT_TYPE) {
679
+ if (msdosAttributes && (typeof msdosAttributes !== OBJECT_TYPE || Array.isArray(msdosAttributes))) {
654
680
  throw new Error(ERR_INVALID_MSDOS_DATA);
655
681
  }
656
682
  if (versionMadeBy > MAX_16_BITS) {
@@ -738,7 +764,7 @@ function resolveAttributes(zipWriter, name, options) {
738
764
  }
739
765
 
740
766
  function resolveMetadata(zipWriter, name, options) {
741
- const encode = getOptionValue(zipWriter, options, OPTION_ENCODE_TEXT, encodeText);
767
+ const encode = getFunctionOptionValue(zipWriter, options, OPTION_ENCODE_TEXT) || encodeText;
742
768
  let rawFilename = encode(name, TEXT_TYPE_FILENAME);
743
769
  if (rawFilename === UNDEFINED_VALUE) {
744
770
  rawFilename = encodeText(name);
@@ -747,6 +773,10 @@ function resolveMetadata(zipWriter, name, options) {
747
773
  throw new Error(ERR_INVALID_ENTRY_NAME);
748
774
  }
749
775
  const comment = options[PROPERTY_NAME_COMMENT] || "";
776
+ // deno-lint-ignore valid-typeof
777
+ if (typeof comment != STRING_TYPE) {
778
+ throw new Error(ERR_INVALID_ENTRY_COMMENT_TYPE);
779
+ }
750
780
  let rawComment = encode(comment, TEXT_TYPE_COMMENT);
751
781
  if (rawComment === UNDEFINED_VALUE) {
752
782
  rawComment = encodeText(comment);
@@ -758,16 +788,14 @@ function resolveMetadata(zipWriter, name, options) {
758
788
  if (version > MAX_16_BITS) {
759
789
  throw new Error(ERR_INVALID_VERSION);
760
790
  }
761
- const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
762
- const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
763
- const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
791
+ const lastModDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
792
+ const lastAccessDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
793
+ const creationDate = getDateOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
764
794
  const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
765
795
  const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
766
796
  const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
767
797
  const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
768
- if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
769
- throw new Error(ERR_INVALID_PASSWORD_TYPE);
770
- }
798
+ checkPasswordOption(password, rawPassword);
771
799
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
772
800
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
773
801
  const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
@@ -776,9 +804,9 @@ function resolveMetadata(zipWriter, name, options) {
776
804
  const useWebWorkers = getOptionValue(zipWriter, options, OPTION_USE_WEB_WORKERS);
777
805
  const transferStreams = getOptionValue(zipWriter, options, OPTION_TRANSFER_STREAMS);
778
806
  const bufferedWrite = getOptionValue(zipWriter, options, OPTION_BUFFERED_WRITE);
779
- const createTempStream = getOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
807
+ const createTempStream = getFunctionOptionValue(zipWriter, options, OPTION_CREATE_TEMP_STREAM);
780
808
  const dataDescriptorSignature = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR_SIGNATURE, true);
781
- const signal = getOptionValue(zipWriter, options, OPTION_SIGNAL);
809
+ const signal = checkSignalOption(getOptionValue(zipWriter, options, OPTION_SIGNAL));
782
810
  const useUnicodeFileNames = getOptionValue(zipWriter, options, OPTION_USE_UNICODE_FILE_NAMES, true);
783
811
  const compressionMethod = getOptionValue(zipWriter, options, PROPERTY_NAME_COMPRESSION_METHOD);
784
812
  const registeredCodec = passThrough || compressionMethod === UNDEFINED_VALUE ? UNDEFINED_VALUE : getRegisteredCodec(compressionMethod);
@@ -798,6 +826,9 @@ function resolveMetadata(zipWriter, name, options) {
798
826
  level = 0;
799
827
  }
800
828
  }
829
+ if (passThrough) {
830
+ level = UNDEFINED_VALUE;
831
+ }
801
832
  let useCompressionStream = getOptionValue(zipWriter, options, OPTION_USE_COMPRESSION_STREAM);
802
833
  let dataDescriptor = getOptionValue(zipWriter, options, OPTION_DATA_DESCRIPTOR);
803
834
  if (bufferedWrite && dataDescriptor === UNDEFINED_VALUE) {
@@ -858,18 +889,26 @@ function serializeExtraField(extraField) {
858
889
  if (!extraField) {
859
890
  return EMPTY_UINT8_ARRAY;
860
891
  }
892
+ if (!(extraField instanceof Map)) {
893
+ throw new Error(ERR_INVALID_EXTRAFIELD);
894
+ }
861
895
  let extraFieldSize = 0;
862
896
  let offset = 0;
863
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
864
- const rawExtraField = new Uint8Array(extraFieldSize);
865
- const rawExtraFieldView = getDataView(rawExtraField);
866
897
  extraField.forEach((data, type) => {
867
- if (type > MAX_16_BITS) {
898
+ if (!Number.isInteger(type) || type < 0 || type > MAX_16_BITS) {
868
899
  throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
869
900
  }
901
+ if (!(data instanceof Uint8Array)) {
902
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA_TYPE);
903
+ }
870
904
  if (getLength(data) > MAX_16_BITS) {
871
905
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
872
906
  }
907
+ extraFieldSize += 4 + getLength(data);
908
+ });
909
+ const rawExtraField = new Uint8Array(extraFieldSize);
910
+ const rawExtraFieldView = getDataView(rawExtraField);
911
+ extraField.forEach((data, type) => {
873
912
  setUint16(rawExtraFieldView, offset, type);
874
913
  setUint16(rawExtraFieldView, offset + 2, getLength(data));
875
914
  arraySet(rawExtraField, data, offset + 4);
@@ -901,6 +940,9 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
901
940
  if (uncompressedSize === UNDEFINED_VALUE) {
902
941
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
903
942
  }
943
+ if (compressionMethod === UNDEFINED_VALUE) {
944
+ throw new Error(ERR_UNDEFINED_COMPRESSION_METHOD);
945
+ }
904
946
  }
905
947
  const zip64Enabled = zip64 === true;
906
948
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
@@ -956,8 +998,8 @@ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options
956
998
  }
957
999
 
958
1000
  async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
959
- const zipWriter = { options: writerOptions, config: getConfiguration() };
960
- if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
1001
+ const zipWriter = { options: writerOptions };
1002
+ if (checkFunctionOption(writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY])) {
961
1003
  throw new Error(ERR_UNDETERMINED_SIZE);
962
1004
  }
963
1005
  if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
@@ -983,7 +1025,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
983
1025
  ({ name } = attributesInfo);
984
1026
  const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
985
1027
  if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
986
- !metadata.passThrough && !(await supportsDeflate(zipWriter.config))) {
1028
+ !metadata.passThrough && !(await supportsDeflate(getConfiguration()))) {
987
1029
  metadata.level = 0;
988
1030
  }
989
1031
  const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
@@ -1032,7 +1074,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
1032
1074
 
1033
1075
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1034
1076
  const {
1035
- files,
1077
+ fileEntries,
1036
1078
  writer
1037
1079
  } = zipWriter;
1038
1080
  const {
@@ -1054,12 +1096,12 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1054
1096
  let writerSizeBeforeEntry;
1055
1097
  let flushedBufferedSize = 0;
1056
1098
  let fileWriter;
1057
- files.set(name, fileEntry);
1099
+ fileEntries.set(name, fileEntry);
1058
1100
  zipWriter.lastFileEntry = fileEntry;
1059
1101
  try {
1060
1102
  let lockPreviousFileEntry;
1061
1103
  if (keepOrder) {
1062
- lockPreviousFileEntry = previousFileEntry && previousFileEntry.lock;
1104
+ lockPreviousFileEntry = previousFileEntry && previousFileEntry.lockFileEntry;
1063
1105
  requestLockCurrentFileEntry();
1064
1106
  }
1065
1107
  if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || !dataDescriptor) {
@@ -1080,11 +1122,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1080
1122
  const diskOffset = getDiskOffset(writer);
1081
1123
  if (zipWriter.addSplitZipSignature) {
1082
1124
  delete zipWriter.addSplitZipSignature;
1083
- const signatureArray = new Uint8Array(4);
1084
- const signatureArrayView = getDataView(signatureArray);
1085
- setUint32(signatureArrayView, 0, SPLIT_ZIP_FILE_SIGNATURE);
1086
- await writeData(writer, signatureArray);
1087
- zipWriter.offset += 4;
1125
+ await writeData(writer, getSplitZipSignatureArray());
1126
+ zipWriter.offset += SPLIT_ZIP_FILE_SIGNATURE_LENGTH;
1088
1127
  }
1089
1128
  if (usdz && !bufferedWrite) {
1090
1129
  appendExtraFieldUSDZ(entryInfo, zipWriter.offset - diskOffset);
@@ -1102,11 +1141,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1102
1141
  writerSizeBeforeEntry = writer.size;
1103
1142
  await writeData(fileWriter, localHeaderArray);
1104
1143
  }
1105
- fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
1144
+ fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, getConfiguration(), options);
1106
1145
  if (!bufferedWrite) {
1107
1146
  writingEntryData = false;
1108
1147
  }
1109
- files.set(name, fileEntry);
1148
+ fileEntries.set(name, fileEntry);
1110
1149
  fileEntry.filename = name;
1111
1150
  if (bufferedWrite) {
1112
1151
  await Promise.all([fileWriter.writable.getWriter().close(), lockPreviousFileEntry]);
@@ -1147,7 +1186,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1147
1186
  zipWriter.offset += flushedBufferedSize;
1148
1187
  }
1149
1188
  }
1150
- files.delete(name);
1189
+ fileEntries.delete(name);
1151
1190
  throw error;
1152
1191
  } finally {
1153
1192
  if (bufferedWrite) {
@@ -1169,7 +1208,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1169
1208
  }
1170
1209
 
1171
1210
  function requestLockCurrentFileEntry() {
1172
- fileEntry.lock = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
1211
+ fileEntry.lockFileEntry = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
1173
1212
  }
1174
1213
 
1175
1214
  async function requestLockWriter() {
@@ -1189,7 +1228,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
1189
1228
  }
1190
1229
  }
1191
1230
 
1192
- async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryInfo, config, options) {
1231
+ async function createFileEntry(reader, writer, { diskNumberStart, lockFileEntry }, entryInfo, config, options) {
1193
1232
  const {
1194
1233
  headerInfo,
1195
1234
  dataDescriptorInfo,
@@ -1257,7 +1296,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1257
1296
  codecURI
1258
1297
  } = options;
1259
1298
  const fileEntry = {
1260
- lock,
1299
+ lockFileEntry,
1261
1300
  versionMadeBy,
1262
1301
  zip64,
1263
1302
  directory: Boolean(directory),
@@ -1299,7 +1338,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1299
1338
  }
1300
1339
  const { writable } = writer;
1301
1340
  if (reader) {
1302
- const readable = toCompatibleReadable(reader.createReadable ? reader.createReadable() : reader.readable);
1341
+ const readable = toCompatibleReadable(createReadable(reader));
1303
1342
  const size = reader.size;
1304
1343
  const workerOptions = {
1305
1344
  options: {
@@ -1411,14 +1450,14 @@ function getHeaderInfo(options) {
1411
1450
  if (zip64 && (zip64UncompressedSize || zip64CompressedSize)) {
1412
1451
  const length = 4 + 16;
1413
1452
  const extraFieldZip64 = createRecordWriter(length);
1414
- extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
1415
- extraFieldZip64.uint16(length - 4);
1453
+ extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
1454
+ extraFieldZip64.writeUint16(length - 4);
1416
1455
  rawLocalExtraFieldZip64 = extraFieldZip64.array;
1417
1456
  if (zip64ExtraFieldComplete) {
1418
- extraFieldZip64.uint64(uncompressedSize);
1457
+ extraFieldZip64.writeUint64(uncompressedSize);
1419
1458
  if (uncompressedFile) {
1420
1459
  const encryptionOverhead = encrypted ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
1421
- extraFieldZip64.uint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
1460
+ extraFieldZip64.writeUint64(passThrough ? 0 : uncompressedSize + encryptionOverhead);
1422
1461
  }
1423
1462
  }
1424
1463
  } else {
@@ -1427,8 +1466,8 @@ function getHeaderInfo(options) {
1427
1466
  let rawExtraFieldAES;
1428
1467
  if (encrypted && !zipCrypto) {
1429
1468
  const extraFieldAES = createRecordWriter(getLength(EXTRAFIELD_DATA_AES) + 2);
1430
- extraFieldAES.uint16(EXTRAFIELD_TYPE_AES);
1431
- extraFieldAES.bytes(EXTRAFIELD_DATA_AES);
1469
+ extraFieldAES.writeUint16(EXTRAFIELD_TYPE_AES);
1470
+ extraFieldAES.writeBytes(EXTRAFIELD_DATA_AES);
1432
1471
  rawExtraFieldAES = extraFieldAES.array;
1433
1472
  rawExtraFieldAES[8] = encryptionStrength;
1434
1473
  } else {
@@ -1444,15 +1483,15 @@ function getHeaderInfo(options) {
1444
1483
  const extraFieldTimestampLength = 9 + (lastAccessDate ? 4 : 0) + (creationDate ? 4 : 0);
1445
1484
  const extraFieldTimestamp = createRecordWriter(extraFieldTimestampLength);
1446
1485
  extraFieldExtendedTimestampFlag = 0x1 + (lastAccessDate ? 0x2 : 0) + (creationDate ? 0x4 : 0);
1447
- extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
1448
- extraFieldTimestamp.uint16(extraFieldTimestampLength - 4);
1449
- extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
1450
- extraFieldTimestamp.uint32(lastModTimeUnix);
1486
+ extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
1487
+ extraFieldTimestamp.writeUint16(extraFieldTimestampLength - 4);
1488
+ extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
1489
+ extraFieldTimestamp.writeUint32(lastModTimeUnix);
1451
1490
  if (lastAccessDate) {
1452
- extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(lastAccessDate)));
1491
+ extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(lastAccessDate)));
1453
1492
  }
1454
1493
  if (creationDate) {
1455
- extraFieldTimestamp.uint32(clampUnixTime(getTimeUnix(creationDate)));
1494
+ extraFieldTimestamp.writeUint32(clampUnixTime(getTimeUnix(creationDate)));
1456
1495
  }
1457
1496
  rawExtraFieldExtendedTimestamp = extraFieldTimestamp.array;
1458
1497
  } else {
@@ -1465,14 +1504,14 @@ function getHeaderInfo(options) {
1465
1504
  try {
1466
1505
  const lastModTimeNTFS = getTimeNTFS(lastModDate);
1467
1506
  const extraFieldNTFS = createRecordWriter(36);
1468
- extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS);
1469
- extraFieldNTFS.uint16(32);
1507
+ extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS);
1508
+ extraFieldNTFS.writeUint16(32);
1470
1509
  extraFieldNTFS.skip(4);
1471
- extraFieldNTFS.uint16(EXTRAFIELD_TYPE_NTFS_TAG1);
1472
- extraFieldNTFS.uint16(24);
1473
- extraFieldNTFS.uint64(lastModTimeNTFS);
1474
- extraFieldNTFS.uint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
1475
- extraFieldNTFS.uint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
1510
+ extraFieldNTFS.writeUint16(EXTRAFIELD_TYPE_NTFS_TAG1);
1511
+ extraFieldNTFS.writeUint16(24);
1512
+ extraFieldNTFS.writeUint64(lastModTimeNTFS);
1513
+ extraFieldNTFS.writeUint64(lastAccessDate ? getTimeNTFS(lastAccessDate) : lastModTimeNTFS);
1514
+ extraFieldNTFS.writeUint64(creationDate ? getTimeNTFS(creationDate) : lastModTimeNTFS);
1476
1515
  rawExtraFieldNTFS = extraFieldNTFS.array;
1477
1516
  } catch {
1478
1517
  rawExtraFieldNTFS = EMPTY_UINT8_ARRAY;
@@ -1491,20 +1530,20 @@ function getHeaderInfo(options) {
1491
1530
  const gidBytes = packUnixId(gid);
1492
1531
  const payloadLength = 3 + uidBytes.length + gidBytes.length;
1493
1532
  const extraFieldUnix = createRecordWriter(4 + payloadLength);
1494
- extraFieldUnix.uint16(EXTRAFIELD_TYPE_INFOZIP);
1495
- extraFieldUnix.uint16(payloadLength);
1496
- extraFieldUnix.uint8(1);
1497
- extraFieldUnix.uint8(uidBytes.length);
1498
- extraFieldUnix.bytes(uidBytes);
1499
- extraFieldUnix.uint8(gidBytes.length);
1500
- extraFieldUnix.bytes(gidBytes);
1533
+ extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_INFOZIP);
1534
+ extraFieldUnix.writeUint16(payloadLength);
1535
+ extraFieldUnix.writeUint8(1);
1536
+ extraFieldUnix.writeUint8(uidBytes.length);
1537
+ extraFieldUnix.writeBytes(uidBytes);
1538
+ extraFieldUnix.writeUint8(gidBytes.length);
1539
+ extraFieldUnix.writeBytes(gidBytes);
1501
1540
  rawExtraFieldUnix = extraFieldUnix.array;
1502
1541
  } else if (unixExtraFieldType == UNIX_EXTRA_FIELD_TYPE && (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE)) {
1503
1542
  const extraFieldUnix = createRecordWriter(8);
1504
- extraFieldUnix.uint16(EXTRAFIELD_TYPE_UNIX);
1505
- extraFieldUnix.uint16(4);
1506
- extraFieldUnix.uint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
1507
- extraFieldUnix.uint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
1543
+ extraFieldUnix.writeUint16(EXTRAFIELD_TYPE_UNIX);
1544
+ extraFieldUnix.writeUint16(4);
1545
+ extraFieldUnix.writeUint16((uid === UNDEFINED_VALUE ? 0 : uid) & MAX_16_BITS);
1546
+ extraFieldUnix.writeUint16((gid === UNDEFINED_VALUE ? 0 : gid) & MAX_16_BITS);
1508
1547
  rawExtraFieldUnix = extraFieldUnix.array;
1509
1548
  } else {
1510
1549
  rawExtraFieldUnix = EMPTY_UINT8_ARRAY;
@@ -1554,18 +1593,18 @@ function getHeaderInfo(options) {
1554
1593
  const localHeader = createRecordWriter(HEADER_SIZE + getLength(rawFilename) + extraFieldLength);
1555
1594
  const localHeaderArray = localHeader.array;
1556
1595
  const localHeaderView = getDataView(localHeaderArray);
1557
- localHeader.uint32(LOCAL_FILE_HEADER_SIGNATURE);
1558
- localHeader.bytes(headerArray);
1559
- localHeader.bytes(rawFilename);
1596
+ localHeader.writeUint32(LOCAL_FILE_HEADER_SIGNATURE);
1597
+ localHeader.writeBytes(headerArray);
1598
+ localHeader.writeBytes(rawFilename);
1560
1599
  if (writeLocalExtraFieldZip64) {
1561
- localHeader.bytes(rawLocalExtraFieldZip64);
1562
- }
1563
- localHeader.bytes(rawExtraFieldAES);
1564
- localHeader.bytes(rawExtraFieldExtendedTimestamp);
1565
- localHeader.bytes(rawExtraFieldNTFS);
1566
- localHeader.bytes(rawExtraFieldUnix);
1567
- localHeader.bytes(rawExtraField);
1568
- localHeader.bytes(rawLocalExtraField);
1600
+ localHeader.writeBytes(rawLocalExtraFieldZip64);
1601
+ }
1602
+ localHeader.writeBytes(rawExtraFieldAES);
1603
+ localHeader.writeBytes(rawExtraFieldExtendedTimestamp);
1604
+ localHeader.writeBytes(rawExtraFieldNTFS);
1605
+ localHeader.writeBytes(rawExtraFieldUnix);
1606
+ localHeader.writeBytes(rawExtraField);
1607
+ localHeader.writeBytes(rawLocalExtraField);
1569
1608
  if (dataDescriptor) {
1570
1609
  if (!zip64CompressedSize) {
1571
1610
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -1755,7 +1794,7 @@ function updateLocalHeader({
1755
1794
 
1756
1795
 
1757
1796
  async function closeFile(zipWriter, comment, options) {
1758
- const directoryDataLength = createDirectoryRecords(zipWriter.files);
1797
+ const directoryDataLength = createDirectoryRecords(zipWriter.fileEntries);
1759
1798
  const { directoryStart, directoryArray } = await writeDirectoryRecords(zipWriter, directoryDataLength, options);
1760
1799
  const signatureLength = await writeDigitalSignatureRecord(zipWriter, directoryArray, options);
1761
1800
  await writeEndOfDirectoryRecord(zipWriter, comment, options, { directoryStart, directoryDataLength, signatureLength });
@@ -1785,19 +1824,19 @@ function createDirectoryRecords(files) {
1785
1824
  if (zip64Offset || zip64DiskNumberStart || zip64UncompressedSize || zip64CompressedSize) {
1786
1825
  const length = 4 + (zip64UncompressedSize ? 8 : 0) + (zip64CompressedSize ? 8 : 0) + (zip64Offset ? 8 : 0) + (zip64DiskNumberStart ? 4 : 0);
1787
1826
  const extraFieldZip64 = createRecordWriter(length);
1788
- extraFieldZip64.uint16(EXTRAFIELD_TYPE_ZIP64);
1789
- extraFieldZip64.uint16(length - 4);
1827
+ extraFieldZip64.writeUint16(EXTRAFIELD_TYPE_ZIP64);
1828
+ extraFieldZip64.writeUint16(length - 4);
1790
1829
  if (zip64UncompressedSize) {
1791
- extraFieldZip64.uint64(uncompressedSize);
1830
+ extraFieldZip64.writeUint64(uncompressedSize);
1792
1831
  }
1793
1832
  if (zip64CompressedSize) {
1794
- extraFieldZip64.uint64(compressedSize);
1833
+ extraFieldZip64.writeUint64(compressedSize);
1795
1834
  }
1796
1835
  if (zip64Offset) {
1797
- extraFieldZip64.uint64(fileEntry.offset);
1836
+ extraFieldZip64.writeUint64(fileEntry.offset);
1798
1837
  }
1799
1838
  if (zip64DiskNumberStart) {
1800
- extraFieldZip64.uint32(fileEntry.diskNumberStart);
1839
+ extraFieldZip64.writeUint32(fileEntry.diskNumberStart);
1801
1840
  }
1802
1841
  rawExtraFieldZip64 = extraFieldZip64.array;
1803
1842
  } else {
@@ -1810,10 +1849,10 @@ function createDirectoryRecords(files) {
1810
1849
  const lastModTimeUnix = getTimeUnix(lastModDate);
1811
1850
  if (extendedTimestamp && inUnixTimeRange(lastModTimeUnix)) {
1812
1851
  const extraFieldTimestamp = createRecordWriter(9);
1813
- extraFieldTimestamp.uint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
1814
- extraFieldTimestamp.uint16(5);
1815
- extraFieldTimestamp.uint8(extraFieldExtendedTimestampFlag);
1816
- extraFieldTimestamp.uint32(lastModTimeUnix);
1852
+ extraFieldTimestamp.writeUint16(EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP);
1853
+ extraFieldTimestamp.writeUint16(5);
1854
+ extraFieldTimestamp.writeUint8(extraFieldExtendedTimestampFlag);
1855
+ extraFieldTimestamp.writeUint32(lastModTimeUnix);
1817
1856
  rawExtraFieldTimestamp = extraFieldTimestamp.array;
1818
1857
  } else {
1819
1858
  rawExtraFieldTimestamp = EMPTY_UINT8_ARRAY;
@@ -1835,14 +1874,14 @@ function createDirectoryRecords(files) {
1835
1874
  }
1836
1875
 
1837
1876
  async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
1838
- const { files, writer } = zipWriter;
1877
+ const { fileEntries, writer } = zipWriter;
1839
1878
  const directoryArray = new Uint8Array(directoryDataLength);
1840
1879
  await initStream(writer);
1841
1880
  let offset = 0;
1842
1881
  let directoryDiskOffset = 0;
1843
1882
  let directoryStartDiskNumber = getDiskNumber(writer);
1844
1883
  let directoryStartDiskOffset = getDiskOffset(writer);
1845
- for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
1884
+ for (const [indexFileEntry, fileEntry] of Array.from(fileEntries.values()).entries()) {
1846
1885
  const {
1847
1886
  offset: fileEntryOffset,
1848
1887
  rawFilename,
@@ -1887,28 +1926,28 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
1887
1926
  setUint16(headerView, HEADER_OFFSET_VERSION, VERSION_ZIP64);
1888
1927
  }
1889
1928
  const directoryRecord = createRecordWriter(directoryRecordLength);
1890
- directoryRecord.uint32(CENTRAL_FILE_HEADER_SIGNATURE);
1891
- directoryRecord.uint16(versionMadeBy);
1892
- directoryRecord.bytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
1893
- directoryRecord.uint16(extraFieldLength);
1894
- directoryRecord.uint16(getLength(rawComment));
1895
- directoryRecord.uint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
1896
- directoryRecord.uint16(internalFileAttributes);
1897
- directoryRecord.uint32(externalFileAttributes);
1898
- directoryRecord.uint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
1899
- directoryRecord.bytes(rawFilename);
1900
- directoryRecord.bytes(rawExtraFieldZip64);
1901
- directoryRecord.bytes(rawExtraFieldAES);
1902
- directoryRecord.bytes(rawExtraFieldExtendedTimestamp);
1903
- directoryRecord.bytes(rawExtraFieldNTFS);
1904
- directoryRecord.bytes(rawExtraFieldUnix);
1905
- directoryRecord.bytes(rawExtraField);
1906
- directoryRecord.bytes(rawComment);
1929
+ directoryRecord.writeUint32(CENTRAL_FILE_HEADER_SIGNATURE);
1930
+ directoryRecord.writeUint16(versionMadeBy);
1931
+ directoryRecord.writeBytes(headerArray.subarray(0, HEADER_SIZE - 4 - 2));
1932
+ directoryRecord.writeUint16(extraFieldLength);
1933
+ directoryRecord.writeUint16(getLength(rawComment));
1934
+ directoryRecord.writeUint16(zip64DiskNumberStart ? MAX_16_BITS : diskNumberStart);
1935
+ directoryRecord.writeUint16(internalFileAttributes);
1936
+ directoryRecord.writeUint32(externalFileAttributes);
1937
+ directoryRecord.writeUint32(zip64Offset ? MAX_32_BITS : fileEntryOffset);
1938
+ directoryRecord.writeBytes(rawFilename);
1939
+ directoryRecord.writeBytes(rawExtraFieldZip64);
1940
+ directoryRecord.writeBytes(rawExtraFieldAES);
1941
+ directoryRecord.writeBytes(rawExtraFieldExtendedTimestamp);
1942
+ directoryRecord.writeBytes(rawExtraFieldNTFS);
1943
+ directoryRecord.writeBytes(rawExtraFieldUnix);
1944
+ directoryRecord.writeBytes(rawExtraField);
1945
+ directoryRecord.writeBytes(rawComment);
1907
1946
  arraySet(directoryArray, directoryRecord.array, offset);
1908
1947
  offset += directoryRecordLength;
1909
1948
  if (options.onprogress) {
1910
1949
  try {
1911
- await options.onprogress(indexFileEntry + 1, files.size, new Entry(fileEntry));
1950
+ await options.onprogress(indexFileEntry + 1, fileEntries.size, new Entry(fileEntry));
1912
1951
  } catch {
1913
1952
  // ignored
1914
1953
  }
@@ -1922,7 +1961,7 @@ async function writeDirectoryRecords(zipWriter, directoryDataLength, options) {
1922
1961
  }
1923
1962
 
1924
1963
  async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
1925
- const signCentralDirectory = getOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
1964
+ const signCentralDirectory = getFunctionOptionValue(zipWriter, options, OPTION_SIGN_CENTRAL_DIRECTORY);
1926
1965
  if (signCentralDirectory) {
1927
1966
  const signatureData = await signCentralDirectory(directoryArray);
1928
1967
  const signatureDataLength = getLength(signatureData);
@@ -1930,9 +1969,9 @@ async function writeDigitalSignatureRecord(zipWriter, directoryArray, options) {
1930
1969
  throw new Error(ERR_INVALID_SIGNATURE_DATA);
1931
1970
  }
1932
1971
  const signatureRecord = createRecordWriter(6 + signatureDataLength);
1933
- signatureRecord.uint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
1934
- signatureRecord.uint16(signatureDataLength);
1935
- signatureRecord.bytes(signatureData);
1972
+ signatureRecord.writeUint32(DIGITAL_SIGNATURE_RECORD_SIGNATURE);
1973
+ signatureRecord.writeUint16(signatureDataLength);
1974
+ signatureRecord.writeBytes(signatureData);
1936
1975
  await writeData(zipWriter.writer, signatureRecord.array);
1937
1976
  return 6 + signatureDataLength;
1938
1977
  }
@@ -1943,7 +1982,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
1943
1982
  const { writer } = zipWriter;
1944
1983
  const { directoryStart, signatureLength } = cdInfo;
1945
1984
  let { directoryDataLength } = cdInfo;
1946
- let filesLength = zipWriter.files.size;
1985
+ let fileEntriesLength = zipWriter.fileEntries.size;
1947
1986
  let diskNumber = directoryStart.diskNumber;
1948
1987
  let directoryOffset = getSegmentOffset(zipWriter, directoryStart);
1949
1988
  let lastDiskNumber = getDiskNumber(writer);
@@ -1951,7 +1990,7 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
1951
1990
  lastDiskNumber++;
1952
1991
  }
1953
1992
  let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
1954
- if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
1993
+ if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || fileEntriesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
1955
1994
  if (zip64 === false) {
1956
1995
  throw new Error(ERR_UNSUPPORTED_FORMAT);
1957
1996
  } else {
@@ -1968,37 +2007,37 @@ async function writeEndOfDirectoryRecord(zipWriter, comment, options, cdInfo) {
1968
2007
  }
1969
2008
  lastDiskNumber = getDiskNumber(writer);
1970
2009
  if (zip64) {
1971
- endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
1972
- endOfdirectoryRecord.uint64(44);
1973
- endOfdirectoryRecord.uint16(45);
1974
- endOfdirectoryRecord.uint16(45);
1975
- endOfdirectoryRecord.uint32(lastDiskNumber);
1976
- endOfdirectoryRecord.uint32(diskNumber);
1977
- endOfdirectoryRecord.uint64(filesLength);
1978
- endOfdirectoryRecord.uint64(filesLength);
1979
- endOfdirectoryRecord.uint64(directoryDataLength);
1980
- endOfdirectoryRecord.uint64(directoryOffset);
1981
- endOfdirectoryRecord.uint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
1982
- endOfdirectoryRecord.uint32(lastDiskNumber);
1983
- endOfdirectoryRecord.uint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
1984
- endOfdirectoryRecord.uint32(lastDiskNumber + 1);
2010
+ endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
2011
+ endOfdirectoryRecord.writeUint64(44);
2012
+ endOfdirectoryRecord.writeUint16(45);
2013
+ endOfdirectoryRecord.writeUint16(45);
2014
+ endOfdirectoryRecord.writeUint32(lastDiskNumber);
2015
+ endOfdirectoryRecord.writeUint32(diskNumber);
2016
+ endOfdirectoryRecord.writeUint64(fileEntriesLength);
2017
+ endOfdirectoryRecord.writeUint64(fileEntriesLength);
2018
+ endOfdirectoryRecord.writeUint64(directoryDataLength);
2019
+ endOfdirectoryRecord.writeUint64(directoryOffset);
2020
+ endOfdirectoryRecord.writeUint32(ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE);
2021
+ endOfdirectoryRecord.writeUint32(lastDiskNumber);
2022
+ endOfdirectoryRecord.writeUint64(BigInt(getSegmentOffset(zipWriter, writer)) + BigInt(directoryDataLength) + BigInt(signatureLength));
2023
+ endOfdirectoryRecord.writeUint32(lastDiskNumber + 1);
1985
2024
  const supportZip64SplitFile = getOptionValue(zipWriter, options, OPTION_SUPPORT_ZIP64_SPLIT_FILE, true);
1986
2025
  if (supportZip64SplitFile) {
1987
2026
  lastDiskNumber = MAX_16_BITS;
1988
2027
  diskNumber = MAX_16_BITS;
1989
2028
  }
1990
- filesLength = MAX_16_BITS;
2029
+ fileEntriesLength = MAX_16_BITS;
1991
2030
  directoryOffset = MAX_32_BITS;
1992
2031
  directoryDataLength = MAX_32_BITS;
1993
2032
  }
1994
- endOfdirectoryRecord.uint32(END_OF_CENTRAL_DIR_SIGNATURE);
1995
- endOfdirectoryRecord.uint16(lastDiskNumber);
1996
- endOfdirectoryRecord.uint16(diskNumber);
1997
- endOfdirectoryRecord.uint16(filesLength);
1998
- endOfdirectoryRecord.uint16(filesLength);
1999
- endOfdirectoryRecord.uint32(directoryDataLength);
2000
- endOfdirectoryRecord.uint32(directoryOffset);
2001
- endOfdirectoryRecord.uint16(commentLength);
2033
+ endOfdirectoryRecord.writeUint32(END_OF_CENTRAL_DIR_SIGNATURE);
2034
+ endOfdirectoryRecord.writeUint16(lastDiskNumber);
2035
+ endOfdirectoryRecord.writeUint16(diskNumber);
2036
+ endOfdirectoryRecord.writeUint16(fileEntriesLength);
2037
+ endOfdirectoryRecord.writeUint16(fileEntriesLength);
2038
+ endOfdirectoryRecord.writeUint32(directoryDataLength);
2039
+ endOfdirectoryRecord.writeUint32(directoryOffset);
2040
+ endOfdirectoryRecord.writeUint16(commentLength);
2002
2041
  await writeData(writer, endOfdirectoryRecord.array);
2003
2042
  if (commentLength) {
2004
2043
  await writeData(writer, comment);
@@ -2011,11 +2050,11 @@ function createRecordWriter(length) {
2011
2050
  let offset = 0;
2012
2051
  return {
2013
2052
  array,
2014
- uint8: value => { setUint8(view, offset, value); offset += 1; },
2015
- uint16: value => { setUint16(view, offset, value); offset += 2; },
2016
- uint32: value => { setUint32(view, offset, value); offset += 4; },
2017
- uint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
2018
- bytes: value => { arraySet(array, value, offset); offset += getLength(value); },
2053
+ writeUint8: value => { setUint8(view, offset, value); offset += 1; },
2054
+ writeUint16: value => { setUint16(view, offset, value); offset += 2; },
2055
+ writeUint32: value => { setUint32(view, offset, value); offset += 4; },
2056
+ writeUint64: value => { setBigUint64(view, offset, BigInt(value)); offset += 8; },
2057
+ writeBytes: value => { arraySet(array, value, offset); offset += getLength(value); },
2019
2058
  skip: count => offset += count
2020
2059
  };
2021
2060
  }
@@ -2039,6 +2078,71 @@ function getSegmentOffset(zipWriter, { diskNumber = 0, diskOffset = 0 }) {
2039
2078
  return zipWriter.offset - diskOffset - (diskNumber ? zipWriter.initialOffset : 0);
2040
2079
  }
2041
2080
 
2081
+ async function startsWithSplitZipSignature(reader) {
2082
+ const signatureArray = await readUint8Array(reader, 0, SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
2083
+ return getUint32(getDataView(signatureArray), 0) == SPLIT_ZIP_FILE_SIGNATURE;
2084
+ }
2085
+
2086
+ async function copyZipData(zipWriter, reader, entries, directoryOffset, splitZipSignatureLength) {
2087
+ const { writer } = zipWriter;
2088
+ const entryPositions = new Map();
2089
+ if (writer.closeDisk) {
2090
+ const sortedEntries = Array.from(entries).sort((firstEntry, secondEntry) =>
2091
+ getSourceOffset(reader, firstEntry) - getSourceOffset(reader, secondEntry));
2092
+ let copiedLength = 0;
2093
+ for (const entry of sortedEntries) {
2094
+ const sourceOffset = getSourceOffset(reader, entry);
2095
+ await copyData(zipWriter, reader, copiedLength, sourceOffset - copiedLength);
2096
+ if (exceedsAvailableSize(writer, await getLocalHeaderLength(reader, sourceOffset))) {
2097
+ await writer.closeDisk();
2098
+ }
2099
+ entryPositions.set(entry, {
2100
+ offset: getSegmentOffset(zipWriter, writer),
2101
+ diskNumberStart: getDiskNumber(writer)
2102
+ });
2103
+ copiedLength = sourceOffset;
2104
+ }
2105
+ await copyData(zipWriter, reader, copiedLength, directoryOffset - copiedLength);
2106
+ } else {
2107
+ await copyData(zipWriter, reader, 0, directoryOffset);
2108
+ entries.forEach(entry => entryPositions.set(entry, {
2109
+ offset: splitZipSignatureLength + getSourceOffset(reader, entry),
2110
+ diskNumberStart: 0
2111
+ }));
2112
+ }
2113
+ return entryPositions;
2114
+ }
2115
+
2116
+ async function copyData(zipWriter, reader, offset, size) {
2117
+ if (size > 0) {
2118
+ const { writer } = zipWriter;
2119
+ await createReadable(reader, { offset, size }).pipeTo(writer.writable, { preventClose: true, preventAbort: true });
2120
+ writer.size += size;
2121
+ zipWriter.offset += size;
2122
+ }
2123
+ }
2124
+
2125
+ async function getLocalHeaderLength(reader, offset) {
2126
+ const headerArray = await readUint8Array(reader, offset, HEADER_SIZE);
2127
+ if (getLength(headerArray) < HEADER_SIZE) {
2128
+ return HEADER_SIZE;
2129
+ }
2130
+ const headerView = getDataView(headerArray);
2131
+ return HEADER_SIZE +
2132
+ getUint16(headerView, HEADER_OFFSET_FILENAME_LENGTH + LOCAL_HEADER_COMMON_OFFSET) +
2133
+ getUint16(headerView, HEADER_OFFSET_EXTRAFIELD_LENGTH + LOCAL_HEADER_COMMON_OFFSET);
2134
+ }
2135
+
2136
+ function getSourceOffset(reader, { offset, diskNumberStart }) {
2137
+ return offset + (reader.getDiskOffset ? reader.getDiskOffset(diskNumberStart) : 0);
2138
+ }
2139
+
2140
+ function getSplitZipSignatureArray() {
2141
+ const signatureArray = new Uint8Array(SPLIT_ZIP_FILE_SIGNATURE_LENGTH);
2142
+ setUint32(getDataView(signatureArray), 0, SPLIT_ZIP_FILE_SIGNATURE);
2143
+ return signatureArray;
2144
+ }
2145
+
2042
2146
  async function writeData(writer, array) {
2043
2147
  const { writable } = writer;
2044
2148
  const streamWriter = writable.getWriter();
@@ -2090,6 +2194,21 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
2090
2194
  return result === UNDEFINED_VALUE ? defaultValue : result;
2091
2195
  }
2092
2196
 
2197
+ function getDateOptionValue(zipWriter, options, name, defaultValue) {
2198
+ const date = getOptionValue(zipWriter, options, name, defaultValue);
2199
+ if (date === null) {
2200
+ return defaultValue;
2201
+ }
2202
+ if (date !== UNDEFINED_VALUE && (typeof date.getTime != FUNCTION_TYPE || Number.isNaN(date.getTime()))) {
2203
+ throw new Error(ERR_INVALID_DATE);
2204
+ }
2205
+ return date;
2206
+ }
2207
+
2208
+ function getFunctionOptionValue(zipWriter, options, name) {
2209
+ return checkFunctionOption(getOptionValue(zipWriter, options, name));
2210
+ }
2211
+
2093
2212
  function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
2094
2213
  const value = getAliasedValue(options, name, deprecatedName);
2095
2214
  const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
@@ -2104,9 +2223,6 @@ function getNumberOptionValue(zipWriter, options, name, defaultValue) {
2104
2223
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
2105
2224
  }
2106
2225
 
2107
- function toNumber(value) {
2108
- return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
2109
- }
2110
2226
 
2111
2227
  function getMaximumCompressedSize(uncompressedSize) {
2112
2228
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
@@ -2118,6 +2234,14 @@ function isCompressed(compressionMethod, level) {
2118
2234
  : compressionMethod !== COMPRESSION_METHOD_STORE;
2119
2235
  }
2120
2236
 
2237
+ function getUint16(view, offset) {
2238
+ return view.getUint16(offset, true);
2239
+ }
2240
+
2241
+ function getUint32(view, offset) {
2242
+ return view.getUint32(offset, true);
2243
+ }
2244
+
2121
2245
  function setUint8(view, offset, value) {
2122
2246
  view.setUint8(offset, value);
2123
2247
  }
@@ -2161,9 +2285,9 @@ function getHeaderArrayData({
2161
2285
  const headerRecord = createRecordWriter(HEADER_SIZE - 4);
2162
2286
  const headerArray = headerRecord.array;
2163
2287
  const headerView = getDataView(headerArray);
2164
- headerRecord.uint16(version);
2165
- headerRecord.uint16(bitFlag);
2166
- headerRecord.uint16(compressionMethod);
2288
+ headerRecord.writeUint16(version);
2289
+ headerRecord.writeUint16(bitFlag);
2290
+ headerRecord.writeUint16(compressionMethod);
2167
2291
  if (rawLastModDate === UNDEFINED_VALUE) {
2168
2292
  const dateArray = new Uint32Array(1);
2169
2293
  const dateView = getDataView(dateArray);
@@ -2171,20 +2295,20 @@ function getHeaderArrayData({
2171
2295
  setUint16(dateView, 2, ((((lastModDate.getFullYear() - 1980) << 4) | (lastModDate.getMonth() + 1)) << 5) | lastModDate.getDate());
2172
2296
  rawLastModDate = dateArray[0];
2173
2297
  }
2174
- headerRecord.uint32(rawLastModDate);
2298
+ headerRecord.writeUint32(rawLastModDate);
2175
2299
  headerRecord.skip(4);
2176
2300
  if (zip64CompressedSize || compressedSize !== UNDEFINED_VALUE) {
2177
- headerRecord.uint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
2301
+ headerRecord.writeUint32(zip64CompressedSize ? MAX_32_BITS : compressedSize);
2178
2302
  } else {
2179
2303
  headerRecord.skip(4);
2180
2304
  }
2181
2305
  if (zip64UncompressedSize || uncompressedSize !== UNDEFINED_VALUE) {
2182
- headerRecord.uint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
2306
+ headerRecord.writeUint32(zip64UncompressedSize ? MAX_32_BITS : uncompressedSize);
2183
2307
  } else {
2184
2308
  headerRecord.skip(4);
2185
2309
  }
2186
- headerRecord.uint16(getLength(rawFilename));
2187
- headerRecord.uint16(extraFieldLength);
2310
+ headerRecord.writeUint16(getLength(rawFilename));
2311
+ headerRecord.writeUint16(extraFieldLength);
2188
2312
  return {
2189
2313
  headerArray,
2190
2314
  headerView,