@zip.js/zip.js 2.6.42 → 2.6.44

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,7 +117,7 @@ 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,
@@ -174,13 +174,15 @@ class ZipWriter {
174
174
  }
175
175
 
176
176
  async close(comment = new Uint8Array(), options = {}) {
177
+ const zipWriter = this;
177
178
  const { pendingAddFileCalls, writer } = this;
178
179
  const { writable } = writer;
179
180
  while (pendingAddFileCalls.size) {
180
181
  await Promise.all(Array.from(pendingAddFileCalls));
181
182
  }
182
183
  await closeFile(this, comment, options);
183
- if (!writer.preventClose && !options.preventClose) {
184
+ const preventClose = getOptionValue(zipWriter, options, "preventClose");
185
+ if (!preventClose) {
184
186
  await writable.close();
185
187
  }
186
188
  return writer.getData ? writer.getData() : writable;
@@ -216,20 +218,33 @@ async function addFile(zipWriter, name, reader, options) {
216
218
  if (getLength(rawComment) > MAX_16_BITS) {
217
219
  throw new Error(ERR_INVALID_ENTRY_COMMENT);
218
220
  }
219
- const version = zipWriter.options.version || options.version || 0;
221
+ const version = getOptionValue(zipWriter, options, "version", VERSION_DEFLATE);
220
222
  if (version > MAX_16_BITS) {
221
223
  throw new Error(ERR_INVALID_VERSION);
222
224
  }
223
- const versionMadeBy = zipWriter.options.versionMadeBy || options.versionMadeBy || 20;
225
+ const versionMadeBy = getOptionValue(zipWriter, options, "versionMadeBy", 20);
224
226
  if (versionMadeBy > MAX_16_BITS) {
225
227
  throw new Error(ERR_INVALID_VERSION);
226
228
  }
227
- const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE) || new Date();
229
+ const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
228
230
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
229
231
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
232
+ const msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE, true);
233
+ const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
234
+ const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
230
235
  const password = getOptionValue(zipWriter, options, "password");
231
- const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength") || 3;
236
+ const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength", 3);
232
237
  const zipCrypto = getOptionValue(zipWriter, options, "zipCrypto");
238
+ const extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp", true);
239
+ const keepOrder = getOptionValue(zipWriter, options, "keepOrder", true);
240
+ const level = getOptionValue(zipWriter, options, "level");
241
+ const useWebWorkers = getOptionValue(zipWriter, options, "useWebWorkers");
242
+ const bufferedWrite = getOptionValue(zipWriter, options, "bufferedWrite");
243
+ const dataDescriptorSignature = getOptionValue(zipWriter, options, "dataDescriptorSignature", false);
244
+ const signal = getOptionValue(zipWriter, options, "signal");
245
+ const useCompressionStream = getOptionValue(zipWriter, options, "useCompressionStream");
246
+ let dataDescriptor = getOptionValue(zipWriter, options, "dataDescriptor", true);
247
+ let zip64 = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIP64);
233
248
  if (password !== UNDEFINED_VALUE && encryptionStrength !== UNDEFINED_VALUE && (encryptionStrength < 1 || encryptionStrength > 3)) {
234
249
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
235
250
  }
@@ -253,24 +268,9 @@ async function addFile(zipWriter, name, reader, options) {
253
268
  offset += 4 + getLength(data);
254
269
  });
255
270
  }
256
- let extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp");
257
- if (extendedTimestamp === UNDEFINED_VALUE) {
258
- extendedTimestamp = true;
259
- }
260
271
  let maximumCompressedSize = 0;
261
272
  let maximumEntrySize = 0;
262
- let keepOrder = getOptionValue(zipWriter, options, "keepOrder");
263
- if (keepOrder === UNDEFINED_VALUE) {
264
- keepOrder = true;
265
- }
266
273
  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
