@zip.js/zip.js 2.16.0 → 2.16.1

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 (42) hide show
  1. package/deno.json +1 -1
  2. package/dist/zip-core-external.js +284 -179
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +108 -61
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +426 -189
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +251 -70
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +426 -189
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +253 -72
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +428 -189
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +110 -63
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +110 -63
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +285 -180
  23. package/dist/zip.min.js +1 -1
  24. package/eslint.config.mjs +1 -1
  25. package/index-native.cjs +253 -72
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +428 -189
  28. package/index.d.cts +117 -16
  29. package/index.d.ts +117 -16
  30. package/index.min.js +1 -1
  31. package/lib/core/streams/aes-crypto-stream.js +60 -17
  32. package/lib/core/streams/zip-crypto-stream.js +7 -7
  33. package/lib/core/streams/zip-entry-stream.js +22 -26
  34. package/lib/core/streams/zlib-wasm/zlib-streams.js +176 -118
  35. package/lib/core/util/compatible-streams.js +10 -5
  36. package/lib/core/version.js +1 -1
  37. package/lib/core/web-worker-inline-native.js +1 -1
  38. package/lib/core/web-worker-inline-wasm.js +1 -1
  39. package/lib/core/zip-fs.js +144 -10
  40. package/lib/core/zip-reader.js +5 -5
  41. package/lib/core/zip-writer.js +4 -2
  42. package/package.json +3 -2
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zip-js/zip-js",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "exports": {
5
5
  ".": "./index.js",
6
6
  "./external": "./lib/zip-fs-external.js",
@@ -1310,12 +1310,12 @@ let createEngine$1 = createEngine$2;
1310
1310
  class AESDecryptionStream extends TransformStream {
1311
1311
 
1312
1312
  constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
1313
+ const aesCrypto = {};
1313
1314
  super({
1314
1315
  start() {
1315
- initAesCrypto(this, password, rawPassword, encryptionStrength);
1316
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
1316
1317
  },
1317
1318
  async transform(chunk, controller) {
1318
- const aesCrypto = this;
1319
1319
  const {
1320
1320
  password,
1321
1321
  strength,
@@ -1334,6 +1334,9 @@ class AESDecryptionStream extends TransformStream {
1334
1334
  } else {
1335
1335
  await ready;
1336
1336
  }
1337
+ if (aesCrypto.discarded) {
1338
+ return;
1339
+ }
1337
1340
  const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
1338
1341
  controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
1339
1342
  },
@@ -1342,9 +1345,12 @@ class AESDecryptionStream extends TransformStream {
1342
1345
  engine,
1343
1346
  pendingInput,
1344
1347
  ready
1345
- } = this;
1348
+ } = aesCrypto;
1346
1349
  if (engine) {
1347
1350
  await ready;
1351
+ if (aesCrypto.discarded) {
1352
+ return;
1353
+ }
1348
1354
  const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
1349
1355
  const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
1350
1356
  engine.process(decryptedChunkArray, true);
@@ -1354,27 +1360,26 @@ class AESDecryptionStream extends TransformStream {
1354
1360
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
1355
1361
  }
1356
1362
  if (invalidAuthenticationCode && checkAuthenticationCode) {
1357
- throw new Error(ERR_INVALID_AUTHENTICATION_CODE);
1363
+ controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
1364
+ return;
1358
1365
  }
1359
1366
  controller.enqueue(decryptedChunkArray);
1360
1367
  }
1361
- },
1362
- cancel() {
1363
- disposeEngine(this);
1364
1368
  }
1365
1369
  });
1370
+ setDisposingReadable(this, aesCrypto);
1366
1371
  }
1367
1372
  }
1368
1373
 
