zlib-streams 1.2.3 → 1.3.0

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/Makefile CHANGED
@@ -298,6 +298,8 @@ run_all_tests: dist/zlib-streams-dev.wasm
298
298
  @node src/wasm/tests/test_process_error_encoding.js dist/zlib-streams-dev.wasm
299
299
  # Buffers and zlib state released whichever end ends the stream, with no transformer hook
300
300
  @node src/wasm/tests/test_stream_abort_releases_memory.js dist/zlib-streams-dev.wasm
301
+ # Bytes after the end of the stream rejected, as the platform inflaters do
302
+ @node src/wasm/tests/test_trailing_data.js dist/zlib-streams-dev.wasm
301
303
  @echo "Completed run_all_tests"
302
304
 
303
305
  dist/zlib-streams-dev.wasm: $(WASM_SRCS)
@@ -32,6 +32,8 @@ const FORMAT_DEFLATE = "deflate";
32
32
  const FORMAT_DEFLATE_RAW = "deflate-raw";
33
33
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
34
34
  const FORMAT_GZIP = "gzip";
35
+ const Z_MEM_ERROR = -4;
36
+ const Z_MEM_ERROR_CODE = "Z_MEM_ERROR";
35
37
 
36
38
  let wasm, malloc, free, memory, initError;
37
39
 
@@ -52,6 +54,13 @@ export function resetWasmExports() {
52
54
  wasm = malloc = free = memory = initError = null;
53
55
  }
54
56
 
