@zip.js/zip.js 2.15.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.
- package/BENCHMARKS.md +4 -2
- package/deno.json +1 -1
- package/dist/zip-core-external.js +410 -227
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +234 -109
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +552 -237
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +377 -118
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +552 -237
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +379 -120
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +554 -237
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +236 -111
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +236 -111
- package/dist/zip-native.min.js +1 -1
- package/dist/zip-web-worker-native.js +1 -1
- package/dist/zip-web-worker.js +1 -1
- package/dist/zip.js +411 -228
- package/dist/zip.min.js +1 -1
- package/eslint.config.mjs +1 -1
- package/index-native.cjs +379 -120
- package/index-native.min.js +1 -1
- package/index.cjs +554 -237
- package/index.d.cts +143 -16
- package/index.d.ts +143 -16
- package/index.min.js +1 -1
- package/lib/core/io.js +3 -2
- package/lib/core/streams/aes-crypto-stream.js +60 -17
- package/lib/core/streams/zip-crypto-stream.js +7 -7
- package/lib/core/streams/zip-entry-stream.js +146 -73
- package/lib/core/streams/zlib-wasm/zlib-streams.js +176 -118
- package/lib/core/util/compatible-streams.js +10 -5
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-fs.js +144 -10
- package/lib/core/zip-reader.js +5 -5
- package/lib/core/zip-writer.js +4 -2
- package/package.json +3 -2
|
@@ -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(
|
|
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
|
-
} =
|
|
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
|
-
|
|
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(
|
|
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
|
-
} =
|
|
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(
|
|
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
|
|
1670
|
+
const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
|
|
1627
1671
|
Object.assign(target, {
|
|
1628
|
-
|
|
1629
|
-
crcKey0: new Crc32(
|
|
1630
|
-
crcKey2: new Crc32(
|
|
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.
|
|
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.
|
|
1694
|
+
target.cryptoKeys = [key0, key1, key2];
|
|
1651
1695
|
}
|
|
1652
1696
|
|
|
1653
1697
|
function getByte(target) {
|
|
1654
|
-
const temp = target.
|
|
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
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
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) {
|
|
@@ -1889,7 +1938,6 @@ const FORMAT_GZIP$1 = "gzip";
|
|
|
1889
1938
|
const GZIP_HEADER_LENGTH = 10;
|
|
1890
1939
|
const GZIP_TRAILER_LENGTH = 8;
|
|
1891
1940
|
const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
|
|
1892
|
-
const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
|
|
1893
1941
|
|
|
1894
1942
|
class DeflateStream extends TransformStream {
|
|
1895
1943
|
|
|
@@ -1900,7 +1948,7 @@ class DeflateStream extends TransformStream {
|
|
|
1900
1948
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
1901
1949
|
let readable = super.readable;
|
|
1902
1950
|
const codecStreams = format && getCodecStreams(format);
|
|
1903
|
-
const GzipCompressionStream =
|
|
1951
|
+
const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
|
|
1904
1952
|
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
|
|
1905
1953
|
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
1906
1954
|
crc32Stream = new Crc32Stream();
|
|
@@ -1917,6 +1965,9 @@ class DeflateStream extends TransformStream {
|
|
|
1917
1965
|
try {
|
|
1918
1966
|
readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
|
|
1919
1967
|
} catch (error) {
|
|
1968
|
+
if (!useCompressionStream && CompressionStreamFallback) {
|
|
1969
|
+
throw error;
|
|
1970
|
+
}
|
|
1920
1971
|
let gzipStream;
|
|
1921
1972
|
try {
|
|
1922
1973
|
gzipStream = new CompressionStream(FORMAT_GZIP$1);
|
|
@@ -1986,74 +2037,134 @@ class GzipToRawDeflateStream extends TransformStream {
|
|
|
1986
2037
|
}
|
|
1987
2038
|
|
|
1988
2039
|
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
|
|
2040
|
+
const writer = gzipStream.writable.getWriter();
|
|
2041
|
+
const reader = gzipStream.readable.getReader();
|
|
2042
|
+
const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
|
|
1989
2043
|
let outputLength = 0;
|
|
1990
2044
|
let inputDone = false;
|
|
1991
|
-
let
|
|
2045
|
+
let trailerWritten = false;
|
|
2046
|
+
let idleCheckArmed = false;
|
|
2047
|
+
let readCount = 0;
|
|
2048
|
+
let readPending = false;
|
|
1992
2049
|
let resolveTrailerReady, rejectTrailerReady;
|
|
1993
2050
|
const trailerReady = new Promise((resolve, reject) => {
|
|
1994
2051
|
resolveTrailerReady = resolve;
|
|
1995
2052
|
rejectTrailerReady = reject;
|
|
1996
2053
|
});
|
|
1997
2054
|
trailerReady.catch(() => { });
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2055
|
+
pump();
|
|
2056
|
+
return new ReadableStream({
|
|
2057
|
+
async pull(controller) {
|
|
2058
|
+
try {
|
|
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
|
+
}
|
|
2072
|
+
} catch (error) {
|
|
2073
|
+
rejectTrailerReady(error);
|
|
2074
|
+
await cancel(reader, error);
|
|
2075
|
+
throw trailerWritten ? getTrailerError(error) : error;
|
|
2076
|
+
}
|
|
2077
|
+
},
|
|
2078
|
+
cancel(reason) {
|
|
2079
|
+
rejectTrailerReady(reason);
|
|
2080
|
+
return reader.cancel(reason);
|
|
2081
|
+
}
|
|
2082
|
+
});
|
|
2083
|
+
|
|
2084
|
+
async function pump() {
|
|
2085
|
+
const inputReader = readable.getReader();
|
|
2086
|
+
try {
|
|
2003
2087
|
const header = new Uint8Array(GZIP_HEADER_LENGTH);
|
|
2004
2088
|
header.set(GZIP_HEADER_BYTES);
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2089
|
+
await writer.write(header);
|
|
2090
|
+
for (; ;) {
|
|
2091
|
+
await writer.ready;
|
|
2092
|
+
const { value, done } = await inputReader.read();
|
|
2093
|
+
if (done) {
|
|
2094
|
+
break;
|
|
2095
|
+
}
|
|
2096
|
+
await writer.write(value);
|
|
2097
|
+
}
|
|
2011
2098
|
inputDone = true;
|
|
2012
|
-
|
|
2013
|
-
|
|
2099
|
+
if (outputCrc32) {
|
|
2100
|
+
if (readPending) {
|
|
2101
|
+
armIdleCheck();
|
|
2102
|
+
}
|
|
2014
2103
|
await trailerReady;
|
|
2015
|
-
} finally {
|
|
2016
|
-
stopWatchdog();
|
|
2017
2104
|
}
|
|
2018
2105
|
const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
|
|
2019
2106
|
const dataView = getDataView(trailer);
|
|
2020
|
-
dataView.setUint32(0,
|
|
2107
|
+
dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
|
|
2021
2108
|
dataView.setUint32(4, outputSize, true);
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2109
|
+
trailerWritten = true;
|
|
2110
|
+
await writer.write(trailer);
|
|
2111
|
+
await writer.close();
|
|
2112
|
+
} catch (error) {
|
|
2113
|
+
await abort(writer, error);
|
|
2114
|
+
await cancel(inputReader, error);
|
|
2026
2115
|
}
|
|
2027
|
-
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
}
|
|
2037
|
-
controller.enqueue(chunk);
|
|
2038
|
-
},
|
|
2039
|
-
cancel(reason) {
|
|
2040
|
-
rejectTrailerReady(reason);
|
|
2116
|
+
}
|
|
2117
|
+
|
|
2118
|
+
function read() {
|
|
2119
|
+
readCount++;
|
|
2120
|
+
readPending = true;
|
|
2121
|
+
const result = reader.read();
|
|
2122
|
+
result.then(onReadSettled, onReadSettled);
|
|
2123
|
+
if (inputDone && outputCrc32) {
|
|
2124
|
+
armIdleCheck();
|
|
2041
2125
|
}
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
readable = pipeThroughBackpressured(readable, gzipStream);
|
|
2045
|
-
return pipeThrough(readable, outputStream);
|
|
2126
|
+
return result;
|
|
2127
|
+
}
|
|
2046
2128
|
|
|
2047
|
-
function
|
|
2048
|
-
|
|
2049
|
-
|
|
2129
|
+
function onReadSettled() {
|
|
2130
|
+
readPending = false;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
async function armIdleCheck() {
|
|
2134
|
+
if (!idleCheckArmed) {
|
|
2135
|
+
idleCheckArmed = true;
|
|
2136
|
+
const count = readCount;
|
|
2137
|
+
await nextTask();
|
|
2138
|
+
idleCheckArmed = false;
|
|
2139
|
+
if (readPending) {
|
|
2140
|
+
if (readCount == count) {
|
|
2141
|
+
resolveTrailerReady();
|
|
2142
|
+
} else {
|
|
2143
|
+
armIdleCheck();
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2050
2147
|
}
|
|
2051
2148
|
|
|
2052
|
-
function
|
|
2053
|
-
|
|
2149
|
+
function getTrailerError(error) {
|
|
2150
|
+
const trailerError = new Error(outputLength == outputSize ? ERR_INVALID_CRC32 : ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
2151
|
+
trailerError.cause = error;
|
|
2152
|
+
return trailerError;
|
|
2054
2153
|
}
|
|
2055
2154
|
}
|
|
2056
2155
|
|
|
2156
|
+
function nextTask() {
|
|
2157
|
+
return new Promise(resolve => {
|
|
2158
|
+
const { port1, port2 } = new MessageChannel();
|
|
2159
|
+
port2.onmessage = () => {
|
|
2160
|
+
port1.close();
|
|
2161
|
+
port2.close();
|
|
2162
|
+
resolve();
|
|
2163
|
+
};
|
|
2164
|
+
port1.postMessage(UNDEFINED_VALUE);
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2057
2168
|
class InflateStream extends TransformStream {
|
|
2058
2169
|
|
|
2059
2170
|
constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
|
|
@@ -2074,20 +2185,32 @@ class InflateStream extends TransformStream {
|
|
|
2074
2185
|
if (codecStreams) {
|
|
2075
2186
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
|
|
2076
2187
|
} else {
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
if (deflate64 || outputSize === UNDEFINED_VALUE) {
|
|
2081
|
-
throw error;
|
|
2082
|
-
}
|
|
2083
|
-
let gzipStream;
|
|
2188
|
+
let gzipStream;
|
|
2189
|
+
const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
|
|
2190
|
+
if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
|
|
2084
2191
|
try {
|
|
2085
|
-
gzipStream = new
|
|
2192
|
+
gzipStream = new GzipDecompressionStream(FORMAT_GZIP$1, { chunkSize });
|
|
2086
2193
|
} catch {
|
|
2087
|
-
|
|
2194
|
+
gzipStream = UNDEFINED_VALUE;
|
|
2088
2195
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2196
|
+
}
|
|
2197
|
+
if (!gzipStream) {
|
|
2198
|
+
try {
|
|
2199
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
|
|
2200
|
+
} catch (error) {
|
|
2201
|
+
if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
|
|
2202
|
+
throw error;
|
|
2203
|
+
}
|
|
2204
|
+
try {
|
|
2205
|
+
gzipStream = new DecompressionStream(FORMAT_GZIP$1);
|
|
2206
|
+
} catch {
|
|
2207
|
+
throw error;
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
if (gzipStream) {
|
|
2212
|
+
gzipCrc32 = true;
|
|
2213
|
+
readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32);
|
|
2091
2214
|
}
|
|
2092
2215
|
}
|
|
2093
2216
|
readable = mapInflateStreamError(readable);
|
|
@@ -2097,8 +2220,8 @@ class InflateStream extends TransformStream {
|
|
|
2097
2220
|
readable = pipeThrough(readable, crc32Stream);
|
|
2098
2221
|
}
|
|
2099
2222
|
setReadable(this, readable, () => {
|
|
2100
|
-
if (
|
|
2101
|
-
const computedCrc32 =
|
|
2223
|
+
if (crc32Stream) {
|
|
2224
|
+
const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
|
|
2102
2225
|
if (crc32 != computedCrc32) {
|
|
2103
2226
|
throw new Error(ERR_INVALID_CRC32);
|
|
2104
2227
|
}
|
|
@@ -2155,11 +2278,11 @@ function createCodecStream(CodecStreamClass, format, options) {
|
|
|
2155
2278
|
return new CodecStreamClass(format, options);
|
|
2156
2279
|
}
|
|
2157
2280
|
|
|
2158
|
-
function
|
|
2159
|
-
if (useCompressionStream &&
|
|
2160
|
-
return
|
|
2161
|
-
} else if (
|
|
2162
|
-
return
|
|
2281
|
+
function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
|
|
2282
|
+
if (useCompressionStream && CodecStreamNative) {
|
|
2283
|
+
return CodecStreamNative;
|
|
2284
|
+
} else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
|
|
2285
|
+
return CodecStreamFallback;
|
|
2163
2286
|
}
|
|
2164
2287
|
}
|
|
2165
2288
|
|
|
@@ -2229,10 +2352,15 @@ function mapInflateStreamError(readable) {
|
|
|
2229
2352
|
const reader = readable.getReader();
|
|
2230
2353
|
return new ReadableStream({
|
|
2231
2354
|
async pull(controller) {
|
|
2232
|
-
let result;
|
|
2233
2355
|
try {
|
|
2234
|
-
|
|
2356
|
+
const { value, done } = await reader.read();
|
|
2357
|
+
if (done) {
|
|
2358
|
+
controller.close();
|
|
2359
|
+
} else {
|
|
2360
|
+
controller.enqueue(value);
|
|
2361
|
+
}
|
|
2235
2362
|
} catch (error) {
|
|
2363
|
+
await cancel(reader, error);
|
|
2236
2364
|
if (error && error.message) {
|
|
2237
2365
|
throw error;
|
|
2238
2366
|
}
|
|
@@ -2240,12 +2368,6 @@ function mapInflateStreamError(readable) {
|
|
|
2240
2368
|
mappedError.cause = error;
|
|
2241
2369
|
throw mappedError;
|
|
2242
2370
|
}
|
|
2243
|
-
const { value, done } = result;
|
|
2244
|
-
if (done) {
|
|
2245
|
-
controller.close();
|
|
2246
|
-
} else {
|
|
2247
|
-
controller.enqueue(value);
|
|
2248
|
-
}
|
|
2249
2371
|
},
|
|
2250
2372
|
cancel(reason) {
|
|
2251
2373
|
return reader.cancel(reason);
|
|
@@ -3741,10 +3863,11 @@ class FetchReader extends Reader {
|
|
|
3741
3863
|
|
|
3742
3864
|
createReadable(options) {
|
|
3743
3865
|
const reader = this;
|
|
3744
|
-
const { useRangeHeader, forceRangeRequests, size } = reader;
|
|
3866
|
+
const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
|
|
3745
3867
|
if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
|
|
3746
3868
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
3747
|
-
|
|
3869
|
+
const cached = eocdCache && offset >= size - eocdCache.length;
|
|
3870
|
+
if (readSize > 0 && offset < size && !cached) {
|
|
3748
3871
|
return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
|
|
3749
3872
|
}
|
|
3750
3873
|
}
|
|
@@ -5303,8 +5426,8 @@ class ZipEntry {
|
|
|
5303
5426
|
const passThroughCompression = Boolean(passThrough);
|
|
5304
5427
|
const passThroughEncryption = passThrough === true;
|
|
5305
5428
|
checkPasswordOption(password, rawPassword);
|
|
5306
|
-
password = password && password.length
|
|
5307
|
-
rawPassword = rawPassword && rawPassword.length
|
|
5429
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
5430
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
5308
5431
|
if (extraFieldAES) {
|
|
5309
5432
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
5310
5433
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -6065,7 +6188,7 @@ function getMaxAppendedDataSize(maxAppendedDataSize, strictness) {
|
|
|
6065
6188
|
async function findEndOfCentralDirectory(reader, rejectAmbiguous, maxAppendedDataSize) {
|
|
6066
6189
|
const { size } = reader;
|
|
6067
6190
|
const anchoredLength = Math.min(size, END_OF_CENTRAL_DIR_LENGTH + MAX_16_BITS);
|
|
6068
|
-
const remoteProbeBudget = {
|
|
6191
|
+
const remoteProbeBudget = { remaining: MAX_END_OF_CENTRAL_DIR_PROBES };
|
|
6069
6192
|
let endOfDirectoryInfo;
|
|
6070
6193
|
let plausibleEndOfDirectoryInfo;
|
|
6071
6194
|
let endOfDirectoryReachingEndCount = 0;
|
|
@@ -6158,8 +6281,8 @@ async function readSignature(reader, view, anchoredOffset, signatureOffset, size
|
|
|
6158
6281
|
if (signatureOffset >= anchoredOffset) {
|
|
6159
6282
|
return getUint32$1(view, signatureOffset - anchoredOffset);
|
|
6160
6283
|
}
|
|
6161
|
-
if (remoteProbeBudget.
|
|
6162
|
-
remoteProbeBudget.
|
|
6284
|
+
if (remoteProbeBudget.remaining > 0) {
|
|
6285
|
+
remoteProbeBudget.remaining--;
|
|
6163
6286
|
const signatureArray = await readUint8Array(reader, signatureOffset, 4);
|
|
6164
6287
|
return getUint32$1(getDataView(signatureArray), 0);
|
|
6165
6288
|
}
|
|
@@ -7075,9 +7198,11 @@ function resolveMetadata(zipWriter, name, options) {
|
|
|
7075
7198
|
const passThrough = checkPassThroughOption(getOptionValue(zipWriter, options, OPTION_PASS_THROUGH));
|
|
7076
7199
|
const passThroughCompression = Boolean(passThrough);
|
|
7077
7200
|
const passThroughEncryption = passThrough === true;
|
|
7078
|
-
|
|
7079
|
-
|
|
7201
|
+
let password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
|
|
7202
|
+
let rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
|
|
7080
7203
|
checkPasswordOption(password, rawPassword);
|
|
7204
|
+
password = password && password.length ? password : UNDEFINED_VALUE;
|
|
7205
|
+
rawPassword = rawPassword && rawPassword.length ? rawPassword : UNDEFINED_VALUE;
|
|
7081
7206
|
const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
|
|
7082
7207
|
const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
|
|
7083
7208
|
const extendedTimestamp = getOptionValue(zipWriter, options, OPTION_EXTENDED_TIMESTAMP, true);
|
|
@@ -8775,7 +8900,7 @@ function formatSupported(StreamClass, format) {
|
|
|
8775
8900
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
8776
8901
|
*/
|
|
8777
8902
|
|
|
8778
|
-
const VERSION = "2.
|
|
8903
|
+
const VERSION = "2.16.1";
|
|
8779
8904
|
|
|
8780
8905
|
/*
|
|
8781
8906
|
Copyright (c) 2025 Gildas Lormeau. All rights reserved.
|
|
@@ -9252,7 +9377,7 @@ try {
|
|
|
9252
9377
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
9253
9378
|
*/
|
|
9254
9379
|
|
|
9255
|
-
/* global
|
|
9380
|
+
/* global ReadableStream, WritableStream */
|
|
9256
9381
|
|
|
9257
9382
|
const FORMAT_DEFLATE = "deflate";
|
|
9258
9383
|
const FORMAT_DEFLATE_RAW = "deflate-raw";
|
|
@@ -9287,137 +9412,195 @@ function _make(isCompress, type, options = {}) {
|
|
|
9287
9412
|
const level = (typeof options.level === "number") ? options.level : -1;
|
|
9288
9413
|
const outBufferSize = (typeof options.outBuffer === "number") ? options.outBuffer : 64 * 1024;
|
|
9289
9414
|
const inBufferSize = (typeof options.inBufferSize === "number") ? options.inBufferSize : 64 * 1024;
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
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
|
+
}
|
|
9293
9447
|
try {
|
|
9294
|
-
|
|
9295
|
-
this.out = malloc(outBufferSize);
|
|
9296
|
-
this.in = malloc(inBufferSize);
|
|
9297
|
-
this.inBufferSize = inBufferSize;
|
|
9298
|
-
if (!this.out || !this.in) {
|
|
9299
|
-
throw new Error("allocation failed");
|
|
9300
|
-
}
|
|
9301
|
-
if (isCompress) {
|
|
9302
|
-
this._process = wasm$1.deflate_process;
|
|
9303
|
-
this._last_consumed = wasm$1.deflate_last_consumed;
|
|
9304
|
-
this._end = wasm$1.deflate_end;
|
|
9305
|
-
this.streamHandle = wasm$1.deflate_new();
|
|
9306
|
-
if (type === FORMAT_GZIP) {
|
|
9307
|
-
result = wasm$1.deflate_init_gzip(this.streamHandle, level);
|
|
9308
|
-
} else if (type === FORMAT_DEFLATE_RAW) {
|
|
9309
|
-
result = wasm$1.deflate_init_raw(this.streamHandle, level);
|
|
9310
|
-
} else {
|
|
9311
|
-
result = wasm$1.deflate_init(this.streamHandle, level);
|
|
9312
|
-
}
|
|
9313
|
-
} else {
|
|
9314
|
-
if (type === FORMAT_DEFLATE64_RAW) {
|
|
9315
|
-
this._process = wasm$1.inflate9_process;
|
|
9316
|
-
this._last_consumed = wasm$1.inflate9_last_consumed;
|
|
9317
|
-
this._end = wasm$1.inflate9_end;
|
|
9318
|
-
this.streamHandle = wasm$1.inflate9_new();
|
|
9319
|
-
result = wasm$1.inflate9_init_raw(this.streamHandle);
|
|
9320
|
-
} else {
|
|
9321
|
-
this._process = wasm$1.inflate_process;
|
|
9322
|
-
this._last_consumed = wasm$1.inflate_last_consumed;
|
|
9323
|
-
this._end = wasm$1.inflate_end;
|
|
9324
|
-
this.streamHandle = wasm$1.inflate_new();
|
|
9325
|
-
if (type === FORMAT_DEFLATE_RAW) {
|
|
9326
|
-
result = wasm$1.inflate_init_raw(this.streamHandle);
|
|
9327
|
-
} else if (type === FORMAT_GZIP) {
|
|
9328
|
-
result = wasm$1.inflate_init_gzip(this.streamHandle);
|
|
9329
|
-
} else {
|
|
9330
|
-
result = wasm$1.inflate_init(this.streamHandle);
|
|
9331
|
-
}
|
|
9332
|
-
}
|
|
9333
|
-
}
|
|
9334
|
-
if (result !== 0) {
|
|
9335
|
-
throw new Error("init failed:" + result);
|
|
9336
|
-
}
|
|
9448
|
+
processChunk(chunk);
|
|
9337
9449
|
} catch (error) {
|
|
9338
|
-
disposeStream(
|
|
9450
|
+
disposeStream(state);
|
|
9451
|
+
readableController.error(error);
|
|
9339
9452
|
throw error;
|
|
9340
9453
|
}
|
|
9341
9454
|
},
|
|
9342
|
-
|
|
9455
|
+
close() {
|
|
9456
|
+
if (cancelled) {
|
|
9457
|
+
return;
|
|
9458
|
+
}
|
|
9343
9459
|
try {
|
|
9344
|
-
|
|
9345
|
-
const heap = new Uint8Array(memory.buffer);
|
|
9346
|
-
const process = this._process;
|
|
9347
|
-
const last_consumed = this._last_consumed;
|
|
9348
|
-
const out = this.out;
|
|
9349
|
-
let offset = 0;
|
|
9350
|
-
while (offset < buffer.length) {
|
|
9351
|
-
const toRead = Math.min(buffer.length - offset, 32 * 1024);
|
|
9352
|
-
if (!this.in || this.inBufferSize < toRead) {
|
|
9353
|
-
if (this.in && free) {
|
|
9354
|
-
free(this.in);
|
|
9355
|
-
this.in = 0;
|
|
9356
|
-
}
|
|
9357
|
-
this.in = malloc(toRead);
|
|
9358
|
-
this.inBufferSize = toRead;
|
|
9359
|
-
if (!this.in) {
|
|
9360
|
-
throw new Error("allocation failed");
|
|
9361
|
-
}
|
|
9362
|
-
}
|
|
9363
|
-
heap.set(buffer.subarray(offset, offset + toRead), this.in);
|
|
9364
|
-
const result = process(this.streamHandle, this.in, toRead, out, outBufferSize, 0);
|
|
9365
|
-
// checked before the byte count is used, so a status code can never be read as one
|
|
9366
|
-
const code = (result >> 24) & 0xff;
|
|
9367
|
-
const signedCode = (code & 0x80) ? code - 256 : code;
|
|
9368
|
-
if (signedCode < 0) {
|
|
9369
|
-
throw new Error("process error:" + signedCode);
|
|
9370
|
-
}
|
|
9371
|
-
const prod = result & 0x00ffffff;
|
|
9372
|
-
if (prod) {
|
|
9373
|
-
controller.enqueue(heap.slice(out, out + prod));
|
|
9374
|
-
}
|
|
9375
|
-
const consumed = last_consumed(this.streamHandle);
|
|
9376
|
-
if (consumed === 0 && prod === 0) {
|
|
9377
|
-
break;
|
|
9378
|
-
}
|
|
9379
|
-
offset += consumed;
|
|
9380
|
-
}
|
|
9460
|
+
flushStream();
|
|
9381
9461
|
} catch (error) {
|
|
9382
|
-
disposeStream(
|
|
9383
|
-
|
|
9462
|
+
disposeStream(state);
|
|
9463
|
+
readableController.error(error);
|
|
9464
|
+
throw error;
|
|
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;
|
|
9384
9471
|
}
|
|
9472
|
+
readableController.close();
|
|
9385
9473
|
},
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
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);
|
|
9404
9520
|
}
|
|
9405
9521
|
}
|
|
9406
|
-
}
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
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");
|
|
9412
9549
|
}
|
|
9413
9550
|
}
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
//
|
|
9417
|
-
|
|
9418
|
-
|
|
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;
|
|
9419
9568
|
}
|
|
9420
|
-
}
|
|
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
|
+
}
|
|
9421
9604
|
|
|
9422
9605
|
function disposeStream(state) {
|
|
9423
9606
|
let endResult = 0;
|