1369
1374
  class AESEncryptionStream extends TransformStream {
1370
1375
 
1371
1376
  constructor({ password, rawPassword, encryptionStrength }) {
1377
+ const aesCrypto = {};
1372
1378
  super({
1373
1379
  start() {
1374
- initAesCrypto(this, password, rawPassword, encryptionStrength);
1380
+ initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
1375
1381
  },
1376
1382
  async transform(chunk, controller) {
1377
- const aesCrypto = this;
1378
1383
  const {
1379
1384
  password,
1380
1385
  strength,
@@ -1388,6 +1393,9 @@ class AESEncryptionStream extends TransformStream {
1388
1393
  } else {
1389
1394
  await ready;
1390
1395
  }
1396
+ if (aesCrypto.discarded) {
1397
+ return;
1398
+ }
1391
1399
  const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
1392
1400
  output.set(preamble, 0);
1393
1401
  controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
@@ -1397,19 +1405,20 @@ class AESEncryptionStream extends TransformStream {
1397
1405
  engine,
1398
1406
  pendingInput,
1399
1407
  ready
1400
- } = this;
1408
+ } = aesCrypto;
1401
1409
  if (engine) {
1402
1410
  await ready;
1411
+ if (aesCrypto.discarded) {
1412
+ return;
1413
+ }
1403
1414
  const encryptedChunkArray = new Uint8Array(pendingInput);
1404
1415
  engine.process(encryptedChunkArray, false);
1405
1416
  const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
1406
1417
  controller.enqueue(concat(encryptedChunkArray, authenticationCode));
1407
1418
  }
1408
- },
1409
- cancel() {
1410
- disposeEngine(this);
1411
1419
  }
1412
1420
  });
1421
+ setDisposingReadable(this, aesCrypto);
1413
1422
  }
1414
1423
  }
1415
1424
 
@@ -1422,7 +1431,37 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
1422
1431
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
1423
1432
  password: encodePassword(password, rawPassword),
1424
1433
  strength: encryptionStrength - 1,
1425
- pendingInput: EMPTY_UINT8_ARRAY
1434
+ pendingInput: EMPTY_UINT8_ARRAY,
1435
+ discarded: false
1436
+ });
1437
+ }
1438
+
1439
+ function setDisposingReadable(stream, aesCrypto) {
1440
+ const reader = stream.readable.getReader();
1441
+ const readable = new ReadableStream({
1442
+ async pull(controller) {
1443
+ try {
1444
+ const { value, done } = await reader.read();
1445
+ if (done) {
1446
+ controller.close();
1447
+ } else {
1448
+ controller.enqueue(value);
1449
+ }
1450
+ } catch (error) {
1451
+ disposeEngine(aesCrypto);
1452
+ reader.cancel(error).catch(() => { });
1453
+ throw error;
1454
+ }
1455
+ },
1456
+ cancel(reason) {
1457
+ disposeEngine(aesCrypto);
1458
+ return reader.cancel(reason);
1459
+ }
1460
+ });
1461
+ Object.defineProperty(stream, "readable", {
1462
+ get() {
1463
+ return readable;
1464
+ }
1426
1465
  });
1427
1466
  }
1428
1467
 
@@ -1455,7 +1494,9 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
1455
1494
  }
1456
1495
  }
1457
1496
 
