@zip.js/zip.js 2.8.30 → 2.8.32

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 (56) hide show
  1. package/BENCHMARKS.md +82 -1
  2. package/deno.json +5 -4
  3. package/dist/zip-core.js +403 -339
  4. package/dist/zip-core.min.js +1 -1
  5. package/dist/zip-fs-core.js +116 -278
  6. package/dist/zip-fs-core.min.js +1 -1
  7. package/dist/zip-fs-native.js +440 -378
  8. package/dist/zip-fs-native.min.js +1 -1
  9. package/dist/zip-fs.js +439 -377
  10. package/dist/zip-fs.min.js +1 -1
  11. package/dist/zip-legacy.js +408 -344
  12. package/dist/zip-legacy.min.js +1 -1
  13. package/dist/zip-module.wasm +0 -0
  14. package/dist/zip-native.js +411 -347
  15. package/dist/zip-native.min.js +1 -1
  16. package/dist/zip-web-worker-native.js +1 -1
  17. package/dist/zip-web-worker.js +1 -1
  18. package/dist/zip.js +410 -346
  19. package/dist/zip.min.js +1 -1
  20. package/index-native.cjs +440 -378
  21. package/index-native.min.js +1 -1
  22. package/index.cjs +439 -377
  23. package/index.d.cts +2853 -0
  24. package/index.d.ts +278 -1
  25. package/index.min.js +1 -1
  26. package/lib/core/codec-worker.js +1 -11
  27. package/lib/core/configuration.js +21 -33
  28. package/lib/core/constants.js +3 -0
  29. package/lib/core/io.js +11 -19
  30. package/lib/core/streams/aes-crypto-stream.js +16 -20
  31. package/lib/core/streams/common-crypto.js +0 -2
  32. package/lib/core/streams/zip-crypto-stream.js +12 -16
  33. package/lib/core/streams/zip-entry-stream.js +2 -32
  34. package/lib/core/streams/zlib-js/zlib-streams.min.js +1 -1
  35. package/lib/core/streams/zlib-wasm/zlib-streams-loader.js +1 -3
  36. package/lib/core/streams/zlib-wasm/zlib-streams.wasm +0 -0
  37. package/lib/core/util/base64.js +68 -0
  38. package/lib/core/util/blob-temp-stream.js +124 -0
  39. package/lib/core/util/decode-text.js +0 -1
  40. package/lib/core/util/default-mime-type.js +0 -3
  41. package/lib/core/util/inflate.js +194 -0
  42. package/lib/core/util/mime-type.js +26 -22
  43. package/lib/core/util/opfs-temp-stream.js +1 -37
  44. package/lib/core/util/sync-access-handle-temp-stream.js +147 -0
  45. package/lib/core/web-worker-inline-native.js +1 -1
  46. package/lib/core/web-worker-inline-template-native.js +5 -5
  47. package/lib/core/web-worker-inline-wasm.js +1 -1
  48. package/lib/core/zip-fs.js +6 -13
  49. package/lib/core/zip-reader.js +48 -127
  50. package/lib/core/zip-writer.js +27 -45
  51. package/lib/core/zlib-streams-inline-template.js +3 -2
  52. package/lib/core/zlib-streams-inline.js +1 -1
  53. package/lib/zip-core-base.js +10 -2
  54. package/package.json +9 -6
  55. package/reserved-property-names.js +50 -0
  56. package/lib/core/util/mini-lz.js +0 -198
package/BENCHMARKS.md CHANGED
@@ -16,7 +16,9 @@ should not trust anyone's benchmark (including this one) without reproducing it.
16
16
  > `CompressionStream` run on the threadpool while you simply issue concurrent `add()`
17
17
  > calls. It also streams arbitrarily large files at a flat, low memory ceiling. For
18
18
  > deflating thousands of tiny buffers in one shot, **fflate** remains the throughput
19
- > and footprint champion.
19
+ > and footprint champion. Against native tooling, zip.js on a modern runtime is a bit
20
+ > faster *and* tighter than 7-Zip's fast mode on single-file streaming; 7-Zip keeps a
21
+ > real edge only on thousands of tiny files.
20
22
 
