@zip.js/zip.js 2.5.3 → 2.5.7

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.
Files changed (51) hide show
  1. package/dist/z-worker-fflate.js +1 -1
  2. package/dist/z-worker-pako.js +1 -1
  3. package/dist/z-worker.js +1 -1
  4. package/dist/zip-fs-full.js +470 -499
  5. package/dist/zip-fs-full.min.js +1 -1
  6. package/dist/zip-fs.js +470 -499
  7. package/dist/zip-fs.min.js +1 -1
  8. package/dist/zip-full.js +470 -499
  9. package/dist/zip-full.min.js +1 -1
  10. package/dist/zip-no-worker-deflate.min.js +1 -1
  11. package/dist/zip-no-worker-inflate.min.js +1 -1
  12. package/dist/zip-no-worker.min.js +1 -1
  13. package/dist/zip.js +470 -499
  14. package/dist/zip.min.js +1 -1
  15. package/index-fflate.js +1 -1
  16. package/index.d.ts +1 -1
  17. package/index.js +3 -3
  18. package/lib/core/{engine.js → codec-interface.js} +52 -50
  19. package/lib/core/{codecs/codec-pool-worker.js → codec-pool-worker.js} +55 -29
  20. package/lib/core/{codecs/codec-pool.js → codec-pool.js} +28 -9
  21. package/lib/core/configuration.js +10 -1
  22. package/lib/core/io.js +102 -100
  23. package/lib/core/{codecs → streams}/aes-crypto-stream.js +68 -54
  24. package/lib/core/{codecs → streams}/codec-stream.js +6 -6
  25. package/lib/core/{codecs → streams/codecs}/crc32.js +0 -0
  26. package/lib/core/{codecs → streams/codecs}/deflate.js +0 -0
  27. package/lib/core/{codecs → streams/codecs}/inflate.js +0 -0
  28. package/lib/core/{codecs → streams/codecs}/sjcl.js +0 -0
  29. package/lib/core/{codecs → streams}/crc32-stream.js +3 -4
  30. package/lib/core/{codecs → streams}/zip-crypto-stream.js +28 -32
  31. package/lib/core/streams/zip-entry-stream.js +185 -0
  32. package/lib/core/z-worker-core.js +30 -15
  33. package/lib/core/zip-fs-core.js +1 -1
  34. package/lib/core/zip-reader.js +21 -12
  35. package/lib/core/zip-writer.js +33 -25
  36. package/lib/z-worker-fflate.js +4 -1
  37. package/lib/z-worker-inline.js +1 -1
  38. package/lib/z-worker.js +2 -2
  39. package/lib/zip-fflate-shim.js +4 -1
  40. package/lib/zip-fs.js +6 -2
  41. package/lib/zip-full-fflate.js +6 -3
  42. package/lib/zip-full.js +8 -5
  43. package/lib/zip-no-worker-deflate.js +7 -3
  44. package/lib/zip-no-worker-fflate-deflate.js +6 -2
  45. package/lib/zip-no-worker-fflate-inflate.js +6 -3
  46. package/lib/zip-no-worker-fflate.js +6 -3
  47. package/lib/zip-no-worker-inflate.js +7 -4
  48. package/lib/zip-no-worker.js +8 -5
  49. package/lib/zip.js +6 -3
  50. package/package.json +2 -8
  51. package/lib/core/codecs/codec.js +0 -246
@@ -26,62 +26,64 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- const MINIMUM_CHUNK_SIZE = 64;
30
- const ERR_ABORT = "Abort error";
29
+ /* global AbortController */
30
+ // deno-lint-ignore-file no-this-alias
31
+
32
+ import {
33
+ InflateStream,
34
+ DeflateStream,
35
+ ERR_INVALID_PASSWORD,
36
+ ERR_INVALID_SIGNATURE
37
+ } from "./streams/zip-entry-stream.js";
38
+
39
+ const CODEC_DEFLATE = "deflate";
40
+ const CODEC_INFLATE = "inflate";
41
+ const MESSAGE_EVENT_TYPE = "message";
42
+ const MESSAGE_START = "start";
43
+ const MESSAGE_PULL = "pull";
44
+ const MESSAGE_DATA = "data";
45
+ const MESSAGE_ABORT = "abort";
46
+ const MESSAGE_CLOSE = "close";
47
+ const ERR_ABORT = "AbortError";
31
48
 
32
49
  export {
33
- ERR_ABORT,
34
- processData
50
+ createCodec,
51
+ CODEC_DEFLATE,
52
+ CODEC_INFLATE,
53
+ ERR_INVALID_SIGNATURE,
54
+ ERR_INVALID_PASSWORD,
55
+ MESSAGE_EVENT_TYPE,
56
+ MESSAGE_START,
57
+ MESSAGE_PULL,
58
+ MESSAGE_DATA,
59
+ MESSAGE_ABORT,
60
+ MESSAGE_CLOSE,
61
+ ERR_ABORT
35
62
  };
