@zip.js/zip.js 2.11.4 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist/zip-core-external.js +549 -139
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +559 -136
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +615 -260
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +628 -257
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +615 -260
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +630 -259
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +631 -260
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +561 -138
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +561 -138
- 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 +562 -139
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +630 -259
- package/index-native.min.js +1 -1
- package/index.cjs +631 -260
- package/index.d.cts +474 -59
- package/index.d.ts +474 -59
- package/index.min.js +1 -1
- package/lib/core/codec-worker-web.js +72 -22
- package/lib/core/codec-worker.js +18 -5
- package/lib/core/configuration.js +20 -5
- package/lib/core/constants.js +2 -0
- package/lib/core/io.js +13 -5
- package/lib/core/options.js +16 -0
- package/lib/core/streams/codec-stream.js +6 -0
- package/lib/core/util/error.js +35 -0
- package/lib/core/util/warnings.js +42 -0
- package/lib/core/version.js +1 -1
- package/lib/core/web-worker-base.js +46 -9
- package/lib/core/web-worker-inline-native.js +1 -1
- package/lib/core/web-worker-inline-wasm.js +1 -1
- package/lib/core/zip-entry.js +49 -1
- package/lib/core/zip-fs.js +45 -133
- package/lib/core/zip-reader.js +115 -52
- package/lib/core/zip-writer.js +244 -57
- package/lib/zip-core-base.js +9 -3
- package/lib/zip-core-reader.js +2 -0
- package/lib/zip-core-writer.js +6 -1
- package/lib/zip-module-wasm-base.js +2 -2
- package/package.json +5 -3
- package/worker-message-property-names.js +1 -1
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
FUNCTION_TYPE
|
|
34
34
|
} from "./constants.js";
|
|
35
35
|
import { toExactUint8Array } from "./util/array.js";
|
|
36
|
+
import { isErrorObject } from "./util/error.js";
|
|
36
37
|
import {
|
|
37
38
|
MESSAGE_EVENT_TYPE,
|
|
38
39
|
MESSAGE_START,
|
|
@@ -121,11 +122,23 @@ async function runWebWorker(workerData, config) {
|
|
|
121
122
|
let resolveResult, rejectResult;
|
|
122
123
|
const result = new Promise((resolve, reject) => {
|
|
123
124
|
resolveResult = resolve;
|
|
124
|
-
rejectResult =
|
|
125
|
+
rejectResult = error => {
|
|
126
|
+
const { outputSize, workerOptions } = workerData;
|
|
127
|
+
workerOptions.outputSize = outputSize;
|
|
128
|
+
if (isErrorObject(error) && error.outputSize === UNDEFINED_VALUE) {
|
|
129
|
+
try {
|
|
130
|
+
error.outputSize = outputSize;
|
|
131
|
+
} catch {
|
|
132
|
+
// ignored
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
reject(error);
|
|
136
|
+
};
|
|
125
137
|
});
|
|
126
138
|
Object.assign(workerData, {
|
|
127
139
|
reader: null,
|
|
128
140
|
writer: null,
|
|
141
|
+
outputSize: 0,
|
|
129
142
|
resolveResult,
|
|
130
143
|
rejectResult,
|
|
131
144
|
result
|
|
@@ -386,21 +399,15 @@ function sendMessage(message, { worker, writer, transferStreams, workerAlive })
|
|
|
386
399
|
}
|
|
387
400
|
|
|
388
401
|
async function onMessage({ data }, workerData) {
|
|
389
|
-
const { type, value, messageId, result, error } = data;
|
|
402
|
+
const { type, value, messageId, result, error, errorValue } = data;
|
|
390
403
|
const { reader, writer, resolveResult, rejectResult, onTaskFinished, generation } = workerData;
|
|
391
404
|
const stale = () => workerData.generation != generation;
|
|
392
405
|
try {
|
|
393
406
|
if (error) {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
Object.assign(responseError, { stack, code, name, outputSize });
|
|
397
|
-
if (cause) {
|
|
398
|
-
responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
|
|
399
|
-
}
|
|
400
|
-
if (codecImportFailed) {
|
|
401
|
-
responseError.codecImportFailed = true;
|
|
407
|
+
if (error.outputSize !== UNDEFINED_VALUE) {
|
|
408
|
+
workerData.outputSize = error.outputSize;
|
|
402
409
|
}
|
|
403
|
-
|
|
410
|
+
fail(getResponseError(error, errorValue));
|
|
404
411
|
} else {
|
|
405
412
|
if (type == MESSAGE_PULL) {
|
|
406
413
|
const { value, done } = await reader.read();
|
|
@@ -409,37 +416,80 @@ async function onMessage({ data }, workerData) {
|
|
|
409
416
|
}
|
|
410
417
|
}
|
|
411
418
|
if (type == MESSAGE_DATA) {
|
|
419
|
+
const chunk = new Uint8Array(value);
|
|
412
420
|
await writer.ready;
|
|
413
|
-
await writer.write(
|
|
421
|
+
await writer.write(chunk);
|
|
422
|
+
workerData.outputSize += chunk.length;
|
|
414
423
|
if (!stale()) {
|
|
415
424
|
sendMessage({ type: MESSAGE_ACK_DATA, messageId }, workerData);
|
|
416
425
|
}
|
|
417
426
|
}
|
|
418
427
|
if (type == MESSAGE_CLOSE) {
|
|
419
|
-
|
|
428
|
+
succeed(result);
|
|
420
429
|
}
|
|
421
430
|
}
|
|
422
431
|
} catch (error) {
|
|
423
432
|
if (!stale()) {
|
|
424
433
|
terminateWorker(workerData);
|
|
425
|
-
|
|
434
|
+
fail(error);
|
|
426
435
|
}
|
|
427
436
|
}
|
|
428
437
|
|
|
429
|
-
function
|
|
430
|
-
if (stale()) {
|
|
431
|
-
return;
|
|
432
|
-
}
|
|
433
|
-
if (error) {
|
|
438
|
+
function fail(error) {
|
|
439
|
+
if (!stale()) {
|
|
434
440
|
rejectResult(error);
|
|
435
|
-
|
|
441
|
+
releaseWriter();
|
|
442
|
+
if (!(isErrorObject(error) && error.codecImportFailed)) {
|
|
443
|
+
onTaskFinished();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function succeed(result) {
|
|
449
|
+
if (!stale()) {
|
|
436
450
|
resolveResult(result);
|
|
451
|
+
releaseWriter();
|
|
452
|
+
onTaskFinished();
|
|
437
453
|
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function releaseWriter() {
|
|
438
457
|
if (writer) {
|
|
439
458
|
writer.releaseLock();
|
|
440
459
|
}
|
|
441
|
-
|
|
442
|
-
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function getResponseError(errorData, errorValue) {
|
|
464
|
+
const { message, stack, code, name, outputSize, cause, codecImportFailed } = errorData;
|
|
465
|
+
let responseError;
|
|
466
|
+
if (errorValue) {
|
|
467
|
+
responseError = errorValue.value;
|
|
468
|
+
} else {
|
|
469
|
+
responseError = Object.assign(new Error(message), { stack, code, name });
|
|
470
|
+
if (cause) {
|
|
471
|
+
responseError.cause = Object.assign(new Error(cause.message), { name: cause.name });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (isErrorObject(responseError)) {
|
|
475
|
+
try {
|
|
476
|
+
if (outputSize !== UNDEFINED_VALUE) {
|
|
477
|
+
responseError.outputSize = outputSize;
|
|
478
|
+
}
|
|
479
|
+
if (codecImportFailed) {
|
|
480
|
+
responseError.codecImportFailed = true;
|
|
481
|
+
}
|
|
482
|
+
if (errorValue) {
|
|
483
|
+
if (responseError.name !== name) {
|
|
484
|
+
responseError.name = name;
|
|
485
|
+
}
|
|
486
|
+
if (responseError.code !== code) {
|
|
487
|
+
responseError.code = code;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
} catch {
|
|
491
|
+
// ignored
|
|
443
492
|
}
|
|
444
493
|
}
|
|
494
|
+
return responseError;
|
|
445
495
|
}
|
package/lib/core/codec-worker.js
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
UNDEFINED_TYPE
|
|
34
34
|
} from "./constants.js";
|
|
35
35
|
import { getChunkSize } from "./configuration.js";
|
|
36
|
+
import { isErrorObject } from "./util/error.js";
|
|
36
37
|
import {
|
|
37
38
|
CODEC_DEFLATE,
|
|
38
39
|
CodecStream,
|
|
@@ -102,7 +103,9 @@ function disableWebWorker(workerData) {
|
|
|
102
103
|
|
|
103
104
|
class CodecWorker {
|
|
104
105
|
|
|
105
|
-
constructor(workerData, { readable, writable },
|
|
106
|
+
constructor(workerData, { readable, writable }, workerOptions, onTaskFinished) {
|
|
107
|
+
const { options, config, streamOptions, useWebWorkers, transferStreams, workerURI } = workerOptions;
|
|
108
|
+
let { createWorker } = workerOptions;
|
|
106
109
|
const { signal } = streamOptions;
|
|
107
110
|
if (createWorkerFailed) {
|
|
108
111
|
createWorker = UNDEFINED_VALUE;
|
|
@@ -115,6 +118,7 @@ class CodecWorker {
|
|
|
115
118
|
.pipeThrough(new ProgressWatcherStream(streamOptions), { signal }),
|
|
116
119
|
writable,
|
|
117
120
|
options: Object.assign({}, options),
|
|
121
|
+
workerOptions,
|
|
118
122
|
workerURI,
|
|
119
123
|
createWorker,
|
|
120
124
|
transferStreams,
|
|
@@ -196,8 +200,8 @@ function createWorkerInterface(workerData, config) {
|
|
|
196
200
|
};
|
|
197
201
|
}
|
|
198
202
|
|
|
199
|
-
async function runWorker({ options, readable, writable, onTaskFinished }, config) {
|
|
200
|
-
let codecStream;
|
|
203
|
+
async function runWorker({ options, readable, writable, onTaskFinished, workerOptions }, config) {
|
|
204
|
+
let codecStream, chunkStream;
|
|
201
205
|
try {
|
|
202
206
|
if (options.compressed && !options.format) {
|
|
203
207
|
const deflate = options.codecType.startsWith(CODEC_DEFLATE);
|
|
@@ -220,9 +224,10 @@ async function runWorker({ options, readable, writable, onTaskFinished }, config
|
|
|
220
224
|
}
|
|
221
225
|
}
|
|
222
226
|
codecStream = new CodecStream(options, config);
|
|
227
|
+
chunkStream = new ChunkStream(getChunkSize(config));
|
|
223
228
|
await readable
|
|
224
229
|
.pipeThrough(codecStream)
|
|
225
|
-
.pipeThrough(
|
|
230
|
+
.pipeThrough(chunkStream)
|
|
226
231
|
.pipeTo(writable, { preventClose: true, preventAbort: true });
|
|
227
232
|
const {
|
|
228
233
|
crc32,
|
|
@@ -236,7 +241,15 @@ async function runWorker({ options, readable, writable, onTaskFinished }, config
|
|
|
236
241
|
};
|
|
237
242
|
} catch (error) {
|
|
238
243
|
if (codecStream) {
|
|
239
|
-
|
|
244
|
+
const outputSize = chunkStream ? chunkStream.outputSize : 0;
|
|
245
|
+
workerOptions.outputSize = outputSize;
|
|
246
|
+
if (isErrorObject(error)) {
|
|
247
|
+
try {
|
|
248
|
+
error.outputSize = outputSize;
|
|
249
|
+
} catch {
|
|
250
|
+
// ignored
|
|
251
|
+
}
|
|
252
|
+
}
|
|
240
253
|
}
|
|
241
254
|
throw error;
|
|
242
255
|
} finally {
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
|
|
31
31
|
import {
|
|
32
32
|
UNDEFINED_VALUE,
|
|
33
|
-
UNDEFINED_TYPE
|
|
33
|
+
UNDEFINED_TYPE,
|
|
34
|
+
FUNCTION_TYPE,
|
|
35
|
+
STRING_TYPE
|
|
34
36
|
} from "./constants.js";
|
|
35
37
|
import {
|
|
36
38
|
checkFunctionOption,
|
|
@@ -41,6 +43,8 @@ const DEFAULT_CHUNK_SIZE = 64 * 1024;
|
|
|
41
43
|
const MINIMUM_CHUNK_SIZE = 64;
|
|
42
44
|
const MINIMUM_PROPERTY_VALUE = 1;
|
|
43
45
|
const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
|
|
46
|
+
const ERR_INVALID_BASE_URI = "Invalid baseURI (must be a string)";
|
|
47
|
+
const ERR_INVALID_URI = "Invalid URI (must be a string or a function returning a string)";
|
|
44
48
|
let maxWorkers = 2;
|
|
45
49
|
try {
|
|
46
50
|
if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
|
|
@@ -65,9 +69,9 @@ const DEFAULT_CONFIGURATION = {
|
|
|
65
69
|
};
|
|
66
70
|
|
|
67
71
|
const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
|
|
72
|
+
const PROPERTY_NAME_BASE_URI = "baseURI";
|
|
68
73
|
|
|
69
|
-
const
|
|
70
|
-
"baseURI",
|
|
74
|
+
const URI_PROPERTY_NAMES = [
|
|
71
75
|
"wasmURI",
|
|
72
76
|
"workerURI"
|
|
73
77
|
];
|
|
@@ -91,7 +95,8 @@ const FUNCTION_PROPERTY_NAMES = [
|
|
|
91
95
|
"DecompressionStreamFallback"
|
|
92
96
|
];
|
|
93
97
|
const CONFIGURABLE_PROPERTY_NAMES = [
|
|
94
|
-
|
|
98
|
+
PROPERTY_NAME_BASE_URI,
|
|
99
|
+
...URI_PROPERTY_NAMES,
|
|
95
100
|
...BOOLEAN_PROPERTY_NAMES,
|
|
96
101
|
...NUMBER_PROPERTY_NAMES,
|
|
97
102
|
...FUNCTION_PROPERTY_NAMES
|
|
@@ -106,7 +111,9 @@ export {
|
|
|
106
111
|
getConfiguration,
|
|
107
112
|
getChunkSize,
|
|
108
113
|
normalizeChunkSize,
|
|
109
|
-
ERR_INVALID_MAX_WORKERS
|
|
114
|
+
ERR_INVALID_MAX_WORKERS,
|
|
115
|
+
ERR_INVALID_BASE_URI,
|
|
116
|
+
ERR_INVALID_URI
|
|
110
117
|
};
|
|
111
118
|
|
|
112
119
|
function getConfiguration() {
|
|
@@ -145,6 +152,14 @@ function checkPropertyValue(propertyName, propertyValue) {
|
|
|
145
152
|
}
|
|
146
153
|
} else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
|
|
147
154
|
checkFunctionOption(propertyValue);
|
|
155
|
+
} else if (propertyName == PROPERTY_NAME_BASE_URI) {
|
|
156
|
+
if (propertyValue && typeof propertyValue != STRING_TYPE) {
|
|
157
|
+
throw new Error(ERR_INVALID_BASE_URI);
|
|
158
|
+
}
|
|
159
|
+
} else if (URI_PROPERTY_NAMES.includes(propertyName)) {
|
|
160
|
+
if (propertyValue && typeof propertyValue != STRING_TYPE && typeof propertyValue != FUNCTION_TYPE) {
|
|
161
|
+
throw new Error(ERR_INVALID_URI);
|
|
162
|
+
}
|
|
148
163
|
}
|
|
149
164
|
return propertyValue;
|
|
150
165
|
}
|
package/lib/core/constants.js
CHANGED
|
@@ -125,9 +125,11 @@ const NUMBER_TYPE = "number";
|
|
|
125
125
|
const BOOLEAN_TYPE = "boolean";
|
|
126
126
|
|
|
127
127
|
const EMPTY_UINT8_ARRAY = new Uint8Array();
|
|
128
|
+
const SYMBOL_ASYNC_DISPOSE = Symbol.asyncDispose || Symbol();
|
|
128
129
|
|
|
129
130
|
export {
|
|
130
131
|
EMPTY_UINT8_ARRAY,
|
|
132
|
+
SYMBOL_ASYNC_DISPOSE,
|
|
131
133
|
MAX_32_BITS,
|
|
132
134
|
MAX_16_BITS,
|
|
133
135
|
MAX_8_BITS,
|
package/lib/core/io.js
CHANGED
|
@@ -42,10 +42,13 @@ import { toCompatibleReadable, toCompatibleWritable, streamToBlob } from "./util
|
|
|
42
42
|
import { decodeTextRemovingBOM } from "./util/decode-text.js";
|
|
43
43
|
|
|
44
44
|
const ERR_HTTP_STATUS = "HTTP error ";
|
|
45
|
+
const MIN_SUCCESS_HTTP_STATUS = 200;
|
|
46
|
+
const MAX_SUCCESS_HTTP_STATUS = 299;
|
|
45
47
|
const ERR_HTTP_RANGE = "HTTP Range not supported";
|
|
46
48
|
const ERR_HTTP_RESOURCE_CHANGED = "HTTP resource changed";
|
|
47
49
|
const ERR_ITERATOR_COMPLETED_TOO_SOON = "Writer iterator completed too soon";
|
|
48
50
|
const ERR_WRITER_NOT_INITIALIZED = "Writer not initialized";
|
|
51
|
+
const ERR_WRITER_SIZE_NOT_WRITABLE = "Invalid writer (size must be writable)";
|
|
49
52
|
|
|
50
53
|
const CONTENT_TYPE_TEXT_PLAIN = "text/plain";
|
|
51
54
|
const HTTP_HEADER_CONTENT_LENGTH = "Content-Length";
|
|
@@ -237,6 +240,7 @@ class BlobReader extends Reader {
|
|
|
237
240
|
const reader = this;
|
|
238
241
|
const { sourceBlob, size } = reader;
|
|
239
242
|
const { offset = 0, size: readSize = size - offset } = options || {};
|
|
243
|
+
// deno-lint-ignore valid-typeof
|
|
240
244
|
if (typeof sourceBlob.stream == FUNCTION_TYPE) {
|
|
241
245
|
if (!offset && readSize >= size) {
|
|
242
246
|
return toCompatibleReadable(sourceBlob.stream());
|
|
@@ -643,7 +647,7 @@ async function getContentLength(httpReader, sendRequest, getRequestData) {
|
|
|
643
647
|
|
|
644
648
|
async function sendFetchRequest(method, { fetch: fetchFunction = fetch, options, url }, headers) {
|
|
645
649
|
const response = await fetchFunction(url, Object.assign({}, options, { method, headers }));
|
|
646
|
-
if (response.status
|
|
650
|
+
if (response.status >= MIN_SUCCESS_HTTP_STATUS && response.status <= MAX_SUCCESS_HTTP_STATUS) {
|
|
647
651
|
return response;
|
|
648
652
|
} else {
|
|
649
653
|
throw response.status == 416 ? new Error(ERR_HTTP_RANGE) : new Error(ERR_HTTP_STATUS + (response.statusText || response.status));
|
|
@@ -654,7 +658,7 @@ function sendXMLHttpRequest(method, { url }, headers) {
|
|
|
654
658
|
return new Promise((resolve, reject) => {
|
|
655
659
|
const request = new XMLHttpRequest();
|
|
656
660
|
request.addEventListener("load", () => {
|
|
657
|
-
if (request.status
|
|
661
|
+
if (request.status >= MIN_SUCCESS_HTTP_STATUS && request.status <= MAX_SUCCESS_HTTP_STATUS) {
|
|
658
662
|
const headers = [];
|
|
659
663
|
request.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(header => {
|
|
660
664
|
const splitHeader = header.trim().split(/\s*:\s*/);
|
|
@@ -958,8 +962,10 @@ class GenericWriter {
|
|
|
958
962
|
writable: toCompatibleWritable(writer)
|
|
959
963
|
};
|
|
960
964
|
}
|
|
961
|
-
|
|
962
|
-
writer.size = 0;
|
|
965
|
+
try {
|
|
966
|
+
writer.size = writer.size === UNDEFINED_VALUE ? 0 : writer.size;
|
|
967
|
+
} catch {
|
|
968
|
+
throw new Error(ERR_WRITER_SIZE_NOT_WRITABLE);
|
|
963
969
|
}
|
|
964
970
|
return writer;
|
|
965
971
|
}
|
|
@@ -1030,7 +1036,9 @@ export {
|
|
|
1030
1036
|
SplitDataReader,
|
|
1031
1037
|
SplitDataWriter,
|
|
1032
1038
|
ERR_HTTP_RANGE,
|
|
1039
|
+
ERR_HTTP_STATUS,
|
|
1033
1040
|
ERR_HTTP_RESOURCE_CHANGED,
|
|
1034
1041
|
ERR_ITERATOR_COMPLETED_TOO_SOON,
|
|
1035
|
-
ERR_WRITER_NOT_INITIALIZED
|
|
1042
|
+
ERR_WRITER_NOT_INITIALIZED,
|
|
1043
|
+
ERR_WRITER_SIZE_NOT_WRITABLE
|
|
1036
1044
|
};
|
package/lib/core/options.js
CHANGED
|
@@ -49,6 +49,7 @@ const OPTION_CHECK_OVERLAPPING_ENTRY_ONLY = "checkOverlappingEntryOnly";
|
|
|
49
49
|
const OPTION_CHECK_OVERLAPPING_ENTRY = "checkOverlappingEntry";
|
|
50
50
|
const OPTION_CHECK_AMBIGUITY = "checkAmbiguity";
|
|
51
51
|
const OPTION_CHECK_LOCAL_DIRECTORY = "checkLocalDirectory";
|
|
52
|
+
const OPTION_CHECK_LOCAL_FILENAME = "checkLocalFilename";
|
|
52
53
|
const OPTION_CHECK_SIGNATURE = "checkSignature";
|
|
53
54
|
const OPTION_CHECK_CRC32 = "checkCrc32";
|
|
54
55
|
const OPTION_CHECK_AUTHENTICATION_CODE = "checkAuthenticationCode";
|
|
@@ -79,15 +80,18 @@ const OPTION_NORMALIZE_FILENAME = "normalizeFilename";
|
|
|
79
80
|
const OPTION_MAX_APPENDED_DATA_SIZE = "maxAppendedDataSize";
|
|
80
81
|
const OPTION_DECRYPT_CENTRAL_DIRECTORY = "decryptCentralDirectory";
|
|
81
82
|
const OPTION_SIGN_CENTRAL_DIRECTORY = "signCentralDirectory";
|
|
83
|
+
const OPTION_ENTRY = "entry";
|
|
82
84
|
const TEXT_TYPE_FILENAME = "filename";
|
|
83
85
|
const TEXT_TYPE_COMMENT = "comment";
|
|
84
86
|
const STRICTNESS_STRICT = "strict";
|
|
85
87
|
const STRICTNESS_BALANCED = "balanced";
|
|
86
88
|
const STRICTNESS_TOLERANT = "tolerant";
|
|
89
|
+
const PASS_THROUGH_COMPRESSED = "compressed";
|
|
87
90
|
|
|
88
91
|
const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
|
|
89
92
|
const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
|
|
90
93
|
const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
|
|
94
|
+
const ERR_INVALID_PASS_THROUGH_VALUE = "Invalid passThrough option (must be a boolean or 'compressed')";
|
|
91
95
|
const ERR_ABORTED = "The operation was aborted";
|
|
92
96
|
const ABORT_ERROR_NAME = "AbortError";
|
|
93
97
|
|
|
@@ -106,6 +110,7 @@ export {
|
|
|
106
110
|
OPTION_CHECK_OVERLAPPING_ENTRY,
|
|
107
111
|
OPTION_CHECK_AMBIGUITY,
|
|
108
112
|
OPTION_CHECK_LOCAL_DIRECTORY,
|
|
113
|
+
OPTION_CHECK_LOCAL_FILENAME,
|
|
109
114
|
OPTION_CHECK_SIGNATURE,
|
|
110
115
|
OPTION_CHECK_CRC32,
|
|
111
116
|
OPTION_CHECK_AUTHENTICATION_CODE,
|
|
@@ -136,20 +141,24 @@ export {
|
|
|
136
141
|
OPTION_MAX_APPENDED_DATA_SIZE,
|
|
137
142
|
OPTION_DECRYPT_CENTRAL_DIRECTORY,
|
|
138
143
|
OPTION_SIGN_CENTRAL_DIRECTORY,
|
|
144
|
+
OPTION_ENTRY,
|
|
139
145
|
TEXT_TYPE_FILENAME,
|
|
140
146
|
TEXT_TYPE_COMMENT,
|
|
141
147
|
STRICTNESS_STRICT,
|
|
142
148
|
STRICTNESS_BALANCED,
|
|
143
149
|
STRICTNESS_TOLERANT,
|
|
150
|
+
PASS_THROUGH_COMPRESSED,
|
|
144
151
|
ERR_INVALID_FUNCTION_OPTION,
|
|
145
152
|
ERR_INVALID_SIGNAL,
|
|
146
153
|
ERR_INVALID_PASSWORD_TYPE,
|
|
154
|
+
ERR_INVALID_PASS_THROUGH_VALUE,
|
|
147
155
|
ERR_ABORTED,
|
|
148
156
|
ABORT_ERROR_NAME,
|
|
149
157
|
checkFunctionOption,
|
|
150
158
|
checkSignalOption,
|
|
151
159
|
throwIfAborted,
|
|
152
160
|
checkPasswordOption,
|
|
161
|
+
checkPassThroughOption,
|
|
153
162
|
checkInteger,
|
|
154
163
|
checkIntegerOption,
|
|
155
164
|
toNumber
|
|
@@ -181,6 +190,13 @@ function checkPasswordOption(password, rawPassword) {
|
|
|
181
190
|
}
|
|
182
191
|
}
|
|
183
192
|
|
|
193
|
+
function checkPassThroughOption(passThrough) {
|
|
194
|
+
if (passThrough !== UNDEFINED_VALUE && typeof passThrough != BOOLEAN_TYPE && passThrough !== PASS_THROUGH_COMPRESSED) {
|
|
195
|
+
throw new Error(ERR_INVALID_PASS_THROUGH_VALUE);
|
|
196
|
+
}
|
|
197
|
+
return passThrough;
|
|
198
|
+
}
|
|
199
|
+
|
|
184
200
|
function checkInteger(value, maxValue, errorMessage) {
|
|
185
201
|
if (!Number.isInteger(value) || value < 0 || value > maxValue) {
|
|
186
202
|
throw new Error(errorMessage);
|
|
@@ -145,6 +145,7 @@ class ChunkStream extends TransformStream {
|
|
|
145
145
|
constructor(chunkSize) {
|
|
146
146
|
const pendingChunks = [];
|
|
147
147
|
let pendingLength = 0;
|
|
148
|
+
let outputSize = 0;
|
|
148
149
|
if (!Number.isFinite(chunkSize) || chunkSize < 1) {
|
|
149
150
|
chunkSize = DEFAULT_CHUNK_SIZE;
|
|
150
151
|
}
|
|
@@ -153,15 +154,20 @@ class ChunkStream extends TransformStream {
|
|
|
153
154
|
pendingChunks.push(chunk);
|
|
154
155
|
pendingLength += chunk.length;
|
|
155
156
|
while (pendingLength > chunkSize) {
|
|
157
|
+
outputSize += chunkSize;
|
|
156
158
|
controller.enqueue(shiftChunk());
|
|
157
159
|
}
|
|
158
160
|
},
|
|
159
161
|
flush(controller) {
|
|
160
162
|
if (pendingLength) {
|
|
163
|
+
outputSize += pendingLength;
|
|
161
164
|
controller.enqueue(concatChunks(pendingChunks, pendingLength));
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
});
|
|
168
|
+
Object.defineProperty(this, "outputSize", {
|
|
169
|
+
get: () => outputSize
|
|
170
|
+
});
|
|
165
171
|
|
|
166
172
|
function shiftChunk() {
|
|
167
173
|
const result = new Uint8Array(chunkSize);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2026 Gildas Lormeau. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
|
+
the documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. The names of the authors may not be used to endorse or promote products
|
|
15
|
+
derived from this software without specific prior written permission.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
18
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
|
20
|
+
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
22
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
23
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
24
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
isErrorObject
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function isErrorObject(error) {
|
|
34
|
+
return Boolean(error) && typeof error == "object";
|
|
35
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (c) 2026 Gildas Lormeau. All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
8
|
+
this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
|
+
the documentation and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. The names of the authors may not be used to endorse or promote products
|
|
15
|
+
derived from this software without specific prior written permission.
|
|
16
|
+
|
|
17
|
+
THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
|
18
|
+
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
|
20
|
+
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
21
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
22
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
23
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
24
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
25
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
import { UNDEFINED_VALUE } from "../constants.js";
|
|
31
|
+
|
|
32
|
+
export { addWarning };
|
|
33
|
+
|
|
34
|
+
function addWarning(warnings, reason, filename) {
|
|
35
|
+
if (!warnings.some(warning => warning.reason == reason)) {
|
|
36
|
+
const warning = { reason };
|
|
37
|
+
if (filename !== UNDEFINED_VALUE) {
|
|
38
|
+
warning.filename = filename;
|
|
39
|
+
}
|
|
40
|
+
warnings.push(warning);
|
|
41
|
+
}
|
|
42
|
+
}
|
package/lib/core/version.js
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
/* global self, addEventListener, postMessage, ReadableStream, WritableStream, AbortController */
|
|
31
|
+
/* global self, addEventListener, postMessage, ReadableStream, WritableStream, AbortController, structuredClone */
|
|
32
32
|
|
|
33
33
|
import {
|
|
34
34
|
CODEC_DEFLATE,
|
|
@@ -46,10 +46,13 @@ import {
|
|
|
46
46
|
import { getChunkSize } from "./configuration.js";
|
|
47
47
|
import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-streams.js";
|
|
48
48
|
import { toExactUint8Array } from "./util/array.js";
|
|
49
|
+
import { isErrorObject } from "./util/error.js";
|
|
50
|
+
import { UNDEFINED_VALUE } from "./constants.js";
|
|
49
51
|
import { ensureCodecStreams } from "./codec-registry.js";
|
|
50
52
|
|
|
51
53
|
const pendingPullMessages = new Map();
|
|
52
54
|
const pendingDataMessages = new Map();
|
|
55
|
+
const errorValueSerializable = testErrorValueSerializable();
|
|
53
56
|
|
|
54
57
|
let abortController, messageId = 0;
|
|
55
58
|
|
|
@@ -99,14 +102,20 @@ addEventListener(MESSAGE_EVENT_TYPE, ({ data }) => {
|
|
|
99
102
|
postMessage({ type: MESSAGE_READY });
|
|
100
103
|
|
|
101
104
|
async function init(message) {
|
|
102
|
-
let codecStream, writable;
|
|
105
|
+
let codecStream, chunkStream, writable;
|
|
103
106
|
try {
|
|
104
107
|
const { options, config } = message;
|
|
105
108
|
if (options.format) {
|
|
106
109
|
try {
|
|
107
110
|
await ensureCodecStreams(options.format, options.codecURI);
|
|
108
111
|
} catch (error) {
|
|
109
|
-
error
|
|
112
|
+
if (isErrorObject(error)) {
|
|
113
|
+
try {
|
|
114
|
+
error.codecImportFailed = true;
|
|
115
|
+
} catch {
|
|
116
|
+
// ignored
|
|
117
|
+
}
|
|
118
|
+
}
|
|
110
119
|
throw error;
|
|
111
120
|
}
|
|
112
121
|
}
|
|
@@ -162,11 +171,12 @@ async function init(message) {
|
|
|
162
171
|
}
|
|
163
172
|
}, strategy);
|
|
164
173
|
codecStream = new CodecStream(options, config);
|
|
174
|
+
chunkStream = new ChunkStream(getChunkSize(config));
|
|
165
175
|
abortController = new AbortController();
|
|
166
176
|
const { signal } = abortController;
|
|
167
177
|
await readable
|
|
168
178
|
.pipeThrough(codecStream)
|
|
169
|
-
.pipeThrough(
|
|
179
|
+
.pipeThrough(chunkStream)
|
|
170
180
|
.pipeTo(writable, { signal, preventClose: true, preventAbort: true });
|
|
171
181
|
await writable.getWriter().close();
|
|
172
182
|
const {
|
|
@@ -183,7 +193,14 @@ async function init(message) {
|
|
|
183
193
|
}
|
|
184
194
|
});
|
|
185
195
|
} catch (error) {
|
|
186
|
-
|
|
196
|
+
const outputSize = chunkStream ? chunkStream.outputSize : 0;
|
|
197
|
+
if (isErrorObject(error)) {
|
|
198
|
+
try {
|
|
199
|
+
error.outputSize = outputSize;
|
|
200
|
+
} catch {
|
|
201
|
+
// ignored
|
|
202
|
+
}
|
|
203
|
+
}
|
|
187
204
|
if (writable && !writable.locked) {
|
|
188
205
|
try {
|
|
189
206
|
await writable.getWriter().close();
|
|
@@ -191,7 +208,7 @@ async function init(message) {
|
|
|
191
208
|
// ignored
|
|
192
209
|
}
|
|
193
210
|
}
|
|
194
|
-
sendErrorMessage(error);
|
|
211
|
+
sendErrorMessage(error, outputSize);
|
|
195
212
|
}
|
|
196
213
|
}
|
|
197
214
|
|
|
@@ -213,14 +230,34 @@ function sendMessage(message) {
|
|
|
213
230
|
}
|
|
214
231
|
}
|
|
215
232
|
|
|
216
|
-
function sendErrorMessage(
|
|
217
|
-
const { message, stack, code, name, outputSize, cause, codecImportFailed } =
|
|
218
|
-
const errorData = { message, stack, code, name, outputSize };
|
|
233
|
+
function sendErrorMessage(errorValue, writtenSize) {
|
|
234
|
+
const { message, stack, code, name, outputSize, cause, codecImportFailed } = getErrorObject(errorValue);
|
|
235
|
+
const errorData = { message, stack, code, name, outputSize: outputSize === UNDEFINED_VALUE ? writtenSize : outputSize };
|
|
219
236
|
if (cause) {
|
|
220
237
|
errorData.cause = { name: cause.name, message: cause.message };
|
|
221
238
|
}
|
|
222
239
|
if (codecImportFailed) {
|
|
223
240
|
errorData.codecImportFailed = true;
|
|
224
241
|
}
|
|
242
|
+
if (errorValueSerializable) {
|
|
243
|
+
try {
|
|
244
|
+
postMessage({ error: errorData, errorValue: { value: errorValue } });
|
|
245
|
+
return;
|
|
246
|
+
} catch {
|
|
247
|
+
// ignored
|
|
248
|
+
}
|
|
249
|
+
}
|
|
225
250
|
postMessage({ error: errorData });
|
|
226
251
|
}
|
|
252
|
+
|
|
253
|
+
function getErrorObject(error = new Error("Unknown error")) {
|
|
254
|
+
return isErrorObject(error) ? error : new Error(String(error));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function testErrorValueSerializable() {
|
|
258
|
+
try {
|
|
259
|
+
return structuredClone(new Error()) instanceof Error;
|
|
260
|
+
} catch {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|