@zip.js/zip.js 2.7.33 → 2.7.35

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.
@@ -56,26 +56,28 @@ let indexWorker = 0;
56
56
  async function runWorker(stream, workerOptions) {
57
57
  const { options, config } = workerOptions;
58
58
  const { transferStreams, useWebWorkers, useCompressionStream, codecType, compressed, signed, encrypted } = options;
59
- const { workerScripts, maxWorkers, terminateWorkerTimeout } = config;
59
+ const { workerScripts, maxWorkers } = config;
60
60
  workerOptions.transferStreams = transferStreams || transferStreams === UNDEFINED_VALUE;
61
61
  const streamCopy = !compressed && !signed && !encrypted && !workerOptions.transferStreams;
62
62
  workerOptions.useWebWorkers = !streamCopy && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
63
63
  workerOptions.scripts = workerOptions.useWebWorkers && workerScripts ? workerScripts[codecType] : [];
64
64
  options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
65
- let worker;
66
- const workerData = pool.find(workerData => !workerData.busy);
67
- if (workerData) {
68
- clearTerminateTimeout(workerData);
69
- worker = new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
70
- } else if (pool.length < maxWorkers) {
71
- const workerData = { indexWorker };
72
- indexWorker++;
73
- pool.push(workerData);
74
- worker = new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
75
- } else {
76
- worker = await new Promise(resolve => pendingRequests.push({ resolve, stream, workerOptions }));
65
+ return (await getWorker()).run();
66
+
67
+ async function getWorker() {
68
+ const workerData = pool.find(workerData => !workerData.busy);
69
+ if (workerData) {
70
+ clearTerminateTimeout(workerData);
71
+ return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
72
+ } else if (pool.length < maxWorkers) {
73
+ const workerData = { indexWorker };
74
+ indexWorker++;
75
+ pool.push(workerData);
76
+ return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
77
+ } else {
78
+ return new Promise(resolve => pendingRequests.push({ resolve, stream, workerOptions }));
79
+ }
77
80
  }
78
- return worker.run();
79
81
 
80
82
  function onTaskFinished(workerData) {
81
83
  if (pendingRequests.length) {
@@ -83,26 +85,32 @@ async function runWorker(stream, workerOptions) {
83
85
  resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
84
86
  } else if (workerData.worker) {
85
87
  clearTerminateTimeout(workerData);
86
- if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
87
- if (workerData.terminated) {
88
- workerData.terminated = false;
89
- } else {
90
- workerData.terminateTimeout = setTimeout(async () => {
91
- pool = pool.filter(data => data != workerData);
92
- try {
93
- await workerData.terminate();
94
- } catch (_error) {
95
- // ignored
96
- }
97
- }, terminateWorkerTimeout);
98
- }
99
- }
88
+ terminateWorker(workerData, workerOptions);
100
89
  } else {
101
90
  pool = pool.filter(data => data != workerData);
102
91
  }
103
92
  }
104
93
  }
105
94
 
95
+ function terminateWorker(workerData, workerOptions) {
96
+ const { config } = workerOptions;
97
+ const { terminateWorkerTimeout } = config;
98
+ if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
99
+ if (workerData.terminated) {
100
+ workerData.terminated = false;
101
+ } else {
102
+ workerData.terminateTimeout = setTimeout(async () => {
103
+ pool = pool.filter(data => data != workerData);
104
+ try {
105
+ await workerData.terminate();
106
+ } catch (_error) {
107
+ // ignored
108
+ }
109
+ }, terminateWorkerTimeout);
110
+ }
111
+ }
112
+ }
113
+
106
114
  function clearTerminateTimeout(workerData) {
107
115
  const { terminateTimeout } = workerData;
108
116
  if (terminateTimeout) {
@@ -100,9 +100,9 @@ class ProgressWatcherStream extends TransformStream {
100
100
  constructor(readableSource, { onstart, onprogress, size, onend }) {
101
101
  let chunkOffset = 0;
102
102
  super({
103
- start() {
103
+ async start() {
104
104
  if (onstart) {
105
- callHandler(onstart, size);
105
+ await callHandler(onstart, size);
106
106
  }
107
107
  },
108
108
  async transform(chunk, controller) {
@@ -112,10 +112,10 @@ class ProgressWatcherStream extends TransformStream {
112
112
  }
113
113
  controller.enqueue(chunk);
114
114
  },
115
- flush() {
115
+ async flush() {
116
116
  readableSource.size = chunkOffset;
117
117
  if (onend) {
118
- callHandler(onend, chunkOffset);
118
+ await callHandler(onend, chunkOffset);
119
119
  }
120
120
  }
121
121
  });
package/lib/core/io.js CHANGED
@@ -262,7 +262,7 @@ class FetchReader extends Reader {
262
262
 
263
263
  constructor(url, options) {
264
264
  super();
265
- createHtpReader(this, url, options);
265
+ createHttpReader(this, url, options);
266
266
  }
267
267
 
268
268
  async init() {
@@ -279,7 +279,7 @@ class XHRReader extends Reader {
279
279
 
280
280
  constructor(url, options) {
281
281
  super();
282
- createHtpReader(this, url, options);
282
+ createHttpReader(this, url, options);
283
283
  }
284
284
 
285
285
  async init() {
@@ -292,7 +292,7 @@ class XHRReader extends Reader {
292
292
  }
293
293
  }
294
294
 
295
- function createHtpReader(httpReader, url, options) {
295
+ function createHttpReader(httpReader, url, options) {
296
296
  const {
297
297
  preventHeadRequest,
298
298
  useRangeHeader,
@@ -584,8 +584,8 @@ class SplitDataWriter extends Stream {
584
584
 
585
585
  constructor(writerGenerator, maxSize = 4294967295) {
586
586
  super();
587
- const zipWriter = this;
588
- Object.assign(zipWriter, {
587
+ const writer = this;
588
+ Object.assign(writer, {
589
589
  diskNumber: 0,
590
590
  diskOffset: 0,
591
591
  size: 0,
@@ -595,7 +595,7 @@ class SplitDataWriter extends Stream {
595
595
  let diskSourceWriter, diskWritable, diskWriter;
596
596
  const writable = new WritableStream({
597
597
  async write(chunk) {
598
- const { availableSize } = zipWriter;
598
+ const { availableSize } = writer;
599
599
  if (!diskWriter) {
600
600
  const { value, done } = await writerGenerator.next();
601
601
  if (done && !value) {
@@ -604,9 +604,9 @@ class SplitDataWriter extends Stream {
604
604
  diskSourceWriter = value;
605
605
  diskSourceWriter.size = 0;
606
606
  if (diskSourceWriter.maxSize) {
607
- zipWriter.maxSize = diskSourceWriter.maxSize;
607
+ writer.maxSize = diskSourceWriter.maxSize;
608
608
  }
609
- zipWriter.availableSize = zipWriter.maxSize;
609
+ writer.availableSize = writer.maxSize;
610
610
  await initStream(diskSourceWriter);
611
611
  diskWritable = value.writable;
612
612
  diskWriter = diskWritable.getWriter();
@@ -615,8 +615,8 @@ class SplitDataWriter extends Stream {
615
615
  } else if (chunk.length >= availableSize) {
616
616
  await writeChunk(chunk.slice(0, availableSize));
617
617
  await closeDisk();
618
- zipWriter.diskOffset += diskSourceWriter.size;
619
- zipWriter.diskNumber++;
618
+ writer.diskOffset += diskSourceWriter.size;
619
+ writer.diskNumber++;
620
620
  diskWriter = null;
621
621
  await this.write(chunk.slice(availableSize));
622
622
  } else {
@@ -628,7 +628,7 @@ class SplitDataWriter extends Stream {
628
628
  await closeDisk();
629
629
  }
630
630
  });
631
- Object.defineProperty(zipWriter, PROPERTY_NAME_WRITABLE, {
631
+ Object.defineProperty(writer, PROPERTY_NAME_WRITABLE, {
632
632
  get() {
633
633
  return writable;
634
634
  }
@@ -640,8 +640,8 @@ class SplitDataWriter extends Stream {
640
640
  await diskWriter.ready;
641
641
  await diskWriter.write(chunk);
642
642
  diskSourceWriter.size += chunkLength;
643
- zipWriter.size += chunkLength;
644
- zipWriter.availableSize -= chunkLength;
643
+ writer.size += chunkLength;
644
+ writer.availableSize -= chunkLength;
645
645
  }
646
646
  }
647
647
 
@@ -661,6 +661,8 @@ function isHttpFamily(url) {
661
661
  async function initStream(stream, initSize) {
662
662
  if (stream.init && !stream.initialized) {
663
663
  await stream.init(initSize);
664
+ } else {
665
+ return Promise.resolve();
664
666
  }
665
667
  }
666
668
 
@@ -689,8 +691,7 @@ function initWriter(writer) {
689
691
  if (writable.size === UNDEFINED_VALUE) {
690
692
  writable.size = 0;
691
693
  }
692
- const splitZipFile = writer instanceof SplitDataWriter;
693
- if (!splitZipFile) {
694
+ if (!(writer instanceof SplitDataWriter)) {
694
695
  Object.assign(writer, {
695
696
  diskNumber: 0,
696
697
  diskOffset: 0,
@@ -29,6 +29,7 @@
29
29
  /* global crypto, TransformStream */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
+ import { UNDEFINED_VALUE, UNDEFINED_TYPE, FUNCTION_TYPE } from "../constants.js";
32
33
  import { encodeText } from "./../util/encode-text.js";
33
34
  import {
34
35
  cipher,
@@ -55,8 +56,6 @@ const SALT_LENGTH = [8, 12, 16];
55
56
  const KEY_LENGTH = [16, 24, 32];
56
57
  const SIGNATURE_LENGTH = 10;
57
58
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
58
- const UNDEFINED_TYPE = "undefined";
59
- const FUNCTION_TYPE = "function";
60
59
  // deno-lint-ignore valid-typeof
61
60
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
62
61
  const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
@@ -71,12 +70,12 @@ let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && type
71
70
 
72
71
  class AESDecryptionStream extends TransformStream {
73
72
 
74
- constructor({ password, signed, encryptionStrength, checkPasswordOnly }) {
73
+ constructor({ password, rawPassword, signed, encryptionStrength, checkPasswordOnly }) {
75
74
  super({
76
75
  start() {
77
76
  Object.assign(this, {
78
77
  ready: new Promise(resolve => this.resolveReady = resolve),
79
- password,
78
+ password: encodePassword(password, rawPassword),
80
79
  signed,
81
80
  strength: encryptionStrength - 1,
82
81
  pending: new Uint8Array()
@@ -140,14 +139,14 @@ class AESDecryptionStream extends TransformStream {
140
139
 
141
140
  class AESEncryptionStream extends TransformStream {
142
141
 
143
- constructor({ password, encryptionStrength }) {
142
+ constructor({ password, rawPassword, encryptionStrength }) {
144
143
  // deno-lint-ignore prefer-const
145
144
  let stream;
146
145
  super({
147
146
  start() {
148
147
  Object.assign(this, {
149
148
  ready: new Promise(resolve => this.resolveReady = resolve),
150
- password,
149
+ password: encodePassword(password, rawPassword),
151
150
  strength: encryptionStrength - 1,
152
151
  pending: new Uint8Array()
153
152
  });
@@ -244,8 +243,7 @@ async function createEncryptionKeys(encrypt, strength, password) {
244
243
 
245
244
  async function createKeys(aesCrypto, strength, password, salt) {
246
245
  aesCrypto.password = null;
247
- const encodedPassword = encodeText(password);
248
- const baseKey = await importKey(RAW_FORMAT, encodedPassword, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
246
+ const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
249
247
  const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * ((KEY_LENGTH[strength] * 2) + 2));
250
248
  const compositeKey = new Uint8Array(derivedBits);
251
249
  const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
@@ -289,6 +287,14 @@ async function deriveBits(algorithm, baseKey, length) {
289
287
  }
290
288
  }
291
289
 
290
+ function encodePassword(password, rawPassword) {
291
+ if (rawPassword === UNDEFINED_VALUE) {
292
+ return encodeText(password);
293
+ } else {
294
+ return rawPassword;
295
+ }
296
+ }
297
+
292
298
  function concat(leftArray, rightArray) {
293
299
  let array = leftArray;
294
300
  if (leftArray.length + rightArray.length) {
@@ -28,11 +28,12 @@
28
28
 
29
29
  /* global crypto */
30
30
 
31
+ import { FUNCTION_TYPE, UNDEFINED_TYPE } from "../constants.js";
31
32
  import {
32
33
  random
33
34
  } from "./codecs/sjcl.js";
34
35
 
35
- const GET_RANDOM_VALUES_SUPPORTED = typeof crypto != "undefined" && typeof crypto.getRandomValues == "function";
36
+ const GET_RANDOM_VALUES_SUPPORTED = typeof crypto != UNDEFINED_TYPE && typeof crypto.getRandomValues == FUNCTION_TYPE;
36
37
 
37
38
  const ERR_INVALID_PASSWORD = "Invalid password";
38
39
  const ERR_INVALID_SIGNATURE = "Invalid signature";
@@ -28,12 +28,14 @@
28
28
 
29
29
  /* global TextEncoder */
30
30
 
31
+ import { UNDEFINED_TYPE } from "../constants.js";
32
+
31
33
  export {
32
34
  encodeText
33
35
  };
34
36
 
35
37
  function encodeText(value) {
36
- if (typeof TextEncoder == "undefined") {
38
+ if (typeof TextEncoder == UNDEFINED_TYPE) {
37
39
  value = unescape(encodeURIComponent(value));
38
40
  const result = new Uint8Array(value.length);
39
41
  for (let i = 0; i < result.length; i++) {
@@ -29,6 +29,8 @@
29
29
 
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
+ import { FUNCTION_TYPE, UNDEFINED_VALUE } from "../constants.js";
33
+
32
34
  export {
33
35
  initShimAsyncCodec
34
36
  };
@@ -42,7 +44,7 @@ function initShimAsyncCodec(library, options = {}, registerDataHandler) {
42
44
 
43
45
  function objectHasOwn(object, propertyName) {
44
46
  // eslint-disable-next-line no-prototype-builtins
45
- return typeof Object.hasOwn === "function" ? Object.hasOwn(object, propertyName) : object.hasOwnProperty(propertyName);
47
+ return typeof Object.hasOwn === FUNCTION_TYPE ? Object.hasOwn(object, propertyName) : object.hasOwnProperty(propertyName);
46
48
  }
47
49
 
48
50
  function createCodecClass(constructor, constructorOptions, registerDataHandler) {
@@ -61,7 +63,7 @@ function createCodecClass(constructor, constructorOptions, registerDataHandler)
61
63
  codecAdapter.pendingData = new Uint8Array(data);
62
64
  }
63
65
  };
64
- if (objectHasOwn(options, "level") && options.level === undefined) {
66
+ if (objectHasOwn(options, "level") && options.level === UNDEFINED_VALUE) {
65
67
  delete options.level;
66
68
  }
67
69
  codecAdapter.codec = new constructor(Object.assign({}, constructorOptions, options));
@@ -52,6 +52,7 @@ import {
52
52
  import {
53
53
  Entry
54
54
  } from "./zip-entry.js";
55
+ import { UNDEFINED_VALUE } from "./constants.js";
55
56
 
56
57
  class ZipEntry {
57
58
 
@@ -433,7 +434,7 @@ class ZipDirectoryEntry extends ZipEntry {
433
434
 
434
435
  async exportZip(writer, options) {
435
436
  const zipEntry = this;
436
- if (options.bufferedWrite === undefined) {
437
+ if (options.bufferedWrite === UNDEFINED_VALUE) {
437
438
  options.bufferedWrite = true;
438
439
  }
439
440
  await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
@@ -7,8 +7,8 @@
7
7
  1. Redistributions of source code must retain the above copyright notice,
8
8
  this list of conditions and the following disclaimer.
9
9
 
10
- 2. Redistributions in binary form must reproduce the above copyright
11
- notice, this list of conditions and the following disclaimer in
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
12
  the documentation and/or other materials provided with the distribution.
13
13
 
14
14
  3. The names of the authors may not be used to endorse or promote products
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global BigInt, Response, WritableStream */
29
+ /* global BigInt, Response, WritableStream, ReadableStream, TransformStream */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import {
@@ -209,7 +209,7 @@ class ZipReader {
209
209
  }
210
210
  if (directoryDataOffset >= reader.size) {
211
211
  prependedDataLength = reader.size - directoryDataOffset - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
212
- directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
212
+ directoryDataOffset = reader.size - directoryDataLength - END_OF_CENTRAL_DIR_LENGTH;
213
213
  }
214
214
  if (expectedLastDiskNumber != lastDiskNumber) {
215
215
  throw new Error(ERR_SPLIT_ZIP_FILE);
@@ -326,8 +326,37 @@ class ZipReader {
326
326
  }
327
327
  }
328
328
 
329
+ class ZipReaderStream {
330
+
331
+ constructor(options = {}) {
332
+ const { readable, writable } = new TransformStream();
333
+ const gen = new ZipReader(readable, options).getEntriesGenerator();
334
+ this.readable = new ReadableStream({
335
+ async pull(controller) {
336
+ const { done, value } = await gen.next();
337
+ if (done)
338
+ return controller.close();
339
+ const chunk = {
340
+ ...value,
341
+ readable: (function () {
342
+ const { readable, writable } = new TransformStream();
343
+ if (value.getData) {
344
+ value.getData(writable);
345
+ return readable;
346
+ }
347
+ })()
348
+ };
349
+ delete chunk.getData;
350
+ controller.enqueue(chunk);
351
+ }
352
+ });
353
+ this.writable = writable;
354
+ }
355
+ }
356
+
329
357
  export {
330
358
  ZipReader,
359
+ ZipReaderStream,
331
360
  ERR_BAD_FORMAT,
332
361
  ERR_EOCDR_NOT_FOUND,
333
362
  ERR_EOCDR_ZIP64_NOT_FOUND,
@@ -372,7 +401,9 @@ class ZipEntry {
372
401
  const dataArray = await readUint8Array(reader, offset, 30, diskNumberStart);
373
402
  const dataView = getDataView(dataArray);
374
403
  let password = getOptionValue(zipEntry, options, "password");
404
+ let rawPassword = getOptionValue(zipEntry, options, "rawPassword");
375
405
  password = password && password.length && password;
406
+ rawPassword = rawPassword && rawPassword.length && rawPassword;
376
407
  if (extraFieldAES) {
377
408
  if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
378
409
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
@@ -398,7 +429,7 @@ class ZipEntry {
398
429
  if (encrypted) {
399
430
  if (!zipCrypto && extraFieldAES.strength === UNDEFINED_VALUE) {
400
431
  throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
401
- } else if (!password) {
432
+ } else if (!password && !rawPassword) {
402
433
  throw new Error(ERR_ENCRYPTED);
403
434
  }
404
435
  }
@@ -423,6 +454,7 @@ class ZipEntry {
423
454
  options: {
424
455
  codecType: CODEC_INFLATE,
425
456
  password,
457
+ rawPassword,
426
458
  zipCrypto,
427
459
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
428
460
  signed: getOptionValue(zipEntry, options, "checkSignature"),
@@ -452,7 +484,7 @@ class ZipEntry {
452
484
  await writable.getWriter().close();
453
485
  }
454
486
  }
455
- return checkPasswordOnly ? undefined : writer.getData ? writer.getData() : writable;
487
+ return checkPasswordOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
456
488
  }
457
489
  }
458
490
 
@@ -718,4 +750,4 @@ function setUint32(view, offset, value) {
718
750
 
719
751
  function getDataView(array) {
720
752
  return new DataView(array.buffer);
721
- }
753
+ }
@@ -7,8 +7,8 @@
7
7
  1. Redistributions of source code must retain the above copyright notice,
8
8
  this list of conditions and the following disclaimer.
9
9
 
10
- 2. Redistributions in binary form must reproduce the above copyright
11
- notice, this list of conditions and the following disclaimer in
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
12
  the documentation and/or other materials provided with the distribution.
13
13
 
14
14
  3. The names of the authors may not be used to endorse or promote products
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global BigInt */
29
+ /* global BigInt, TransformStream, Response */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import {
@@ -75,9 +75,7 @@ import {
75
75
  import {
76
76
  initStream,
77
77
  initReader,
78
- initWriter,
79
- BlobWriter,
80
- SplitDataWriter
78
+ initWriter
81
79
  } from "./io.js";
82
80
  import { encodeText } from "./util/encode-text.js";
83
81
  import {
@@ -110,9 +108,12 @@ class ZipWriter {
110
108
 
111
109
  constructor(writer, options = {}) {
112
110
  writer = initWriter(writer);
111
+ const addSplitZipSignature =
112
+ writer.availableSize !== UNDEFINED_VALUE && writer.availableSize > 0 && writer.availableSize !== Infinity &&
113
+ writer.maxSize !== UNDEFINED_VALUE && writer.maxSize > 0 && writer.maxSize !== Infinity;
113
114
  Object.assign(this, {
114
115
  writer,
115
- addSplitZipSignature: writer instanceof SplitDataWriter,
116
+ addSplitZipSignature,
116
117
  options,
117
118
  config: getConfiguration(),
118
119
  files: new Map(),
@@ -175,8 +176,36 @@ class ZipWriter {
175
176
  }
176
177
  }
177
178
 
179
+ class ZipWriterStream {
180
+
181
+ constructor(options = {}) {
182
+ const { readable, writable } = new TransformStream();
183
+ this.readable = readable;
184
+ this.zipWriter = new ZipWriter(writable, options);
185
+ }
186
+
187
+ transform(path) {
188
+ const { readable, writable } = new TransformStream({
189
+ flush: () => { this.zipWriter.close(); }
190
+ });
191
+ this.zipWriter.add(path, readable);
192
+ return { readable: this.readable, writable };
193
+ }
194
+
195
+ writable(path) {
196
+ const { readable, writable } = new TransformStream();
197
+ this.zipWriter.add(path, readable);
198
+ return writable;
199
+ }
200
+
201
+ close(comment = undefined, options = {}) {
202
+ return this.zipWriter.close(comment, options);
203
+ }
204
+ }
205
+
178
206
  export {
179
207
  ZipWriter,
208
+ ZipWriterStream,
180
209
  ERR_DUPLICATED_NAME,
181
210
  ERR_INVALID_COMMENT,
182
211
  ERR_INVALID_ENTRY_NAME,
@@ -219,6 +248,7 @@ async function addFile(zipWriter, name, reader, options) {
219
248
  const internalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTE, 0);
220
249
  const externalFileAttribute = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTE, 0);
221
250
  const password = getOptionValue(zipWriter, options, "password");
251
+ const rawPassword = getOptionValue(zipWriter, options, "rawPassword");
222
252
  const encryptionStrength = getOptionValue(zipWriter, options, "encryptionStrength", 3);
223
253
  const zipCrypto = getOptionValue(zipWriter, options, "zipCrypto");
224
254
  const extendedTimestamp = getOptionValue(zipWriter, options, "extendedTimestamp", true);
@@ -301,6 +331,7 @@ async function addFile(zipWriter, name, reader, options) {
301
331
  zip64Offset,
302
332
  zip64DiskNumberStart,
303
333
  password,
334
+ rawPassword,
304
335
  level,
305
336
  useWebWorkers,
306
337
  encryptionStrength,
@@ -356,6 +387,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
356
387
  let writingBufferedEntryData;
357
388
  let writingEntryData;
358
389
  let fileWriter;
390
+ let blobPromise;
359
391
  files.set(name, fileEntry);
360
392
  try {
361
393
  let lockPreviousFileEntry;
@@ -364,7 +396,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
364
396
  requestLockCurrentFileEntry();
365
397
  }
366
398
  if ((options.bufferedWrite || zipWriter.writerLocked || (zipWriter.bufferedWrites && keepOrder) || !dataDescriptor) && !usdz) {
367
- fileWriter = new BlobWriter();
399
+ fileWriter = new TransformStream();
400
+ blobPromise = new Response(fileWriter.readable).blob();
368
401
  fileWriter.writable.size = 0;
369
402
  bufferedWrite = true;
370
403
  zipWriter.bufferedWrites++;
@@ -400,7 +433,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
400
433
  fileEntry.filename = name;
401
434
  if (bufferedWrite) {
402
435
  await fileWriter.writable.getWriter().close();
403
- let blob = await fileWriter.getData();
436
+ let blob = await blobPromise;
404
437
  await lockPreviousFileEntry;
405
438
  await requestLockWriter();
406
439
  writingBufferedEntryData = true;
@@ -467,7 +500,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
467
500
  }
468
501
 
469
502
  async function skipDiskIfNeeded(writable) {
470
- if (headerInfo.localHeaderArray.length > writer.availableSize) {
503
+ if (getLength(headerInfo.localHeaderArray) > writer.availableSize) {
471
504
  writer.availableSize = 0;
472
505
  await writeData(writable, new Uint8Array());
473
506
  }
@@ -500,6 +533,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
500
533
  lastAccessDate,
501
534
  creationDate,
502
535
  password,
536
+ rawPassword,
503
537
  level,
504
538
  zip64,
505
539
  zip64UncompressedSize,
@@ -556,6 +590,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
556
590
  options: {
557
591
  codecType: CODEC_DEFLATE,
558
592
  level,
593
+ rawPassword,
559
594
  password,
560
595
  encryptionStrength,
561
596
  zipCrypto: encrypted && zipCrypto,
@@ -637,6 +672,7 @@ function getHeaderInfo(options) {
637
672
  lastModDate,
638
673
  lastAccessDate,
639
674
  creationDate,
675
+ rawPassword,
640
676
  password,
641
677
  level,
642
678
  zip64,
@@ -648,7 +684,7 @@ function getHeaderInfo(options) {
648
684
  extendedTimestamp
649
685
  } = options;
650
686
  const compressed = level !== 0 && !directory;
651
- const encrypted = Boolean(password && getLength(password));
687
+ const encrypted = Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword)));
652
688
  let version = options.version;
653
689
  let rawExtraFieldAES;
654
690
  if (encrypted && !zipCrypto) {
@@ -771,7 +807,7 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
771
807
  const { headerInfo } = entryInfo;
772
808
  let { localHeaderArray, extraFieldLength } = headerInfo;
773
809
  let localHeaderArrayView = getDataView(localHeaderArray);
774
- let extraBytesLength = 64 - ((zipWriterOffset + localHeaderArray.length) % 64);
810
+ let extraBytesLength = 64 - ((zipWriterOffset + getLength(localHeaderArray)) % 64);
775
811
  if (extraBytesLength < 4) {
776
812
  extraBytesLength += 64;
777
813
  }
@@ -780,9 +816,9 @@ function appendExtraFieldUSDZ(entryInfo, zipWriterOffset) {
780
816
  setUint16(extraFieldUSDZView, 0, EXTRAFIELD_TYPE_USDZ);
781
817
  setUint16(extraFieldUSDZView, 2, extraBytesLength - 2);
782
818
  const previousLocalHeaderArray = localHeaderArray;
783
- headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(previousLocalHeaderArray.length + extraBytesLength);
819
+ headerInfo.localHeaderArray = localHeaderArray = new Uint8Array(getLength(previousLocalHeaderArray) + extraBytesLength);
784
820
  arraySet(localHeaderArray, previousLocalHeaderArray);
785
- arraySet(localHeaderArray, rawExtraFieldUSDZ, previousLocalHeaderArray.length);
821
+ arraySet(localHeaderArray, rawExtraFieldUSDZ, getLength(previousLocalHeaderArray));
786
822
  localHeaderArrayView = getDataView(localHeaderArray);
787
823
  setUint16(localHeaderArrayView, 28, extraFieldLength + extraBytesLength);
788
824
  entryInfo.metadataSize += extraBytesLength;
@@ -844,7 +880,7 @@ function setEntryInfo(entryInfo, options) {
844
880
  if (zip64) {
845
881
  const rawExtraFieldZip64View = getDataView(rawExtraFieldZip64);
846
882
  setUint16(rawExtraFieldZip64View, 0, EXTRAFIELD_TYPE_ZIP64);
847
- setUint16(rawExtraFieldZip64View, 2, rawExtraFieldZip64.length - 4);
883
+ setUint16(rawExtraFieldZip64View, 2, getLength(rawExtraFieldZip64) - 4);
848
884
  let rawExtraFieldZip64Offset = 4;
849
885
  if (zip64UncompressedSize) {
850
886
  setUint32(headerView, 18, MAX_32_BITS);
@@ -1140,4 +1176,4 @@ function getLength(...arrayLikes) {
1140
1176
  let result = 0;
1141
1177
  arrayLikes.forEach(arrayLike => arrayLike && (result += arrayLike.length));
1142
1178
  return result;
1143
- }
1179
+ }
@@ -31,9 +31,10 @@
31
31
 
32
32
  import "./core/z-worker-core.js";
33
33
  import { initShimAsyncCodec } from "./core/util/stream-codec-shim.js";
34
+ import { UNDEFINED_VALUE } from "./core/constants.js";
34
35
 
35
36
  self.initCodec = () => {
36
- const { Deflate, Inflate } = initShimAsyncCodec(fflate, undefined, (codec, onData) => codec.ondata = onData);
37
+ const { Deflate, Inflate } = initShimAsyncCodec(fflate, UNDEFINED_VALUE, (codec, onData) => codec.ondata = onData);
37
38
  self.Deflate = Deflate;
38
39
  self.Inflate = Inflate;
39
40
  };