@zip.js/zip.js 2.5.3 → 2.5.4

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.
package/lib/core/io.js CHANGED
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global Blob, FileReader, atob, btoa, XMLHttpRequest, document, fetch */
29
+ /* global Blob, FileReader, atob, btoa, XMLHttpRequest, document, fetch, ReadableStream, WritableStream */
30
30
 
31
31
  const ERR_HTTP_STATUS = "HTTP error ";
32
32
  const ERR_HTTP_RANGE = "HTTP Range not supported";
@@ -40,6 +40,7 @@ const HTTP_HEADER_RANGE = "Range";
40
40
  const HTTP_METHOD_HEAD = "HEAD";
41
41
  const HTTP_METHOD_GET = "GET";
42
42
  const HTTP_RANGE_UNIT = "bytes";
43
+ const DEFAULT_CHUNK_SIZE = 64 * 1024;
43
44
 
44
45
  class Stream {
45
46
 
@@ -53,9 +54,48 @@ class Stream {
53
54
  }
54
55
 
55
56
  class Reader extends Stream {
57
+
58
+ getStream({ offset, size, chunkSize } = { offset: 0, chunkSize: DEFAULT_CHUNK_SIZE }) {
59
+ const reader = this;
60
+ return new ReadableStream({
61
+ start() {
62
+ this.chunkOffset = 0;
63
+ },
64
+ async pull(controller) {
65
+ const { chunkOffset } = this;
66
+ controller.enqueue(await reader.readUint8Array(offset + chunkOffset, Math.min(chunkSize, size() - chunkOffset)));
67
+ if (chunkOffset + chunkSize > size()) {
68
+ controller.close();
69
+ } else {
70
+ this.chunkOffset += chunkSize;
71
+ }
72
+ }
73
+ });
74
+ }
75
+ }
76
+
77
+ class WriterStream extends Stream {
78
+ getStream() {
79
+ const writer = this;
80
+ return new WritableStream({
81
+ write(chunk) {
82
+ if (chunk && chunk.length) {
83
+ return writer.writeUint8Array(chunk);
84
+ }
85
+ }
86
+ });
87
+ }
88
+
89
+ getStreamWriter() {
90
+ const writer = this;
91
+ if (!writer.streamWriter) {
92
+ writer.streamWriter = writer.getStream().getWriter();
93
+ }
94
+ return writer.streamWriter;
95
+ }
56
96
  }
57
97
 
58
- class Writer extends Stream {
98
+ class Writer extends WriterStream {
59
99
 
60
100
  writeUint8Array(array) {
61
101
  this.size += array.length;
@@ -70,9 +110,10 @@ class TextReader extends Reader {
70
110
  }
71
111
 
72
112
  init() {
113
+ const reader = this;
73
114
  super.init();
74
- this.blobReader.init();
75
- this.size = this.blobReader.size;
115
+ reader.blobReader.init();
116
+ reader.size = reader.blobReader.size;
76
117
  }
77
118
 
78
119
  readUint8Array(offset, length) {
@@ -94,14 +135,15 @@ class TextWriter extends Writer {
94
135
  }
95
136
 
96
137
  getData() {
97
- if (this.blob.text) {
98
- return this.blob.text();
138
+ const writer = this;
139
+ if (writer.blob.text) {
140
+ return writer.blob.text();
99
141
  } else {
100
142
  const reader = new FileReader();
101
143
  return new Promise((resolve, reject) => {
102
144
  reader.onload = event => resolve(event.target.result);
103
145
  reader.onerror = () => reject(reader.error);
104
- reader.readAsText(this.blob, this.encoding);
146
+ reader.readAsText(writer.blob, writer.encoding);
105
147
  });
106
148
  }
107
149
  }
@@ -111,19 +153,21 @@ class Data64URIReader extends Reader {
111
153
 
112
154
  constructor(dataURI) {
113
155
  super();
114
- this.dataURI = dataURI;
156
+ const reader = this;
157
+ reader.dataURI = dataURI;
115
158
  let dataEnd = dataURI.length;
116
159
  while (dataURI.charAt(dataEnd - 1) == "=") {
117
160
  dataEnd--;
118
161
  }
119
- this.dataStart = dataURI.indexOf(",") + 1;
120
- this.size = Math.floor((dataEnd - this.dataStart) * 0.75);
162
+ reader.dataStart = dataURI.indexOf(",") + 1;
163
+ reader.size = Math.floor((dataEnd - reader.dataStart) * 0.75);
121
164
  }
122
165
 
123
166
  readUint8Array(offset, length) {
124
167
  const dataArray = new Uint8Array(length);
125
168
  const start = Math.floor(offset / 3) * 4;
126
- const bytes = atob(this.dataURI.substring(start + this.dataStart, Math.ceil((offset + length) / 3) * 4 + this.dataStart));
169
+ const dataStart = this.dataStart;
170
+ const bytes = atob(this.dataURI.substring(start + dataStart, Math.ceil((offset + length) / 3) * 4 + dataStart));
127
171
  const delta = offset - Math.floor(start / 4) * 3;
128
172
  for (let indexByte = delta; indexByte < delta + length; indexByte++) {
129
173
  dataArray[indexByte - delta] = bytes.charCodeAt(indexByte);
@@ -142,20 +186,21 @@ class Data64URIWriter extends Writer {
142
186
 
143
187
  writeUint8Array(array) {
144
188
  super.writeUint8Array(array);
189
+ const writer = this;
145
190
  let indexArray = 0;
146
- let dataString = this.pending;
147
- const delta = this.pending.length;
148
- this.pending = "";
191
+ let dataString = writer.pending;
192
+ const delta = writer.pending.length;
193
+ writer.pending = "";
149
194
  for (indexArray = 0; indexArray < (Math.floor((delta + array.length) / 3) * 3) - delta; indexArray++) {
150
195
  dataString += String.fromCharCode(array[indexArray]);
151
196
  }
152
197
  for (; indexArray < array.length; indexArray++) {
153
- this.pending += String.fromCharCode(array[indexArray]);
198
+ writer.pending += String.fromCharCode(array[indexArray]);
154
199
  }
155
200
  if (dataString.length > 2) {
156
- this.data += btoa(dataString);
201
+ writer.data += btoa(dataString);
157
202
  } else {
158
- this.pending = dataString;
203
+ writer.pending = dataString;
159
204
  }
160
205
  }
161
206
 
@@ -173,14 +218,15 @@ class BlobReader extends Reader {
173
218
  }
174
219
 
175
220
  async readUint8Array(offset, length) {
176
- if (this.blob.arrayBuffer) {
177
- return new Uint8Array(await this.blob.slice(offset, offset + length).arrayBuffer());
221
+ const reader = this;
222
+ if (reader.blob.arrayBuffer) {
223
+ return new Uint8Array(await reader.blob.slice(offset, offset + length).arrayBuffer());
178
224
  } else {
179
225
  const reader = new FileReader();
180
226
  return new Promise((resolve, reject) => {
181
227
  reader.onload = event => resolve(new Uint8Array(event.target.result));
182
228
  reader.onerror = () => reject(reader.error);
183
- reader.readAsArrayBuffer(this.blob.slice(offset, offset + length));
229
+ reader.readAsArrayBuffer(reader.blob.slice(offset, offset + length));
184
230
  });
185
231
  }
186
232
  }
@@ -197,21 +243,23 @@ class BlobWriter extends Writer {
197
243
 
198
244
  writeUint8Array(array) {
199
245
  super.writeUint8Array(array);
200
- if (this.arrayBuffers.length == this.arrayBuffersMaxlength) {
201
- flushArrayBuffers(this);
246
+ const writer = this;
247
+ if (writer.arrayBuffers.length == writer.arrayBuffersMaxlength) {
248
+ flushArrayBuffers(writer);
202
249
  }
203
- this.arrayBuffers.push(array.buffer);
250
+ writer.arrayBuffers.push(array.buffer);
204
251
  }
205
252
 
206
253
  getData() {
207
- if (!this.blob) {
208
- if (this.arrayBuffers.length) {
209
- flushArrayBuffers(this);
254
+ const writer = this;
255
+ if (!writer.blob) {
256
+ if (writer.arrayBuffers.length) {
257
+ flushArrayBuffers(writer);
210
258
  }
211
- this.blob = this.pendingBlob;
212
- initArrayBuffers(this);
259
+ writer.blob = writer.pendingBlob;
260
+ initArrayBuffers(writer);
213
261
  }
214
- return this.blob;
262
+ return writer.blob;
215
263
  }
216
264
  }
217
265
 
@@ -229,58 +277,16 @@ class ReadableStreamReader {
229
277
 
230
278
  constructor(readableStream) {
231
279
  this.readableStream = readableStream;
232
- this.reader = readableStream.getReader();
233
280
  this.size = Infinity;
234
- this.index = 0;
235
- this.currentSize = 0;
236
- this.pendingValue = new Uint8Array();
237
281
  }
238
282
 
239
- init() {
283
+ init(size) {
284
+ this.size = size;
240
285
  this.initialized = true;
241
286
  }
242
287
 
243
- async readUint8Array(index, length) {
244
- if (this.index != index) {
245
- throw new Error(ERR_NOT_SEEKABLE_READER);
246
- }
247
- let data = new Uint8Array(length);
248
- let size = 0, done;
249
- do {
250
- const result = await this.reader.read();
251
- let { value } = result;
252
- done = result.done;
253
- if (value) {
254
- this.currentSize += value.length;
255
- } else {
256
- value = this.pendingValue;
257
- this.pendingValue = new Uint8Array();
258
- }
259
- if (this.pendingValue.length) {
260
- const newValue = new Uint8Array(this.pendingValue.length + value.length);
261
- newValue.set(this.pendingValue);
262
- newValue.set(value, this.pendingValue.length);
263
- this.pendingValue = new Uint8Array();
264
- value = newValue;
265
- }
266
- if (size + value.length > length) {
267
- data.set(value.subarray(0, length), size);
268
- this.pendingValue = value.subarray(length);
269
- size += length;
270
- } else {
271
- data.set(value, size);
272
- size += value.length;
273
- }
274
- } while (size < length && !done);
275
- if (done && this.size == Infinity) {
276
- this.size = this.currentSize;
277
- }
278
- if (this.size < length) {
279
- data = data.slice(0, this.size);
280
- length = this.size;
281
- }
282
- this.index += length;
283
- return data;
288
+ getStream() {
289
+ return this.readableStream;
284
290
  }
285
291
  }
286
292
 
@@ -288,8 +294,9 @@ class WritableStreamWriter extends Writer {
288
294
 
289
295
  constructor(writableStream) {
290
296
  super();
291
- this.writableStream = writableStream;
292
- this.writer = writableStream.getWriter();
297
+ const writer = this;
298
+ writer.writableStream = writableStream;
299
+ writer.writer = writer.getStreamWriter();
293
300
  }
294
301
 
295
302
  async writeUint8Array(array) {
@@ -297,26 +304,32 @@ class WritableStreamWriter extends Writer {
297
304
  return this.writer.write(array);
298
305
  }
299
306
 
300
- async getData() {
301
- await this.writer.ready;
302
- await this.writer.close();
307
+ getStream() {
303
308
  return this.writableStream;
304
309
  }
310
+
311
+ async getData() {
312
+ const writer = this;
313
+ await writer.writer.ready;
314
+ await writer.writer.close();
315
+ return writer.writableStream;
316
+ }
305
317
  }
306
318
 
307
319
  class FetchReader extends Reader {
308
320
 
309
321
  constructor(url, options) {
310
322
  super();
311
- this.url = url;
312
- this.preventHeadRequest = options.preventHeadRequest;
313
- this.useRangeHeader = options.useRangeHeader;
314
- this.forceRangeRequests = options.forceRangeRequests;
315
- this.options = Object.assign({}, options);
316
- delete this.options.preventHeadRequest;
317
- delete this.options.useRangeHeader;
318
- delete this.options.forceRangeRequests;
319
- delete this.options.useXHR;
323
+ const reader = this;
324
+ reader.url = url;
325
+ reader.preventHeadRequest = options.preventHeadRequest;
326
+ reader.useRangeHeader = options.useRangeHeader;
327
+ reader.forceRangeRequests = options.forceRangeRequests;
328
+ reader.options = Object.assign({}, options);
329
+ delete reader.options.preventHeadRequest;
330
+ delete reader.options.useRangeHeader;
331
+ delete reader.options.forceRangeRequests;
332
+ delete reader.options.useXHR;
320
333
  }
321
334
 
322
335
  async init() {
@@ -333,11 +346,12 @@ class XHRReader extends Reader {
333
346
 
334
347
  constructor(url, options) {
335
348
  super();
336
- this.url = url;
337
- this.preventHeadRequest = options.preventHeadRequest;
338
- this.useRangeHeader = options.useRangeHeader;
339
- this.forceRangeRequests = options.forceRangeRequests;
340
- this.options = options;
349
+ const reader = this;
350
+ reader.url = url;
351
+ reader.preventHeadRequest = options.preventHeadRequest;
352
+ reader.useRangeHeader = options.useRangeHeader;
353
+ reader.forceRangeRequests = options.forceRangeRequests;
354
+ reader.options = options;
341
355
  }
342
356
 
343
357
  async init() {
@@ -540,10 +554,11 @@ class Uint8ArrayWriter extends Writer {
540
554
 
541
555
  writeUint8Array(array) {
542
556
  super.writeUint8Array(array);
543
- const previousArray = this.array;
544
- this.array = new Uint8Array(previousArray.length + array.length);
545
- this.array.set(previousArray);
546
- this.array.set(array, previousArray.length);
557
+ const writer = this;
558
+ const previousArray = writer.array;
559
+ writer.array = new Uint8Array(previousArray.length + array.length);
560
+ writer.array.set(previousArray);
561
+ writer.array.set(array, previousArray.length);
547
562
  }
548
563
 
549
564
  getData() {
@@ -56,7 +56,7 @@ import {
56
56
  FILE_ATTR_MSDOS_DIR_MASK,
57
57
  DIRECTORY_SIGNATURE
58
58
  } from "./constants.js";
59
- import { getConfiguration } from "./configuration.js";
59
+ import { getConfiguration, getChunkSize } from "./configuration.js";
60
60
  import { createCodec, CODEC_INFLATE, ERR_INVALID_SIGNATURE, ERR_INVALID_PASSWORD } from "./codecs/codec-pool.js";
61
61
  import decodeText from "./util/decode-text.js";
62
62
  import Crc32 from "./codecs/crc32.js";
@@ -310,7 +310,13 @@ class ZipEntry {
310
310
  }
311
311
  const signal = getOptionValue(zipEntry, options, "signal");
312
312
  const dataOffset = offset + 30 + localDirectory.filenameLength + localDirectory.extraFieldLength;
313
- await processData(codec, reader, writer, dataOffset, () => compressedSize, config, { onprogress: options.onprogress, signal });
313
+ const size = () => compressedSize;
314
+ await processData(
315
+ codec,
316
+ reader.getStream({ offset: dataOffset, size, chunkSize: getChunkSize(config) }).getReader(),
317
+ writer.getStreamWriter(),
318
+ size,
319
+ { onprogress: options.onprogress, signal });
314
320
  return writer.getData();
315
321
  }
316
322
  }
@@ -59,7 +59,7 @@ import {
59
59
  MIN_DATE,
60
60
  MAX_DATE
61
61
  } from "./constants.js";
62
- import { getConfiguration } from "./configuration.js";
62
+ import { getConfiguration, getChunkSize } from "./configuration.js";
63
63
  import { CODEC_DEFLATE, createCodec } from "./codecs/codec-pool.js";
64
64
  import encodeText from "./util/encode-text.js";
65
65
  import { BlobWriter } from "./io.js";
@@ -280,8 +280,8 @@ async function addFile(zipWriter, name, reader, options) {
280
280
  }
281
281
 
282
282
  async function getFileEntry(zipWriter, name, reader, options) {
283
- const files = zipWriter.files;
284
- const writer = zipWriter.writer;
283
+ const { files, writer } = zipWriter;
284
+ const streamWriter = writer.getStreamWriter();
285
285
  const previousFileEntry = Array.from(files.values()).pop();
286
286
  let fileEntry = {};
287
287
  let bufferedWrite;
@@ -307,7 +307,7 @@ async function getFileEntry(zipWriter, name, reader, options) {
307
307
  }
308
308
  fileWriter = writer;
309
309
  }
310
- fileEntry = await createFileEntry(reader, fileWriter, zipWriter.config, options);
310
+ fileEntry = await createFileEntry(reader, fileWriter.getStreamWriter(), zipWriter.config, options);
311
311
  fileEntry.lock = lockCurrentFileEntry;
312
312
  files.set(name, fileEntry);
313
313
  fileEntry.filename = name;
@@ -337,10 +337,10 @@ async function getFileEntry(zipWriter, name, reader, options) {
337
337
  setUint32(arrayBufferView, 18, fileEntry.compressedSize);
338
338
  setUint32(arrayBufferView, 22, fileEntry.uncompressedSize);
339
339
  }
340
- await writer.writeUint8Array(new Uint8Array(arrayBuffer));
340
+ await writeUint8Array(streamWriter, new Uint8Array(arrayBuffer));
341
341
  indexWrittenData = headerLength;
342
342
  }
343
- await writeBlob(writer, blob, indexWrittenData);
343
+ await writeBlob(streamWriter, blob, indexWrittenData);
344
344
  delete fileEntry.writingBufferedData;
345
345
  }
346
346
  fileEntry.offset = zipWriter.offset;
@@ -369,7 +369,7 @@ async function getFileEntry(zipWriter, name, reader, options) {
369
369
  }
370
370
  }
371
371
 
372
- async function createFileEntry(reader, writer, config, options) {
372
+ async function createFileEntry(reader, streamWriter, config, options) {
373
373
  const {
374
374
  rawFilename,
375
375
  lastAccessDate,
@@ -529,13 +529,19 @@ async function createFileEntry(reader, writer, config, options) {
529
529
  useWebWorkers,
530
530
  useCompressionStream
531
531
  }, config);
532
- await writer.writeUint8Array(localHeaderArray);
532
+ await writeUint8Array(streamWriter, localHeaderArray);
533
533
  fileEntry.dataWritten = true;
534
- result = await processData(codec, reader, writer, 0, () => reader.size, config, { onprogress, signal });
534
+ const size = () => reader.size;
535
+ result = await processData(
536
+ codec,
537
+ reader.getStream({ offset: 0, size, chunkSize: getChunkSize(config) }).getReader(),
538
+ streamWriter,
539
+ () => reader.size,
540
+ { onprogress, signal });
535
541
  uncompressedSize = fileEntry.uncompressedSize = reader.size;
536
542
  compressedSize = result.length;
537
543
  } else {
538
- await writer.writeUint8Array(localHeaderArray);
544
+ await writeUint8Array(streamWriter, localHeaderArray);
539
545
  fileEntry.dataWritten = true;
540
546
  }
541
547
  let dataDescriptorArray = new Uint8Array(0);
@@ -579,7 +585,7 @@ async function createFileEntry(reader, writer, config, options) {
579
585
  }
580
586
  }
581
587
  if (dataDescriptor) {
582
- await writer.writeUint8Array(dataDescriptorArray);
588
+ await writeUint8Array(streamWriter, dataDescriptorArray);
583
589
  }
584
590
  const length = localHeaderArray.length + compressedSize + dataDescriptorArray.length;
585
591
  Object.assign(fileEntry, { compressedSize, lastModDate, rawLastModDate, creationDate, lastAccessDate, encrypted, length });
@@ -587,8 +593,8 @@ async function createFileEntry(reader, writer, config, options) {
587
593
  }
588
594
 
589
595
  async function closeFile(zipWriter, comment, options) {
590
- const writer = zipWriter.writer;
591
- const files = zipWriter.files;
596
+ const { files } = zipWriter;
597
+ const streamWriter = zipWriter.writer.getStreamWriter();
592
598
  let offset = 0;
593
599
  let directoryDataLength = 0;
594
600
  let directoryOffset = zipWriter.offset;
@@ -703,9 +709,9 @@ async function closeFile(zipWriter, comment, options) {
703
709
  setUint16(directoryView, offset + 10, filesLength);
704
710
  setUint32(directoryView, offset + 12, directoryDataLength);
705
711
  setUint32(directoryView, offset + 16, directoryOffset);
706
- await writer.writeUint8Array(directoryArray);
712
+ await writeUint8Array(streamWriter, directoryArray);
707
713
  if (comment && comment.length) {
708
- await writer.writeUint8Array(comment);
714
+ await writeUint8Array(streamWriter, comment);
709
715
  }
710
716
  }
711
717
 
@@ -726,20 +732,25 @@ function sliceAsArrayBuffer(blob, start, end) {
726
732
  }
727
733
  }
728
734
 
729
- async function writeBlob(writer, blob, start = 0) {
735
+ async function writeBlob(streamWriter, blob, start = 0) {
730
736
  const blockSize = 512 * 1024 * 1024;
731
737
  await writeSlice();
732
738
 
733
739
  async function writeSlice() {
734
740
  if (start < blob.size) {
735
741
  const arrayBuffer = await sliceAsArrayBuffer(blob, start, start + blockSize);
736
- await writer.writeUint8Array(new Uint8Array(arrayBuffer));
742
+ await writeUint8Array(streamWriter, new Uint8Array(arrayBuffer));
737
743
  start += blockSize;
738
744
  await writeSlice();
739
745
  }
740
746
  }
741
747
  }
742
748
 
749
+ async function writeUint8Array(streamWriter, array) {
750
+ await streamWriter.ready;
751
+ await streamWriter.write(array);
752
+ }
753
+
743
754
  function getTimeNTFS(date) {
744
755
  if (date) {
745
756
  return ((BigInt(date.getTime()) + BigInt(11644473600000)) * BigInt(10000));