21
23
  ## Environment
22
24
 
@@ -172,6 +174,80 @@ compression pipeline. **jszip buffers the entire file** and needs ~527 MB, at mo
172
174
  twice the wall-clock time. If you process files that do not fit comfortably in memory,
173
175
  avoid jszip.
174
176
 
177
+ ## Against native tooling — 7-Zip
178
+
179
+ How far is zip.js from a native archiver? [`benchmarks/bench-7z.js`](benchmarks/bench-7z.js)
180
+ compares it against the `7zz` CLI (7-Zip 25.01), disk-to-disk on both sides, under Deno
181
+ 2.9.3 and Bun 1.3.14 (both runtimes agree within noise; Deno numbers shown). 7-Zip
182
+ timings include process spawn (~ms).
183
+
184
+ One comparison is impossible to make perfectly fair: **no 7-Zip preset runs zlib's
185
+ algorithm.** `-mx=5+` is a near-optimal parser (much slower, smaller output) and
186
+ `-mx=1..4` a greedy one (faster, larger output) — they bracket zlib level 6. So the
187
+ table carries two anchors: `-mx=6` as the *ratio* anchor and `-mx=1` as the *speed*
188
+ anchor. On this machine the `-mx` ladder on the 256 MB file reads: `-mx=1/3` → 5.9 s,
189
+ `-mx=5/6` → 34 s, `-mx=7` → 85 s — the 6× jump at `-mx=5` is the switch from greedy
190
+ matching to optimal parsing, and it cannot be hidden by threads (one file = one deflate
191
+ stream = one core).
192
+
193
+ | Workload (compress) | zip.js (workers) | 7-Zip `-mx=6` (mt) | 7-Zip `-mx=1` (mt) |
194
+ |---|--:|--:|--:|
195
+ | Compressible text (20 MB) | **426 ms** / 6.2 MB | 2606 ms / 5.8 MB | 470 ms / 6.8 MB |
196
+ | Incompressible data (20 MB) | **342 ms** | 410 ms | 372 ms |
197
+ | 5,000 files × ~2 KB | 780 ms / 5.5 MB | 199 ms / 4.9 MB | **168 ms** / 5.0 MB |
198
+ | Large file, disk-to-disk (256 MB) | **5.5 s** / 79.5 MB | 33.4 s / 73.6 MB | 5.9 s / 86.7 MB |
199
+
200
+ | Workload (decompress) | zip.js (workers) | 7-Zip (mt) |
201
+ |---|--:|--:|
202
+ | Compressible text (20 MB) | **69 ms** | 88 ms |
203
+ | 5,000 files × ~2 KB | 976 ms | **471 ms** |
204
+
205
+ - **On single-file streaming, zip.js strictly dominates 7-Zip's speed tier**: a bit
206
+ faster *and* ~9 % smaller output, because zlib-6's lazy matching is a better
207
+ speed/ratio point than 7-Zip's greedy fast mode. What `-mx=6` buys for its 6× time is
208
+ ~7 % more compression — a trade zip.js cannot make, but also one most workloads don't
209
+ want.
210
+ - **7-Zip legitimately dominates many small files** (~4× on compress, ~2× on
211
+ decompress): its per-entry cost is near zero, while zip.js pays per-entry
212
+ orchestration (worker round trips, header writes, one output stream per extracted
213
+ file). Same lesson as the fflate rows above — tiny-entry workloads are zip.js's cost
214
+ center, and the codec backend is irrelevant there.
215
+
216
+ ## The runtime's zlib decides zip.js throughput
217
+
218
+ On bulk data zip.js is a thin wrapper around the platform's `CompressionStream` — it
219
+ adds ~7 % over the raw encoder on the 256 MB stream. That means throughput is decided
220
+ by **which zlib the runtime vendors**, and they differ a lot. Same 256 MB compressible
221
+ file, one thread, level-6-class output everywhere:
222
+
223
+ | Encoder | Time | Output |
224
+ |---|--:|--:|
225
+ | zlib-ng — Deno & Bun `CompressionStream` | **4.8–5.1 s** | 79.4 MB |
226
+ | Chromium zlib — Node `CompressionStream` / `node:zlib` | 8.9 s | 78.3 MB |
227
+ | classic zlib — Apple `gzip -6` | 12.5 s | 78.9 MB |
228
+ | classic zlib compiled to WASM — zip.js `useCompressionStream: false` | ~16 s | 78.9 MB |
229
+ | (reference) 7-Zip `-mx=6` | 33.5 s | 73.6 MB |
230
+
231
+ Verified in the runtimes' sources: Deno builds `flate2` with vendored
232
+ **zlib-ng** (`__vendored_zlib_ng` default feature), Bun vendors **zlib-ng 2.3.3**
233
+ (SIMD CRC/adler/match kernels, NEON on arm64) behind `node:zlib` and
234
+ `CompressionStream`, and Node vendors **Chromium's zlib fork** (SIMD checksums and
235
+ hash sliding, but a match finder much closer to classic zlib).
236
+
237
+ Consequences worth knowing:
238
+
239
+ - **The same zip.js code runs ~1.75× faster on Deno/Bun than on Node** for bulk
240
+ compression. A "zip.js is fast/slow" measurement is often really a statement about
241
+ the host's zlib — and the Node tables above are the *pessimistic* end.
242
+ - **The WASM backend is the portability floor, not a peer**: classic zlib plus ~30 %
243
+ WebAssembly overhead ≈ 3× slower than native on compress. Decompression barely
244
+ suffers (inflate is cheap — within ~10 % of native). It still lands mid-curve
245
+ against 7-Zip: 16 s / 78.9 MB sits between `-mx=1` (5.9 s / 86.7 MB) and `-mx=6`
246
+ (33.5 s / 73.6 MB).
247
+ - Output sizes across the zlib family are interchangeable (78–79 MB): it is one
248
+ algorithm at four levels of implementation tuning. zip.js inherits whichever the
249
+ host provides — including future upgrades, for free.
250
+
175
251
  ## When to pick which