57
+ function setZlibCode(error, result) {
58
+ if (result === Z_MEM_ERROR) {
59
+ error.code = Z_MEM_ERROR_CODE;
60
+ }
61
+ return error;
62
+ }
63
+
55
64
  function _make(isCompress, type, options = {}) {
56
65
  if (!wasm) {
57
66
  const error = new Error("WASM module not loaded");
@@ -61,7 +70,7 @@ function _make(isCompress, type, options = {}) {
61
70
  const level = (typeof options.level === "number") ? options.level : -1;
62
71
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
63
72
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
64
- const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0 };
73
+ const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0, streamEnded: false };
65
74
  let readableController, writableController, resolveWrite, cancelReason;
66
75
  let backpressure = true;
67
76
  let cancelled = false;
@@ -114,7 +123,7 @@ function _make(isCompress, type, options = {}) {
114
123
  }
115
124
  const result = disposeStream(state);
116
125
  if (result !== 0) {
117
- const error = new Error("end error:" + result);
126
+ const error = setZlibCode(new Error("end error:" + result), result);
118
127
  readableController.error(error);
119
128
  throw error;
120
129
  }
@@ -134,7 +143,7 @@ function _make(isCompress, type, options = {}) {
134
143
  state.in = malloc(inBufferSize);
135
144
  state.inBufferSize = inBufferSize;
136
145
  if (!state.out || !state.in) {
137
- throw new Error("allocation failed");
146
+ throw setZlibCode(new Error("allocation failed"), Z_MEM_ERROR);
138
147
  }
139
148
  if (isCompress) {
140
149
  state._process = wasm.deflate_process;
@@ -170,7 +179,7 @@ function _make(isCompress, type, options = {}) {
170
179
  }
171
180
  }
172
181
  if (result !== 0) {
173
- throw new Error("init failed:" + result);
182
+ throw setZlibCode(new Error("init failed:" + result), result);
174
183
  }
175
184
  } catch (error) {
176
185
  disposeStream(state);
@@ -185,6 +194,9 @@ function _make(isCompress, type, options = {}) {
185
194
  const out = state.out;
186
195
  let offset = 0;
187
196
  while (offset < chunk.length) {
197
+ if (state.streamEnded) {
198
+ throw new Error("trailing data after the end of the stream");
199
+ }
188
200
  const toRead = Math.min(chunk.length - offset, 32 * 1024);
189
201
  if (!state.in || state.inBufferSize < toRead) {
190
202
  if (state.in && free) {
@@ -194,7 +206,7 @@ function _make(isCompress, type, options = {}) {
194
206
  state.in = malloc(toRead);
195
207
  state.inBufferSize = toRead;
196
208
  if (!state.in) {
197
- throw new Error("allocation failed");
209
+ throw setZlibCode(new Error("allocation failed"), Z_MEM_ERROR);
198
210
  }
199
211
  }
200
212
  heap.set(chunk.subarray(offset, offset + toRead), state.in);
@@ -203,14 +215,16 @@ function _make(isCompress, type, options = {}) {
203
215
  const code = (result >> 24) & 0xff;
204
216
  const signedCode = (code & 0x80) ? code - 256 : code;
205
217
  if (signedCode < 0) {
206
- throw new Error("process error:" + signedCode);
218
+ throw setZlibCode(new Error("process error:" + signedCode), signedCode);
207
219
  }
208
220
  const prod = result & 0x00ffffff;
209
221
  if (prod) {
210
222
  enqueue(heap.slice(out, out + prod));
211
223
  }
212
224
  const consumed = last_consumed(state.streamHandle);
213
- if (consumed === 0 && prod === 0) {
225
+ if (code === 1) {
226
+ state.streamEnded = true;
227
+ } else if (consumed === 0 && prod === 0) {
214
228
  break;
215
229
  }
216
230
  offset += consumed;
@@ -226,7 +240,7 @@ function _make(isCompress, type, options = {}) {
226
240
  const code = (result >> 24) & 0xff;
227
241
  const signedCode = (code & 0x80) ? code - 256 : code;
228
242
  if (signedCode < 0) {
229
- throw new Error("process error:" + signedCode);
243
+ throw setZlibCode(new Error("process error:" + signedCode), signedCode);
230
244
  }
231
245
  const produced = result & 0x00ffffff;
232
246
  if (produced) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "WASM-based Compression Streams API implementation using zlib, with support for deflate64 decompression.",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "1.2.3",
6
+ "version": "1.3.0",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "deflate",
@@ -32,6 +32,8 @@ const FORMAT_DEFLATE = "deflate";
32
32
  const FORMAT_DEFLATE_RAW = "deflate-raw";
33
33
  const FORMAT_DEFLATE64_RAW = "deflate64-raw";
34
34
  const FORMAT_GZIP = "gzip";
35
+ const Z_MEM_ERROR = -4;
36
+ const Z_MEM_ERROR_CODE = "Z_MEM_ERROR";
35
37
 
36
38
  let wasm, malloc, free, memory, initError;
37
39
 
@@ -52,6 +54,13 @@ export function resetWasmExports() {
52
54
  wasm = malloc = free = memory = initError = null;
53
55
  }
54
56
 
57
+ function setZlibCode(error, result) {
58
+ if (result === Z_MEM_ERROR) {
59
+ error.code = Z_MEM_ERROR_CODE;
60
+ }
61
+ return error;
62
+ }
63
+
55
64
  function _make(isCompress, type, options = {}) {
56
65
  if (!wasm) {
57
66
  const error = new Error("WASM module not loaded");
@@ -61,7 +70,7 @@ function _make(isCompress, type, options = {}) {
61
70
  const level = (typeof options.level === "number") ? options.level : -1;
62
71
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
63
72
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
64
- const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0 };
73
+ const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0, streamEnded: false };
65
74
  let readableController, writableController, resolveWrite, cancelReason;
66
75
  let backpressure = true;
67
76
  let cancelled = false;
@@ -114,7 +123,7 @@ function _make(isCompress, type, options = {}) {
114
123
  }
115
124
  const result = disposeStream(state);
116
125
  if (result !== 0) {
117
- const error = new Error("end error:" + result);
126
+ const error = setZlibCode(new Error("end error:" + result), result);
118
127
  readableController.error(error);
119
128
  throw error;
120
129
  }
@@ -134,7 +143,7 @@ function _make(isCompress, type, options = {}) {
134
143
  state.in = malloc(inBufferSize);
135
144
  state.inBufferSize = inBufferSize;
136
145
  if (!state.out || !state.in) {
137
- throw new Error("allocation failed");
146
+ throw setZlibCode(new Error("allocation failed"), Z_MEM_ERROR);
138
147
  }
139
148
  if (isCompress) {
140
149
  state._process = wasm.deflate_process;
@@ -170,7 +179,7 @@ function _make(isCompress, type, options = {}) {
170
179
  }
171
180
  }
172
181
  if (result !== 0) {
173
- throw new Error("init failed:" + result);
182
+ throw setZlibCode(new Error("init failed:" + result), result);
174
183
  }
175
184
  } catch (error) {
176
185
  disposeStream(state);
@@ -185,6 +194,9 @@ function _make(isCompress, type, options = {}) {
185
194
  const out = state.out;
186
195
  let offset = 0;
187
196
  while (offset < chunk.length) {
197
+ if (state.streamEnded) {
198
+ throw new Error("trailing data after the end of the stream");
199
+ }
188
200
  const toRead = Math.min(chunk.length - offset, 32 * 1024);
189
201
  if (!state.in || state.inBufferSize < toRead) {
190
202
  if (state.in && free) {
@@ -194,7 +206,7 @@ function _make(isCompress, type, options = {}) {
194
206
  state.in = malloc(toRead);
195
207
  state.inBufferSize = toRead;
196
208
  if (!state.in) {
197
- throw new Error("allocation failed");
209
+ throw setZlibCode(new Error("allocation failed"), Z_MEM_ERROR);
198
210
  }
199
211
  }
200
212
  heap.set(chunk.subarray(offset, offset + toRead), state.in);
@@ -203,14 +215,16 @@ function _make(isCompress, type, options = {}) {
203
215
  const code = (result >> 24) & 0xff;
204
216
  const signedCode = (code & 0x80) ? code - 256 : code;
205
217
  if (signedCode < 0) {
206
- throw new Error("process error:" + signedCode);
218
+ throw setZlibCode(new Error("process error:" + signedCode), signedCode);
207
219
  }
208
220
  const prod = result & 0x00ffffff;
209
221
  if (prod) {
210
222
  enqueue(heap.slice(out, out + prod));
211
223
  }
212
224
  const consumed = last_consumed(state.streamHandle);
213
- if (consumed === 0 && prod === 0) {
225
+ if (code === 1) {
226
+ state.streamEnded = true;
227
+ } else if (consumed === 0 && prod === 0) {
214
228
  break;
215
229
  }
216
230
  offset += consumed;
@@ -226,7 +240,7 @@ function _make(isCompress, type, options = {}) {
226
240
  const code = (result >> 24) & 0xff;
227
241
  const signedCode = (code & 0x80) ? code - 256 : code;
228
242
  if (signedCode < 0) {
229
- throw new Error("process error:" + signedCode);
243
+ throw setZlibCode(new Error("process error:" + signedCode), signedCode);
230
244
  }
231
245
  const produced = result & 0x00ffffff;
232
246
  if (produced) {