1458
- function disposeEngine({ engine }) {
1497
+ function disposeEngine(aesCrypto) {
1498
+ const { engine } = aesCrypto;
1499
+ aesCrypto.discarded = true;
1459
1500
  if (engine && engine.dispose) {
1460
1501
  engine.dispose();
1461
1502
  }
@@ -1472,6 +1513,9 @@ async function createKeys$1(aesCrypto, strength, password, salt) {
1472
1513
  const keyLength = KEY_LENGTH[strength];
1473
1514
  const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
1474
1515
  aesCrypto.engine = createEngine$1(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
1516
+ if (aesCrypto.discarded) {
1517
+ disposeEngine(aesCrypto);
1518
+ }
1475
1519
  return subarray(compositeKey, keyLength * 2);
1476
1520
  }
1477
1521
 
@@ -1623,11 +1667,11 @@ function encrypt(target, input) {
1623
1667
  }
1624
1668
 
1625
1669
  function createKeys(target, password, rawPassword) {
1626
- const keys = [0x12345678, 0x23456789, 0x34567890];
1670
+ const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
1627
1671
  Object.assign(target, {
1628
- keys,
1629
- crcKey0: new Crc32(keys[0]),
1630
- crcKey2: new Crc32(keys[2])
1672
+ cryptoKeys,
1673
+ crcKey0: new Crc32(cryptoKeys[0]),
1674
+ crcKey2: new Crc32(cryptoKeys[2])
1631
1675
  });
1632
1676
  if (rawPassword) {
1633
1677
  for (let index = 0; index < rawPassword.length; index++) {
@@ -1641,17 +1685,17 @@ function createKeys(target, password, rawPassword) {
1641
1685
  }
1642
1686
 
1643
1687
  function updateKeys(target, byte) {
1644
- let [, key1] = target.keys;
1688
+ let [, key1] = target.cryptoKeys;
1645
1689
  target.crcKey0.append([byte]);
1646
1690
  const key0 = ~target.crcKey0.get();
1647
1691
  key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
1648
1692
  target.crcKey2.append([key1 >>> 24]);
1649
1693
  const key2 = ~target.crcKey2.get();
1650
- target.keys = [key0, key1, key2];
1694
+ target.cryptoKeys = [key0, key1, key2];
1651
1695
  }
1652
1696
 
1653
1697
  function getByte(target) {
1654
- const temp = target.keys[2] | 2;
1698
+ const temp = target.cryptoKeys[2] | 2;
1655
1699
  return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
1656
1700
  }
1657
1701
 
@@ -1699,11 +1743,16 @@ function toCompatibleReadable(readable) {
1699
1743
  const reader = readable.getReader();
1700
1744
  return new ReadableStream({
1701
1745
  async pull(controller) {
1702
- const { value, done } = await reader.read();
1703
- if (done) {
1704
- controller.close();
1705
- } else {
1706
- controller.enqueue(value);
1746
+ try {
1747
+ const { value, done } = await reader.read();
1748
+ if (done) {
1749
+ controller.close();
1750
+ } else {
1751
+ controller.enqueue(value);
1752
+ }
1753
+ } catch (error) {
1754
+ reader.cancel(error).catch(() => { });
1755
+ throw error;
1707
1756
  }
1708
1757
  },
1709
1758
  cancel(reason) {
@@ -2006,28 +2055,25 @@ function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, cr
2006
2055
  pump();
2007
2056
  return new ReadableStream({
2008
2057
  async pull(controller) {
2009
- let result;
2010
2058
  try {
2011
- result = await read();
2059
+ const { value, done } = await read();
2060
+ if (done) {
2061
+ controller.close();
2062
+ } else {
2063
+ outputLength += value.length;
2064
+ if (outputLength > outputSize) {
2065
+ throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
2066
+ }
2067
+ if (outputCrc32) {
2068
+ outputCrc32.append(value);
2069
+ }
2070
+ controller.enqueue(value);
2071
+ }
2012
2072
  } catch (error) {
2073
+ rejectTrailerReady(error);
2074
+ await cancel(reader, error);
2013
2075
  throw trailerWritten ? getTrailerError(error) : error;
2014
2076
  }
2015
- const { value, done } = result;
2016
- if (done) {
2017
- controller.close();
2018
- } else {
2019
- outputLength += value.length;
2020
- if (outputLength > outputSize) {
2021
- const error = new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
2022
- rejectTrailerReady(error);
2023
- await cancel(reader, error);
2024
- throw error;
2025
- }
2026
- if (outputCrc32) {
2027
- outputCrc32.append(value);
2028
- }
2029
- controller.enqueue(value);
2030
- }
2031
2077
  },
2032
2078
  cancel(reason) {
2033
2079
  rejectTrailerReady(reason);
@@ -2306,10 +2352,15 @@ function mapInflateStreamError(readable) {
2306
2352
  const reader = readable.getReader();
2307
2353
  return new ReadableStream({
2308
2354
  async pull(controller) {
2309
- let result;
2310
2355
  try {
2311
- result = await reader.read();
2356
+ const { value, done } = await reader.read();
2357
+ if (done) {
2358
+ controller.close();
2359
+ } else {
2360
+ controller.enqueue(value);
2361
+ }
2312
2362
  } catch (error) {
2363
+ await cancel(reader, error);
2313
2364
  if (error && error.message) {
2314
2365
  throw error;
2315
2366
  }
@@ -2317,12 +2368,6 @@ function mapInflateStreamError(readable) {
2317
2368
  mappedError.cause = error;
2318
2369
  throw mappedError;
2319
2370
  }
2320
- const { value, done } = result;
2321
- if (done) {
2322
- controller.close();
2323
- } else {
2324
- controller.enqueue(value);
2325
- }
2326
2371
  },
2327
2372
  cancel(reason) {
2328
2373
  return reader.cancel(reason);
@@ -5381,8 +5426,8 @@ class ZipEntry {
5381
5426
  const passThroughCompression = Boolean(passThrough);
5382
5427
  const passThroughEncryption = passThrough === true;
5383
5428
  checkPasswordOption(password, rawPassword);
5384
- password = password && password.length && password;
5385
- rawPassword = rawPassword && rawPassword.length && rawPassword;
5429
+ password = password && password.length ? password : UNDEFINED_VALUE;
5430
+ rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
5386
5431
  if (extraFieldAES) {
5387
5432
  if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
5388
5433
  throw new Error(ERR_UNSUPPORTED_COMPRESSION);
@@ -6143,7 +6188,7 @@ function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
6143
6188
  async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
6144
6189
  const { size } = reader;
6145
6190
  const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
6146
- const remoteProbeBudget = { count: MAX_END_OF_CENTRAL_DIR_PROBES };
6191
+ const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
6147
6192
  let endOfDirectoryInfo;
6148
6193
  let plausibleEndOfDirectoryInfo;
6149
6194
  let endOfDirectoryReachingEndCount = 0;
@@ -6236,8 +6281,8 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
6236
6281
  if (signatureOffset >= anchoredOffset) {
6237
6282
  return getUint32$1(view, signatureOffset - anchoredOffset);
6238
6283
  }
6239
- if (remoteProbeBudget.count > 0) {
6240
- remoteProbeBudget.count--;
6284
+ if (remoteProbeBudget.remaining > 0) {
6285
+ remoteProbeBudget.remaining--;
6241
6286
  const signatureArray = await readUint8Array(reader, signatureOffset, 4);
6242
6287
  return getUint32$1(getDataView(signatureArray), 0);
6243
6288
  }
@@ -7153,9 +7198,11 @@ function resolveMetadata(zipWriter, name, options) {
7153
7198
  const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
7154
7199
  const passThroughCompression = Boolean(passThrough);
7155
7200
  const passThroughEncryption = passThrough === true;
7156
- const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
7157
- const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
7201
+ let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
7202
+ let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
7158
7203
  checkPasswordOption(password, rawPassword);
7204
+ password = password && password.length ? password : UNDEFINED_VALUE;
7205
+ rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
7159
7206
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
7160
7207
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
7161
7208
  const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
@@ -8853,7 +8900,7 @@ function formatSupported(StreamClass, format) {
8853
8900
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8854
8901
  */
8855
8902
 
8856
- const VERSION = "2.16.0";
8903
+ const VERSION = "2.16.1";
8857
8904
 
8858
8905
  /*
8859
8906
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
@@ -9330,7 +9377,7 @@ try {
9330
9377
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9331
9378
  */
9332
9379
 
9333
- /* global TransformStream */
9380
+ /* global ReadableStream, WritableStream */
9334
9381
 
9335
9382
  const FORMAT_DEFLATE = "deflate";
9336
9383
  const FORMAT_DEFLATE_RAW = "deflate-raw";
@@ -9365,137 +9412,195 @@ function _make(isCompress, type, options = {}) {
9365
9412
  const level = (typeof options.level === "number") ? options.level : -1;
9366
9413
  const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
9367
9414
  const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
9368
-
9369
- return new TransformStream({
9370
- start() {
9415
+ const state = { out: 0, in: 0, inBufferSize: 0, streamHandle: 0 };
9416
+ let readableController, writableController, resolveWrite, cancelReason;
9417
+ let backpressure = true;
9418
+ let cancelled = false;
9419
+ initStream();
9420
+ const readable = new ReadableStream({
9421
+ start(controller) {
9422
+ readableController = controller;
9423
+ },
9424
+ pull() {
9425
+ backpressure = false;
9426
+ resumeWrite();
9427
+ },
9428
+ cancel(reason) {
9429
+ cancelled = true;
9430
+ cancelReason = reason;
9431
+ disposeStream(state);
9432
+ writableController.error(reason);
9433
+ resumeWrite();
9434
+ }
9435
+ }, { highWaterMark: 0 });
9436
+ const writable = new WritableStream({
9437
+ start(controller) {
9438
+ writableController = controller;
9439
+ },
9440
+ async write(chunk) {
9441
+ if (backpressure) {
9442
+ await new Promise(resolve => resolveWrite = resolve);
9443
+ }
9444
+ if (cancelled) {
9445
+ throw cancelReason;
9446
+ }
9371
9447
  try {
9372
- let result;
9373
- this.out = malloc(outBufferSize);
9374
- this.in = malloc(inBufferSize);
9375
- this.inBufferSize = inBufferSize;
9376
- if (!this.out || !this.in) {
9377
- throw new Error("allocation failed");
9378
- }
9379
- if (isCompress) {
9380
- this._process = wasm$1.deflate_process;
9381
- this._last_consumed = wasm$1.deflate_last_consumed;
9382
- this._end = wasm$1.deflate_end;
9383
- this.streamHandle = wasm$1.deflate_new();
9384
- if (type === FORMAT_GZIP) {
9385
- result = wasm$1.deflate_init_gzip(this.streamHandle, level);
9386
- } else if (type === FORMAT_DEFLATE_RAW) {
9387
- result = wasm$1.deflate_init_raw(this.streamHandle, level);
9388
- } else {
9389
- result = wasm$1.deflate_init(this.streamHandle, level);
9390
- }
9391
- } else {
9392
- if (type === FORMAT_DEFLATE64_RAW) {
9393
- this._process = wasm$1.inflate9_process;
9394
- this._last_consumed = wasm$1.inflate9_last_consumed;
9395
- this._end = wasm$1.inflate9_end;
9396
- this.streamHandle = wasm$1.inflate9_new();
9397
- result = wasm$1.inflate9_init_raw(this.streamHandle);
9398
- } else {
9399
- this._process = wasm$1.inflate_process;
9400
- this._last_consumed = wasm$1.inflate_last_consumed;
9401
- this._end = wasm$1.inflate_end;
9402
- this.streamHandle = wasm$1.inflate_new();
9403
- if (type === FORMAT_DEFLATE_RAW) {
9404
- result = wasm$1.inflate_init_raw(this.streamHandle);
9405
- } else if (type === FORMAT_GZIP) {
9406
- result = wasm$1.inflate_init_gzip(this.streamHandle);
9407
- } else {
9408
- result = wasm$1.inflate_init(this.streamHandle);
9409
- }
9410
- }
9411
- }
9412
- if (result !== 0) {
9413
- throw new Error("init failed:" + result);
9414
- }
9448
+ processChunk(chunk);
9415
9449
  } catch (error) {
9416
- disposeStream(this);
9450
+ disposeStream(state);
9451
+ readableController.error(error);
9417
9452
  throw error;
9418
9453
  }
9419
9454
  },
9420
- transform(chunk, controller) {
9455
+ close() {
9456
+ if (cancelled) {
9457
+ return;
9458
+ }
9421
9459
  try {
9422
- const buffer = chunk;
9423
- const heap = new Uint8Array(memory.buffer);
9424
- const process = this._process;
9425
- const last_consumed = this._last_consumed;
9426
- const out = this.out;
9427
- let offset = 0;
9428
- while (offset < buffer.length) {
9429
- const toRead = Math.min(buffer.length - offset, 32 * 1024);
9430
- if (!this.in || this.inBufferSize < toRead) {
9431
- if (this.in && free) {
9432
- free(this.in);
9433
- this.in = 0;
9434
- }
9435
- this.in = malloc(toRead);
9436
- this.inBufferSize = toRead;
9437
- if (!this.in) {
9438
- throw new Error("allocation failed");
9439
- }
9440
- }
9441
- heap.set(buffer.subarray(offset, offset + toRead), this.in);
9442
- const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
9443
- // checked before the byte count is used, so a status code can never be read as one
9444
- const code = (result >> 24) & 0xff;
9445
- const signedCode = (code & 0x80) ? code - 256 : code;
9446
- if (signedCode < 0) {
9447
- throw new Error("process error:" + signedCode);
9448
- }
9449
- const prod = result & 0x00ffffff;
9450
- if (prod) {
9451
- controller.enqueue(heap.slice(out, out + prod));
9452
- }
9453
- const consumed = last_consumed(this.streamHandle);
9454
- if (consumed === 0 && prod === 0) {
9455
- break;
9456
- }
9457
- offset += consumed;
9458
- }
9460
+ flushStream();
9459
9461
  } catch (error) {
9460
- disposeStream(this);
9461
- controller.error(error);
9462
+ disposeStream(state);
9463
+ readableController.error(error);
9464
+ throw error;
9462
9465
  }
9466
+ const result = disposeStream(state);
9467
+ if (result !== 0) {
9468
+ const error = new Error("end error:" + result);
9469
+ readableController.error(error);
9470
+ throw error;
9471
+ }
9472
+ readableController.close();
9463
9473
  },
9464
- flush(controller) {
9465
- try {
9466
- const heap = new Uint8Array(memory.buffer);
9467
- const process = this._process;
9468
- const out = this.out;
9469
- while (true) {
9470
- const result = process(this.streamHandle, 0, 0, out, outBufferSize, 4);
9471
- const code = (result >> 24) & 0xff;
9472
- const signedCode = (code & 0x80) ? code - 256 : code;
9473
- if (signedCode < 0) {
9474
- throw new Error("process error:" + signedCode);
9475
- }
9476
- const produced = result & 0x00ffffff;
9477
- if (produced) {
9478
- controller.enqueue(heap.slice(out, out + produced));
9479
- }
9480
- if (code === 1 || produced === 0) {
9481
- break;
9474
+ abort(reason) {
9475
+ disposeStream(state);
9476
+ readableController.error(reason);
9477
+ }
9478
+ }, { highWaterMark: 1 });
9479
+ return { readable, writable };
9480
+
9481
+ function initStream() {
9482
+ try {
9483
+ let result;
9484
+ state.out = malloc(outBufferSize);
9485
+ state.in = malloc(inBufferSize);
9486
+ state.inBufferSize = inBufferSize;
9487
+ if (!state.out || !state.in) {
9488
+ throw new Error("allocation failed");
9489
+ }
9490
+ if (isCompress) {
9491
+ state._process = wasm$1.deflate_process;
9492
+ state._last_consumed = wasm$1.deflate_last_consumed;
9493
+ state._end = wasm$1.deflate_end;
9494
+ state.streamHandle = wasm$1.deflate_new();
9495
+ if (type === FORMAT_GZIP) {
9496
+ result = wasm$1.deflate_init_gzip(state.streamHandle, level);
9497
+ } else if (type === FORMAT_DEFLATE_RAW) {
9498
+ result = wasm$1.deflate_init_raw(state.streamHandle, level);
9499
+ } else {
9500
+ result = wasm$1.deflate_init(state.streamHandle, level);
9501
+ }
9502
+ } else {
9503
+ if (type === FORMAT_DEFLATE64_RAW) {
9504
+ state._process = wasm$1.inflate9_process;
9505
+ state._last_consumed = wasm$1.inflate9_last_consumed;
9506
+ state._end = wasm$1.inflate9_end;
9507
+ state.streamHandle = wasm$1.inflate9_new();
9508
+ result = wasm$1.inflate9_init_raw(state.streamHandle);
9509
+ } else {
9510
+ state._process = wasm$1.inflate_process;
9511
+ state._last_consumed = wasm$1.inflate_last_consumed;
9512
+ state._end = wasm$1.inflate_end;
9513
+ state.streamHandle = wasm$1.inflate_new();
9514
+ if (type === FORMAT_DEFLATE_RAW) {
9515
+ result = wasm$1.inflate_init_raw(state.streamHandle);
9516
+ } else if (type === FORMAT_GZIP) {
9517
+ result = wasm$1.inflate_init_gzip(state.streamHandle);
9518
+ } else {
9519
+ result = wasm$1.inflate_init(state.streamHandle);
9482
9520
  }
9483
9521
  }
9484
- } catch (error) {
9485
- controller.error(error);
9486
- } finally {
9487
- const result = disposeStream(this);
9488
- if (result !== 0) {
9489
- controller.error(new Error("end error:" + result));
9522
+ }
9523
+ if (result !== 0) {
9524
+ throw new Error("init failed:" + result);
9525
+ }
9526
+ } catch (error) {
9527
+ disposeStream(state);
9528
+ throw error;
9529
+ }
9530
+ }
9531
+
9532
+ function processChunk(chunk) {
9533
+ const heap = new Uint8Array(memory.buffer);
9534
+ const process = state._process;
9535
+ const last_consumed = state._last_consumed;
9536
+ const out = state.out;
9537
+ let offset = 0;
9538
+ while (offset < chunk.length) {
9539
+ const toRead = Math.min(chunk.length - offset, 32 * 1024);
9540
+ if (!state.in || state.inBufferSize < toRead) {
9541
+ if (state.in && free) {
9542
+ free(state.in);
9543
+ state.in = 0;
9544
+ }
9545
+ state.in = malloc(toRead);
9546
+ state.inBufferSize = toRead;
9547
+ if (!state.in) {
9548
+ throw new Error("allocation failed");
9490
9549
  }
9491
9550
  }
9492
- },
9493
- cancel() {
9494
- // release the stream handle and buffers when the pipeline is aborted,
9495
- // they would be leaked in the process-lifetime wasm heap otherwise
9496
- disposeStream(this);
9551
+ heap.set(chunk.subarray(offset, offset + toRead), state.in);
9552
+ const result = process(state.streamHandle, state.in, toRead, out, outBufferSize, 0);
9553
+ // checked before the byte count is used, so a status code can never be read as one
9554
+ const code = (result >> 24) & 0xff;
9555
+ const signedCode = (code & 0x80) ? code - 256 : code;
9556
+ if (signedCode < 0) {
9557
+ throw new Error("process error:" + signedCode);
9558
+ }
9559
+ const prod = result & 0x00ffffff;
9560
+ if (prod) {
9561
+ enqueue(heap.slice(out, out + prod));
9562
+ }
9563
+ const consumed = last_consumed(state.streamHandle);
9564
+ if (consumed === 0 && prod === 0) {
9565
+ break;
9566
+ }
9567
+ offset += consumed;
9497
9568
  }
9498
- });
9569
+ }
9570
+
9571
+ function flushStream() {
9572
+ const heap = new Uint8Array(memory.buffer);
9573
+ const process = state._process;
9574
+ const out = state.out;
9575
+ while (true) {
9576
+ const result = process(state.streamHandle, 0, 0, out, outBufferSize, 4);
9577
+ const code = (result >> 24) & 0xff;
9578
+ const signedCode = (code & 0x80) ? code - 256 : code;
9579
+ if (signedCode < 0) {
9580
+ throw new Error("process error:" + signedCode);
9581
+ }
9582
+ const produced = result & 0x00ffffff;
9583
+ if (produced) {
9584
+ enqueue(heap.slice(out, out + produced));
9585
+ }
9586
+ if (code === 1 || produced === 0) {
9587
+ break;
9588
+ }
9589
+ }
9590
+ }
9591
+
9592
+ function enqueue(chunk) {
9593
+ backpressure = true;
9594
+ readableController.enqueue(chunk);
9595
+ }
9596
+
9597
+ function resumeWrite() {
9598
+ if (resolveWrite) {
9599
+ const resolve = resolveWrite;
9600
+ resolveWrite = null;
9601
+ resolve();
9602
+ }
9603
+ }
9499
9604
 
9500
9605
  function disposeStream(state) {
9501
9606
  let endResult = 0;