zlib-streams 1.0.6 → 1.1.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
@@ -1,6 +1,11 @@
1
1
  CC=gcc
2
- CFLAGS=-I./src/zlib -I./src -I./test -I./src/zlib/contrib/infback9 -O2 -w -MMD -MP
3
- DEBUG_CFLAGS=-I./src/zlib -I./src -I./test -I./src/zlib/contrib/infback9 -O0 -g3 -ggdb3 -fno-inline -fno-omit-frame-pointer -w -MMD -MP
2
+ # INFLATE_CHUNK_GENERIC selects the portable chunk copies in chunkcopy.h, which has
3
+ # no wasm SIMD path and would #error without one of its three arch macros.
4
+ # INFLATE_CHUNK_READ_64LE buffers the input bits in a uint64_t inside inffast_chunk.c
5
+ # only; state->hold stays unsigned long. Both are needed wherever inflate.c is built.
6
+ INFLATE_CHUNK_CFLAGS = -DINFLATE_CHUNK_GENERIC -DINFLATE_CHUNK_READ_64LE
7
+ CFLAGS=-I./src/zlib -I./src -I./test -I./src/zlib/contrib/infback9 -O2 -w -MMD -MP $(INFLATE_CHUNK_CFLAGS)
8
+ DEBUG_CFLAGS=-I./src/zlib -I./src -I./test -I./src/zlib/contrib/infback9 -O0 -g3 -ggdb3 -fno-inline -fno-omit-frame-pointer -w -MMD -MP $(INFLATE_CHUNK_CFLAGS)
4
9
  ## By default we don't enable the INF9 tracing macros so debug binaries
5
10
  ## don't embed large diagnostic strings. To enable tracing for local
6
11
  ## debugging, uncomment and set DEBUG_DEFINES accordingly.
@@ -9,18 +14,18 @@ DEBUG_CFLAGS=-I./src/zlib -I./src -I./test -I./src/zlib/contrib/infback9 -O0 -g3
9
14
  ## Debug defines are disabled by default for a clean commit-ready Makefile.
10
15
  DEBUG_DEFINES=
11
16
  DEBUG_DEFINES_TRACED=
12
- SRC=src/inflate9.c src/zlib/contrib/infback9/inftree9.c src/zlib/zutil.c src/zlib/inflate.c src/zlib/inftrees.c
17
+ SRC=src/inflate.c src/inffast_chunk.c src/inftrees.c src/zlib/zutil.c
13
18
  TESTSRC=zlib/crc32.c
14
19
  LIBS=-lz
15
20
 
16
21
  ## Build the payload decompressor test binary used for verification (deduplicated sources)
17
22
  PD_SRCS = test/payload_decompress.c \
18
- src/inflate9.c src/zlib/inffast.c src/zlib/inftrees.c src/zlib/zutil.c src/zlib/inflate.c src/zlib/infback.c \
19
- src/zlib/contrib/infback9/infback9.c src/zlib/contrib/infback9/inftree9.c src/zlib/crc32.c src/zlib/adler32.c src/zlib/trees.c
23
+ src/inflate.c src/inffast_chunk.c src/inftrees.c src/zlib/zutil.c \
24
+ src/zlib/crc32.c src/zlib/adler32.c
20
25
 
21
26
  PD_NOWINDOW_SRCS = test/payload_decompress_nowindow.c \
22
- src/inflate9.c src/zlib/inffast.c src/zlib/inftrees.c src/zlib/zutil.c src/zlib/inflate.c src/zlib/infback.c \
23
- src/zlib/contrib/infback9/infback9.c src/zlib/contrib/infback9/inftree9.c src/zlib/crc32.c src/zlib/adler32.c src/zlib/trees.c
27
+ src/inflate.c src/inffast_chunk.c src/inftrees.c src/zlib/zutil.c \
28
+ src/zlib/crc32.c src/zlib/adler32.c
24
29
 
25
30
  PD_NOWINDOW_DEBUG_OBJS = $(PD_NOWINDOW_SRCS:%.c=build/debug/%.o)