176
252
 
177
253
  - **Choose zip.js** for the fastest compression of large or multiple entries
@@ -195,8 +271,13 @@ npm install # jszip, fflate, archiver (zip.js is used from the repo)
195
271
  npm run corpus # generate the deterministic datasets under .corpus/
196
272
  node bench.js # the head-to-head tables (compress / decompress / disk streaming)
197
273
  node bench-backends.js # the parallelism & codec-backend matrix
274
+ deno run -A bench-7z.js # zip.js vs the 7zz CLI (also: bun bench-7z.js)
198
275
  ```
199
276
 
277
+ `bench-7z.js` needs the 7-Zip CLI (`brew install sevenzip`) and runs under Deno or Bun;
278
+ set `ZIPJS_BACKEND=wasm` to measure the WebAssembly codec instead of the native
279
+ `CompressionStream`, and `SKIP_HUGE=1` to skip the 256 MB combo.
280
+
200
281
  Both scripts write JSON and a human-readable log to `benchmarks/results/`. Set
201
282
  `RUNS=<n>` to change the number of repetitions (default 3). The datasets are generated
202
283
  from a seeded PRNG (`benchmarks/lib/corpus.js`), so every run — and every library —
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zip-js/zip-js",
3
- "version": "2.8.30",
3
+ "version": "2.8.32",
4
4
  "exports": {
5
5
  ".": "./index.js"
6
6
  },
@@ -8,9 +8,10 @@
8
8
  "exclude": [
9
9
  "dist/*.js",
10
10
  "*-inline.js",
11
- "tests/vendor/*.js",
12
- "index.cjs",
13
- "index.min.js"
11
+ "tests/",
12
+ "benchmarks/",
13
+ "**/*.cjs",
14
+ "**/*.min.js"
14
15
  ]
15
16
  },
16
17
  "exclude": [