@zip.js/zip.js 2.16.0 → 2.16.1

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 (42) hide show
  1. package/deno.json +1 -1
  2. package/dist/zip-core-external.js +284 -179
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +108 -61
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +426 -189
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +251 -70
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +426 -189
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +253 -72
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +428 -189
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +110 -63
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +110 -63
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +285 -180
  23. package/dist/zip.min.js +1 -1
  24. package/eslint.config.mjs +1 -1
  25. package/index-native.cjs +253 -72
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +428 -189
  28. package/index.d.cts +117 -16
  29. package/index.d.ts +117 -16
  30. package/index.min.js +1 -1
  31. package/lib/core/streams/aes-crypto-stream.js +60 -17
  32. package/lib/core/streams/zip-crypto-stream.js +7 -7
  33. package/lib/core/streams/zip-entry-stream.js +22 -26
  34. package/lib/core/streams/zlib-wasm/zlib-streams.js +176 -118
  35. package/lib/core/util/compatible-streams.js +10 -5
  36. package/lib/core/version.js +1 -1
  37. package/lib/core/web-worker-inline-native.js +1 -1
  38. package/lib/core/web-worker-inline-wasm.js +1 -1
  39. package/lib/core/zip-fs.js +144 -10
  40. package/lib/core/zip-reader.js +5 -5
  41. package/lib/core/zip-writer.js +4 -2
  42. package/package.json +3 -2
@@ -26,8 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global crypto, TransformStream */
30
- // deno-lint-ignore-file no-this-alias
29
+ /* global crypto, TransformStream, ReadableStream */
31
30
 
32
31
  import { UNDEFINED_VALUE, UNDEFINED_TYPE, FUNCTION_TYPE, EMPTY_UINT8_ARRAY } from "../constants.js";
33
32
  import { encodeText } from "./../util/encode-text.js";
@@ -64,12 +63,12 @@ let createEngine = createDefaultEngine;
64
63
  class AESDecryptionStream extends TransformStream {
65
64
 
66
65
  constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
66
+ const aesCrypto = {};
67
67
  super({
68
68
  start() {
69
- initAesCrypto(this, password, rawPassword, encryptionStrength);
69
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
70
70
  },
71
71
  async transform(chunk, controller) {
72
- const aesCrypto = this;
73
72
  const {
74
73
  password,
75
74
  strength,
@@ -88,6 +87,9 @@ class AESDecryptionStream extends TransformStream {
88
87
  } else {
89
88
  await ready;
90
89
  }
90
+ if (aesCrypto.discarded) {
91
+ return;
92
+ }
91
93
  const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
92
94
  controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
93
95
  },
@@ -96,9 +98,12 @@ class AESDecryptionStream extends TransformStream {
96
98
  engine,
97
99
  pendingInput,
98
100
  ready
99
- } = this;
101
+ } = aesCrypto;
100
102
  if (engine) {
101
103
  await ready;
104
+ if (aesCrypto.discarded) {
105
+ return;
106
+ }
102
107
  const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
103
108
  const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
104
109
  engine.process(decryptedChunkArray, true);
@@ -108,27 +113,26 @@ class AESDecryptionStream extends TransformStream {
108
113
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
109
114
  }
110
115
  if (invalidAuthenticationCode && checkAuthenticationCode) {
111
- throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
116
+ controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
117
+ return;
112
118
  }
113
119
  controller.enqueue(decryptedChunkArray);
114
120
  }
115
- },
116
- cancel() {
117
- disposeEngine(this);
118
121
  }
119
122
  });
123
+ setDisposingReadable(this, aesCrypto);
120
124
  }
121
125
  }
122
126
 