26
31
 
@@ -128,17 +133,22 @@ ci:
128
133
  # WASM build target (convenience target to produce dist/zlib-streams-dev.wasm)
129
134
  # -----------------------------------------------------------------------------
130
135
  EMCC ?= emsdk/upstream/emscripten/emcc
136
+ WASM_OPT ?= emsdk/upstream/bin/wasm-opt
131
137
 
132
- WASM_SRCS = src/wasm/inflate9_stream_wasm.c src/wasm/inflate_stream_wasm.c src/wasm/deflate_stream_wasm.c src/wasm/wasm_stream_common.c src/wasm/allocator.c src/inflate9.c \
133
- src/zlib/contrib/infback9/inftree9.c \
134
- src/zlib/inffast.c src/zlib/inflate.c src/zlib/inftrees.c src/zlib/zutil.c \
135
- src/zlib/crc32.c src/zlib/adler32.c src/zlib/trees.c src/zlib/deflate.c
138
+ WASM_SRCS = src/wasm/inflate9_stream_wasm.c src/wasm/inflate_stream_wasm.c src/wasm/deflate_stream_wasm.c src/wasm/wasm_stream_common.c src/wasm/allocator.c \
139
+ src/inflate.c src/inffast_chunk.c src/inftrees.c src/zlib/zutil.c \
140
+ src/zlib/crc32.c src/zlib/adler32.c src/trees.c src/deflate.c src/deflate_crc32.c
136
141
  # CRC-32: -DZ_SOLO suppresses zlib's Z_U4/Z_U8 word types, which makes crc32.c's braid
137
142
  # path (#elif defined(Z_U4)) fall back to a byte-at-a-time loop. Restore the types and
138
143
  # force the 8-byte braid (Z_TESTW=8) so the slicing/braided CRC compiles for wasm:
139
144
  # ~12x faster CRC (342 -> ~4100 MB/s), bit-identical output. wasm32 has native i64.
140
145
  WASM_CRC_CFLAGS = -DZ_U4=unsigned -DZ_U8='unsigned long long' -DZ_TESTW=8
141
- WASM_CFLAGS = -Isrc -Isrc/zlib -Isrc/zlib/contrib/infback9 -O2 -flto -DDYNAMIC_CRC_TABLE -DBUILDFIXED -DZ_SOLO $(WASM_CRC_CFLAGS)
146
+ # DEFLATE_COMPARE256_64LE extends matches 8 bytes at a time in longest_match, which is
147
+ # the same match length computed faster: ~7% at every level, byte-identical output.
148
+ # USE_ZLIB_RABIN_KARP_ROLLING_HASH turns Chromium's own hash OFF so the deflate stream
149
+ # stays bit-for-bit what madler's deflate.c produces.
150
+ WASM_DEFLATE_CFLAGS = -DDEFLATE_COMPARE256_64LE -DUSE_ZLIB_RABIN_KARP_ROLLING_HASH
151
+ WASM_CFLAGS = -Isrc -Isrc/zlib -Isrc/zlib/contrib/infback9 -O2 -flto -DDYNAMIC_CRC_TABLE -DBUILDFIXED -DZ_SOLO $(WASM_CRC_CFLAGS) $(WASM_DEFLATE_CFLAGS) $(INFLATE_CHUNK_CFLAGS)
142
152
 
143
153
  .PHONY: wasm
144
154
  wasm: dist/zlib-streams-dev.wasm
@@ -279,6 +289,9 @@ run_all_tests: dist/zlib-streams-dev.wasm
279
289
  @node src/wasm/tests/run_roundtrip_cli.js deflate 24000 dist/zlib-streams-dev.wasm
280
290
  @$(MAKE) run_transform_roundtrip
281
291
  @$(MAKE) test_decompressionstream_inflate9
292
+ # Output buffer filling before any input is consumed, including a deflate64
293
+ # match longer than the buffer, which no encoder we have can produce
294
+ @node src/wasm/tests/test_output_buffer_boundary.js dist/zlib-streams-dev.wasm
282
295
  @echo "Completed run_all_tests"