36
63
 
37
- async function processData(codec, reader, writer, offset, inputLengthGetter, config, options) {
38
- const chunkSize = Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
39
- const signal = options.signal;
40
- let length = 0;
41
- let chunkOffset = 0;
42
-
43
- const result = new Promise((resolve, reject) => {
44
- codec.pull = async () => {
45
- testAborted(signal, codec);
46
- const inputLength = inputLengthGetter();
47
- let currentChunkOffset = chunkOffset;
48
- chunkOffset += chunkSize;
49
- const value = await reader.readUint8Array(currentChunkOffset + offset, Math.min(chunkSize, inputLength - currentChunkOffset));
50
- const done = chunkOffset > inputLength;
51
- return { value, done };
64
+ function createCodec(codecConstructor, readable, writable, options, config) {
65
+ const controller = new AbortController();
66
+ const { signal } = controller;
67
+ if (options.codecType.startsWith(CODEC_DEFLATE)) {
68
+ return {
69
+ run: () => run(DeflateStream),
70
+ abort
52
71
  };
53
- codec.ondata = async ({ value, done }) => {
54
- try {
55
- testAborted(signal, codec);
56
- const inputLength = inputLengthGetter();
57
- const { data, signature } = value;
58
- if (data && data.length) {
59
- length += data.length;
60
- await writer.writeUint8Array(data);
61
- }
62
- if (options.onprogress) {
63
- try {
64
- options.onprogress(chunkOffset, inputLength);
65
- } catch (error) {
66
- // ignored
67
- }
68
- }
69
- if (done) {
70
- resolve({ signature, length });
71
- }
72
- } catch (error) {
73
- reject(error);
74
- }
72
+ } else if (options.codecType.startsWith(CODEC_INFLATE)) {
73
+ return {
74
+ run: () => run(InflateStream),
75
+ abort
75
76
  };
76
- codec.onerror = reject;
77
- });
78
- await codec.start();
79
- return result;
80
- }
77
+ }
78
+
79
+ async function run(StreamConstructor) {
80
+ const stream = new StreamConstructor(codecConstructor, options, config);
81
+ await readable.pipeThrough(stream, { signal }).pipeTo(writable);
82
+ const { length, signature } = stream;
83
+ return { length, signature };
84
+ }
81
85
 
82
- function testAborted(signal, codec) {
83
- if (signal && signal.aborted) {
84
- codec.abort();
85
- throw new Error(ERR_ABORT);
86
+ function abort() {
87
+ controller.abort();
86
88
  }
87
89
  }
@@ -26,9 +26,17 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global Worker, URL */
30
-
31
- import { createCodec, MESSAGE_EVENT_TYPE, MESSAGE_START, MESSAGE_PULL, MESSAGE_DATA, MESSAGE_ABORT } from "./codec.js";
29
+ /* global Worker, URL, TransformStream */
30
+
31
+ import {
32
+ createCodec,
33
+ MESSAGE_EVENT_TYPE,
34
+ MESSAGE_START,
35
+ MESSAGE_PULL,
36
+ MESSAGE_DATA,
37
+ MESSAGE_ABORT,
38
+ MESSAGE_CLOSE
39
+ } from "./codec-interface.js";
32
40
 
33
41
  let classicWorkersSupported = true;
34
42
 
@@ -36,10 +44,12 @@ export {
36
44
  getWorker
37
45
  };
38
46
 
39
- function getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts) {
47
+ function getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts) {
40
48
  Object.assign(workerData, {
41
49
  busy: true,
42
50
  codecConstructor,
51
+ readable,
52
+ writable,
43
53
  options: Object.assign({}, options),
44
54
  scripts,
45
55
  terminate() {
@@ -53,27 +63,50 @@ function getWorker(workerData, codecConstructor, options, config, onTaskFinished
53
63
  onTaskFinished(workerData);
54
64
  }
55
65
  });
66
+ const { signal, onprogress, size } = streamOptions;
67
+ if (signal || onprogress) {
68
+ let chunkOffset = 0;
69
+ const transformer = {};
70
+ if (onprogress) {
71
+ transformer.transform = (chunk, controller) => {
72
+ chunkOffset += chunk.length;
73
+ try {
74
+ onprogress(chunkOffset, size());
75
+ } catch (_error) {
76
+ // ignored
77
+ }
78
+ controller.enqueue(chunk);
79
+ };
80
+ }
81
+ workerData.readable = readable.pipeThrough(new TransformStream(transformer), { signal });
82
+ }
56
83
  return webWorker ? createWebWorkerInterface(workerData, config) : createWorkerInterface(workerData, config);
57
84
  }
58
85
 
59
86
  function createWorkerInterface(workerData, config) {
60
- const interfaceCodec = createCodec(workerData.codecConstructor, workerData.options, config);
87
+ const interfaceCodec = createCodec(workerData.codecConstructor, workerData.readable, workerData.writable, workerData.options, config);
61
88
  const codec = {
62
89
  abort() {
63
90
  interfaceCodec.abort();
64
91
  workerData.onTaskFinished();
65
92
  },
66
- start() {
67
- return interfaceCodec.start();
93
+ run() {
94
+ const result = interfaceCodec.run();
95
+ workerData.onTaskFinished();
96
+ return result;
68
97
  }
69
98
  };
70
- interfaceCodec.pull = () => codec.pull();
71
- interfaceCodec.ondata = data => ondata(workerData, codec, data);
72
99
  return codec;
73
100
  }
74
101
 
75
102
  function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
76
103
  const workerOptions = { type: "module" };
104
+ workerData.reader = workerData.readable.getReader();
105
+ workerData.writer = workerData.writable.getWriter();
106
+ workerData.result = new Promise((resolve, reject) => {
107
+ workerData.resolveResult = resolve;
108
+ workerData.rejectResult = reject;
109
+ });
77
110
  if (!workerData.interface) {
78
111
  if (!classicWorkersSupported) {
79
112
  workerData.worker = getWorker(workerOptions);
@@ -91,10 +124,11 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
91
124
  sendMessage({ type: MESSAGE_ABORT });
92
125
  workerData.onTaskFinished();
93
126
  },
94
- start() {
127
+ run() {
95
128
  const options = workerData.options;
96
129
  const scripts = workerData.scripts.slice(1);
97
130
  sendMessage({ type: MESSAGE_START, scripts, options, config: { chunkSize } });
131
+ return workerData.result;
98
132
  }
99
133
  };
100
134
  }
@@ -136,39 +170,31 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
136
170
  async function onMessage(event) {
137
171
  const message = event.data;
138
172
  const reponseError = message.error;
139
- const codec = workerData.interface;
140
173
  try {
141
174
  if (reponseError) {
142
175
  const error = new Error(reponseError.message);
143
176
  error.stack = reponseError.stack;
144
- codec.onerror(error);
177
+ workerData.rejectResult(error);
145
178
  workerData.onTaskFinished();
146
179
  } else {
147
180
  if (message.type == MESSAGE_PULL) {
148
- const { value, done } = await codec.pull();
181
+ const { value, done } = await workerData.reader.read();
149
182
  sendMessage({ type: MESSAGE_DATA, data: value, done, messageId: message.messageId });
150
183
  }
151
184
  if (message.type == MESSAGE_DATA) {
152
- const { value } = message.data;
153
- if (value && value.data) {
154
- value.data = new Uint8Array(value.data);
155
- }
156
- await ondata(workerData, codec, message.data);
185
+ let { data } = message;
186
+ data = new Uint8Array(data);
187
+ await workerData.writer.ready;
188
+ workerData.writer.write(data);
189
+ }
190
+ if (message.type == MESSAGE_CLOSE) {
191
+ workerData.resolveResult(message.result);
192
+ workerData.onTaskFinished();
157
193
  }
158
194
  }
159
195
  } catch (error) {
160
- codec.onerror(error);
196
+ workerData.rejectResult(error);
161
197
  workerData.onTaskFinished();
162
198
  }
163
199
  }
164
- }
165
-
166
- async function ondata(workerData, codec, data) {
167
- let { value, done } = data;
168
- if (done) {
169
- await codec.ondata({ value: { data: value.data, signature: value.signature }, done });
170
- workerData.onTaskFinished();
171
- } else if (value.data) {
172
- await codec.ondata({ value: { data: value.data } });
173
- }
174
200
  }
@@ -28,47 +28,66 @@
28
28
 
29
29
  /* global setTimeout, clearTimeout */
30
30
 
31
- import { CODEC_INFLATE, CODEC_DEFLATE, ERR_INVALID_SIGNATURE, ERR_INVALID_PASSWORD } from "./codec.js";
31
+ import {
32
+ CODEC_INFLATE,
33
+ CODEC_DEFLATE,
34
+ ERR_INVALID_SIGNATURE,
35
+ ERR_INVALID_PASSWORD,
36
+ ERR_ABORT
37
+ } from "./codec-interface.js";
32
38
  import { getWorker } from "./codec-pool-worker.js";
33
39
 
34
40
  let pool = [];
35
41
  const pendingRequests = [];
36
42
 
37
43
  export {
38
- createCodec,
44
+ runCodec,
39
45
  terminateWorkers,
40
46
  CODEC_DEFLATE,
41
47
  CODEC_INFLATE,
42
48
  ERR_INVALID_SIGNATURE,
43
- ERR_INVALID_PASSWORD
49
+ ERR_INVALID_PASSWORD,
50
+ ERR_ABORT
44
51
  };
45
52
 
46
53
  let indexWorker = 0;
47
54
 
48
- function createCodec(codecConstructor, options, config) {
55
+ async function runCodec(codecConstructor, readable, writable, options, config, streamOptions) {
49
56
  const streamCopy = !options.compressed && !options.signed && !options.encrypted;
50
57
  const webWorker = !streamCopy && (options.useWebWorkers || (options.useWebWorkers === undefined && config.useWebWorkers));
51
58
  const scripts = webWorker && config.workerScripts ? config.workerScripts[options.codecType] : [];
52
59
  options.useCompressionStream = options.useCompressionStream === undefined ? config.useCompressionStream : options.useCompressionStream;
60
+ let codec;
53
61
  if (pool.length < config.maxWorkers) {
54
62
  const workerData = { indexWorker };
55
63
  indexWorker++;
56
64
  pool.push(workerData);
57
- return getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts);
65
+ codec = getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts);
58
66
  } else {
59
67
  const workerData = pool.find(workerData => !workerData.busy);
60
68
  if (workerData) {
61
69
  clearTerminateTimeout(workerData);
62
- return getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts);
70
+ codec = getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts);
71
+ } else {
72
+ codec = await new Promise(resolve => pendingRequests.push({ resolve, codecConstructor, readable, writable, options, webWorker, scripts }));
73
+ }
74
+ }
75
+ const { signal } = streamOptions;
76
+ try {
77
+ return await codec.run(signal);
78
+ } catch (error) {
79
+ if (signal && signal.aborted && (signal.reason == error || error.name == ERR_ABORT)) {
80
+ codec.abort();
81
+ throw new Error(ERR_ABORT);
63
82
  } else {
64
- return new Promise(resolve => pendingRequests.push({ resolve, codecConstructor, options, webWorker, scripts }));
83
+ throw error;
65
84
  }
66
85
  }
67
86
 
68
87
  function onTaskFinished(workerData) {
69
88
  if (pendingRequests.length) {
70
- const [{ resolve, codecConstructor, options, webWorker, scripts }] = pendingRequests.splice(0, 1);
71
- resolve(getWorker(workerData, codecConstructor, options, config, onTaskFinished, webWorker, scripts));
89
+ const [{ resolve, codecConstructor, readable, writable, options, webWorker, scripts }] = pendingRequests.splice(0, 1);
90
+ resolve(getWorker(workerData, codecConstructor, readable, writable, options, config, streamOptions, onTaskFinished, webWorker, scripts));
72
91
  } else if (workerData.worker) {
73
92
  clearTerminateTimeout(workerData);
74
93
  if (Number.isFinite(config.terminateWorkerTimeout) && config.terminateWorkerTimeout >= 0) {
@@ -28,6 +28,7 @@
28
28
 
29
29
  /* global navigator */
30
30
 
31
+ const MINIMUM_CHUNK_SIZE = 64;
31
32
  const DEFAULT_CONFIGURATION = {
32
33
  chunkSize: 512 * 1024,
33
34
  maxWorkers: (typeof navigator != "undefined" && navigator.hardwareConcurrency) || 2,
@@ -40,13 +41,18 @@ const config = Object.assign({}, DEFAULT_CONFIGURATION);
40
41
 
41
42
  export {
42
43
  configure,
43
- getConfiguration
44
+ getConfiguration,
45
+ getChunkSize
44
46
  };
45
47
 
46
48
  function getConfiguration() {
47
49
  return config;
48
50
  }
49
51
 
52
+ function getChunkSize(config) {
53
+ return Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
54
+ }
55
+
50
56
  function configure(configuration) {
51
57
  if (configuration.baseURL !== undefined) {
52
58
  config.baseURL = configuration.baseURL;
@@ -60,6 +66,9 @@ function configure(configuration) {
60
66
  if (configuration.terminateWorkerTimeout !== undefined) {
61
67
  config.terminateWorkerTimeout = configuration.terminateWorkerTimeout;
62
68
  }
69
+ if (configuration.useCompressionStream !== undefined) {
70
+ config.useCompressionStream = configuration.useCompressionStream;
71
+ }
63
72
  if (configuration.useWebWorkers !== undefined) {
64
73
  config.useWebWorkers = configuration.useWebWorkers;
65
74
  }