123
127
  class AESEncryptionStream extends TransformStream {
124
128
 
125
129
  constructor({ password, rawPassword, encryptionStrength }) {
130
+ const aesCrypto = {};
126
131
  super({
127
132
  start() {
128
- initAesCrypto(this, password, rawPassword, encryptionStrength);
133
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
129
134
  },
130
135
  async transform(chunk, controller) {
131
- const aesCrypto = this;
132
136
  const {
133
137
  password,
134
138
  strength,
@@ -142,6 +146,9 @@ class AESEncryptionStream extends TransformStream {
142
146
  } else {
143
147
  await ready;
144
148
  }
149
+ if (aesCrypto.discarded) {
150
+ return;
151
+ }
145
152
  const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
146
153
  output.set(preamble, 0);
147
154
  controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
@@ -151,19 +158,20 @@ class AESEncryptionStream extends TransformStream {
151
158
  engine,
152
159
  pendingInput,
153
160
  ready
154
- } = this;
161
+ } = aesCrypto;
155
162
  if (engine) {
156
163
  await ready;
164
+ if (aesCrypto.discarded) {
165
+ return;
166
+ }
157
167
  const encryptedChunkArray = new Uint8Array(pendingInput);
158
168
  engine.process(encryptedChunkArray, false);
159
169
  const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
160
170
  controller.enqueue(concat(encryptedChunkArray, authenticationCode));
161
171
  }
162
- },
163
- cancel() {
164
- disposeEngine(this);
165
172
  }
166
173
  });
174
+ setDisposingReadable(this, aesCrypto);
167
175
  }
168
176
  }
169
177
 
@@ -182,7 +190,37 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
182
190
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
183
191
  password: encodePassword(password, rawPassword),
184
192
  strength: encryptionStrength - 1,
185
- pendingInput: EMPTY_UINT8_ARRAY
193
+ pendingInput: EMPTY_UINT8_ARRAY,
194
+ discarded: false
195
+ });
196
+ }
197
+
198
+ function setDisposingReadable(stream, aesCrypto) {
199
+ const reader = stream.readable.getReader();
200
+ const readable = new ReadableStream({
201
+ async pull(controller) {
202
+ try {
203
+ const { value, done } = await reader.read();
204
+ if (done) {
205
+ controller.close();
206
+ } else {
207
+ controller.enqueue(value);
208
+ }
209
+ } catch (error) {
210
+ disposeEngine(aesCrypto);
211
+ reader.cancel(error).catch(() => { });
212
+ throw error;
213
+ }
214
+ },
215
+ cancel(reason) {
216
+ disposeEngine(aesCrypto);
217
+ return reader.cancel(reason);
218
+ }
219
+ });
220
+ Object.defineProperty(stream, "readable", {
221
+ get() {
222
+ return readable;
223
+ }
186
224
  });
187
225
  }
188
226
 
@@ -215,7 +253,9 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
215
253
  }
216
254
  }
217
255
 
