@zip.js/zip.js 2.7.73 → 2.8.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.
Files changed (69) hide show
  1. package/deno.json +2 -3
  2. package/dist/README.md +7 -25
  3. package/dist/zip-core.js +5961 -0
  4. package/dist/zip-core.min.js +1 -0
  5. package/dist/{zip-full.js → zip-fs-core.js} +4160 -7358
  6. package/dist/zip-fs-core.min.js +1 -0
  7. package/dist/zip-fs.js +4355 -2542
  8. package/dist/zip-fs.min.js +1 -1
  9. package/dist/zip-module.wasm +0 -0
  10. package/dist/zip-web-worker.js +1 -0
  11. package/dist/zip.js +2647 -2466
  12. package/dist/zip.min.js +1 -1
  13. package/index.cjs +4624 -8659
  14. package/index.d.ts +27 -176
  15. package/index.js +2 -63
  16. package/index.min.js +1 -1
  17. package/lib/core/codec-pool.js +6 -4
  18. package/lib/core/codec-worker.js +37 -20
  19. package/lib/core/configuration.js +16 -37
  20. package/lib/core/io.js +3 -8
  21. package/lib/core/streams/aes-crypto-stream.js +1 -0
  22. package/lib/core/streams/zip-entry-stream.js +19 -11
  23. package/lib/core/streams/zlib/README.md +1 -0
  24. package/lib/core/streams/{stream-adapter.js → zlib/zlib-streams-loader.js} +54 -25
  25. package/lib/core/streams/zlib/zlib-streams.js +184 -0
  26. package/lib/core/streams/zlib/zlib-streams.wasm +0 -0
  27. package/lib/core/util/decode-text.js +1 -1
  28. package/lib/core/util/encode-text.js +1 -0
  29. package/lib/core/util/mini-lz.js +198 -0
  30. package/lib/{z-worker.js → core/web-worker-inline-template.js} +10 -9
  31. package/lib/core/web-worker-inline.js +1 -0
  32. package/lib/core/{z-worker-core.js → web-worker.js} +17 -36
  33. package/lib/core/zip-entry.js +3 -7
  34. package/lib/core/zip-reader.js +11 -4
  35. package/lib/core/zip-writer.js +11 -13
  36. package/lib/{z-worker-bootstrap-pako.js → core/zlib-streams-inline-template.js} +8 -10
  37. package/lib/core/zlib-streams-inline.js +1 -0
  38. package/{index-fflate.js → lib/zip-core.js} +43 -22
  39. package/lib/{z-worker-fflate.js → zip-fs-core.js} +5 -15
  40. package/lib/zip-fs.js +7 -24
  41. package/lib/zip.js +6 -23
  42. package/package.json +5 -19
  43. package/dist/z-worker-fflate.js +0 -1
  44. package/dist/z-worker-pako.js +0 -1
  45. package/dist/z-worker.js +0 -1
  46. package/dist/zip-fs-full.js +0 -12536
  47. package/dist/zip-fs-full.min.js +0 -1
  48. package/dist/zip-full.min.js +0 -1
  49. package/dist/zip-no-worker-deflate.min.js +0 -1
  50. package/dist/zip-no-worker-inflate.min.js +0 -1
  51. package/dist/zip-no-worker.min.js +0 -1
  52. package/lib/core/streams/codecs/deflate.js +0 -2059
  53. package/lib/core/streams/codecs/inflate.js +0 -2163
  54. package/lib/core/util/stream-codec-shim.js +0 -91
  55. package/lib/z-worker-bootstrap-fflate.js +0 -40
  56. package/lib/z-worker-inline-template.js +0 -42
  57. package/lib/z-worker-inline.js +0 -1
  58. package/lib/zip-data-uri.js +0 -56
  59. package/lib/zip-fflate-shim.js +0 -37
  60. package/lib/zip-full-fflate.js +0 -54
  61. package/lib/zip-full.js +0 -55
  62. package/lib/zip-no-worker-deflate.js +0 -42
  63. package/lib/zip-no-worker-fflate-deflate.js +0 -42
  64. package/lib/zip-no-worker-fflate-inflate.js +0 -42
  65. package/lib/zip-no-worker-fflate.js +0 -43
  66. package/lib/zip-no-worker-inflate.js +0 -42
  67. package/lib/zip-no-worker.js +0 -44
  68. /package/lib/core/util/{cp437-decode.js → decode-cp437.js} +0 -0
  69. /package/lib/core/{zip-fs-core.js → zip-fs.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -38,6 +38,7 @@ import {
38
38
  ERR_ABORT_CHECK_PASSWORD
39
39
  } from "./streams/codec-stream.js";
40
40
  import { CodecWorker } from "./codec-worker.js";
41
+ import { resetWasmModule } from "./streams/zlib/zlib-streams-loader.js";
41
42
 
42
43
  let pool = [];
43
44
  const pendingRequests = [];
@@ -57,12 +58,12 @@ let indexWorker = 0;
57
58
 
58
59
  async function runWorker(stream, workerOptions) {
59
60
  const { options, config } = workerOptions;
60
- const { transferStreams, useWebWorkers, useCompressionStream, codecType, compressed, signed, encrypted } = options;
61
- const { workerScripts, maxWorkers } = config;
61
+ const { transferStreams, useWebWorkers, useCompressionStream, compressed, signed, encrypted } = options;
62
+ const { workerURI, maxWorkers } = config;
62
63
  workerOptions.transferStreams = transferStreams || transferStreams === UNDEFINED_VALUE;
63
64
  const streamCopy = !compressed && !signed && !encrypted && !workerOptions.transferStreams;
64
65
  workerOptions.useWebWorkers = !streamCopy && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
65
- workerOptions.scripts = workerOptions.useWebWorkers && workerScripts ? workerScripts[codecType] : [];
66
+ workerOptions.workerURI = workerOptions.useWebWorkers && workerURI ? workerURI : UNDEFINED_VALUE;
66
67
  options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
67
68
  return (await getWorker()).run();
68
69
 
@@ -128,4 +129,5 @@ async function terminateWorkers() {
128
129
  clearTerminateTimeout(workerData);
129
130
  return workerData.terminate();
130
131
  }));
