@zip.js/zip.js 2.6.20 → 2.6.23

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.
@@ -103,7 +103,7 @@ class ZipWriter {
103
103
  files: new Map(),
104
104
  filenames: new Set(),
105
105
  offset: writer.writable.size,
106
- pendingCompressedSize: 0,
106
+ pendingEntriesSize: 0,
107
107
  pendingAddFileCalls: new Set()
108
108
  });
109
109
  }
@@ -228,6 +228,7 @@ async function addFile(zipWriter, name, reader, options) {
228
228
  extendedTimestamp = true;
229
229
  }
230
230
  let maximumCompressedSize = 0;
231
+ let maximumEntrySize = 0;
231
232
  let keepOrder = getOptionValue(zipWriter, options, "keepOrder");
232
233
  if (keepOrder === undefined) {
233
234
  keepOrder = true;
@@ -249,7 +250,7 @@ async function addFile(zipWriter, name, reader, options) {
249
250
  maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
250
251
  }
251
252
  let zip64 = options.zip64 || zipWriter.options.zip64 || false;
252
- if (zipWriter.offset + zipWriter.pendingCompressedSize >= MAX_32_BITS ||
253
+ if (zipWriter.offset + zipWriter.pendingEntriesSize >= MAX_32_BITS ||
253
254
  uncompressedSize >= MAX_32_BITS ||
254
255
  maximumCompressedSize >= MAX_32_BITS) {
255
256
  if (options.zip64 === false || zipWriter.options.zip64 === false || !keepOrder) {
@@ -258,8 +259,6 @@ async function addFile(zipWriter, name, reader, options) {
258
259
  zip64 = true;
259
260
  }
260
261
  }
261
- zipWriter.pendingCompressedSize += maximumCompressedSize;
262
- await Promise.resolve();
263
262
  const level = getOptionValue(zipWriter, options, "level");
264
263
  const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
265
264
  const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
@@ -273,7 +272,7 @@ async function addFile(zipWriter, name, reader, options) {
273
272
  if (dataDescriptor && dataDescriptorSignature === undefined) {
274
273
  dataDescriptorSignature = false;
275
274
  }
276
- const fileEntry = await getFileEntry(zipWriter, name, reader, Object.assign({}, options, {
275
+ options = Object.assign({}, options, {
277
276
  rawFilename,
278
277
  rawComment,
279
278
  version,
@@ -298,15 +297,20 @@ async function addFile(zipWriter, name, reader, options) {
298
297
  internalFileAttribute,
299
298
  externalFileAttribute,
300
299
  useCompressionStream
301
- }));
302
- if (maximumCompressedSize) {
303
- zipWriter.pendingCompressedSize -= maximumCompressedSize;
300
+ });
301
+ const headerInfo = getHeaderInfo(options);
302
+ const dataDescriptorInfo = getDataDescriptorInfo(options);
303
+ maximumEntrySize = headerInfo.localHeaderArray.length + maximumCompressedSize + dataDescriptorInfo.dataDescriptorArray.length;
304
+ zipWriter.pendingEntriesSize += maximumEntrySize;
305
+ const fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo }, options);
306
+ if (maximumEntrySize) {
307
+ zipWriter.pendingEntriesSize -= maximumEntrySize;
304
308
  }
305
309
  Object.assign(fileEntry, { name, comment, extraField });
306
310
  return new Entry(fileEntry);
307
311
  }
308
312
 
309
- async function getFileEntry(zipWriter, name, reader, options) {
313
+ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
310
314
  const {
311
315
  files,
312
316
  writer
@@ -345,7 +349,8 @@ async function getFileEntry(zipWriter, name, reader, options) {
345
349
  if (!bufferedWrite) {
346
350
  await lockPreviousFileEntry;
347
351
  }
348
- fileEntry = await createFileEntry(reader, fileWriter, fileEntry, zipWriter.config, options);
352
+ fileEntry.writingData = true;
353
+ fileEntry = await createFileEntry(reader, fileWriter, fileEntry, entryInfo, zipWriter.config, options);
349
354
  files.set(name, fileEntry);
350
355
  fileEntry.filename = name;
351
356
  if (bufferedWrite) {
@@ -421,7 +426,25 @@ async function getFileEntry(zipWriter, name, reader, options) {
421
426
  }
422
427
  }
423
428
 
424
- async function createFileEntry(reader, writer, pendingFileEntry, config, options) {
429
+ async function createFileEntry(reader, writer, pendingFileEntry, entryInfo, config, options) {
430
+ const {
431
+ headerInfo,
432
+ dataDescriptorInfo
433
+ } = entryInfo;
434
+ const {
435
+ localHeaderArray,
436
+ headerArray,
437
+ lastModDate,
438
+ rawLastModDate,
439
+ encrypted,
440
+ compressed,
441
+ version,
442
+ compressionMethod,
443
+ rawExtraFieldExtendedTimestamp,
444
+ rawExtraFieldNTFS,
445
+ rawExtraFieldAES
446
+ } = headerInfo;
447
+ const { dataDescriptorArray } = dataDescriptorInfo;
425
448
  const {
426
449
  rawFilename,
427
450
  lastAccessDate,
@@ -431,9 +454,7 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
431
454
  zip64,
432
455
  zipCrypto,
433
456
  dataDescriptor,
434
- dataDescriptorSignature,
435
457
  directory,
436
- version,
437
458
  versionMadeBy,
438
459
  rawComment,
439
460
  rawExtraField,
@@ -449,8 +470,108 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
449
470
  externalFileAttribute,
450
471
  useCompressionStream
451
472
  } = options;
452
- const encrypted = Boolean(password && password.length);
473
+ const fileEntry = {
474
+ lock: pendingFileEntry.lock,
475
+ versionMadeBy,
476
+ zip64,
477
+ directory: Boolean(directory),
478
+ filenameUTF8: true,
479
+ rawFilename,
480
+ commentUTF8: true,
481
+ rawComment,
482
+ rawExtraFieldExtendedTimestamp,
483
+ rawExtraFieldNTFS,
484
+ rawExtraFieldAES,
485
+ rawExtraField,
486
+ extendedTimestamp,
487
+ msDosCompatible,
488
+ internalFileAttribute,
489
+ externalFileAttribute
490
+ };
491
+ let uncompressedSize = 0;
492
+ let signature;
493
+ let compressedSize = 0;
494
+ const { writable } = writer;
495
+ if (reader) {
496
+ reader.chunkSize = getChunkSize(config);
497
+ await writeData(writable, localHeaderArray);
498
+ const size = () => reader.size;
499
+ const readable = reader.readable;
500
+ readable.size = size;
501
+ const workerOptions = {
502
+ options: {
503
+ codecType: CODEC_DEFLATE,
504
+ level,
505
+ password,
506
+ encryptionStrength,
507
+ zipCrypto: encrypted && zipCrypto,
508
+ passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
509
+ signed: true,
510
+ compressed,
511
+ encrypted,
512
+ useWebWorkers,
513
+ useCompressionStream
514
+ },
515
+ config,
516
+ streamOptions: { signal, size, onstart, onprogress, onend },
517
+ codecConstructor: config.Deflate
518
+ };
519
+ const previousSize = writable.size;
520
+ signature = (await runWorker({ readable, writable }, workerOptions)).signature;
521
+ uncompressedSize = reader.size = readable.size();
522
+ compressedSize = writable.size - previousSize;
523
+ } else {
524
+ await writeData(writable, localHeaderArray);
525
+ }
526
+ const rawExtraFieldZip64 = zip64 ? new Uint8Array(EXTRAFIELD_LENGTH_ZIP64 + 4) : new Uint8Array();
527
+ if (reader) {
528
+ setEntryInfo({
529
+ signature,
530
+ rawExtraFieldZip64,
531
+ compressedSize,
532
+ uncompressedSize,
533
+ headerInfo,
534
+ dataDescriptorInfo
535
+ }, options);
536
+ }
537
+ if (dataDescriptor) {
538
+ await writeData(writable, dataDescriptorArray);
539
+ }
540
+ Object.assign(fileEntry, {
541
+ compressedSize,
542
+ lastModDate,
543
+ rawLastModDate,
544
+ creationDate,
545
+ lastAccessDate,
546
+ encrypted,
547
+ length: localHeaderArray.length + compressedSize + dataDescriptorArray.length,
548
+ compressionMethod,
549
+ version,
550
+ headerArray,
551
+ signature,
552
+ rawExtraFieldZip64
553
+ });
554
+ return fileEntry;
555
+ }
556
+
557
+ function getHeaderInfo(options) {
558
+ const {
559
+ rawFilename,
560
+ lastAccessDate,
561
+ creationDate,
562
+ password,
563
+ level,
564
+ zip64,
565
+ zipCrypto,
566
+ dataDescriptor,
567
+ directory,
568
+ rawExtraField,
569
+ encryptionStrength,
570
+ extendedTimestamp,
571
+ } = options;
572
+ let version = options.version || VERSION_DEFLATE;
453
573
  const compressed = level !== 0 && !directory;
574
+ const encrypted = Boolean(password && password.length);
454
575
  let rawExtraFieldAES;
455
576
  if (encrypted && !zipCrypto) {
456
577
  rawExtraFieldAES = new Uint8Array(EXTRAFIELD_DATA_AES.length + 2);
@@ -494,27 +615,6 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
494
615
  } else {
495
616
  rawExtraFieldNTFS = rawExtraFieldExtendedTimestamp = new Uint8Array();
496
617
  }
497
- const fileEntry = {
498
- lock: pendingFileEntry.lock,
499
- version: version || VERSION_DEFLATE,
500
- versionMadeBy,
501
- zip64,
502
- directory: Boolean(directory),
503
- filenameUTF8: true,
504
- rawFilename,
505
- commentUTF8: true,
506
- rawComment,
507
- rawExtraFieldZip64: zip64 ? new Uint8Array(EXTRAFIELD_LENGTH_ZIP64 + 4) : new Uint8Array(),
508
- rawExtraFieldExtendedTimestamp,
509
- rawExtraFieldNTFS,
510
- rawExtraFieldAES,
511
- rawExtraField,
512
- extendedTimestamp,
513
- msDosCompatible,
514
- internalFileAttribute,
515
- externalFileAttribute
516
- };
517
- let uncompressedSize = 0;
518
618
  let bitFlag = BITFLAG_LANG_ENCODING_FLAG;
519
619
  if (dataDescriptor) {
520
620
  bitFlag = bitFlag | BITFLAG_DATA_DESCRIPTOR;
@@ -524,22 +624,21 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
524
624
  compressionMethod = COMPRESSION_METHOD_DEFLATE;
525
625
  }
526
626
  if (zip64) {
527
- fileEntry.version = fileEntry.version > VERSION_ZIP64 ? fileEntry.version : VERSION_ZIP64;
627
+ version = version > VERSION_ZIP64 ? version : VERSION_ZIP64;
528
628
  }
529
629
  if (encrypted) {
530
630
  bitFlag = bitFlag | BITFLAG_ENCRYPTED;
531
631
  if (!zipCrypto) {
532
- fileEntry.version = fileEntry.version > VERSION_AES ? fileEntry.version : VERSION_AES;
632
+ version = version > VERSION_AES ? version : VERSION_AES;
533
633
  compressionMethod = COMPRESSION_METHOD_AES;
534
634
  if (compressed) {
535
- fileEntry.rawExtraFieldAES[9] = COMPRESSION_METHOD_DEFLATE;
635
+ rawExtraFieldAES[9] = COMPRESSION_METHOD_DEFLATE;
536
636
  }
537
637
  }
538
638
  }
539
- fileEntry.compressionMethod = compressionMethod;
540
- const headerArray = fileEntry.headerArray = new Uint8Array(26);
639
+ const headerArray = new Uint8Array(26);
541
640
  const headerView = getDataView(headerArray);
542
- setUint16(headerView, 0, fileEntry.version);
641
+ setUint16(headerView, 0, version);
543
642
  setUint16(headerView, 2, bitFlag);
544
643
  setUint16(headerView, 4, compressionMethod);
545
644
  const dateArray = new Uint32Array(1);
@@ -568,41 +667,28 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
568
667
  arraySet(localHeaderArray, rawExtraFieldExtendedTimestamp, 30 + rawFilename.length + rawExtraFieldAES.length);
569
668
  arraySet(localHeaderArray, rawExtraFieldNTFS, 30 + rawFilename.length + rawExtraFieldAES.length + rawExtraFieldExtendedTimestamp.length);
570
669
  arraySet(localHeaderArray, rawExtraField, 30 + rawFilename.length + rawExtraFieldAES.length + rawExtraFieldExtendedTimestamp.length + rawExtraFieldNTFS.length);
571
- let result;
572
- let compressedSize = 0;
573
- const { writable } = writer;
574
- fileEntry.writingData = pendingFileEntry.writingData = true;
575
- if (reader) {
576
- reader.chunkSize = getChunkSize(config);
577
- await writeData(writable, localHeaderArray);
578
- const size = () => reader.size;
579
- const readable = reader.readable;
580
- readable.size = size;
581
- const workerOptions = {
582
- options: {
583
- codecType: CODEC_DEFLATE,
584
- level,
585
- password,
586
- encryptionStrength,
587
- zipCrypto: encrypted && zipCrypto,
588
- passwordVerification: encrypted && zipCrypto && (rawLastModDate >> 8) & 0xFF,
589
- signed: true,
590
- compressed,
591
- encrypted,
592
- useWebWorkers,
593
- useCompressionStream
594
- },
595
- config,
596
- streamOptions: { signal, size, onstart, onprogress, onend },
597
- codecConstructor: config.Deflate
598
- };
599
- const previousSize = writable.size;
600
- result = await runWorker({ readable, writable }, workerOptions);
601
- uncompressedSize = reader.size = readable.size();
602
- compressedSize = writable.size - previousSize;
603
- } else {
604
- await writeData(writable, localHeaderArray);
605
- }
670
+ return {
671
+ localHeaderArray,
672
+ headerArray,
673
+ headerView,
674
+ lastModDate,
675
+ rawLastModDate,
676
+ encrypted,
677
+ compressed,
678
+ version,
679
+ compressionMethod,
680
+ rawExtraFieldExtendedTimestamp,
681
+ rawExtraFieldNTFS,
682
+ rawExtraFieldAES
683
+ };
684
+ }
685
+
686
+ function getDataDescriptorInfo(options) {
687
+ const {
688
+ zip64,
689
+ dataDescriptor,
690
+ dataDescriptorSignature
691
+ } = options;
606
692
  let dataDescriptorArray = new Uint8Array();
607
693
  let dataDescriptorView, dataDescriptorOffset = 0;
608
694
  if (dataDescriptor) {
@@ -613,51 +699,61 @@ async function createFileEntry(reader, writer, pendingFileEntry, config, options
613
699
  setUint32(dataDescriptorView, 0, DATA_DESCRIPTOR_RECORD_SIGNATURE);
614
700
  }
615
701
  }
616
- if (reader) {
617
- const { signature } = result;
618
- if ((!encrypted || zipCrypto) && signature !== undefined) {
619
- setUint32(headerView, 10, signature);
620
- fileEntry.signature = signature;
621
- if (dataDescriptor) {
622
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
623
- }
624
- }
625
- if (zip64) {
626
- const rawExtraFieldZip64View = getDataView(fileEntry.rawExtraFieldZip64);
627
- setUint16(rawExtraFieldZip64View, 0, EXTRAFIELD_TYPE_ZIP64);
628
- setUint16(rawExtraFieldZip64View, 2, EXTRAFIELD_LENGTH_ZIP64);
629
- setUint32(headerView, 14, MAX_32_BITS);
630
- setBigUint64(rawExtraFieldZip64View, 12, BigInt(compressedSize));
631
- setUint32(headerView, 18, MAX_32_BITS);
632
- setBigUint64(rawExtraFieldZip64View, 4, BigInt(uncompressedSize));
633
- if (dataDescriptor) {
634
- setBigUint64(dataDescriptorView, dataDescriptorOffset + 4, BigInt(compressedSize));
635
- setBigUint64(dataDescriptorView, dataDescriptorOffset + 12, BigInt(uncompressedSize));
636
- }
637
- } else {
638
- setUint32(headerView, 14, compressedSize);
639
- setUint32(headerView, 18, uncompressedSize);
640
- if (dataDescriptor) {
641
- setUint32(dataDescriptorView, dataDescriptorOffset + 4, compressedSize);
642
- setUint32(dataDescriptorView, dataDescriptorOffset + 8, uncompressedSize);
643
- }
702
+ return {
703
+ dataDescriptorArray,
704
+ dataDescriptorView,
705
+ dataDescriptorOffset
706
+ };
707
+ }
708
+
709
+ function setEntryInfo(entryInfo, options) {
710
+ const {
711
+ signature,
712
+ rawExtraFieldZip64,
713
+ compressedSize,
714
+ uncompressedSize,
715
+ headerInfo,
716
+ dataDescriptorInfo
717
+ } = entryInfo;
718
+ const {
719
+ headerView,
720
+ encrypted
721
+ } = headerInfo;
722
+ const {
723
+ dataDescriptorView,
724
+ dataDescriptorOffset
725
+ } = dataDescriptorInfo;
726
+ const {
727
+ zip64,
728
+ zipCrypto,
729
+ dataDescriptor
730
+ } = options;
731
+ if ((!encrypted || zipCrypto) && signature !== undefined) {
732
+ setUint32(headerView, 10, signature);
733
+ if (dataDescriptor) {
734
+ setUint32(dataDescriptorView, dataDescriptorOffset, signature);
644
735
  }
645
736
  }
646
- if (dataDescriptor) {
647
- await writeData(writable, dataDescriptorArray);
737
+ if (zip64) {
738
+ const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
739
+ setUint16(rawExtraFieldZip64View, 0, EXTRAFIELD_TYPE_ZIP64);
740
+ setUint16(rawExtraFieldZip64View, 2, EXTRAFIELD_LENGTH_ZIP64);
741
+ setUint32(headerView, 14, MAX_32_BITS);
742
+ setBigUint64(rawExtraFieldZip64View, 12, BigInt(compressedSize));
743
+ setUint32(headerView, 18, MAX_32_BITS);
744
+ setBigUint64(rawExtraFieldZip64View, 4, BigInt(uncompressedSize));
745
+ if (dataDescriptor) {
746
+ setBigUint64(dataDescriptorView, dataDescriptorOffset + 4, BigInt(compressedSize));
747
+ setBigUint64(dataDescriptorView, dataDescriptorOffset + 12, BigInt(uncompressedSize));
748
+ }
749
+ } else {
750
+ setUint32(headerView, 14, compressedSize);
751
+ setUint32(headerView, 18, uncompressedSize);
752
+ if (dataDescriptor) {
753
+ setUint32(dataDescriptorView, dataDescriptorOffset + 4, compressedSize);
754
+ setUint32(dataDescriptorView, dataDescriptorOffset + 8, uncompressedSize);
755
+ }
648
756
  }
649
- const length = localHeaderArray.length + compressedSize + dataDescriptorArray.length;
650
- Object.assign(fileEntry, {
651
- compressedSize,
652
- lastModDate,
653
- rawLastModDate,
654
- creationDate,
655
- lastAccessDate,
656
- encrypted,
657
- length,
658
- writingData: false
659
- });
660
- return fileEntry;
661
757
  }
662
758
 
663
759
  async function closeFile(zipWriter, comment, options) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.6.20",
6
+ "version": "2.6.23",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -53,20 +53,26 @@ async function test() {
53
53
  zip.configure({ chunkSize: 128, useWebWorkers: true });
54
54
  const blobWriter = new CustomBlobWriter("application/zip");
55
55
  blobWriter.writable.size = 0;
56
- const array = new Uint8Array(64 * 1024 * 1024);
57
- for (let index = 0; index < 64; index++) {
56
+ let array = new Uint8Array(64 * 1024 * 1024);
57
+ for (let index = 0; index < 63; index++) {
58
58
  blobWriter.writeUint8Array(array);
59
59
  blobWriter.writable.size += array.length;
60
60
  }
61
+ array = new Uint8Array((64 * 1024 * 1024) - 1265);
62
+ blobWriter.writeUint8Array(array);
63
+ blobWriter.writable.size += array.length;
61
64
  const zipWriter = new zip.ZipWriter(blobWriter, { keepOrder: true });
62
- await zipWriter.add(FILENAME, new zip.BlobReader(BLOB));
65
+ await Promise.all([
66
+ zipWriter.add(FILENAME, new zip.BlobReader(BLOB)),
67
+ zipWriter.add(FILENAME + "1", new zip.BlobReader(BLOB)),
68
+ zipWriter.add(FILENAME + "2", new zip.BlobReader(BLOB))
69
+ ]);
63
70
  await zipWriter.close();
64
71
  const zipReader = new zip.ZipReader(new zip.BlobReader(await blobWriter.getData()));
65
72
  const entries = await zipReader.getEntries();
66
- const data = await entries[0].getData(new zip.BlobWriter(zip.getMimeType(entries[0].filename)));
67
73
  await zipReader.close();
68
74
  zip.terminateWorkers();
69
- if (TEXT_CONTENT != await data.text() && !entries[0].zip64) {
75
+ if (entries[0].zip64 || entries[1].zip64 || !entries[2].zip64) {
70
76
  throw new Error();
71
77
  }
72
78
  }