@zip.js/zip.js 2.7.32 → 2.7.34
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/dist/z-worker-fflate.js +1 -1
- package/dist/z-worker-pako.js +1 -1
- package/dist/z-worker.js +1 -1
- package/dist/zip-fs-full.js +206 -95
- package/dist/zip-fs-full.min.js +1 -1
- package/dist/zip-fs.js +206 -95
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-full.js +205 -94
- package/dist/zip-full.min.js +1 -1
- package/dist/zip-no-worker-deflate.min.js +1 -1
- package/dist/zip-no-worker-inflate.min.js +1 -1
- package/dist/zip-no-worker.min.js +1 -1
- package/dist/zip.js +205 -94
- package/dist/zip.min.js +1 -1
- package/index.cjs +206 -95
- package/index.d.ts +12 -4
- package/index.min.js +1 -1
- package/lib/core/codec-pool.js +40 -24
- package/lib/core/codec-worker.js +51 -20
- package/lib/core/io.js +4 -5
- package/lib/core/streams/aes-crypto-stream.js +14 -8
- package/lib/core/streams/codec-stream.js +53 -6
- package/lib/core/streams/common-crypto.js +2 -1
- package/lib/core/streams/zip-entry-stream.js +6 -2
- package/lib/core/util/encode-text.js +3 -1
- package/lib/core/util/stream-codec-shim.js +4 -2
- package/lib/core/z-worker-core.js +33 -7
- package/lib/core/zip-fs-core.js +2 -1
- package/lib/core/zip-reader.js +5 -2
- package/lib/core/zip-writer.js +24 -16
- package/lib/z-worker-bootstrap-fflate.js +2 -1
- package/lib/z-worker-inline.js +1 -1
- package/lib/zip-fflate-shim.js +3 -1
- package/package.json +4 -4
package/lib/core/codec-pool.js
CHANGED
|
@@ -56,26 +56,28 @@ let indexWorker = 0;
|
|
|
56
56
|
async function runWorker(stream, workerOptions) {
|
|
57
57
|
const { options, config } = workerOptions;
|
|
58
58
|
const { transferStreams, useWebWorkers, useCompressionStream, codecType, compressed, signed, encrypted } = options;
|
|
59
|
-
const { workerScripts, maxWorkers
|
|
59
|
+
const { workerScripts, maxWorkers } = config;
|
|
60
60
|
workerOptions.transferStreams = transferStreams || transferStreams === UNDEFINED_VALUE;
|
|
61
61
|
const streamCopy = !compressed && !signed && !encrypted && !workerOptions.transferStreams;
|
|
62
62
|
workerOptions.useWebWorkers = !streamCopy && (useWebWorkers || (useWebWorkers === UNDEFINED_VALUE && config.useWebWorkers));
|
|
63
63
|
workerOptions.scripts = workerOptions.useWebWorkers && workerScripts ? workerScripts[codecType] : [];
|
|
64
64
|
options.useCompressionStream = useCompressionStream || (useCompressionStream === UNDEFINED_VALUE && config.useCompressionStream);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
return (await getWorker()).run();
|
|
66
|
+
|
|
67
|
+
async function getWorker() {
|
|
68
|
+
const workerData = pool.find(workerData => !workerData.busy);
|
|
69
|
+
if (workerData) {
|
|
70
|
+
clearTerminateTimeout(workerData);
|
|
71
|
+
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
72
|
+
} else if (pool.length < maxWorkers) {
|
|
73
|
+
const workerData = { indexWorker };
|
|
74
|
+
indexWorker++;
|
|
75
|
+
pool.push(workerData);
|
|
76
|
+
return new CodecWorker(workerData, stream, workerOptions, onTaskFinished);
|
|
77
|
+
} else {
|
|
78
|
+
return new Promise(resolve => pendingRequests.push({ resolve, stream, workerOptions }));
|
|
79
|
+
}
|
|
77
80
|
}
|
|
78
|
-
return worker.run();
|
|
79
81
|
|
|
80
82
|
function onTaskFinished(workerData) {
|
|
81
83
|
if (pendingRequests.length) {
|
|
@@ -83,18 +85,32 @@ async function runWorker(stream, workerOptions) {
|
|
|
83
85
|
resolve(new CodecWorker(workerData, stream, workerOptions, onTaskFinished));
|
|
84
86
|
} else if (workerData.worker) {
|
|
85
87
|
clearTerminateTimeout(workerData);
|
|
86
|
-
|
|
87
|
-
workerData.terminateTimeout = setTimeout(() => {
|
|
88
|
-
pool = pool.filter(data => data != workerData);
|
|
89
|
-
workerData.terminate();
|
|
90
|
-
}, terminateWorkerTimeout);
|
|
91
|
-
}
|
|
88
|
+
terminateWorker(workerData, workerOptions);
|
|
92
89
|
} else {
|
|
93
90
|
pool = pool.filter(data => data != workerData);
|
|
94
91
|
}
|
|
95
92
|
}
|
|
96
93
|
}
|
|
97
94
|
|
|
95
|
+
function terminateWorker(workerData, workerOptions) {
|
|
96
|
+
const { config } = workerOptions;
|
|
97
|
+
const { terminateWorkerTimeout } = config;
|
|
98
|
+
if (Number.isFinite(terminateWorkerTimeout) && terminateWorkerTimeout >= 0) {
|
|
99
|
+
if (workerData.terminated) {
|
|
100
|
+
workerData.terminated = false;
|
|
101
|
+
} else {
|
|
102
|
+
workerData.terminateTimeout = setTimeout(async () => {
|
|
103
|
+
pool = pool.filter(data => data != workerData);
|
|
104
|
+
try {
|
|
105
|
+
await workerData.terminate();
|
|
106
|
+
} catch (_error) {
|
|
107
|
+
// ignored
|
|
108
|
+
}
|
|
109
|
+
}, terminateWorkerTimeout);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
98
114
|
function clearTerminateTimeout(workerData) {
|
|
99
115
|
const { terminateTimeout } = workerData;
|
|
100
116
|
if (terminateTimeout) {
|
|
@@ -103,9 +119,9 @@ function clearTerminateTimeout(workerData) {
|
|
|
103
119
|
}
|
|
104
120
|
}
|
|
105
121
|
|
|
106
|
-
function terminateWorkers() {
|
|
107
|
-
pool.
|
|
122
|
+
async function terminateWorkers() {
|
|
123
|
+
await Promise.allSettled(pool.map(workerData => {
|
|
108
124
|
clearTerminateTimeout(workerData);
|
|
109
|
-
workerData.terminate();
|
|
110
|
-
});
|
|
125
|
+
return workerData.terminate();
|
|
126
|
+
}));
|
|
111
127
|
}
|
package/lib/core/codec-worker.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from "./constants.js";
|
|
35
35
|
import {
|
|
36
36
|
CodecStream,
|
|
37
|
+
ChunkStream,
|
|
37
38
|
MESSAGE_EVENT_TYPE,
|
|
38
39
|
MESSAGE_START,
|
|
39
40
|
MESSAGE_PULL,
|
|
@@ -43,7 +44,7 @@ import {
|
|
|
43
44
|
} from "./streams/codec-stream.js";
|
|
44
45
|
|
|
45
46
|
// deno-lint-ignore valid-typeof
|
|
46
|
-
|
|
47
|
+
let WEB_WORKERS_SUPPORTED = typeof Worker != UNDEFINED_TYPE;
|
|
47
48
|
|
|
48
49
|
export {
|
|
49
50
|
CodecWorker
|
|
@@ -55,19 +56,37 @@ class CodecWorker {
|
|
|
55
56
|
const { signal } = streamOptions;
|
|
56
57
|
Object.assign(workerData, {
|
|
57
58
|
busy: true,
|
|
58
|
-
readable: readable
|
|
59
|
+
readable: readable
|
|
60
|
+
.pipeThrough(new ChunkStream(config.chunkSize))
|
|
61
|
+
.pipeThrough(new ProgressWatcherStream(readable, streamOptions), { signal }),
|
|
59
62
|
writable,
|
|
60
63
|
options: Object.assign({}, options),
|
|
61
64
|
scripts,
|
|
62
65
|
transferStreams,
|
|
63
66
|
terminate() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
worker
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
return new Promise(resolve => {
|
|
68
|
+
const { worker, busy } = workerData;
|
|
69
|
+
if (worker) {
|
|
70
|
+
if (busy) {
|
|
71
|
+
workerData.resolveTerminated = resolve;
|
|
72
|
+
} else {
|
|
73
|
+
worker.terminate();
|
|
74
|
+
resolve();
|
|
75
|
+
}
|
|
76
|
+
workerData.interface = null;
|
|
77
|
+
} else {
|
|
78
|
+
resolve();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
69
81
|
},
|
|
70
82
|
onTaskFinished() {
|
|
83
|
+
const { resolveTerminated } = workerData;
|
|
84
|
+
if (resolveTerminated) {
|
|
85
|
+
workerData.resolveTerminated = null;
|
|
86
|
+
workerData.terminated = true;
|
|
87
|
+
workerData.worker.terminate();
|
|
88
|
+
resolveTerminated();
|
|
89
|
+
}
|
|
71
90
|
workerData.busy = false;
|
|
72
91
|
onTaskFinished(workerData);
|
|
73
92
|
}
|
|
@@ -78,12 +97,12 @@ class CodecWorker {
|
|
|
78
97
|
|
|
79
98
|
class ProgressWatcherStream extends TransformStream {
|
|
80
99
|
|
|
81
|
-
constructor(readableSource, { onstart, onprogress, size, onend }
|
|
100
|
+
constructor(readableSource, { onstart, onprogress, size, onend }) {
|
|
82
101
|
let chunkOffset = 0;
|
|
83
102
|
super({
|
|
84
|
-
start() {
|
|
103
|
+
async start() {
|
|
85
104
|
if (onstart) {
|
|
86
|
-
callHandler(onstart, size);
|
|
105
|
+
await callHandler(onstart, size);
|
|
87
106
|
}
|
|
88
107
|
},
|
|
89
108
|
async transform(chunk, controller) {
|
|
@@ -93,13 +112,13 @@ class ProgressWatcherStream extends TransformStream {
|
|
|
93
112
|
}
|
|
94
113
|
controller.enqueue(chunk);
|
|
95
114
|
},
|
|
96
|
-
flush() {
|
|
115
|
+
async flush() {
|
|
97
116
|
readableSource.size = chunkOffset;
|
|
98
117
|
if (onend) {
|
|
99
|
-
callHandler(onend, chunkOffset);
|
|
118
|
+
await callHandler(onend, chunkOffset);
|
|
100
119
|
}
|
|
101
120
|
}
|
|
102
|
-
}
|
|
121
|
+
});
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
|
|
@@ -117,10 +136,18 @@ function createWorkerInterface(workerData, config) {
|
|
|
117
136
|
};
|
|
118
137
|
}
|
|
119
138
|
|
|
120
|
-
function createWebWorkerInterface(workerData,
|
|
139
|
+
function createWebWorkerInterface(workerData, config) {
|
|
140
|
+
const { baseURL, chunkSize } = config;
|
|
121
141
|
if (!workerData.interface) {
|
|
142
|
+
let worker;
|
|
143
|
+
try {
|
|
144
|
+
worker = getWebWorker(workerData.scripts[0], baseURL, workerData);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
WEB_WORKERS_SUPPORTED = false;
|
|
147
|
+
return createWorkerInterface(workerData, config);
|
|
148
|
+
}
|
|
122
149
|
Object.assign(workerData, {
|
|
123
|
-
worker
|
|
150
|
+
worker,
|
|
124
151
|
interface: {
|
|
125
152
|
run: () => runWebWorker(workerData, { chunkSize })
|
|
126
153
|
}
|
|
@@ -130,16 +157,18 @@ function createWebWorkerInterface(workerData, { baseURL, chunkSize }) {
|
|
|
130
157
|
}
|
|
131
158
|
|
|
132
159
|
async function runWorker({ options, readable, writable, onTaskFinished }, config) {
|
|
133
|
-
const codecStream = new CodecStream(options, config);
|
|
134
160
|
try {
|
|
161
|
+
const codecStream = new CodecStream(options, config);
|
|
135
162
|
await readable.pipeThrough(codecStream).pipeTo(writable, { preventClose: true, preventAbort: true });
|
|
136
163
|
const {
|
|
137
164
|
signature,
|
|
138
|
-
|
|
165
|
+
inputSize,
|
|
166
|
+
outputSize
|
|
139
167
|
} = codecStream;
|
|
140
168
|
return {
|
|
141
169
|
signature,
|
|
142
|
-
|
|
170
|
+
inputSize,
|
|
171
|
+
outputSize
|
|
143
172
|
};
|
|
144
173
|
} finally {
|
|
145
174
|
onTaskFinished();
|
|
@@ -186,19 +215,20 @@ async function runWebWorker(workerData, config) {
|
|
|
186
215
|
}
|
|
187
216
|
|
|
188
217
|
function watchClosedStream(writableSource) {
|
|
189
|
-
const writer = writableSource.getWriter();
|
|
190
218
|
let resolveStreamClosed;
|
|
191
219
|
const closed = new Promise(resolve => resolveStreamClosed = resolve);
|
|
192
220
|
const writable = new WritableStream({
|
|
193
221
|
async write(chunk) {
|
|
222
|
+
const writer = writableSource.getWriter();
|
|
194
223
|
await writer.ready;
|
|
195
224
|
await writer.write(chunk);
|
|
225
|
+
writer.releaseLock();
|
|
196
226
|
},
|
|
197
227
|
close() {
|
|
198
|
-
writer.releaseLock();
|
|
199
228
|
resolveStreamClosed();
|
|
200
229
|
},
|
|
201
230
|
abort(reason) {
|
|
231
|
+
const writer = writableSource.getWriter();
|
|
202
232
|
return writer.abort(reason);
|
|
203
233
|
}
|
|
204
234
|
});
|
|
@@ -302,6 +332,7 @@ async function onMessage({ data }, workerData) {
|
|
|
302
332
|
}
|
|
303
333
|
}
|
|
304
334
|
} catch (error) {
|
|
335
|
+
sendMessage({ type: MESSAGE_CLOSE, messageId }, workerData);
|
|
305
336
|
close(error);
|
|
306
337
|
}
|
|
307
338
|
|
package/lib/core/io.js
CHANGED
|
@@ -262,7 +262,7 @@ class FetchReader extends Reader {
|
|
|
262
262
|
|
|
263
263
|
constructor(url, options) {
|
|
264
264
|
super();
|
|
265
|
-
|
|
265
|
+
createHttpReader(this, url, options);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
async init() {
|
|
@@ -279,7 +279,7 @@ class XHRReader extends Reader {
|
|
|
279
279
|
|
|
280
280
|
constructor(url, options) {
|
|
281
281
|
super();
|
|
282
|
-
|
|
282
|
+
createHttpReader(this, url, options);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
async init() {
|
|
@@ -292,7 +292,7 @@ class XHRReader extends Reader {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
function
|
|
295
|
+
function createHttpReader(httpReader, url, options) {
|
|
296
296
|
const {
|
|
297
297
|
preventHeadRequest,
|
|
298
298
|
useRangeHeader,
|
|
@@ -689,8 +689,7 @@ function initWriter(writer) {
|
|
|
689
689
|
if (writable.size === UNDEFINED_VALUE) {
|
|
690
690
|
writable.size = 0;
|
|
691
691
|
}
|
|
692
|
-
|
|
693
|
-
if (!splitZipFile) {
|
|
692
|
+
if (!(writer instanceof SplitDataWriter)) {
|
|
694
693
|
Object.assign(writer, {
|
|
695
694
|
diskNumber: 0,
|
|
696
695
|
diskOffset: 0,
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
/* global crypto, TransformStream */
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
|
+
import { UNDEFINED_VALUE, UNDEFINED_TYPE, FUNCTION_TYPE } from "../constants.js";
|
|
32
33
|
import { encodeText } from "./../util/encode-text.js";
|
|
33
34
|
import {
|
|
34
35
|
cipher,
|
|
@@ -55,8 +56,6 @@ const SALT_LENGTH = [8, 12, 16];
|
|
|
55
56
|
const KEY_LENGTH = [16, 24, 32];
|
|
56
57
|
const SIGNATURE_LENGTH = 10;
|
|
57
58
|
const COUNTER_DEFAULT_VALUE = [0, 0, 0, 0];
|
|
58
|
-
const UNDEFINED_TYPE = "undefined";
|
|
59
|
-
const FUNCTION_TYPE = "function";
|
|
60
59
|
// deno-lint-ignore valid-typeof
|
|
61
60
|
const CRYPTO_API_SUPPORTED = typeof crypto != UNDEFINED_TYPE;
|
|
62
61
|
const subtle = CRYPTO_API_SUPPORTED && crypto.subtle;
|
|
@@ -71,12 +70,12 @@ let DERIVE_BITS_SUPPORTED = CRYPTO_API_SUPPORTED && SUBTLE_API_SUPPORTED && type
|
|
|
71
70
|
|
|
72
71
|
class AESDecryptionStream extends TransformStream {
|
|
73
72
|
|
|
74
|
-
constructor({ password, signed, encryptionStrength, checkPasswordOnly }) {
|
|
73
|
+
constructor({ password, rawPassword, signed, encryptionStrength, checkPasswordOnly }) {
|
|
75
74
|
super({
|
|
76
75
|
start() {
|
|
77
76
|
Object.assign(this, {
|
|
78
77
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
79
|
-
password,
|
|
78
|
+
password: encodePassword(password, rawPassword),
|
|
80
79
|
signed,
|
|
81
80
|
strength: encryptionStrength - 1,
|
|
82
81
|
pending: new Uint8Array()
|
|
@@ -140,14 +139,14 @@ class AESDecryptionStream extends TransformStream {
|
|
|
140
139
|
|
|
141
140
|
class AESEncryptionStream extends TransformStream {
|
|
142
141
|
|
|
143
|
-
constructor({ password, encryptionStrength }) {
|
|
142
|
+
constructor({ password, rawPassword, encryptionStrength }) {
|
|
144
143
|
// deno-lint-ignore prefer-const
|
|
145
144
|
let stream;
|
|
146
145
|
super({
|
|
147
146
|
start() {
|
|
148
147
|
Object.assign(this, {
|
|
149
148
|
ready: new Promise(resolve => this.resolveReady = resolve),
|
|
150
|
-
password,
|
|
149
|
+
password: encodePassword(password, rawPassword),
|
|
151
150
|
strength: encryptionStrength - 1,
|
|
152
151
|
pending: new Uint8Array()
|
|
153
152
|
});
|
|
@@ -244,8 +243,7 @@ async function createEncryptionKeys(encrypt, strength, password) {
|
|
|
244
243
|
|
|
245
244
|
async function createKeys(aesCrypto, strength, password, salt) {
|
|
246
245
|
aesCrypto.password = null;
|
|
247
|
-
const
|
|
248
|
-
const baseKey = await importKey(RAW_FORMAT, encodedPassword, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
|
|
246
|
+
const baseKey = await importKey(RAW_FORMAT, password, BASE_KEY_ALGORITHM, false, DERIVED_BITS_USAGE);
|
|
249
247
|
const derivedBits = await deriveBits(Object.assign({ salt }, DERIVED_BITS_ALGORITHM), baseKey, 8 * ((KEY_LENGTH[strength] * 2) + 2));
|
|
250
248
|
const compositeKey = new Uint8Array(derivedBits);
|
|
251
249
|
const key = toBits(codecBytes, subarray(compositeKey, 0, KEY_LENGTH[strength]));
|
|
@@ -289,6 +287,14 @@ async function deriveBits(algorithm, baseKey, length) {
|
|
|
289
287
|
}
|
|
290
288
|
}
|
|
291
289
|
|
|
290
|
+
function encodePassword(password, rawPassword) {
|
|
291
|
+
if (rawPassword === UNDEFINED_VALUE) {
|
|
292
|
+
return encodeText(password);
|
|
293
|
+
} else {
|
|
294
|
+
return rawPassword;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
292
298
|
function concat(leftArray, rightArray) {
|
|
293
299
|
let array = leftArray;
|
|
294
300
|
if (leftArray.length + rightArray.length) {
|
|
@@ -65,7 +65,8 @@ export {
|
|
|
65
65
|
ERR_INVALID_PASSWORD,
|
|
66
66
|
ERR_INVALID_SIGNATURE,
|
|
67
67
|
ERR_ABORT_CHECK_PASSWORD,
|
|
68
|
-
CodecStream
|
|
68
|
+
CodecStream,
|
|
69
|
+
ChunkStream
|
|
69
70
|
};
|
|
70
71
|
|
|
71
72
|
class CodecStream extends TransformStream {
|
|
@@ -80,13 +81,27 @@ class CodecStream extends TransformStream {
|
|
|
80
81
|
} else if (codecType.startsWith(CODEC_INFLATE)) {
|
|
81
82
|
Stream = InflateStream;
|
|
82
83
|
}
|
|
83
|
-
let
|
|
84
|
+
let outputSize = 0;
|
|
85
|
+
let inputSize = 0;
|
|
84
86
|
const stream = new Stream(options, config);
|
|
85
87
|
const readable = super.readable;
|
|
86
|
-
const
|
|
88
|
+
const inputSizeStream = new TransformStream({
|
|
87
89
|
transform(chunk, controller) {
|
|
88
90
|
if (chunk && chunk.length) {
|
|
89
|
-
|
|
91
|
+
inputSize += chunk.length;
|
|
92
|
+
controller.enqueue(chunk);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
flush() {
|
|
96
|
+
Object.assign(codec, {
|
|
97
|
+
inputSize
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const outputSizeStream = new TransformStream({
|
|
102
|
+
transform(chunk, controller) {
|
|
103
|
+
if (chunk && chunk.length) {
|
|
104
|
+
outputSize += chunk.length;
|
|
90
105
|
controller.enqueue(chunk);
|
|
91
106
|
}
|
|
92
107
|
},
|
|
@@ -94,14 +109,46 @@ class CodecStream extends TransformStream {
|
|
|
94
109
|
const { signature } = stream;
|
|
95
110
|
Object.assign(codec, {
|
|
96
111
|
signature,
|
|
97
|
-
|
|
112
|
+
outputSize,
|
|
113
|
+
inputSize
|
|
98
114
|
});
|
|
99
115
|
}
|
|
100
116
|
});
|
|
101
117
|
Object.defineProperty(codec, "readable", {
|
|
102
118
|
get() {
|
|
103
|
-
return readable.pipeThrough(stream).pipeThrough(
|
|
119
|
+
return readable.pipeThrough(inputSizeStream).pipeThrough(stream).pipeThrough(outputSizeStream);
|
|
104
120
|
}
|
|
105
121
|
});
|
|
106
122
|
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
class ChunkStream extends TransformStream {
|
|
126
|
+
|
|
127
|
+
constructor(chunkSize) {
|
|
128
|
+
let pendingChunk;
|
|
129
|
+
super({
|
|
130
|
+
transform,
|
|
131
|
+
flush(controller) {
|
|
132
|
+
if (pendingChunk && pendingChunk.length) {
|
|
133
|
+
controller.enqueue(pendingChunk);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
function transform(chunk, controller) {
|
|
139
|
+
if (pendingChunk) {
|
|
140
|
+
const newChunk = new Uint8Array(pendingChunk.length + chunk.length);
|
|
141
|
+
newChunk.set(pendingChunk);
|
|
142
|
+
newChunk.set(chunk, pendingChunk.length);
|
|
143
|
+
chunk = newChunk;
|
|
144
|
+
pendingChunk = null;
|
|
145
|
+
}
|
|
146
|
+
if (chunk.length > chunkSize) {
|
|
147
|
+
controller.enqueue(chunk.slice(0, chunkSize));
|
|
148
|
+
transform(chunk.slice(chunkSize), controller);
|
|
149
|
+
} else {
|
|
150
|
+
pendingChunk = chunk;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
107
154
|
}
|
|
@@ -28,11 +28,12 @@
|
|
|
28
28
|
|
|
29
29
|
/* global crypto */
|
|
30
30
|
|
|
31
|
+
import { FUNCTION_TYPE, UNDEFINED_TYPE } from "../constants.js";
|
|
31
32
|
import {
|
|
32
33
|
random
|
|
33
34
|
} from "./codecs/sjcl.js";
|
|
34
35
|
|
|
35
|
-
const GET_RANDOM_VALUES_SUPPORTED = typeof crypto !=
|
|
36
|
+
const GET_RANDOM_VALUES_SUPPORTED = typeof crypto != UNDEFINED_TYPE && typeof crypto.getRandomValues == FUNCTION_TYPE;
|
|
36
37
|
|
|
37
38
|
const ERR_INVALID_PASSWORD = "Invalid password";
|
|
38
39
|
const ERR_INVALID_SIGNATURE = "Invalid signature";
|
|
@@ -148,9 +148,13 @@ function pipeThroughCommpressionStream(readable, useCompressionStream, options,
|
|
|
148
148
|
readable = pipeThrough(readable, new CompressionStream(COMPRESSION_FORMAT, options));
|
|
149
149
|
} catch (error) {
|
|
150
150
|
if (useCompressionStream) {
|
|
151
|
-
|
|
151
|
+
try {
|
|
152
|
+
readable = pipeThrough(readable, new CodecStream(COMPRESSION_FORMAT, options));
|
|
153
|
+
} catch (error) {
|
|
154
|
+
return readable;
|
|
155
|
+
}
|
|
152
156
|
} else {
|
|
153
|
-
|
|
157
|
+
return readable;
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
return readable;
|
|
@@ -28,12 +28,14 @@
|
|
|
28
28
|
|
|
29
29
|
/* global TextEncoder */
|
|
30
30
|
|
|
31
|
+
import { UNDEFINED_TYPE } from "../constants.js";
|
|
32
|
+
|
|
31
33
|
export {
|
|
32
34
|
encodeText
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
function encodeText(value) {
|
|
36
|
-
if (typeof TextEncoder ==
|
|
38
|
+
if (typeof TextEncoder == UNDEFINED_TYPE) {
|
|
37
39
|
value = unescape(encodeURIComponent(value));
|
|
38
40
|
const result = new Uint8Array(value.length);
|
|
39
41
|
for (let i = 0; i < result.length; i++) {
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
|
|
30
30
|
// deno-lint-ignore-file no-this-alias
|
|
31
31
|
|
|
32
|
+
import { FUNCTION_TYPE, UNDEFINED_VALUE } from "../constants.js";
|
|
33
|
+
|
|
32
34
|
export {
|
|
33
35
|
initShimAsyncCodec
|
|
34
36
|
};
|
|
@@ -42,7 +44,7 @@ function initShimAsyncCodec(library, options = {}, registerDataHandler) {
|
|
|
42
44
|
|
|
43
45
|
function objectHasOwn(object, propertyName) {
|
|
44
46
|
// eslint-disable-next-line no-prototype-builtins
|
|
45
|
-
return typeof Object.hasOwn ===
|
|
47
|
+
return typeof Object.hasOwn === FUNCTION_TYPE ? Object.hasOwn(object, propertyName) : object.hasOwnProperty(propertyName);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
function createCodecClass(constructor, constructorOptions, registerDataHandler) {
|
|
@@ -61,7 +63,7 @@ function createCodecClass(constructor, constructorOptions, registerDataHandler)
|
|
|
61
63
|
codecAdapter.pendingData = new Uint8Array(data);
|
|
62
64
|
}
|
|
63
65
|
};
|
|
64
|
-
if (objectHasOwn(options, "level") && options.level ===
|
|
66
|
+
if (objectHasOwn(options, "level") && options.level === UNDEFINED_VALUE) {
|
|
65
67
|
delete options.level;
|
|
66
68
|
}
|
|
67
69
|
codecAdapter.codec = new constructor(Object.assign({}, constructorOptions, options));
|
|
@@ -26,12 +26,13 @@
|
|
|
26
26
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
/* global self, importScripts, addEventListener, postMessage, ReadableStream, WritableStream */
|
|
29
|
+
/* global self, importScripts, addEventListener, postMessage, ReadableStream, WritableStream, AbortController */
|
|
30
30
|
|
|
31
31
|
import { UNDEFINED_VALUE } from "./constants.js";
|
|
32
32
|
import { StreamAdapter } from "./streams/stream-adapter.js";
|
|
33
33
|
import {
|
|
34
34
|
CodecStream,
|
|
35
|
+
ChunkStream,
|
|
35
36
|
MESSAGE_EVENT_TYPE,
|
|
36
37
|
MESSAGE_START,
|
|
37
38
|
MESSAGE_PULL,
|
|
@@ -43,7 +44,7 @@ import {
|
|
|
43
44
|
const pendingPullMessages = new Map();
|
|
44
45
|
const pendingDataMessages = new Map();
|
|
45
46
|
|
|
46
|
-
let messageId = 0;
|
|
47
|
+
let abortController, messageId = 0, importScriptSupported = true;
|
|
47
48
|
|
|
48
49
|
addEventListener(MESSAGE_EVENT_TYPE, ({ data }) => {
|
|
49
50
|
const { type, messageId, value, done } = data;
|
|
@@ -61,6 +62,9 @@ addEventListener(MESSAGE_EVENT_TYPE, ({ data }) => {
|
|
|
61
62
|
pendingDataMessages.delete(messageId);
|
|
62
63
|
resolve();
|
|
63
64
|
}
|
|
65
|
+
if (type == MESSAGE_CLOSE) {
|
|
66
|
+
abortController.abort();
|
|
67
|
+
}
|
|
64
68
|
} catch (error) {
|
|
65
69
|
sendErrorMessage(error);
|
|
66
70
|
}
|
|
@@ -70,7 +74,16 @@ async function init(message) {
|
|
|
70
74
|
try {
|
|
71
75
|
const { options, scripts, config } = message;
|
|
72
76
|
if (scripts && scripts.length) {
|
|
73
|
-
|
|
77
|
+
try {
|
|
78
|
+
if (importScriptSupported) {
|
|
79
|
+
importScripts.apply(UNDEFINED_VALUE, scripts);
|
|
80
|
+
} else {
|
|
81
|
+
await imporModuleScripts(scripts);
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
importScriptSupported = false;
|
|
85
|
+
await imporModuleScripts(scripts);
|
|
86
|
+
}
|
|
74
87
|
}
|
|
75
88
|
if (self.initCodec) {
|
|
76
89
|
self.initCodec();
|
|
@@ -83,7 +96,7 @@ async function init(message) {
|
|
|
83
96
|
if (self.Inflate) {
|
|
84
97
|
config.DecompressionStream = new StreamAdapter(self.Inflate);
|
|
85
98
|
}
|
|
86
|
-
const strategy = { highWaterMark: 1
|
|
99
|
+
const strategy = { highWaterMark: 1 };
|
|
87
100
|
const readable = message.readable || new ReadableStream({
|
|
88
101
|
async pull(controller) {
|
|
89
102
|
const result = new Promise(resolve => pendingPullMessages.set(messageId, resolve));
|
|
@@ -107,7 +120,12 @@ async function init(message) {
|
|
|
107
120
|
}
|
|
108
121
|
}, strategy);
|
|
109
122
|
const codecStream = new CodecStream(options, config);
|
|
110
|
-
|
|
123
|
+
abortController = new AbortController();
|
|
124
|
+
const { signal } = abortController;
|
|
125
|
+
await readable
|
|
126
|
+
.pipeThrough(codecStream)
|
|
127
|
+
.pipeThrough(new ChunkStream(config.chunkSize))
|
|
128
|
+
.pipeTo(writable, { signal, preventClose: true, preventAbort: true });
|
|
111
129
|
try {
|
|
112
130
|
await writable.getWriter().close();
|
|
113
131
|
} catch (_error) {
|
|
@@ -115,13 +133,15 @@ async function init(message) {
|
|
|
115
133
|
}
|
|
116
134
|
const {
|
|
117
135
|
signature,
|
|
118
|
-
|
|
136
|
+
inputSize,
|
|
137
|
+
outputSize
|
|
119
138
|
} = codecStream;
|
|
120
139
|
sendMessage({
|
|
121
140
|
type: MESSAGE_CLOSE,
|
|
122
141
|
result: {
|
|
123
142
|
signature,
|
|
124
|
-
|
|
143
|
+
inputSize,
|
|
144
|
+
outputSize
|
|
125
145
|
}
|
|
126
146
|
});
|
|
127
147
|
} catch (error) {
|
|
@@ -129,6 +149,12 @@ async function init(message) {
|
|
|
129
149
|
}
|
|
130
150
|
}
|
|
131
151
|
|
|
152
|
+
async function imporModuleScripts(scripts) {
|
|
153
|
+
for (const script of scripts) {
|
|
154
|
+
await import(script);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
132
158
|
function sendMessage(message) {
|
|
133
159
|
let { value } = message;
|
|
134
160
|
if (value) {
|
package/lib/core/zip-fs-core.js
CHANGED
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
import {
|
|
53
53
|
Entry
|
|
54
54
|
} from "./zip-entry.js";
|
|
55
|
+
import { UNDEFINED_VALUE } from "./constants.js";
|
|
55
56
|
|
|
56
57
|
class ZipEntry {
|
|
57
58
|
|
|
@@ -433,7 +434,7 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
433
434
|
|
|
434
435
|
async exportZip(writer, options) {
|
|
435
436
|
const zipEntry = this;
|
|
436
|
-
if (options.bufferedWrite ===
|
|
437
|
+
if (options.bufferedWrite === UNDEFINED_VALUE) {
|
|
437
438
|
options.bufferedWrite = true;
|
|
438
439
|
}
|
|
439
440
|
await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -372,7 +372,9 @@ class ZipEntry {
|
|
|
372
372
|
const dataArray = await readUint8Array(reader, offset, 30, diskNumberStart);
|
|
373
373
|
const dataView = getDataView(dataArray);
|
|
374
374
|
let password = getOptionValue(zipEntry, options, "password");
|
|
375
|
+
let rawPassword = getOptionValue(zipEntry, options, "rawPassword");
|
|
375
376
|
password = password && password.length && password;
|
|
377
|
+
rawPassword = rawPassword && rawPassword.length && rawPassword;
|
|
376
378
|
if (extraFieldAES) {
|
|
377
379
|
if (extraFieldAES.originalCompressionMethod != COMPRESSION_METHOD_AES) {
|
|
378
380
|
throw new Error(ERR_UNSUPPORTED_COMPRESSION);
|
|
@@ -398,7 +400,7 @@ class ZipEntry {
|
|
|
398
400
|
if (encrypted) {
|
|
399
401
|
if (!zipCrypto && extraFieldAES.strength === UNDEFINED_VALUE) {
|
|
400
402
|
throw new Error(ERR_UNSUPPORTED_ENCRYPTION);
|
|
401
|
-
} else if (!password) {
|
|
403
|
+
} else if (!password && !rawPassword) {
|
|
402
404
|
throw new Error(ERR_ENCRYPTED);
|
|
403
405
|
}
|
|
404
406
|
}
|
|
@@ -423,6 +425,7 @@ class ZipEntry {
|
|
|
423
425
|
options: {
|
|
424
426
|
codecType: CODEC_INFLATE,
|
|
425
427
|
password,
|
|
428
|
+
rawPassword,
|
|
426
429
|
zipCrypto,
|
|
427
430
|
encryptionStrength: extraFieldAES && extraFieldAES.strength,
|
|
428
431
|
signed: getOptionValue(zipEntry, options, "checkSignature"),
|
|
@@ -452,7 +455,7 @@ class ZipEntry {
|
|
|
452
455
|
await writable.getWriter().close();
|
|
453
456
|
}
|
|
454
457
|
}
|
|
455
|
-
return checkPasswordOnly ?
|
|
458
|
+
return checkPasswordOnly ? UNDEFINED_VALUE : writer.getData ? writer.getData() : writable;
|
|
456
459
|
}
|
|
457
460
|
}
|
|
458
461
|
|