218
- function disposeEngine({ engine }) {
256
+ function disposeEngine(aesCrypto) {
257
+ const { engine } = aesCrypto;
258
+ aesCrypto.discarded = true;
219
259
  if (engine && engine.dispose) {
220
260
  engine.dispose();
221
261
  }
@@ -232,6 +272,9 @@ async function createKeys(aesCrypto, strength, password, salt) {
232
272
  const keyLength = KEY_LENGTH[strength];
233
273
  const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
234
274
  aesCrypto.engine = createEngine(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
275
+ if (aesCrypto.discarded) {
276
+ disposeEngine(aesCrypto);
277
+ }
235
278
  return subarray(compositeKey, keyLength * 2);
236
279
  }
237
280
 
@@ -127,11 +127,11 @@ function encrypt(target, input) {
127
127
  }
128
128
 
129
129
  function createKeys(target, password, rawPassword) {
130
- const keys = [0x12345678, 0x23456789, 0x34567890];
130
+ const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
131
131
  Object.assign(target, {
132
- keys,
133
- crcKey0: new Crc32(keys[0]),
134
- crcKey2: new Crc32(keys[2])
132
+ cryptoKeys,
133
+ crcKey0: new Crc32(cryptoKeys[0]),
134
+ crcKey2: new Crc32(cryptoKeys[2])
135
135
  });
136
136
  if (rawPassword) {
137
137
  for (let index = 0; index < rawPassword.length; index++) {
@@ -145,17 +145,17 @@ function createKeys(target, password, rawPassword) {
145
145
  }
146
146
 
147
147
  function updateKeys(target, byte) {
148
- let [, key1] = target.keys;
148
+ let [, key1] = target.cryptoKeys;
149
149
  target.crcKey0.append([byte]);
150
150
  const key0 = ~target.crcKey0.get();
151
151
  key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
152
152
  target.crcKey2.append([key1 >>> 24]);
153
153
  const key2 = ~target.crcKey2.get();
154
- target.keys = [key0, key1, key2];
154
+ target.cryptoKeys = [key0, key1, key2];
155
155
  }
156
156
 
157
157
  function getByte(target) {
158
- const temp = target.keys[2] | 2;
158
+ const temp = target.cryptoKeys[2] | 2;
159
159
  return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
160
160
  }
161
161
 
@@ -176,28 +176,25 @@ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, cr
176
176
  pump();
177
177
  return new ReadableStream({
178
178
  async pull(controller) {
179
- let result;
180
179
  try {
181
- result = await read();
180
+ const { value, done } = await read();
181
+ if (done) {
182
+ controller.close();
183
+ } else {
184
+ outputLength += value.length;
185
+ if (outputLength > outputSize) {
186
+ throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
187
+ }
188
+ if (outputCrc32) {
189
+ outputCrc32.append(value);
190
+ }
191
+ controller.enqueue(value);
192
+ }
182
193
  } catch (error) {
194
+ rejectTrailerReady(error);
195
+ await cancel(reader, error);
183
196
  throw trailerWritten ? getTrailerError(error) : error;
184
197
  }
185
- const { value, done } = result;
186
- if (done) {
187
- controller.close();
188
- } else {
189
- outputLength += value.length;
190
- if (outputLength > outputSize) {
191
- const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
192
- rejectTrailerReady(error);
193
- await cancel(reader, error);
194
- throw error;
195
- }
196
- if (outputCrc32) {
197
- outputCrc32.append(value);
198
- }
199
- controller.enqueue(value);
200
- }
201
198
  },
202
199
  cancel(reason) {
203
200
  rejectTrailerReady(reason);
@@ -494,10 +491,15 @@ function mapInflateStreamError(readable) {
494
491
  const reader = readable.getReader();
495
492
  return new ReadableStream({
496
493
  async pull(controller) {
497
- let result;
498
494
  try {
499
- result = await reader.read();
495
+ const { value, done } = await reader.read();
496
+ if (done) {
497
+ controller.close();
498
+ } else {
499
+ controller.enqueue(value);
500
+ }
500
501
  } catch (error) {
502
+ await cancel(reader, error);
501
503
  if (error && error.message) {
502
504
  throw error;
503
505
  }
@@ -505,12 +507,6 @@ function mapInflateStreamError(readable) {
505
507
  mappedError.cause = error;
506
508
  throw mappedError;
507
509
  }
508
- const { value, done } = result;
509
- if (done) {
510
- controller.close();
511
- } else {
512
- controller.enqueue(value);
513
- }
514
510
  },
515
511
  cancel(reason) {
516
512
  return reader.cancel(reason);
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global TransformStream */
29
+ /* global ReadableStream, WritableStream */
30
30
 
31
31
  const FORMAT_DEFLATE = "deflate";
32
32
  const FORMAT_DEFLATE_RAW = "deflate-raw";
@@ -61,137 +61,195 @@ function _make(isCompress, type, options = {}) {
61
61
  const level = (typeof options.level === "number") ? options.level : -1;
62
62
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
63
63
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
64
-
65
- return new TransformStream({
66
- start() {
64
+ const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0 };
65
+ let readableController, writableController, resolveWrite, cancelReason;
66
+ let backpressure = true;
67
+ let cancelled = false;
68
+ initStream();
69
+ const readable = new ReadableStream({
70
+ start(controller) {
71
+ readableController = controller;
72
+ },
73
+ pull() {
74
+ backpressure = false;
75
+ resumeWrite();
76
+ },
77
+ cancel(reason) {
78
+ cancelled = true;
79
+ cancelReason = reason;
80
+ disposeStream(state);
81
+ writableController.error(reason);
82
+ resumeWrite();
83
+ }
84
+ }, { highWaterMark: 0 });
85
+ const writable = new WritableStream({
86
+ start(controller) {
87
+ writableController = controller;
88
+ },
89
+ async write(chunk) {
90
+ if (backpressure) {
91
+ await new Promise(resolve => resolveWrite = resolve);
92
+ }
93
+ if (cancelled) {
94
+ throw cancelReason;
95
+ }
67
96
  try {
68
- let result;
69
- this.out = malloc(outBufferSize);
70
- this.in = malloc(inBufferSize);
71
- this.inBufferSize = inBufferSize;
72
- if (!this.out || !this.in) {
73
- throw new Error("allocation failed");
74
- }
75
- if (isCompress) {
76
- this._process = wasm.deflate_process;
77
- this._last_consumed = wasm.deflate_last_consumed;
78
- this._end = wasm.deflate_end;
79
- this.streamHandle = wasm.deflate_new();
80
- if (type === FORMAT_GZIP) {
81
- result = wasm.deflate_init_gzip(this.streamHandle, level);
82
- } else if (type === FORMAT_DEFLATE_RAW) {
83
- result = wasm.deflate_init_raw(this.streamHandle, level);
84
- } else {
85
- result = wasm.deflate_init(this.streamHandle, level);
86
- }
87
- } else {
88
- if (type === FORMAT_DEFLATE64_RAW) {
89
- this._process = wasm.inflate9_process;
90
- this._last_consumed = wasm.inflate9_last_consumed;
91
- this._end = wasm.inflate9_end;
92
- this.streamHandle = wasm.inflate9_new();
93
- result = wasm.inflate9_init_raw(this.streamHandle);
94
- } else {
95
- this._process = wasm.inflate_process;
96
- this._last_consumed = wasm.inflate_last_consumed;
97
- this._end = wasm.inflate_end;
98
- this.streamHandle = wasm.inflate_new();
99
- if (type === FORMAT_DEFLATE_RAW) {
100
- result = wasm.inflate_init_raw(this.streamHandle);
101
- } else if (type === FORMAT_GZIP) {
102
- result = wasm.inflate_init_gzip(this.streamHandle);
103
- } else {
104
- result = wasm.inflate_init(this.streamHandle);
105
- }
106
- }
107
- }
108
- if (result !== 0) {
109
- throw new Error("init failed:" + result);
110
- }
97
+ processChunk(chunk);
111
98
  } catch (error) {
112
- disposeStream(this);
99
+ disposeStream(state);
100
+ readableController.error(error);
113
101
  throw error;
114
102
  }
115
103
  },
116
- transform(chunk, controller) {
104
+ close() {
105
+ if (cancelled) {
106
+ return;
107
+ }
117
108
  try {
118
- const buffer = chunk;
119
- const heap = new Uint8Array(memory.buffer);
120
- const process = this._process;
121
- const last_consumed = this._last_consumed;
122
- const out = this.out;
123
- let offset = 0;
124
- while (offset < buffer.length) {
125
- const toRead = Math.min(buffer.length - offset, 32 * 1024);
126
- if (!this.in || this.inBufferSize < toRead) {
127
- if (this.in && free) {
128
- free(this.in);
129
- this.in = 0;
130
- }
131
- this.in = malloc(toRead);
132
- this.inBufferSize = toRead;
133
- if (!this.in) {
134
- throw new Error("allocation failed");
135
- }
136
- }
137
- heap.set(buffer.subarray(offset, offset + toRead), this.in);
138
- const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
139
- // checked before the byte count is used, so a status code can never be read as one
140
- const code = (result >> 24) & 0xff;
141
- const signedCode = (code & 0x80) ? code - 256 : code;
142
- if (signedCode < 0) {
143
- throw new Error("process error:" + signedCode);
144
- }
145
- const prod = result & 0x00ffffff;
146
- if (prod) {
147
- controller.enqueue(heap.slice(out, out + prod));
148
- }
149
- const consumed = last_consumed(this.streamHandle);
150
- if (consumed === 0 && prod === 0) {
151
- break;
152
- }
153
- offset += consumed;
154
- }
109
+ flushStream();
155
110
  } catch (error) {
156
- disposeStream(this);
157
- controller.error(error);
111
+ disposeStream(state);
112
+ readableController.error(error);
113
+ throw error;
158
114
  }
115
+ const result = disposeStream(state);
116
+ if (result !== 0) {
117
+ const error = new Error("end error:" + result);
118
+ readableController.error(error);
119
+ throw error;
120
+ }
121
+ readableController.close();
159
122
  },
160
- flush(controller) {
161
- try {
162
- const heap = new Uint8Array(memory.buffer);
163
- const process = this._process;
164
- const out = this.out;
165
- while (true) {
166
- const result = process(this.streamHandle, 0, 0, out, outBufferSize, 4);
167
- const code = (result >> 24) & 0xff;
168
- const signedCode = (code & 0x80) ? code - 256 : code;
169
- if (signedCode < 0) {
170
- throw new Error("process error:" + signedCode);
171
- }
172
- const produced = result & 0x00ffffff;
173
- if (produced) {
174
- controller.enqueue(heap.slice(out, out + produced));
175
- }
176
- if (code === 1 || produced === 0) {
177
- break;
123
+ abort(reason) {
124
+ disposeStream(state);
125
+ readableController.error(reason);
126
+ }
127
+ }, { highWaterMark: 1 });
128
+ return { readable, writable };
129
+
130
+ function initStream() {
131
+ try {
132
+ let result;
133
+ state.out = malloc(outBufferSize);
134
+ state.in = malloc(inBufferSize);
135
+ state.inBufferSize = inBufferSize;
136
+ if (!state.out || !state.in) {
137
+ throw new Error("allocation failed");
138
+ }
139
+ if (isCompress) {
140
+ state._process = wasm.deflate_process;
141
+ state._last_consumed = wasm.deflate_last_consumed;
142
+ state._end = wasm.deflate_end;
143
+ state.streamHandle = wasm.deflate_new();
144
+ if (type === FORMAT_GZIP) {
145
+ result = wasm.deflate_init_gzip(state.streamHandle, level);
146
+ } else if (type === FORMAT_DEFLATE_RAW) {
147
+ result = wasm.deflate_init_raw(state.streamHandle, level);
148
+ } else {
149
+ result = wasm.deflate_init(state.streamHandle, level);
150
+ }
151
+ } else {
152
+ if (type === FORMAT_DEFLATE64_RAW) {
153
+ state._process = wasm.inflate9_process;
154
+ state._last_consumed = wasm.inflate9_last_consumed;
155
+ state._end = wasm.inflate9_end;
156
+ state.streamHandle = wasm.inflate9_new();
157
+ result = wasm.inflate9_init_raw(state.streamHandle);
158
+ } else {
159
+ state._process = wasm.inflate_process;
160
+ state._last_consumed = wasm.inflate_last_consumed;
161
+ state._end = wasm.inflate_end;
162
+ state.streamHandle = wasm.inflate_new();
163
+ if (type === FORMAT_DEFLATE_RAW) {
164
+ result = wasm.inflate_init_raw(state.streamHandle);
165
+ } else if (type === FORMAT_GZIP) {
166
+ result = wasm.inflate_init_gzip(state.streamHandle);
167
+ } else {
168
+ result = wasm.inflate_init(state.streamHandle);
178
169
  }
179
170
  }
180
- } catch (error) {
181
- controller.error(error);
182
- } finally {
183
- const result = disposeStream(this);
184
- if (result !== 0) {
185
- controller.error(new Error("end error:" + result));
171
+ }
172
+ if (result !== 0) {
173
+ throw new Error("init failed:" + result);
174
+ }
175
+ } catch (error) {
176
+ disposeStream(state);
177
+ throw error;
178
+ }
179
+ }
180
+
181
+ function processChunk(chunk) {
182
+ const heap = new Uint8Array(memory.buffer);
183
+ const process = state._process;
184
+ const last_consumed = state._last_consumed;
185
+ const out = state.out;
186
+ let offset = 0;
187
+ while (offset < chunk.length) {
188
+ const toRead = Math.min(chunk.length - offset, 32 * 1024);
189
+ if (!state.in || state.inBufferSize < toRead) {
190
+ if (state.in && free) {
191
+ free(state.in);
192
+ state.in = 0;
193
+ }
194
+ state.in = malloc(toRead);
195
+ state.inBufferSize = toRead;
196
+ if (!state.in) {
197
+ throw new Error("allocation failed");
186
198
  }
187
199
  }
188
- },
189
- cancel() {
190
- // release the stream handle and buffers when the pipeline is aborted,
191
- // they would be leaked in the process-lifetime wasm heap otherwise
192
- disposeStream(this);
200
+ heap.set(chunk.subarray(offset, offset + toRead), state.in);
201
+ const result = process(state.streamHandle, state.in, toRead, out, outBufferSize, 0);
202
+ // checked before the byte count is used, so a status code can never be read as one
203
+ const code = (result >> 24) & 0xff;
204
+ const signedCode = (code & 0x80) ? code - 256 : code;
205
+ if (signedCode < 0) {
206
+ throw new Error("process error:" + signedCode);
207
+ }
208
+ const prod = result & 0x00ffffff;
209
+ if (prod) {
210
+ enqueue(heap.slice(out, out + prod));
211
+ }
212
+ const consumed = last_consumed(state.streamHandle);
213
+ if (consumed === 0 && prod === 0) {
214
+ break;
215
+ }
216
+ offset += consumed;
217
+ }
218
+ }
219
+
220
+ function flushStream() {
221
+ const heap = new Uint8Array(memory.buffer);
222
+ const process = state._process;
223
+ const out = state.out;
224
+ while (true) {
225
+ const result = process(state.streamHandle, 0, 0, out, outBufferSize, 4);
226
+ const code = (result >> 24) & 0xff;
227
+ const signedCode = (code & 0x80) ? code - 256 : code;
228
+ if (signedCode < 0) {
229
+ throw new Error("process error:" + signedCode);
230
+ }
231
+ const produced = result & 0x00ffffff;
232
+ if (produced) {
233
+ enqueue(heap.slice(out, out + produced));
234
+ }
235
+ if (code === 1 || produced === 0) {
236
+ break;
237
+ }
193
238
  }
194
- });
239
+ }
240
+
241
+ function enqueue(chunk) {
242
+ backpressure = true;
243
+ readableController.enqueue(chunk);
244
+ }
245
+
246
+ function resumeWrite() {
247
+ if (resolveWrite) {
248
+ const resolve = resolveWrite;
249
+ resolveWrite = null;
250
+ resolve();
251
+ }
252
+ }
195
253
 
196
254
  function disposeStream(state) {
197
255
  let endResult = 0;
@@ -43,11 +43,16 @@ function toCompatibleReadable(readable) {
43
43
  const reader = readable.getReader();
44
44
  return new ReadableStream({
45
45
  async pull(controller) {
46
- const { value, done } = await reader.read();
47
- if (done) {
48
- controller.close();
49
- } else {
50
- controller.enqueue(value);
46
+ try {
47
+ const { value, done } = await reader.read();
48
+ if (done) {
49
+ controller.close();
50
+ } else {
51
+ controller.enqueue(value);
52
+ }
53
+ } catch (error) {
54
+ reader.cancel(error).catch(() => { });
55
+ throw error;
51
56
  }
52
57
  },
53
58
  cancel(reason) {
@@ -26,6 +26,6 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- const VERSION = "2.16.0";
29
+ const VERSION = "2.16.1";
30
30
 
31
31
  export { VERSION };