274
  if (reader) {
275
275
  if (reader instanceof ReadableStream) {
276
276
  reader = {
@@ -279,7 +279,7 @@ async function addFile(zipWriter, name, reader, options) {
279
279
  }
280
280
  await initStream(reader);
281
281
  if (reader.size === UNDEFINED_VALUE) {
282
- options.dataDescriptor = true;
282
+ dataDescriptor = true;
283
283
  if (zip64 || zip64 === UNDEFINED_VALUE) {
284
284
  zip64 = true;
285
285
  maximumCompressedSize = MAX_32_BITS;
@@ -289,10 +289,11 @@ async function addFile(zipWriter, name, reader, options) {
289
289
  maximumCompressedSize = getMaximumCompressedSize(uncompressedSize);
290
290
  }
291
291
  }
292
- const { diskOffset } = zipWriter.writer;
292
+ const { diskOffset, diskNumber } = zipWriter.writer;
293
293
  if (zipWriter.offset + zipWriter.pendingEntriesSize - diskOffset >= MAX_32_BITS ||
294
294
  uncompressedSize >= MAX_32_BITS ||
295
- maximumCompressedSize >= MAX_32_BITS) {
295
+ maximumCompressedSize >= MAX_32_BITS ||
296
+ diskNumber >= MAX_16_BITS) {
296
297
  if (zip64 === false || !keepOrder) {
297
298
  throw new Error(ERR_UNSUPPORTED_FORMAT);
298
299
  } else {
@@ -300,19 +301,6 @@ async function addFile(zipWriter, name, reader, options) {
300
301
  }
301
302
  }
302
303
  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
304
  options = Object.assign({}, options, {
317
305
  rawFilename,
318
306
  rawComment,
@@ -346,12 +334,8 @@ async function addFile(zipWriter, name, reader, options) {
346
334
  let fileEntry;
347
335
  try {
348
336
  fileEntry = await getFileEntry(zipWriter, name, reader, { headerInfo, dataDescriptorInfo }, options);
337
+ } finally {
349
338
  zipWriter.pendingEntriesSize -= maximumEntrySize;
350
- } catch (error) {
351
- if (!error.corruptedEntry) {
352
- zipWriter.pendingEntriesSize -= maximumEntrySize;
353
- }
354
- throw error;
355
339
  }
356
340
  Object.assign(fileEntry, { name, comment, extraField });
357
341
  return new Entry(fileEntry);
@@ -389,8 +373,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
389
373
  await initStream(writer);
390
374
  } else {
391
375
  fileWriter = writer;
392
- zipWriter.lockWriter = Promise.resolve();
393
- releaseLockWriter = () => delete zipWriter.lockWriter;
376
+ initLockWriter();
394
377
  }
395
378
  await initStream(fileWriter);
396
379
  const { writable, diskNumber } = writer;
@@ -419,7 +402,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
419
402
  await requestLockWriter();
420
403
  writingBufferedEntryData = true;
421
404
  if (!dataDescriptor) {
422
- blob = await setMissingInfo(fileEntry, blob, writable, options);
405
+ blob = await writeMissingHeaderInfo(fileEntry, blob, writable, options);
423
406
  }
424
407
  fileEntry.diskNumberStart = writer.diskNumber;
425
408
  diskOffset = writer.diskOffset;
@@ -429,7 +412,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
429
412
  }
430
413
  fileEntry.offset = zipWriter.offset - diskOffset;
431
414
  if (fileEntry.zip64) {
432
- setZip64Info(fileEntry);
415
+ setZip64OffsetInfo(fileEntry);
433
416
  } else if (fileEntry.offset >= MAX_32_BITS) {
434
417
  throw new Error(ERR_UNSUPPORTED_FORMAT);
435
418
  }
@@ -462,6 +445,11 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
462
445
  fileEntry.lock = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
463
446
  }
464
447
 
448
+ function initLockWriter() {
449
+ zipWriter.lockWriter = Promise.resolve();
450
+ releaseLockWriter = () => delete zipWriter.lockWriter;
451
+ }
452
+
465
453
  async function requestLockWriter() {
466
454
  const { lockWriter } = zipWriter;
467
455
  if (lockWriter) {
@@ -620,6 +608,7 @@ function getHeaderInfo(options) {
620
608
  } = options;
621
609
  const compressed = level !== 0 && !directory;
622
610
  const encrypted = Boolean(password && getLength(password));
611
+ let version = options.version;
623
612
  let rawExtraFieldAES;
624
613
  if (encrypted && !zipCrypto) {
625
614
  rawExtraFieldAES = new Uint8Array(getLength(EXTRAFIELD_DATA_AES) + 2);
@@ -671,7 +660,6 @@ function getHeaderInfo(options) {
671
660
  if (compressed) {
672
661
  compressionMethod = COMPRESSION_METHOD_DEFLATE;
673
662
  }
674
- let version = options.version || VERSION_DEFLATE;
675
663
  if (zip64) {
676
664
  version = version > VERSION_ZIP64 ? version : VERSION_ZIP64;
677
665
  }
@@ -805,7 +793,7 @@ function setEntryInfo(entryInfo, options) {
805
793
  }
806
794
  }
807
795
 
808
- async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
796
+ async function writeMissingHeaderInfo(fileEntry, entryData, writable, { zipCrypto }) {
809
797
  const arrayBuffer = await sliceAsArrayBuffer(entryData, 0, 26);
810
798
  const arrayBufferView = new DataView(arrayBuffer);
811
799
  if (!fileEntry.encrypted || zipCrypto) {
@@ -822,7 +810,7 @@ async function setMissingInfo(fileEntry, entryData, writable, { zipCrypto }) {
822
810
  return entryData.slice(arrayBuffer.byteLength);
823
811
  }
824
812
 
825
- function setZip64Info(fileEntry) {
813
+ function setZip64OffsetInfo(fileEntry) {
826
814
  const { rawExtraFieldZip64, offset, diskNumberStart } = fileEntry;
827
815
  const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
828
816
  setBigUint64(rawExtraFieldZip64View, 20, BigInt(offset));
@@ -831,10 +819,10 @@ function setZip64Info(fileEntry) {
831
819
 
832
820
  async function closeFile(zipWriter, comment, options) {
833
821
  const { files, writer } = zipWriter;
834
- let offset = 0;
835
- let directoryDataLength = 0;
836
822
  const { diskOffset, writable } = writer;
837
823
  let { diskNumber } = writer;
824
+ let offset = 0;
825
+ let directoryDataLength = 0;
838
826
  let directoryOffset = zipWriter.offset - diskOffset;
839
827
  let filesLength = files.size;
840
828
  for (const [, {
@@ -856,14 +844,6 @@ async function closeFile(zipWriter, comment, options) {
856
844
  rawExtraFieldNTFS,
857
845
  rawExtraField);
858
846
  }
859
- let zip64 = options.zip64 || zipWriter.options.zip64 || false;
860
- if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS) {
861
- if (options.zip64 === false || zipWriter.options.zip64 === false) {
862
- throw new Error(ERR_UNSUPPORTED_FORMAT);
863
- } else {
864
- zip64 = true;
865
- }
866
- }
867
847
  const directoryArray = new Uint8Array(directoryDataLength);
868
848
  const directoryView = getDataView(directoryArray);
869
849
  for (const [indexFileEntry, fileEntry] of Array.from(files.values()).entries()) {
@@ -929,13 +909,21 @@ async function closeFile(zipWriter, comment, options) {
929
909
  }
930
910
  await initStream(writer);
931
911
  await writeData(writable, directoryArray);
932
- const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
933
- const endOfdirectoryView = getDataView(endOfdirectoryArray);
934
912
  let lastDiskNumber = writer.diskNumber;
935
913
  const { availableSize } = writer;
936
- if (availableSize < getLength(endOfdirectoryArray)) {
914
+ if (availableSize < END_OF_CENTRAL_DIR_LENGTH) {
937
915
  lastDiskNumber++;
938
916
  }
917
+ let zip64 = getOptionValue(zipWriter, options, "zip64");
918
+ if (directoryOffset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || filesLength >= MAX_16_BITS || lastDiskNumber >= MAX_16_BITS) {
919
+ if (zip64 === false) {
920
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
921
+ } else {
922
+ zip64 = true;
923
+ }
924
+ }
925
+ const endOfdirectoryArray = new Uint8Array(zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
926
+ const endOfdirectoryView = getDataView(endOfdirectoryArray);
939
927
  offset = 0;
940
928
  if (zip64) {
941
929
  setUint32(endOfdirectoryView, 0, ZIP64_END_OF_CENTRAL_DIR_SIGNATURE);
@@ -1000,8 +988,9 @@ function getTimeNTFS(date) {
1000
988
  }
1001
989
  }
1002
990
 
1003
- function getOptionValue(zipWriter, options, name) {
1004
- return options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
991
+ function getOptionValue(zipWriter, options, name, defaultValue) {
992
+ const result = options[name] === UNDEFINED_VALUE ? zipWriter.options[name] : options[name];
993
+ return result === UNDEFINED_VALUE ? defaultValue : result;
1005
994
  }
1006
995
 
1007
996
  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.42",
6
+ "version": "2.6.44",
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,37 @@
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
+ if (text != TEXT_CONTENT + TEXT_CONTENT) {
35
+ throw new Error();
36
+ }
37
+ }
@@ -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" },