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 +26 -13
- package/dist/zlib-streams-dev.wasm +0 -0
- package/dist/zlib-streams.js +135 -62
- package/dist/zlib-streams.wasm +0 -0
- package/package.json +2 -2
- package/src/README.md +61 -1
- package/src/chunkcopy.h +565 -0
- package/src/compare256.h +56 -0
- package/src/cpu_features.h +22 -0
- package/src/deflate.c +2349 -0
- package/src/deflate.h +420 -0
- package/src/deflate_crc32.c +22 -0
- package/src/inffast.h +26 -0
- package/src/inffast_chunk.c +376 -0
- package/src/inffast_chunk.h +42 -0
- package/src/inflate.c +1573 -0
- package/src/inflate.h +128 -0
- package/src/inftrees.c +321 -0
- package/src/inftrees.h +67 -0
- package/src/insert_string.h +80 -0
- package/src/trees.c +1053 -0
- package/src/wasm/api/zlib-streams.js +135 -62
- package/src/wasm/inflate9_stream_wasm.c +6 -18
- package/src/inflate9.c +0 -859
- package/src/inflate9.h +0 -9
package/Makefile
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
CC=gcc
|
|
2
|
-
|
|
3
|
-
|
|
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/
|
|
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/
|
|
19
|
-
src/zlib/
|
|
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/
|
|
23
|
-
src/zlib/
|
|
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
|
|
133
|
-
src/
|
|
134
|
-
src/zlib/
|
|
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
|
-
|
|
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
|
-
@
|
|
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
|
package/dist/zlib-streams.js
CHANGED
|
@@ -1,7 +1,39 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
3
3
|
|
|
4
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
40
|
-
if (
|
|
41
|
-
this._process = wasm.
|
|
42
|
-
this._last_consumed = wasm.
|
|
43
|
-
this._end = wasm.
|
|
44
|
-
this.streamHandle = wasm.
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
result = wasm.
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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 =
|
|
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 =
|
|
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];
|
package/dist/zlib-streams.wasm
CHANGED
|
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
|
+
"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
|
-
|
|
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`.
|