@zip.js/zip.js 2.6.43 → 2.6.45

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.
@@ -75,7 +75,7 @@ import {
75
75
  import {
76
76
  initStream,
77
77
  BlobWriter,
78
- SplitZipWriter
78
+ SplitDataWriter
79
79
  } from "./io.js";
80
80
  import { encodeText } from "./util/encode-text.js";
81
81
  import {
@@ -109,7 +109,7 @@ class ZipWriter {
109
109
 
110
110
  constructor(writer, options = {}) {
111
111
  if (writer.writable === UNDEFINED_VALUE && typeof writer.next == FUNCTION_TYPE) {
112
- writer = new SplitZipWriter(writer);
112
+ writer = new SplitDataWriter(writer);
113
113
  }
114
114
  if (writer instanceof WritableStream) {
115
115
  writer = { writable: writer };
@@ -117,12 +117,13 @@ class ZipWriter {
117
117
  if (writer.writable.size === UNDEFINED_VALUE) {
118
118
  writer.writable.size = 0;
119
119
  }
120
- const splitZipFile = writer instanceof SplitZipWriter;
120
+ const splitZipFile = writer instanceof SplitDataWriter;
121
121
  if (!splitZipFile) {
122
122
  Object.assign(writer, {
123
123
  diskNumber: 0,
124
124
  diskOffset: 0,
125
- availableSize: Infinity
125
+ availableSize: Infinity,
126
+ maxSize: Infinity
126
127
  });
127
128
  }
128
129
  Object.assign(this, {
@@ -174,13 +175,15 @@ class ZipWriter {
174
175
  }
175
176
 
176
177
  async close(comment = new Uint8Array(), options = {}) {
178
+ const zipWriter = this;
177
179
  const { pendingAddFileCalls, writer } = this;
178
180
  const { writable } = writer;
179
181
  while (pendingAddFileCalls.size) {
180
182
  await Promise.all(Array.from(pendingAddFileCalls));
181
183
  }
182
184
  await closeFile(this, comment, options);
183
- if (!writer.preventClose && !options.preventClose) {
185
+ const preventClose = getOptionValue(zipWriter, options, "preventClose");
186
+ if (!preventClose) {
184
187
  await writable.close();
185
188
  }
186
189
  return writer.getData ? writer.getData() : writable;
@@ -216,20 +219,33 @@ async function addFile(zipWriter, name, reader, options) {
216
219
  if (getLength(rawComment) > MAX_16_BITS) {
217
220
  throw new Error(ERR_INVALID_ENTRY_COMMENT);
218
221
  }
219
- const version = zipWriter.options.version || options.version || 0;
222
+ const version = getOptionValue(zipWriter, options, "version", VERSION_DEFLATE);
220
223
  if (version > MAX_16_BITS) {
221
224
  throw new Error(ERR_INVALID_VERSION);
222
225
  }
223
- const versionMadeBy = zipWriter.options.versionMadeBy || options.versionMadeBy || 20;
226
+ const versionMadeBy = getOptionValue(zipWriter, options, "versionMadeBy", 20);
224
227
  if (versionMadeBy > MAX_16_BITS) {
225
228
  throw new Error(ERR_INVALID_VERSION);
226
229
  }
227
- const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE) || new Date();
230
+ const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
228
231
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
229
232
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
233
+ const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE, true);
234
+ const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
235
+ const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
230
236
  const password = getOptionValue(zipWriter, options, "password");
231
- const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength") || 3;
237
+ const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength", 3);
232
238
  const zipCrypto = getOptionValue(zipWriter, options, "zipCrypto");
239
+ const extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp", true);
240
+ const keepOrder = getOptionValue(zipWriter, options, "keepOrder", true);
241
+ const level = getOptionValue(zipWriter, options, "level");
242
+ const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
243
+ const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
244
+ const dataDescriptorSignature = getOptionValue(zipWriter, options, "dataDescriptorSignature", false);
245
+ const signal = getOptionValue(zipWriter, options, "signal");
246
+ const useCompressionStream = getOptionValue(zipWriter, options, "useCompressionStream");
247
+ let dataDescriptor = getOptionValue(zipWriter, options, "dataDescriptor", true);
248
+ let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
233
249
  if (password !== UNDEFINED_VALUE && encryptionStrength !== UNDEFINED_VALUE && (encryptionStrength < 1 || encryptionStrength > 3)) {
234
250
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
235
251
  }
@@ -253,24 +269,9 @@ async function addFile(zipWriter, name, reader, options) {
253
269
  offset += 4 + getLength(data);
254
270
  });
255
271
  }
256
- let extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp");
257
- if (extendedTimestamp === UNDEFINED_VALUE) {
258
- extendedTimestamp = true;
259
- }
260
272
  let maximumCompressedSize = 0;
261
273
  let maximumEntrySize = 0;
262
- let keepOrder = getOptionValue(zipWriter, options, "keepOrder");
263
- if (keepOrder === UNDEFINED_VALUE) {
264
- keepOrder = true;
265
- }
266
274
  let uncompressedSize = 0;
267
- let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
268
- if (msDosCompatible === UNDEFINED_VALUE) {
269
- msDosCompatible = true;
270
- }
271
- const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE) || 0;
272
- const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE) || 0;
273
- let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
274
275
  if (reader) {
275
276
  if (reader instanceof ReadableStream) {
276
277
  reader = {
@@ -279,7 +280,7 @@ async function addFile(zipWriter, name, reader, options) {
279
280
  }
280
281
  await initStream(reader);
281
282
  if (reader.size === UNDEFINED_VALUE) {
282
- options.dataDescriptor = true;
283
+ dataDescriptor = true;
283
284
  if (zip64 || zip64 === UNDEFINED_VALUE) {
284
285
  zip64 = true;
285
286
  maximumCompressedSize = MAX_32_BITS;
@@ -289,10 +290,11 @@ async function addFile(zipWriter, name, reader, options) {
289
290
  maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
290
291
  }
291
292
  }
292
- const { diskOffset } = zipWriter.writer;
293
+ const { diskOffset, diskNumber, maxSize } = zipWriter.writer;
293
294
  if (zipWriter.offset + zipWriter.pendingEntriesSize - diskOffset >= MAX_32_BITS ||
294
295
  uncompressedSize >= MAX_32_BITS ||
295
- maximumCompressedSize >= MAX_32_BITS) {
296
+ maximumCompressedSize >= MAX_32_BITS ||
297
+ diskNumber + Math.ceil(zipWriter.pendingEntriesSize / maxSize) >= MAX_16_BITS) {
296
298
  if (zip64 === false || !keepOrder) {
297
299
  throw new Error(ERR_UNSUPPORTED_FORMAT);
298
300
  } else {
@@ -300,19 +302,6 @@ async function addFile(zipWriter, name, reader, options) {
300
302
  }
301
303
  }
302
304
  zip64 = zip64 || false;
303
- const level = getOptionValue(zipWriter, options, "level");
304
- const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
305
- const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
306
- let dataDescriptor = getOptionValue(zipWriter, options, "dataDescriptor");
307
- let dataDescriptorSignature = getOptionValue(zipWriter, options, "dataDescriptorSignature");
308
- const signal = getOptionValue(zipWriter, options, "signal");
309
- const useCompressionStream = getOptionValue(zipWriter, options, "useCompressionStream");
310
- if (dataDescriptor === UNDEFINED_VALUE) {
311
- dataDescriptor = true;
312
- }
313
- if (dataDescriptor && dataDescriptorSignature === UNDEFINED_VALUE) {
314
- dataDescriptorSignature = false;
315
- }
316
305
  options = Object.assign({}, options, {
317
306
  rawFilename,
318
307
  rawComment,
@@ -385,8 +374,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
385
374
  await initStream(writer);
386
375
  } else {
387
376
  fileWriter = writer;
388
- zipWriter.lockWriter = Promise.resolve();
389
- releaseLockWriter = () => delete zipWriter.lockWriter;
377
+ initLockWriter();
390
378
  }
391
379
  await initStream(fileWriter);
392
380
  const { writable, diskNumber } = writer;
@@ -415,7 +403,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
415
403
  await requestLockWriter();
416
404
  writingBufferedEntryData = true;
417
405
  if (!dataDescriptor) {
418
- blob = await setMissingInfo(fileEntry, blob, writable, options);
406
+ blob = await writeMissingHeaderInfo(fileEntry, blob, writable, options);
419
407
  }
420
408
  fileEntry.diskNumberStart = writer.diskNumber;
421
409
  diskOffset = writer.diskOffset;
@@ -425,7 +413,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
425
413
  }
426
414
  fileEntry.offset = zipWriter.offset - diskOffset;
427
415
  if (fileEntry.zip64) {
428
- setZip64Info(fileEntry);
416
+ setZip64OffsetInfo(fileEntry);
429
417
  } else if (fileEntry.offset >= MAX_32_BITS) {
430
418
  throw new Error(ERR_UNSUPPORTED_FORMAT);
431
419
  }
@@ -458,6 +446,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
458
446
  fileEntry.lock = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
459
447
  }
460
448
 
449
+ function initLockWriter() {
450
+ zipWriter.lockWriter = Promise.resolve();
451
+ releaseLockWriter = () => delete zipWriter.lockWriter;
452
+ }
453
+
461
454
  async function requestLockWriter() {
462
455
  const { lockWriter } = zipWriter;
463
456
  if (lockWriter) {
@@ -616,6 +609,7 @@ function getHeaderInfo(options) {
616
609
  } = options;
617
610
  const compressed = level !== 0 && !directory;
618
611
  const encrypted = Boolean(password && getLength(password));
612
+ let version = options.version;
619
613
  let rawExtraFieldAES;
620
614
  if (encrypted && !zipCrypto) {
621
615
  rawExtraFieldAES = new Uint8Array(getLength(EXTRAFIELD_DATA_AES) + 2);
@@ -667,7 +661,6 @@ function getHeaderInfo(options) {
667
661
  if (compressed) {
668
662
  compressionMethod = COMPRESSION_METHOD_DEFLATE;
669
663
  }
670
- let version = options.version || VERSION_DEFLATE;
671
664
  if (zip64) {
672
665
  version = version > VERSION_ZIP64 ? version : VERSION_ZIP64;
673
666
  }
@@ -801,7 +794,7 @@ function setEntryInfo(entryInfo, options) {
801
794
  }
802
795
  }
803
796
 
804
- async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
797
+ async function writeMissingHeaderInfo(fileEntry, entryData, writable, { zipCrypto }) {
805
798
  const arrayBuffer = await sliceAsArrayBuffer(entryData, 0, 26);
806
799
  const arrayBufferView = new DataView(arrayBuffer);
807
800
  if (!fileEntry.encrypted || zipCrypto) {
@@ -818,7 +811,7 @@ async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
818
811
  return entryData.slice(arrayBuffer.byteLength);
819
812
  }
820
813
 
821
- function setZip64Info(fileEntry) {
814
+ function setZip64OffsetInfo(fileEntry) {
822
815
  const { rawExtraFieldZip64, offset, diskNumberStart } = fileEntry;
823
816
  const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
824
817
  setBigUint64(rawExtraFieldZip64View, 20, BigInt(offset));
@@ -827,10 +820,10 @@ function setZip64Info(fileEntry) {
827
820
 
828
821
  async function closeFile(zipWriter, comment, options) {
829
822
  const { files, writer } = zipWriter;
830
- let offset = 0;
831
- let directoryDataLength = 0;
832
823
  const { diskOffset, writable } = writer;
833
824
  let { diskNumber } = writer;
825
+ let offset = 0;
826
+ let directoryDataLength = 0;
834
827
  let directoryOffset = zipWriter.offset - diskOffset;
835
828
  let filesLength = files.size;
836
829
  for (const [, {
@@ -852,14 +845,6 @@ async function closeFile(zipWriter, comment, options) {
852
845
  rawExtraFieldNTFS,
853
846
  rawExtraField);
854
847
  }
855
- let zip64 = options.zip64 || zipWriter.options.zip64 || false;
856
- if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS) {
857
- if (options.zip64 === false || zipWriter.options.zip64 === false) {
858
- throw new Error(ERR_UNSUPPORTED_FORMAT);
859
- } else {
860
- zip64 = true;
861
- }
862
- }
863
848
  const directoryArray = new Uint8Array(directoryDataLength);
864
849
  const directoryView = getDataView(directoryArray);
865
850
  for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
@@ -925,13 +910,21 @@ async function closeFile(zipWriter, comment, options) {
925
910
  }
926
911
  await initStream(writer);
927
912
  await writeData(writable, directoryArray);
928
- const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
929
- const endOfdirectoryView = getDataView(endOfdirectoryArray);
930
913
  let lastDiskNumber = writer.diskNumber;
931
914
  const { availableSize } = writer;
932
- if (availableSize < getLength(endOfdirectoryArray)) {
915
+ if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
933
916
  lastDiskNumber++;
934
917
  }
918
+ let zip64 = getOptionValue(zipWriter, options, "zip64");
919
+ if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
920
+ if (zip64 === false) {
921
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
922
+ } else {
923
+ zip64 = true;
924
+ }
925
+ }
926
+ const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
927
+ const endOfdirectoryView = getDataView(endOfdirectoryArray);
935
928
  offset = 0;
936
929
  if (zip64) {
937
930
  setUint32(endOfdirectoryView, 0, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
@@ -996,8 +989,9 @@ function getTimeNTFS(date) {
996
989
  }
997
990
  }
998
991
 
999
- function getOptionValue(zipWriter, options, name) {
1000
- return options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
992
+ function getOptionValue(zipWriter, options, name, defaultValue) {
993
+ const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
994
+ return result === UNDEFINED_VALUE ? defaultValue : result;
1001
995
  }
1002
996
 
1003
997
  function getMaximumCompressedSize(uncompressedSize) {
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.43",
6
+ "version": "2.6.45",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -24,7 +24,7 @@ export { test };
24
24
  async function test() {
25
25
  zip.configure({ chunkSize: 16 * 1024, useWebWorkers: true });
26
26
  const readers = PATHS.map(url => new zip.HttpReader(new URL(url, import.meta.url).href, { preventHeadRequest: true }));
27
- const zipReader = new zip.ZipReader(new zip.SplitZipReader(readers));
27
+ const zipReader = new zip.ZipReader(new zip.SplitDataReader(readers));
28
28
  const entries = await zipReader.getEntries();
29
29
  const results = await Promise.all(UNCOMPRESSED_SIZES.map(async (uncompressedSize, indexEntry) =>
30
30
  (await entries[indexEntry].getData(new zip.TextWriter())).length == uncompressedSize
@@ -0,0 +1,38 @@
1
+ /* global Blob, TextDecoder */
2
+
3
+ import * as zip from "../../index.js";
4
+
5
+ const TEXT_CONTENT = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.";
6
+ const BLOB_CONTENT = new Blob([TEXT_CONTENT]);
7
+
8
+ export { test };
9
+
10
+ const writers = [];
11
+
12
+ function* arrayWriterGenerator() {
13
+ while (true) {
14
+ const writer = new zip.Uint8ArrayWriter();
15
+ writers.push(writer);
16
+ yield writer;
17
+ }
18
+ }
19
+
20
+ async function test() {
21
+ zip.configure({ chunkSize: 1024, useWebWorkers: true });
22
+ const zipWriter = new zip.ZipWriter(new zip.BlobWriter());
23
+ const readers = [
24
+ new zip.TextReader(TEXT_CONTENT),
25
+ new zip.BlobReader(BLOB_CONTENT)
26
+ ];
27
+ await zipWriter.add("loremx2.txt", new zip.SplitDataReader(readers));
28
+ const blob = await zipWriter.close();
29
+ const zipReader = new zip.ZipReader(new zip.BlobReader(blob));
30
+ const firstEntry = (await zipReader.getEntries()).shift();
31
+ await firstEntry.getData(new zip.SplitDataWriter(arrayWriterGenerator(), 128));
32
+ const chunks = await Promise.all(writers.map(writer => writer.getData()));
33
+ const text = new TextDecoder().decode(new Uint8Array(chunks.map(data => Array.from(data)).flat()));
34
+ zip.terminateWorkers();
35
+ if (text != TEXT_CONTENT + TEXT_CONTENT) {
36
+ throw new Error();
37
+ }
38
+ }
@@ -20,7 +20,7 @@ function* blobWriterGenerator() {
20
20
 
21
21
  async function test() {
22
22
  zip.configure({ chunkSize: 1024, useWebWorkers: true });
23
- const splitZipWriter = new zip.SplitZipWriter(blobWriterGenerator(), 8192);
23
+ const splitZipWriter = new zip.SplitDataWriter(blobWriterGenerator(), 8192);
24
24
  const zipWriter = new zip.ZipWriter(splitZipWriter);
25
25
  await Promise.all([
26
26
  zipWriter.add("lorem1.txt", new zip.BlobReader(BLOB)),
@@ -29,7 +29,7 @@ async function test() {
29
29
  ]);
30
30
  await zipWriter.close();
31
31
  const readers = await Promise.all(writers.map(async writer => new zip.BlobReader(await writer.getData())));
32
- const zipReader = new zip.ZipReader(new zip.SplitZipReader(readers));
32
+ const zipReader = new zip.ZipReader(new zip.SplitDataReader(readers));
33
33
  const entries = await zipReader.getEntries();
34
34
  const results = await Promise.all(entries.map(async entry => (await entry.getData(new zip.TextWriter())).length == TEXT_CONTENT.length * TEXT_CONTENT_REPEAT));
35
35
  await zipReader.close();
@@ -41,7 +41,8 @@ export default ([
41
41
  { title: "Safe closing", script: "./test-safe-closing.js" },
42
42
  { title: "Service worker", script: "./test-sw.js", env: ["browser"] },
43
43
  { title: "Signature CRC32", script: "./test-crc.js" },
44
- { title: "Split file", script: "./test-split-zip.js" },
44
+ { title: "Split data", script: "./test-split-data.js" },
45
+ { title: "Split zip file", script: "./test-split-zip.js" },
45
46
  { title: "Store", script: "./test-store.js" },
46
47
  { title: "Streams", script: "./test-streams.js" },
47
48
  { title: "Worker timeout", script: "./test-worker-timeout.js" },