@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
package/lib/core/io.js
CHANGED
|
@@ -354,10 +354,11 @@ class FetchReader extends Reader {
|
|
|
354
354
|
|
|
355
355
|
createReadable(options) {
|
|
356
356
|
const reader = this;
|
|
357
|
-
const { useRangeHeader, forceRangeRequests, size } = reader;
|
|
357
|
+
const { useRangeHeader, forceRangeRequests, size, eocdCache } = reader;
|
|
358
358
|
if ((useRangeHeader || forceRangeRequests) && size !== UNDEFINED_VALUE) {
|
|
359
359
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
360
|
-
|
|
360
|
+
const cached = eocdCache && offset >= size - eocdCache.length;
|
|
361
|
+
if (readSize > 0 && offset < size && !cached) {
|
|
361
362
|
return createRangeReadable(reader, offset, Math.min(readSize, size - offset));
|
|
362
363
|
}
|
|
363
364
|
}
|
|
@@ -26,8 +26,7 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global crypto, TransformStream */
|
|
30
|
-
// deno-lint-ignore-file no-this-alias
|
|
29
|
+
/* global crypto, TransformStream, ReadableStream */
|
|
31
30
|
|
|
32
31
|
import { UNDEFINED_VALUE, UNDEFINED_TYPE, FUNCTION_TYPE, EMPTY_UINT8_ARRAY } from "../constants.js";
|
|
33
32
|
import { encodeText } from "./../util/encode-text.js";
|
|
@@ -64,12 +63,12 @@ let createEngine = createDefaultEngine;
|
|
|
64
63
|
class AESDecryptionStream extends TransformStream {
|
|
65
64
|
|
|
66
65
|
constructor({ password, rawPassword, encryptionStrength, checkPasswordOnly, checkAuthenticationCode = true }) {
|
|
66
|
+
const aesCrypto = {};
|
|
67
67
|
super({
|
|
68
68
|
start() {
|
|
69
|
-
initAesCrypto(
|
|
69
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
70
70
|
},
|
|
71
71
|
async transform(chunk, controller) {
|
|
72
|
-
const aesCrypto = this;
|
|
73
72
|
const {
|
|
74
73
|
password,
|
|
75
74
|
strength,
|
|
@@ -88,6 +87,9 @@ class AESDecryptionStream extends TransformStream {
|
|
|
88
87
|
} else {
|
|
89
88
|
await ready;
|
|
90
89
|
}
|
|
90
|
+
if (aesCrypto.discarded) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
91
93
|
const output = new Uint8Array(chunk.length - AUTHENTICATION_CODE_LENGTH - ((chunk.length - AUTHENTICATION_CODE_LENGTH) % BLOCK_LENGTH));
|
|
92
94
|
controller.enqueue(append(aesCrypto, chunk, output, 0, AUTHENTICATION_CODE_LENGTH, true));
|
|
93
95
|
},
|
|
@@ -96,9 +98,12 @@ class AESDecryptionStream extends TransformStream {
|
|
|
96
98
|
engine,
|
|
97
99
|
pendingInput,
|
|
98
100
|
ready
|
|
99
|
-
} =
|
|
101
|
+
} = aesCrypto;
|
|
100
102
|
if (engine) {
|
|
101
103
|
await ready;
|
|
104
|
+
if (aesCrypto.discarded) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
102
107
|
const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
|
|
103
108
|
const decryptedChunkArray = new Uint8Array(subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH));
|
|
104
109
|
engine.process(decryptedChunkArray, true);
|
|
@@ -108,27 +113,26 @@ class AESDecryptionStream extends TransformStream {
|
|
|
108
113
|
invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
|
|
109
114
|
}
|
|
110
115
|
if (invalidAuthenticationCode && checkAuthenticationCode) {
|
|
111
|
-
|
|
116
|
+
controller.error(new Error(ERR_INVALID_AUTHENTICATION_CODE));
|
|
117
|
+
return;
|
|
112
118
|
}
|
|
113
119
|
controller.enqueue(decryptedChunkArray);
|
|
114
120
|
}
|
|
115
|
-
},
|
|
116
|
-
cancel() {
|
|
117
|
-
disposeEngine(this);
|
|
118
121
|
}
|
|
119
122
|
});
|
|
123
|
+
setDisposingReadable(this, aesCrypto);
|
|
120
124
|
}
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
class AESEncryptionStream extends TransformStream {
|
|
124
128
|
|
|
125
129
|
constructor({ password, rawPassword, encryptionStrength }) {
|
|
130
|
+
const aesCrypto = {};
|
|
126
131
|
super({
|
|
127
132
|
start() {
|
|
128
|
-
initAesCrypto(
|
|
133
|
+
initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength);
|
|
129
134
|
},
|
|
130
135
|
async transform(chunk, controller) {
|
|
131
|
-
const aesCrypto = this;
|
|
132
136
|
const {
|
|
133
137
|
password,
|
|
134
138
|
strength,
|
|
@@ -142,6 +146,9 @@ class AESEncryptionStream extends TransformStream {
|
|
|
142
146
|
} else {
|
|
143
147
|
await ready;
|
|
144
148
|
}
|
|
149
|
+
if (aesCrypto.discarded) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
145
152
|
const output = new Uint8Array(preamble.length + chunk.length - (chunk.length % BLOCK_LENGTH));
|
|
146
153
|
output.set(preamble, 0);
|
|
147
154
|
controller.enqueue(append(aesCrypto, chunk, output, preamble.length, 0, false));
|
|
@@ -151,19 +158,20 @@ class AESEncryptionStream extends TransformStream {
|
|
|
151
158
|
engine,
|
|
152
159
|
pendingInput,
|
|
153
160
|
ready
|
|
154
|
-
} =
|
|
161
|
+
} = aesCrypto;
|
|
155
162
|
if (engine) {
|
|
156
163
|
await ready;
|
|
164
|
+
if (aesCrypto.discarded) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
157
167
|
const encryptedChunkArray = new Uint8Array(pendingInput);
|
|
158
168
|
engine.process(encryptedChunkArray, false);
|
|
159
169
|
const authenticationCode = subarray(engine.digest(), 0, AUTHENTICATION_CODE_LENGTH);
|
|
160
170
|
controller.enqueue(concat(encryptedChunkArray, authenticationCode));
|
|
161
171
|
}
|
|
162
|
-
},
|
|
163
|
-
cancel() {
|
|
164
|
-
disposeEngine(this);
|
|
165
172
|
}
|
|
166
173
|
});
|
|
174
|
+
setDisposingReadable(this, aesCrypto);
|
|
167
175
|
}
|
|
168
176
|
}
|
|
169
177
|
|
|
@@ -182,7 +190,37 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
|
|
|
182
190
|
ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
|
|
183
191
|
password: encodePassword(password, rawPassword),
|
|
184
192
|
strength: encryptionStrength - 1,
|
|
185
|
-
pendingInput: EMPTY_UINT8_ARRAY
|
|
193
|
+
pendingInput: EMPTY_UINT8_ARRAY,
|
|
194
|
+
discarded: false
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function setDisposingReadable(stream, aesCrypto) {
|
|
199
|
+
const reader = stream.readable.getReader();
|
|
200
|
+
const readable = new ReadableStream({
|
|
201
|
+
async pull(controller) {
|
|
202
|
+
try {
|
|
203
|
+
const { value, done } = await reader.read();
|
|
204
|
+
if (done) {
|
|
205
|
+
controller.close();
|
|
206
|
+
} else {
|
|
207
|
+
controller.enqueue(value);
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
disposeEngine(aesCrypto);
|
|
211
|
+
reader.cancel(error).catch(() => { });
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
cancel(reason) {
|
|
216
|
+
disposeEngine(aesCrypto);
|
|
217
|
+
return reader.cancel(reason);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
Object.defineProperty(stream, "readable", {
|
|
221
|
+
get() {
|
|
222
|
+
return readable;
|
|
223
|
+
}
|
|
186
224
|
});
|
|
187
225
|
}
|
|
188
226
|
|
|
@@ -215,7 +253,9 @@ async function createDecryptionKeys(decrypt, strength, password, preamble) {
|
|
|
215
253
|
}
|
|
216
254
|
}
|
|
217
255
|
|
|
218
|
-
function disposeEngine(
|
|
256
|
+
function disposeEngine(aesCrypto) {
|
|
257
|
+
const { engine } = aesCrypto;
|
|
258
|
+
aesCrypto.discarded = true;
|
|
219
259
|
if (engine && engine.dispose) {
|
|
220
260
|
engine.dispose();
|
|
221
261
|
}
|
|
@@ -232,6 +272,9 @@ async function createKeys(aesCrypto, strength, password, salt) {
|
|
|
232
272
|
const keyLength = KEY_LENGTH[strength];
|
|
233
273
|
const compositeKey = await deriveKey(password, salt, keyLength * 2 + PASSWORD_VERIFICATION_LENGTH);
|
|
234
274
|
aesCrypto.engine = createEngine(subarray(compositeKey, 0, keyLength), subarray(compositeKey, keyLength, keyLength * 2));
|
|
275
|
+
if (aesCrypto.discarded) {
|
|
276
|
+
disposeEngine(aesCrypto);
|
|
277
|
+
}
|
|
235
278
|
return subarray(compositeKey, keyLength * 2);
|
|
236
279
|
}
|
|
237
280
|
|
|
@@ -127,11 +127,11 @@ function encrypt(target, input) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function createKeys(target, password, rawPassword) {
|
|
130
|
-
const
|
|
130
|
+
const cryptoKeys = [0x12345678, 0x23456789, 0x34567890];
|
|
131
131
|
Object.assign(target, {
|
|
132
|
-
|
|
133
|
-
crcKey0: new Crc32(
|
|
134
|
-
crcKey2: new Crc32(
|
|
132
|
+
cryptoKeys,
|
|
133
|
+
crcKey0: new Crc32(cryptoKeys[0]),
|
|
134
|
+
crcKey2: new Crc32(cryptoKeys[2])
|
|
135
135
|
});
|
|
136
136
|
if (rawPassword) {
|
|
137
137
|
for (let index = 0; index < rawPassword.length; index++) {
|
|
@@ -145,17 +145,17 @@ function createKeys(target, password, rawPassword) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
function updateKeys(target, byte) {
|
|
148
|
-
let [, key1] = target.
|
|
148
|
+
let [, key1] = target.cryptoKeys;
|
|
149
149
|
target.crcKey0.append([byte]);
|
|
150
150
|
const key0 = ~target.crcKey0.get();
|
|
151
151
|
key1 = getInt32(Math.imul(getInt32(key1 + getInt8(key0)), 134775813) + 1);
|
|
152
152
|
target.crcKey2.append([key1 >>> 24]);
|
|
153
153
|
const key2 = ~target.crcKey2.get();
|
|
154
|
-
target.
|
|
154
|
+
target.cryptoKeys = [key0, key1, key2];
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
function getByte(target) {
|
|
158
|
-
const temp = target.
|
|
158
|
+
const temp = target.cryptoKeys[2] | 2;
|
|
159
159
|
return getInt8(Math.imul(temp, (temp ^ 1)) >>> 8);
|
|
160
160
|
}
|
|
161
161
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global TransformStream, ReadableStream,
|
|
29
|
+
/* global TransformStream, ReadableStream, MessageChannel */
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
32
|
import { Crc32 } from "./codecs/crc32.js";
|
|
@@ -59,7 +59,6 @@ const FORMAT_GZIP = "gzip";
|
|
|
59
59
|
const GZIP_HEADER_LENGTH = 10;
|
|
60
60
|
const GZIP_TRAILER_LENGTH = 8;
|
|
61
61
|
const GZIP_HEADER_BYTES = [0x1f, 0x8b, 0x08];
|
|
62
|
-
const GZIP_OUTPUT_STALL_TIMEOUT = 5000;
|
|
63
62
|
|
|
64
63
|
class DeflateStream extends TransformStream {
|
|
65
64
|
|
|
@@ -70,7 +69,7 @@ class DeflateStream extends TransformStream {
|
|
|
70
69
|
let crc32Stream, encryptionStream, gzipCrc32Stream;
|
|
71
70
|
let readable = super.readable;
|
|
72
71
|
const codecStreams = format && getCodecStreams(format);
|
|
73
|
-
const GzipCompressionStream =
|
|
72
|
+
const GzipCompressionStream = getGzipCodecStream(useCompressionStream, CompressionStream, CompressionStreamFallback);
|
|
74
73
|
const useGzipCrc32 = computeCrc32 && compressed && !deflate64 && !codecStreams && (!encrypted || zipCrypto) && Boolean(GzipCompressionStream);
|
|
75
74
|
if ((!encrypted || zipCrypto) && computeCrc32 && !useGzipCrc32) {
|
|
76
75
|
crc32Stream = new Crc32Stream();
|
|
@@ -87,6 +86,9 @@ class DeflateStream extends TransformStream {
|
|
|
87
86
|
try {
|
|
88
87
|
readable = pipeThroughCompressionStream(readable, useCompressionStream, { level, chunkSize }, CompressionStream, CompressionStreamFallback);
|
|
89
88
|
} catch (error) {
|
|
89
|
+
if (!useCompressionStream && CompressionStreamFallback) {
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
90
92
|
let gzipStream;
|
|
91
93
|
try {
|
|
92
94
|
gzipStream = new CompressionStream(FORMAT_GZIP);
|
|
@@ -156,74 +158,134 @@ class GzipToRawDeflateStream extends TransformStream {
|
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
function pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32) {
|
|
161
|
+
const writer = gzipStream.writable.getWriter();
|
|
162
|
+
const reader = gzipStream.readable.getReader();
|
|
163
|
+
const outputCrc32 = crc32 === UNDEFINED_VALUE ? new Crc32() : UNDEFINED_VALUE;
|
|
159
164
|
let outputLength = 0;
|
|
160
165
|
let inputDone = false;
|
|
161
|
-
let
|
|
166
|
+
let trailerWritten = false;
|
|
167
|
+
let idleCheckArmed = false;
|
|
168
|
+
let readCount = 0;
|
|
169
|
+
let readPending = false;
|
|
162
170
|
let resolveTrailerReady, rejectTrailerReady;
|
|
163
171
|
const trailerReady = new Promise((resolve, reject) => {
|
|
164
172
|
resolveTrailerReady = resolve;
|
|
165
173
|
rejectTrailerReady = reject;
|
|
166
174
|
});
|
|
167
175
|
trailerReady.catch(() => { });
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
176
|
+
pump();
|
|
177
|
+
return new ReadableStream({
|
|
178
|
+
async pull(controller) {
|
|
179
|
+
try {
|
|
180
|
+
const { value, done } = await read();
|
|
181
|
+
if (done) {
|
|
182
|
+
controller.close();
|
|
183
|
+
} else {
|
|
184
|
+
outputLength += value.length;
|
|
185
|
+
if (outputLength > outputSize) {
|
|
186
|
+
throw new Error(ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
187
|
+
}
|
|
188
|
+
if (outputCrc32) {
|
|
189
|
+
outputCrc32.append(value);
|
|
190
|
+
}
|
|
191
|
+
controller.enqueue(value);
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
rejectTrailerReady(error);
|
|
195
|
+
await cancel(reader, error);
|
|
196
|
+
throw trailerWritten ? getTrailerError(error) : error;
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
cancel(reason) {
|
|
200
|
+
rejectTrailerReady(reason);
|
|
201
|
+
return reader.cancel(reason);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
async function pump() {
|
|
206
|
+
const inputReader = readable.getReader();
|
|
207
|
+
try {
|
|
173
208
|
const header = new Uint8Array(GZIP_HEADER_LENGTH);
|
|
174
209
|
header.set(GZIP_HEADER_BYTES);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
210
|
+
await writer.write(header);
|
|
211
|
+
for (; ;) {
|
|
212
|
+
await writer.ready;
|
|
213
|
+
const { value, done } = await inputReader.read();
|
|
214
|
+
if (done) {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
await writer.write(value);
|
|
218
|
+
}
|
|
181
219
|
inputDone = true;
|
|
182
|
-
|
|
183
|
-
|
|
220
|
+
if (outputCrc32) {
|
|
221
|
+
if (readPending) {
|
|
222
|
+
armIdleCheck();
|
|
223
|
+
}
|
|
184
224
|
await trailerReady;
|
|
185
|
-
} finally {
|
|
186
|
-
stopWatchdog();
|
|
187
225
|
}
|
|
188
226
|
const trailer = new Uint8Array(GZIP_TRAILER_LENGTH);
|
|
189
227
|
const dataView = getDataView(trailer);
|
|
190
|
-
dataView.setUint32(0,
|
|
228
|
+
dataView.setUint32(0, outputCrc32 ? outputCrc32.get() : crc32, true);
|
|
191
229
|
dataView.setUint32(4, outputSize, true);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
230
|
+
trailerWritten = true;
|
|
231
|
+
await writer.write(trailer);
|
|
232
|
+
await writer.close();
|
|
233
|
+
} catch (error) {
|
|
234
|
+
await abort(writer, error);
|
|
235
|
+
await cancel(inputReader, error);
|
|
196
236
|
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
controller.enqueue(chunk);
|
|
208
|
-
},
|
|
209
|
-
cancel(reason) {
|
|
210
|
-
rejectTrailerReady(reason);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function read() {
|
|
240
|
+
readCount++;
|
|
241
|
+
readPending = true;
|
|
242
|
+
const result = reader.read();
|
|
243
|
+
result.then(onReadSettled, onReadSettled);
|
|
244
|
+
if (inputDone && outputCrc32) {
|
|
245
|
+
armIdleCheck();
|
|
211
246
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function onReadSettled() {
|
|
251
|
+
readPending = false;
|
|
252
|
+
}
|
|
216
253
|
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
|
|
254
|
+
async function armIdleCheck() {
|
|
255
|
+
if (!idleCheckArmed) {
|
|
256
|
+
idleCheckArmed = true;
|
|
257
|
+
const count = readCount;
|
|
258
|
+
await nextTask();
|
|
259
|
+
idleCheckArmed = false;
|
|
260
|
+
if (readPending) {
|
|
261
|
+
if (readCount == count) {
|
|
262
|
+
resolveTrailerReady();
|
|
263
|
+
} else {
|
|
264
|
+
armIdleCheck();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
220
268
|
}
|
|
221
269
|
|
|
222
|
-
function
|
|
223
|
-
|
|
270
|
+
function getTrailerError(error) {
|
|
271
|
+
const trailerError = new Error(outputLength == outputSize ? ERR_INVALID_CRC32 : ERR_INVALID_UNCOMPRESSED_SIZE);
|
|
272
|
+
trailerError.cause = error;
|
|
273
|
+
return trailerError;
|
|
224
274
|
}
|
|
225
275
|
}
|
|
226
276
|
|
|
277
|
+
function nextTask() {
|
|
278
|
+
return new Promise(resolve => {
|
|
279
|
+
const { port1, port2 } = new MessageChannel();
|
|
280
|
+
port2.onmessage = () => {
|
|
281
|
+
port1.close();
|
|
282
|
+
port2.close();
|
|
283
|
+
resolve();
|
|
284
|
+
};
|
|
285
|
+
port1.postMessage(UNDEFINED_VALUE);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
227
289
|
class InflateStream extends TransformStream {
|
|
228
290
|
|
|
229
291
|
constructor(options, { chunkSize, DecompressionStreamFallback, DecompressionStream }) {
|
|
@@ -244,20 +306,32 @@ class InflateStream extends TransformStream {
|
|
|
244
306
|
if (codecStreams) {
|
|
245
307
|
readable = pipeThroughBackpressured(readable, createCodecStream(codecStreams.DecompressionStream, format, { chunkSize, compressionMethod, rawBitFlag, uncompressedSize: outputSize }));
|
|
246
308
|
} else {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (deflate64 || outputSize === UNDEFINED_VALUE) {
|
|
251
|
-
throw error;
|
|
252
|
-
}
|
|
253
|
-
let gzipStream;
|
|
309
|
+
let gzipStream;
|
|
310
|
+
const GzipDecompressionStream = getGzipCodecStream(useCompressionStream, DecompressionStream, DecompressionStreamFallback);
|
|
311
|
+
if (checkCrc32 && !deflate64 && crc32 !== UNDEFINED_VALUE && outputSize !== UNDEFINED_VALUE && GzipDecompressionStream) {
|
|
254
312
|
try {
|
|
255
|
-
gzipStream = new
|
|
313
|
+
gzipStream = new GzipDecompressionStream(FORMAT_GZIP, { chunkSize });
|
|
256
314
|
} catch {
|
|
257
|
-
|
|
315
|
+
gzipStream = UNDEFINED_VALUE;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (!gzipStream) {
|
|
319
|
+
try {
|
|
320
|
+
readable = pipeThroughCompressionStream(readable, useCompressionStream, { chunkSize, deflate64 }, DecompressionStream, DecompressionStreamFallback);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
if (deflate64 || outputSize === UNDEFINED_VALUE || (!useCompressionStream && DecompressionStreamFallback)) {
|
|
323
|
+
throw error;
|
|
324
|
+
}
|
|
325
|
+
try {
|
|
326
|
+
gzipStream = new DecompressionStream(FORMAT_GZIP);
|
|
327
|
+
} catch {
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
258
330
|
}
|
|
259
|
-
|
|
260
|
-
|
|
331
|
+
}
|
|
332
|
+
if (gzipStream) {
|
|
333
|
+
gzipCrc32 = true;
|
|
334
|
+
readable = pipeThroughGzipDecompressionStream(readable, gzipStream, outputSize, crc32);
|
|
261
335
|
}
|
|
262
336
|
}
|
|
263
337
|
readable = mapInflateStreamError(readable);
|
|
@@ -267,8 +341,8 @@ class InflateStream extends TransformStream {
|
|
|
267
341
|
readable = pipeThrough(readable, crc32Stream);
|
|
268
342
|
}
|
|
269
343
|
setReadable(this, readable, () => {
|
|
270
|
-
if (
|
|
271
|
-
const computedCrc32 =
|
|
344
|
+
if (crc32Stream) {
|
|
345
|
+
const computedCrc32 = new DataView(crc32Stream.value.buffer).getUint32(0, false);
|
|
272
346
|
if (crc32 != computedCrc32) {
|
|
273
347
|
throw new Error(ERR_INVALID_CRC32);
|
|
274
348
|
}
|
|
@@ -343,11 +417,11 @@ function createCodecStream(CodecStreamClass, format, options) {
|
|
|
343
417
|
return new CodecStreamClass(format, options);
|
|
344
418
|
}
|
|
345
419
|
|
|
346
|
-
function
|
|
347
|
-
if (useCompressionStream &&
|
|
348
|
-
return
|
|
349
|
-
} else if (
|
|
350
|
-
return
|
|
420
|
+
function getGzipCodecStream(useCompressionStream, CodecStreamNative, CodecStreamFallback) {
|
|
421
|
+
if (useCompressionStream && CodecStreamNative) {
|
|
422
|
+
return CodecStreamNative;
|
|
423
|
+
} else if (CodecStreamFallback && CodecStreamFallback.requiresModule) {
|
|
424
|
+
return CodecStreamFallback;
|
|
351
425
|
}
|
|
352
426
|
}
|
|
353
427
|
|
|
@@ -417,10 +491,15 @@ function mapInflateStreamError(readable) {
|
|
|
417
491
|
const reader = readable.getReader();
|
|
418
492
|
return new ReadableStream({
|
|
419
493
|
async pull(controller) {
|
|
420
|
-
let result;
|
|
421
494
|
try {
|
|
422
|
-
|
|
495
|
+
const { value, done } = await reader.read();
|
|
496
|
+
if (done) {
|
|
497
|
+
controller.close();
|
|
498
|
+
} else {
|
|
499
|
+
controller.enqueue(value);
|
|
500
|
+
}
|
|
423
501
|
} catch (error) {
|
|
502
|
+
await cancel(reader, error);
|
|
424
503
|
if (error && error.message) {
|
|
425
504
|
throw error;
|
|
426
505
|
}
|
|
@@ -428,12 +507,6 @@ function mapInflateStreamError(readable) {
|
|
|
428
507
|
mappedError.cause = error;
|
|
429
508
|
throw mappedError;
|
|
430
509
|
}
|
|
431
|
-
const { value, done } = result;
|
|
432
|
-
if (done) {
|
|
433
|
-
controller.close();
|
|
434
|
-
} else {
|
|
435
|
-
controller.enqueue(value);
|
|
436
|
-
}
|
|
437
510
|
},
|
|
438
511
|
cancel(reason) {
|
|
439
512
|
return reader.cancel(reason);
|