283
296
 
284
297
  dist/zlib-streams-dev.wasm: $(WASM_SRCS)
@@ -301,7 +314,7 @@ dist/zlib-streams.wasm: $(WASM_SRCS)
301
314
  -s EXPORTED_FUNCTIONS='["_inflate9_new","_inflate9_init","_inflate9_init_raw","_inflate9_process","_inflate9_end","_inflate9_last_consumed","_inflate_new","_inflate_init","_inflate_init_raw","_inflate_init_gzip","_inflate_process","_inflate_end","_inflate_last_consumed","_deflate_new","_deflate_init","_deflate_init_raw","_deflate_init_gzip","_deflate_process","_deflate_end","_deflate_last_consumed","_malloc","_free"]' \
302
315
  -o $@
303
316
  cp src/wasm/api/zlib-streams.js dist/zlib-streams.js
304
- @which wasm-opt >/dev/null 2>&1 && { echo "Running wasm-opt -Oz --enable-bulk-memory-opt"; wasm-opt -Oz --enable-bulk-memory-opt -o $@ $@ || true; } || true
317
+ @test -x $(WASM_OPT) && { echo "Running wasm-opt -Oz --enable-bulk-memory-opt"; $(WASM_OPT) -Oz --enable-bulk-memory-opt -o $@ $@ || true; } || true
305
318
 
306
319
  # -----------------------------------------------------------------------------
307
320
  # Optional generator: build a C++ tool that creates Deflate64 ZIPs using the
Binary file
@@ -1,7 +1,39 @@
1
- /* eslint-disable no-unused-vars */
2
- /* global Buffer, process, TransformStream */
1
+ /*
2
+ Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
3
 
4
- let wasm, malloc, free, memory;
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in
12
+ the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. The names of the authors may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
+ INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
+ OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ /* global TransformStream */
30
+
31
+ const FORMAT_DEFLATE = "deflate";
32
+ const FORMAT_DEFLATE_RAW = "deflate-raw";
33
+ const FORMAT_DEFLATE64_RAW = "deflate64-raw";
34
+ const FORMAT_GZIP = "gzip";
35
+
36
+ let wasm, malloc, free, memory, initError;
5
37
 
6
38
  export function setWasmExports(wasmAPI) {
7
39
  wasm = wasmAPI;
@@ -12,53 +44,74 @@ export function setWasmExports(wasmAPI) {
12
44
  }
13
45
  }
14
46
 