132
+ resetWasmModule();
131
133
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -42,7 +42,12 @@ import {
42
42
  MESSAGE_ACK_DATA,
43
43
  MESSAGE_CLOSE
44
44
  } from "./streams/codec-stream.js";
45
+ import {
46
+ initModule,
47
+ initializedModule
48
+ } from "./streams/zlib/zlib-streams-loader.js";
45
49
 
50
+ // deno-lint-ignore valid-typeof
46
51
  let WEB_WORKERS_SUPPORTED = typeof Worker != UNDEFINED_TYPE;
47
52
 
48
53
  export {
@@ -51,7 +56,7 @@ export {
51
56
 
52
57
  class CodecWorker {
53
58
 
54
- constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, scripts }, onTaskFinished) {
59
+ constructor(workerData, { readable, writable }, { options, config, streamOptions, useWebWorkers, transferStreams, workerURI }, onTaskFinished) {
55
60
  const { signal } = streamOptions;
56
61
  Object.assign(workerData, {
57
62
  busy: true,
@@ -60,7 +65,7 @@ class CodecWorker {
60
65
  .pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
61
66
  writable,
62
67
  options: Object.assign({}, options),
63
- scripts,
68
+ workerURI,
64
69
  transferStreams,
65
70
  terminate() {
66
71
  return new Promise(resolve => {
@@ -136,11 +141,17 @@ function createWorkerInterface(workerData, config) {
136
141
  }
137
142
 
138
143
  function createWebWorkerInterface(workerData, config) {
139
- const { baseURL, chunkSize } = config;
144
+ const { baseURI, chunkSize } = config;
145
+ let { wasmURI } = config;
146
+
140
147
  if (!workerData.interface) {
148
+ // deno-lint-ignore valid-typeof
149
+ if (typeof wasmURI == FUNCTION_TYPE) {
150
+ wasmURI = wasmURI();
151
+ }
141
152
  let worker;
142
153
  try {
143
- worker = getWebWorker(workerData.scripts[0], baseURL, workerData);
154
+ worker = getWebWorker(workerData.workerURI, baseURI, workerData);
144
155
  // eslint-disable-next-line no-unused-vars
145
156
  } catch (_) {
146
157
  WEB_WORKERS_SUPPORTED = false;
@@ -149,7 +160,7 @@ function createWebWorkerInterface(workerData, config) {
149
160
  Object.assign(workerData, {
150
161
  worker,
151
162
  interface: {
152
- run: () => runWebWorker(workerData, { chunkSize })
163
+ run: () => runWebWorker(workerData, { chunkSize, wasmURI, baseURI })
153
164
  }
154
165
  });
155
166
  }
@@ -159,6 +170,14 @@ function createWebWorkerInterface(workerData, config) {
159
170
  async function runWorker({ options, readable, writable, onTaskFinished }, config) {
160
171
  let codecStream;
161
172
  try {
173
+ if (!options.useCompressionStream && !initializedModule) {
174
+ let { wasmURI } = config;
175
+ // deno-lint-ignore valid-typeof
176
+ if (typeof wasmURI == FUNCTION_TYPE) {
177
+ wasmURI = wasmURI();
178
+ }
179
+ await initModule(wasmURI, config);
180
+ }
162
181
  codecStream = new CodecStream(options, config);
163
182
  await readable.pipeThrough(codecStream).pipeTo(writable, { preventClose: true, preventAbort: true });
164
183
  const {
@@ -194,11 +213,10 @@ async function runWebWorker(workerData, config) {
194
213
  rejectResult,
195
214
  result
196
215
  });
197
- const { readable, options, scripts } = workerData;
216
+ const { readable, options } = workerData;
198
217
  const { writable, closed } = watchClosedStream(workerData.writable);
199
218
  const streamsTransferred = sendMessage({
200
219
  type: MESSAGE_START,
201
- scripts: scripts.slice(1),
202
220
  options,
203
221
  config,
204
222
  readable,
@@ -239,30 +257,29 @@ function watchClosedStream(writableSource) {
239
257
  return { writable, closed };
240
258
  }
241
259
 
242
- let classicWorkersSupported = true;
243
260
  let transferStreamsSupported = true;
244
261
 
245
- function getWebWorker(url, baseURL, workerData) {
262
+ function getWebWorker(url, baseURI, workerData) {
246
263
  const workerOptions = { type: "module" };
247
264
  let scriptUrl, worker;
265
+ // deno-lint-ignore valid-typeof
248
266
  if (typeof url == FUNCTION_TYPE) {
249
267
  url = url();
250
268
  }
251
- try {
252
- scriptUrl = new URL(url, baseURL);
253
- // eslint-disable-next-line no-unused-vars
254
- } catch (_) {
255
- scriptUrl = url;
256
- }
257
- if (classicWorkersSupported) {
269
+ if (url.startsWith("data:") || url.startsWith("blob:")) {
258
270
  try {
259
- worker = new Worker(scriptUrl);
271
+ worker = new Worker(url);
260
272
  // eslint-disable-next-line no-unused-vars
261
273
  } catch (_) {
262
- classicWorkersSupported = false;
263
- worker = new Worker(scriptUrl, workerOptions);
274
+ worker = new Worker(url, workerOptions);
264
275
  }
265
276
  } else {
277
+ try {
278
+ scriptUrl = new URL(url, baseURI);
279
+ // eslint-disable-next-line no-unused-vars
280
+ } catch (_) {
281
+ scriptUrl = url;
282
+ }
266
283
  worker = new Worker(scriptUrl, workerOptions);
267
284
  }
268
285
  worker.addEventListener(MESSAGE_EVENT_TYPE, event => onMessage(event, workerData));
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -32,7 +32,6 @@ import {
32
32
  UNDEFINED_VALUE,
33
33
  UNDEFINED_TYPE
34
34
  } from "./constants.js";
35
- import { StreamAdapter } from "./streams/stream-adapter.js";
36
35
 
37
36
  const MINIMUM_CHUNK_SIZE = 64;
38
37
  let maxWorkers = 2;
@@ -45,14 +44,15 @@ try {
45
44
  // ignored
46
45
  }
47
46
  const DEFAULT_CONFIGURATION = {
48
- chunkSize: 512 * 1024,
47
+ workerURI: "./core/web-worker.js",
48
+ wasmURI: "./core/streams/zlib/zlib-streams.wasm",
49
+ chunkSize: 64 * 1024,
49
50
  maxWorkers,
50
51
  terminateWorkerTimeout: 5000,
51
52
  useWebWorkers: true,
52
53
  useCompressionStream: true,
53
- workerScripts: UNDEFINED_VALUE,
54
- CompressionStreamNative: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
55
- DecompressionStreamNative: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
54
+ CompressionStream: typeof CompressionStream != UNDEFINED_TYPE && CompressionStream,
55
+ DecompressionStream: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
56
56
  };
57
57
 
58
58
  const config = Object.assign({}, DEFAULT_CONFIGURATION);
@@ -73,52 +73,31 @@ function getChunkSize(config) {
73
73
 
74
74
  function configure(configuration) {
75
75
  const {
76
- baseURL,
76
+ baseURI,
77
77
  chunkSize,
78
78
  maxWorkers,
79
79
  terminateWorkerTimeout,
80
80
  useCompressionStream,
81
81
  useWebWorkers,
82
- Deflate,
83
- Inflate,
84
82
  CompressionStream,
85
83
  DecompressionStream,
86
- workerScripts
84
+ CompressionStreamZlib,
85
+ DecompressionStreamZlib,
86
+ workerURI,
87
+ wasmURI
87
88
  } = configuration;
88
- setIfDefined("baseURL", baseURL);
89
+ setIfDefined("baseURI", baseURI);
90
+ setIfDefined("wasmURI", wasmURI);
91
+ setIfDefined("workerURI", workerURI);
89
92
  setIfDefined("chunkSize", chunkSize);
90
93
  setIfDefined("maxWorkers", maxWorkers);
91
94
  setIfDefined("terminateWorkerTimeout", terminateWorkerTimeout);
92
95
  setIfDefined("useCompressionStream", useCompressionStream);
93
96
  setIfDefined("useWebWorkers", useWebWorkers);
94
- if (Deflate) {
95
- config.CompressionStream = new StreamAdapter(Deflate);
96
- }
97
- if (Inflate) {
98
- config.DecompressionStream = new StreamAdapter(Inflate);
99
- }
100
97
  setIfDefined("CompressionStream", CompressionStream);
101
98
  setIfDefined("DecompressionStream", DecompressionStream);
102
- if (workerScripts !== UNDEFINED_VALUE) {
103
- const { deflate, inflate } = workerScripts;
104
- if (deflate || inflate) {
105
- if (!config.workerScripts) {
106
- config.workerScripts = {};
107
- }
108
- }
109
- if (deflate) {
110
- if (!Array.isArray(deflate)) {
111
- throw new Error("workerScripts.deflate must be an array");
112
- }
113
- config.workerScripts.deflate = deflate;
114
- }
115
- if (inflate) {
116
- if (!Array.isArray(inflate)) {
117
- throw new Error("workerScripts.inflate must be an array");
118
- }
119
- config.workerScripts.inflate = inflate;
120
- }
121
- }
99
+ setIfDefined("CompressionStreamZlib", CompressionStreamZlib);
100
+ setIfDefined("DecompressionStreamZlib", DecompressionStreamZlib);
122
101
  }
123
102
 
124
103
  function setIfDefined(propertyName, propertyValue) {
package/lib/core/io.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -738,8 +738,8 @@ class GenericWriter {
738
738
  }
739
739
 
740
740
  function isHttpFamily(url) {
741
- const { baseURL } = getConfiguration();
742
- const { protocol } = new URL(url, baseURL);
741
+ const { baseURI } = getConfiguration();
742
+ const { protocol } = new URL(url, baseURI);
743
743
  return protocol == "http:" || protocol == "https:";
744
744
  }
745
745
 
@@ -755,9 +755,6 @@ function readUint8Array(reader, offset, size, diskNumber) {
755
755
  return reader.readUint8Array(offset, size, diskNumber);
756
756
  }
757
757
 
758
- const SplitZipReader = SplitDataReader;
759
- const SplitZipWriter = SplitDataWriter;
760
-
761
758
  export {
762
759
  initStream,
763
760
  GenericReader,
@@ -775,8 +772,6 @@ export {
775
772
  Uint8ArrayWriter,
776
773
  HttpReader,
777
774
  HttpRangeReader,
778
- SplitZipReader,
779
- SplitZipWriter,
780
775
  SplitDataReader,
781
776
  SplitDataWriter,
782
777
  ERR_HTTP_RANGE,
@@ -56,6 +56,7 @@ const SALT_LENGTH = [8, 12, 16];
56
56
  const KEY_LENGTH = [16, 24, 32];
57
57
  const SIGNATURE_LENGTH = 10;
58
58
  const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
59
+ // deno-lint-ignore valid-typeof
59
60
  const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
60
61
  const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
61
62
  const SUBTLE_API_SUPPORTED = CRYPTO_API_SUPPORTED && typeof subtle != UNDEFINED_TYPE;
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -45,11 +45,12 @@ import {
45
45
  } from "./common-crypto.js";
46
46
 
47
47
  const ERR_INVALID_UNCOMPRESSED_SIZE = "Invalid uncompressed size";
48
- const COMPRESSION_FORMAT = "deflate-raw";
48
+ const FORMAT_DEFLATE_RAW = "deflate-raw";
49
+ const FORMAT_DEFLATE64_RAW = "deflate64-raw";
49
50
 
50
51
  class DeflateStream extends TransformStream {
51
52
 
52
- constructor(options, { chunkSize, CompressionStream, CompressionStreamNative }) {
53
+ constructor(options, { chunkSize, CompressionStreamZlib, CompressionStream }) {
53
54
  super({});
54
55
  const { compressed, encrypted, useCompressionStream, zipCrypto, signed, level } = options;
55
56
  const stream = this;
@@ -60,7 +61,7 @@ class DeflateStream extends TransformStream {
60
61
  readable = pipeThrough(readable, crc32Stream);
61
62
  }
62
63
  if (compressed) {
63
- readable = pipeThroughCommpressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStreamNative, CompressionStream);
64
+ readable = pipeThroughCommpressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamZlib, CompressionStream);
64
65
  }
65
66
  if (encrypted) {
66
67
  if (zipCrypto) {
@@ -85,9 +86,9 @@ class DeflateStream extends TransformStream {
85
86
 
86
87
  class InflateStream extends TransformStream {
87
88
 
88
- constructor(options, { chunkSize, DecompressionStream, DecompressionStreamNative }) {
89
+ constructor(options, { chunkSize, DecompressionStreamZlib, DecompressionStream }) {
89
90
  super({});
90
- const { zipCrypto, encrypted, signed, signature, compressed, useCompressionStream } = options;
91
+ const { zipCrypto, encrypted, signed, signature, compressed, useCompressionStream, deflate64 } = options;
91
92
  let crc32Stream, decryptionStream;
92
93
  let readable = super.readable;
93
94
  if (encrypted) {
@@ -99,7 +100,7 @@ class InflateStream extends TransformStream {
99
100
  }
100
101
  }
101
102
  if (compressed) {
102
- readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize }, DecompressionStreamNative, DecompressionStream);
103
+ readable = pipeThroughCommpressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamZlib, DecompressionStream);
103
104
  }
104
105
  if ((!encrypted || zipCrypto) && signed) {
105
106
  crc32Stream = new Crc32Stream();
@@ -134,13 +135,20 @@ function setReadable(stream, readable, flush) {
134
135
  });
135
136
  }
136
137
 
137
- function pipeThroughCommpressionStream(readable, useCompressionStream, options, CodecStreamNative, CodecStream) {
138
+ function pipeThroughCommpressionStream(readable, useCompressionStream, options, CompressionStreamNative, CompressionStreamZlib, CompressionStream) {
139
+ const Stream = useCompressionStream && CompressionStreamNative ? CompressionStreamNative : CompressionStreamZlib || CompressionStream;
140
+ const format = options.deflate64 ? FORMAT_DEFLATE64_RAW : FORMAT_DEFLATE_RAW;
138
141
  try {
139
- const CompressionStream = useCompressionStream && CodecStreamNative ? CodecStreamNative : CodecStream;
140
- readable = pipeThrough(readable, new CompressionStream(COMPRESSION_FORMAT, options));
142
+ readable = pipeThrough(readable, new Stream(format, options));
141
143
  } catch (error) {
142
144
  if (useCompressionStream) {
143
- readable = pipeThrough(readable, new CodecStream(COMPRESSION_FORMAT, options));
145
+ if (CompressionStreamZlib) {
146
+ readable = pipeThrough(readable, new CompressionStreamZlib(format, options));
147
+ } else if (CompressionStream) {
148
+ readable = pipeThrough(readable, new CompressionStream(format, options));
149
+ } else {
150
+ throw error;
151
+ }
144
152
  } else {
145
153
  throw error;
146
154
  }
@@ -0,0 +1 @@
1
+ See https://github.com/gildas-lormeau/zlib-streams/tree/main/dist
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2022 Gildas Lormeau. All rights reserved.
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
5
  modification, are permitted provided that the following conditions are met:
@@ -26,30 +26,59 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global TransformStream */
29
+ /* global WebAssembly, URL, fetch, atob */
30
30
 
31
- export {
32
- StreamAdapter
33
- };
34
-
35
- class StreamAdapter {
36
-
37
- constructor(Codec) {
38
- return class extends TransformStream {
39
- constructor(_format, options) {
40
- const codec = new Codec(options);
41
- super({
42
- transform(chunk, controller) {
43
- controller.enqueue(codec.append(chunk));
44
- },
45
- flush(controller) {
46
- const chunk = codec.flush();
47
- if (chunk) {
48
- controller.enqueue(chunk);
49
- }
50
- }
51
- });
31
+ import { setWasmExports } from "./zlib-streams.js";
32
+
33
+ let initializedModule = false;
34
+
35
+ async function initModule(wasmURI, { baseURI }) {
36
+ if (!initializedModule) {
37
+ let arrayBuffer, uri;
38
+ try {
39
+ try {
40
+ uri = new URL(wasmURI, baseURI);
41
+ // eslint-disable-next-line no-unused-vars
42
+ } catch (_) {
43
+ // ignored
52
44
  }
53
- };
45
+ const response = await fetch(uri);
46
+ arrayBuffer = await response.arrayBuffer();
47
+ } catch (error) {
48
+ if (wasmURI.startsWith("data:application/wasm;base64,")) {
49
+ arrayBuffer = arrayBufferFromDataURI(wasmURI);
50
+ } else {
51
+ throw error;
52
+ }
53
+ }
54
+ const wasmInstance = await WebAssembly.instantiate(arrayBuffer);
55
+ setWasmExports(wasmInstance.instance.exports);
56
+ initializedModule = true;
57
+ }
58
+ }
59
+
60
+ function resetWasmModule() {
61
+ initializedModule = false;
62
+ }
63
+
64
+ function arrayBufferFromDataURI(dataURI) {
65
+ const base64 = dataURI.split(",")[1];
66
+ const binary = atob(base64);
67
+ const len = binary.length;
68
+ const bytes = new Uint8Array(len);
69
+ for (let i = 0; i < len; ++i) {
70
+ bytes[i] = binary.charCodeAt(i);
54
71
  }
55
- }
72
+ return bytes.buffer;
73
+ }
74
+
75
+ export {
76
+ setWasmExports,
77
+ CompressionStreamZlib,
78
+ DecompressionStreamZlib
79
+ } from "./zlib-streams.js";
80
+ export {
81
+ initModule,
82
+ resetWasmModule,
83
+ initializedModule
84
+ };
@@ -0,0 +1,184 @@
1
+ /*
2
+ Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
+
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
+ let wasm, malloc, free, memory;
32
+
33
+ export function setWasmExports(wasmAPI) {
34
+ wasm = wasmAPI;
35
+ ({ malloc, free, memory } = wasm);
36
+ }
37
+
38
+ function _make(isCompress, type, options = {}) {
39
+ const level = (typeof options.level === "number") ? options.level : -1;
40
+ const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
41
+ const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
42
+
43
+ return new TransformStream({
44
+ start() {
45
+ let result;
46
+ this.out = malloc(outBufferSize);
47
+ this.in = malloc(inBufferSize);
48
+ this.inBufferSize = inBufferSize;
49
+ this._scratch = new Uint8Array(outBufferSize);
50
+ if (isCompress) {
51
+ this._process = wasm.deflate_process;
52
+ this._last_consumed = wasm.deflate_last_consumed;
53
+ this._end = wasm.deflate_end;
54
+ this.streamHandle = wasm.deflate_new();
55
+ if (type === "gzip") {
56
+ result = wasm.deflate_init_gzip(this.streamHandle, level);
57
+ } else if (type === "deflate-raw") {
58
+ result = wasm.deflate_init_raw(this.streamHandle, level);
59
+ } else {
60
+ result = wasm.deflate_init(this.streamHandle, level);
61
+ }
62
+ } else {
63
+ if (type === "deflate64-raw") {
64
+ this._process = wasm.inflate9_process;
65
+ this._last_consumed = wasm.inflate9_last_consumed;
66
+ this._end = wasm.inflate9_end;
67
+ this.streamHandle = wasm.inflate9_new();
68
+ result = wasm.inflate9_init_raw(this.streamHandle);
69
+ } else {
70
+ this._process = wasm.inflate_process;
71
+ this._last_consumed = wasm.inflate_last_consumed;
72
+ this._end = wasm.inflate_end;
73
+ this.streamHandle = wasm.inflate_new();
74
+ if (type === "deflate-raw") {
75
+ result = wasm.inflate_init_raw(this.streamHandle);
76
+ } else if (type === "gzip") {
77
+ result = wasm.inflate_init_gzip(this.streamHandle);
78
+ } else {
79
+ result = wasm.inflate_init(this.streamHandle);
80
+ }
81
+ }
82
+ }
83
+ if (result !== 0) {
84
+ throw new Error("init failed:" + result);
85
+ }
86
+ },
87
+ transform(chunk, controller) {
88
+ try {
89
+ const buffer = chunk;
90
+ const heap = new Uint8Array(memory.buffer);
91
+ const process = this._process;
92
+ const last_consumed = this._last_consumed;
93
+ const out = this.out;
94
+ const scratch = this._scratch;
95
+ let offset = 0;
96
+ while (offset < buffer.length) {
97
+ const toRead = Math.min(buffer.length - offset, 32 * 1024);
98
+ if (!this.in || this.inBufferSize < toRead) {
99
+ if (this.in && free) {
100
+ free(this.in);
101
+ }
102
+ this.in = malloc(toRead);
103
+ this.inBufferSize = toRead;
104
+ }
105
+ heap.set(buffer.subarray(offset, offset + toRead), this.in);
106
+ const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
107
+ if (!isCompress && result < 0) {
108
+ throw new Error("process error:" + result);
109
+ }
110
+ const prod = result & 0x00ffffff;
111
+ if (prod) {
112
+ scratch.set(heap.subarray(out, out + prod), 0);
113
+ controller.enqueue(scratch.slice(0, prod));
114
+ }
115
+ const consumed = last_consumed(this.streamHandle);
116
+ if (consumed === 0) {
117
+ break;
118
+ }
119
+ offset += consumed;
120
+ }
121
+ } catch (error) {
122
+ if (this._end && this.streamHandle) {
123
+ this._end(this.streamHandle);
124
+ }
125
+ if (this.in && free) {
126
+ free(this.in);
127
+ }
128
+ if (this.out && free) {
129
+ free(this.out);
130
+ }
131
+ controller.error(error);
132
+ }
133
+ },
134
+ flush(controller) {
135
+ try {
136
+ const heap = new Uint8Array(memory.buffer);
137
+ const process = this._process;
138
+ const out = this.out;
139
+ const scratch = this._scratch;
140
+ while (true) {
141
+ const result = process(this.streamHandle, 0, 0, out, outBufferSize, 4);
142
+ if (!isCompress && result < 0) {
143
+ throw new Error("process error:" + result);
144
+ }
145
+ const produced = result & 0x00ffffff;
146
+ const code = (result >> 24) & 0xff;
147
+ if (produced) {
148
+ scratch.set(heap.subarray(out, out + produced), 0);
149
+ controller.enqueue(scratch.slice(0, produced));
150
+ }
151
+ if (code === 1 || produced === 0) {
152
+ break;
153
+ }
154
+ }
155
+ } catch (error) {
156
+ controller.error(error);
157
+ } finally {
158
+ if (this._end && this.streamHandle) {
159
+ const result = this._end(this.streamHandle);
160
+ if (result !== 0) {
161
+ controller.error(new Error("end error:" + result));
162
+ }
163
+ }
164
+ if (this.in && free) {
165
+ free(this.in);
166
+ }
167
+ if (this.out && free) {
168
+ free(this.out);
169
+ }
170
+ }
171
+ }
172
+ });
173
+ }
174
+
175
+ export class CompressionStreamZlib {
176
+ constructor(type = "deflate", options) {
177
+ return _make(true, type, options);
178
+ }
179
+ }
180
+ export class DecompressionStreamZlib {
181
+ constructor(type = "deflate", options) {
182
+ return _make(false, type, options);
183
+ }
184
+ }
@@ -28,7 +28,7 @@
28
28
 
29
29
  /* global TextDecoder */
30
30
 
31
- import { decodeCP437 } from "./cp437-decode.js";
31
+ import { decodeCP437 } from "./decode-cp437.js";
32
32
 
33
33
  export {
34
34
  decodeText
@@ -35,6 +35,7 @@ export {
35
35
  };
36
36
 
37
37
  function encodeText(value) {
38
+ // deno-lint-ignore valid-typeof
38
39
  if (typeof TextEncoder == UNDEFINED_TYPE) {
39
40
  value = unescape(encodeURIComponent(value));
40
41
  const result = new Uint8Array(value.length);