47
+ export function setInitError(error) {
48
+ initError = error;
49
+ }
50
+
51
+ export function resetWasmExports() {
52
+ wasm = malloc = free = memory = initError = null;
53
+ }
54
+
15
55
  function _make(isCompress, type, options = {}) {
56
+ if (!wasm) {
57
+ const error = new Error("WASM module not loaded");
58
+ error.cause = initError;
59
+ throw error;
60
+ }
16
61
  const level = (typeof options.level === "number") ? options.level : -1;
17
62
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
18
63
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
19
64
 
20
65
  return new TransformStream({
21
66
  start() {
22
- let result;
23
- this.out = malloc(outBufferSize);
24
- this.in = malloc(inBufferSize);
25
- this.inBufferSize = inBufferSize;
26
- this._scratch = new Uint8Array(outBufferSize);
27
- if (isCompress) {
28
- this._process = wasm.deflate_process;
29
- this._last_consumed = wasm.deflate_last_consumed;
30
- this._end = wasm.deflate_end;
31
- this.streamHandle = wasm.deflate_new();
32
- if (type === "gzip") {
33
- result = wasm.deflate_init_gzip(this.streamHandle, level);
34
- } else if (type === "deflate-raw") {
35
- result = wasm.deflate_init_raw(this.streamHandle, level);
36
- } else {
37
- result = wasm.deflate_init(this.streamHandle, level);
67
+ 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");
38
74
  }
39
- } else {
40
- if (type === "deflate64-raw") {
41
- this._process = wasm.inflate9_process;
42
- this._last_consumed = wasm.inflate9_last_consumed;
43
- this._end = wasm.inflate9_end;
44
- this.streamHandle = wasm.inflate9_new();
45
- result = wasm.inflate9_init_raw(this.streamHandle);
75
+ this._scratch = new Uint8Array(outBufferSize);
76
+ if (isCompress) {
77
+ this._process = wasm.deflate_process;
78
+ this._last_consumed = wasm.deflate_last_consumed;
79
+ this._end = wasm.deflate_end;
80
+ this.streamHandle = wasm.deflate_new();
81
+ if (type === FORMAT_GZIP) {
82
+ result = wasm.deflate_init_gzip(this.streamHandle, level);
83
+ } else if (type === FORMAT_DEFLATE_RAW) {
84
+ result = wasm.deflate_init_raw(this.streamHandle, level);
85
+ } else {
86
+ result = wasm.deflate_init(this.streamHandle, level);
87
+ }
46
88
  } else {
47
- this._process = wasm.inflate_process;
48
- this._last_consumed = wasm.inflate_last_consumed;
49
- this._end = wasm.inflate_end;
50
- this.streamHandle = wasm.inflate_new();
51
- if (type === "deflate-raw") {
52
- result = wasm.inflate_init_raw(this.streamHandle);
53
- } else if (type === "gzip") {
54
- result = wasm.inflate_init_gzip(this.streamHandle);
89
+ if (type === FORMAT_DEFLATE64_RAW) {
90
+ this._process = wasm.inflate9_process;
91
+ this._last_consumed = wasm.inflate9_last_consumed;
92
+ this._end = wasm.inflate9_end;
93
+ this.streamHandle = wasm.inflate9_new();
94
+ result = wasm.inflate9_init_raw(this.streamHandle);
55
95
  } else {
56
- result = wasm.inflate_init(this.streamHandle);
96
+ this._process = wasm.inflate_process;
97
+ this._last_consumed = wasm.inflate_last_consumed;
98
+ this._end = wasm.inflate_end;
99
+ this.streamHandle = wasm.inflate_new();
100
+ if (type === FORMAT_DEFLATE_RAW) {
101
+ result = wasm.inflate_init_raw(this.streamHandle);
102
+ } else if (type === FORMAT_GZIP) {
103
+ result = wasm.inflate_init_gzip(this.streamHandle);
104
+ } else {
105
+ result = wasm.inflate_init(this.streamHandle);
106
+ }
57
107
  }
58
108
  }
59
- }
60
- if (result !== 0) {
61
- throw new Error("init failed:" + result);
109
+ if (result !== 0) {
110
+ throw new Error("init failed:" + result);
111
+ }
112
+ } catch (error) {
113
+ disposeStream(this);
114
+ throw error;
62
115
  }
63
116
  },
64
117
  transform(chunk, controller) {
@@ -75,9 +128,13 @@ function _make(isCompress, type, options = {}) {
75
128
  if (!this.in || this.inBufferSize < toRead) {
76
129
  if (this.in && free) {
77
130
  free(this.in);
131
+ this.in = 0;
78
132
  }
79
133
  this.in = malloc(toRead);
80
134
  this.inBufferSize = toRead;
135
+ if (!this.in) {
136
+ throw new Error("allocation failed");
137
+ }
81
138
  }
82
139
  heap.set(buffer.subarray(offset, offset + toRead), this.in);
83
140
  const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
@@ -94,21 +151,13 @@ function _make(isCompress, type, options = {}) {
94
151
  }
95
152
  }
96
153
  const consumed = last_consumed(this.streamHandle);
97
- if (consumed === 0) {
154
+ if (consumed === 0 && prod === 0) {
98
155
  break;
99
156
  }
100
157
  offset += consumed;
101
158
  }
102
159
  } catch (error) {
103
- if (this._end && this.streamHandle) {
104
- this._end(this.streamHandle);
105
- }
106
- if (this.in && free) {
107
- free(this.in);
108
- }
109
- if (this.out && free) {
110
- free(this.out);
111
- }
160
+ disposeStream(this);
112
161
  controller.error(error);
113
162
  }
114
163
  },
@@ -139,30 +188,54 @@ function _make(isCompress, type, options = {}) {
139
188
  } catch (error) {
140
189
  controller.error(error);
141
190
  } finally {
142
- if (this._end && this.streamHandle) {
143
- const result = this._end(this.streamHandle);
144
- if (result !== 0) {
145
- controller.error(new Error("end error:" + result));
146
- }
147
- }
148
- if (this.in && free) {
149
- free(this.in);
150
- }
151
- if (this.out && free) {
152
- free(this.out);
191
+ const result = disposeStream(this);
192
+ if (result !== 0) {
193
+ controller.error(new Error("end error:" + result));
153
194
  }
154
195
  }
196
+ },
197
+ cancel() {
198
+ // release the stream handle and buffers when the pipeline is aborted,
199
+ // they would be leaked in the process-lifetime wasm heap otherwise
200
+ disposeStream(this);
155
201
  }
156
202
  });
203
+
204
+ function disposeStream(state) {
205
+ let endResult = 0;
206
+ if (state.streamHandle && state._end) {
207
+ endResult = state._end(state.streamHandle);
208
+ }
209
+ state.streamHandle = 0;
210
+ if (state.in && free) {
211
+ free(state.in);
212
+ }
213
+ state.in = 0;
214
+ if (state.out && free) {
215
+ free(state.out);
216
+ }
217
+ state.out = 0;
218
+ return endResult;
219
+ }
157
220
  }
158
221
 
159
222
  export class CompressionStreamZlib {
160
- constructor(type = "deflate", options) {
223
+ constructor(type = FORMAT_DEFLATE, options) {
161
224
  return _make(true, type, options);
162
225
  }
163
226
  }
164
227
  export class DecompressionStreamZlib {
165
- constructor(type = "deflate", options) {
228
+ constructor(type = FORMAT_DEFLATE, options) {
166
229
  return _make(false, type, options);
167
230
  }
168
- }
231
+ }
232
+ // These codecs are backed by the WASM module; they are unusable until setWasmExports() has run.
233
+ // The worker uses this flag to know it must fall back to the native CompressionStream when the
234
+ // module fails to load, rather than discarding a self-contained codec supplied through config.
235
+ CompressionStreamZlib.requiresModule = true;
236
+ DecompressionStreamZlib.requiresModule = true;
237
+ // Constructing these classes before the module is loaded throws, so capability probes cannot rely
238
+ // on trying the constructor; the formats are declared instead, next to the branches implementing
239
+ // them in _make().
240
+ CompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP];
241
+ DecompressionStreamZlib.supportedFormats = [FORMAT_DEFLATE, FORMAT_DEFLATE_RAW, FORMAT_GZIP, FORMAT_DEFLATE64_RAW];
Binary file
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.0.6",
6
+ "version": "1.1.0",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "deflate",
@@ -28,4 +28,4 @@
28
28
  "publishConfig": {
29
29
  "access": "public"
30
30
  }
31
- }
31
+ }
package/src/README.md CHANGED
@@ -1 +1,61 @@
1
- See https://github.com/gildas-lormeau/inflate9.c
1
+ # Sources
2
+
3
+ `src/zlib` is a submodule of [madler/zlib](https://github.com/madler/zlib) and is never edited. The
4
+ files directly under `src/` are forked copies, compiled instead of their submodule counterparts. The
5
+ deflate64 work is described in <https://github.com/gildas-lormeau/inflate9.c>.
6
+
7
+ ## Forked from madler/zlib
8
+
9
+ | file | why it is forked |
10
+ |---|---|
11
+ | `inftrees.c`, `inftrees.h` | deflate64 length code 285 and distance codes 30 and 31 |
12
+ | `trees.c` | builds the static deflate trees at run time instead of embedding them |
13
+
14
+ ## Forked from Chromium's zlib
15
+
16
+ `deflate.c`, `deflate.h`, `compare256.h`, `insert_string.h`, `cpu_features.h`, `inflate.c`,
17
+ `inffast.h`, `inffast_chunk.c`, `inffast_chunk.h` and `chunkcopy.h` come from
18
+ <https://chromium.googlesource.com/chromium/src/third_party/zlib>, revision
19
+ `285e94b8fa95ad3b7d16b80798ec8dce6febb8c8`. They are BSD-licensed, see the headers in the files.
20
+ `inflate.c`, `inffast_chunk.*` and `chunkcopy.h` are their `contrib/optimizations` versions.
21
+
22
+ `inflate.c` still carries the deflate64 support on top. That merge is small because the two are
23
+ orthogonal: deflate64 never enters `inflate_fast`, so the chunked fast path does not know about it.
24
+
25
+ ### Build options
26
+
27
+ Deflate, in `WASM_DEFLATE_CFLAGS`:
28
+
29
+ - `DEFLATE_COMPARE256_64LE` extends matches 8 bytes at a time in `longest_match`. Same match length,
30
+ computed faster. About 7% at every level.
31
+ - `USE_ZLIB_RABIN_KARP_ROLLING_HASH` turns Chromium's own hash off, so the deflate stream stays
32
+ bit-for-bit what madler's `deflate.c` produces. Dropping this flag enables the faster ANZAC hash,
33
+ which is valid DEFLATE but different bytes.
34
+
35
+ Inflate, in `INFLATE_CHUNK_CFLAGS`, needed by every target that builds `inflate.c`, not only the
36
+ wasm one:
37
+
38
+ - `INFLATE_CHUNK_GENERIC` selects the portable chunk copies. `chunkcopy.h` has no wasm SIMD path and
39
+ `#error`s without one of its three arch macros. `-msimd128` was measured and buys nothing.
40
+ - `INFLATE_CHUNK_READ_64LE` buffers the input bits in a `uint64_t` inside `inffast_chunk.c` only.
41
+ `state->hold` stays `unsigned long`. Together they are worth about 20%.
42
+
43
+ ### Deliberate edits, to re-apply when the Chromium files are updated
44
+
45
+ 1. `deflate.c`, `inflate.c` and `inffast_chunk.c` include `"insert_string.h"`, `"inffast_chunk.h"`
46
+ and `"chunkcopy.h"` directly, not through `contrib/optimizations/`, because this repo keeps
47
+ forked zlib sources flat.
48
+ 2. `deflate.h` leaves `LIT_MEM` off, as madler does. Chromium turns it on, which costs 16 KB of
49
+ `pending_buf` per deflate stream for about 1.5% of speed. The wasm heap is fixed at 16.9 MB, so
50
+ that is 62 concurrent deflate streams instead of 59.
51
+ 3. `deflate.h` casts the arguments of `zmemcpy` and `zmemzero`. Chromium's `zutil.h` declares them
52
+ taking `void *`, madler's takes `Bytef *`, and this build keeps madler's.
53
+ 4. `inflate.c` keeps the 9-bit and 6-bit root tables instead of Chromium's 10 and 9. Theirs need
54
+ `ENOUGH_LENS` raised from 852 to 1332, which is 1920 more bytes per inflate state and a fifth of
55
+ the concurrent inflate streams, for about 1% of speed. Without that change to `inftrees.h` they
56
+ fail every dynamic block with "invalid literal/lengths set".
57
+ 5. `chunkcopy.h` includes `<stddef.h>` for `ptrdiff_t`, which `-DZ_SOLO` keeps `zutil.h` from
58
+ pulling in.
59
+
60
+ `deflate_crc32.c` supplies `crc_reset`, `crc_finalize` and `copy_with_crc`. Chromium's `crc32.c` owns
61
+ them and `deflate.c` calls them on the gzip path, but this build keeps madler's `crc32.c`.