@zip.js/zip.js 2.8.53 → 2.8.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +1 -1
  2. package/deno.json +2 -1
  3. package/dist/zip-core-external.js +737 -491
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +745 -490
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +776 -525
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +738 -510
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +776 -525
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +790 -525
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +791 -526
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +746 -491
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +746 -491
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip-web-worker-native.js +1 -1
  22. package/dist/zip-web-worker.js +1 -1
  23. package/dist/zip.js +747 -492
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +1 -0
  26. package/index-native.cjs +790 -525
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +791 -526
  29. package/index.d.cts +422 -49
  30. package/index.d.ts +422 -49
  31. package/index.min.js +1 -1
  32. package/lib/core/configuration.js +62 -21
  33. package/lib/core/constants.js +13 -1
  34. package/lib/core/io.js +33 -27
  35. package/lib/core/options.js +44 -2
  36. package/lib/core/streams/aes-crypto-stream.js +12 -12
  37. package/lib/core/util/decode-text.js +11 -2
  38. package/lib/core/web-worker-base.js +3 -2
  39. package/lib/core/web-worker-inline-native.js +1 -1
  40. package/lib/core/web-worker-inline-wasm.js +1 -1
  41. package/lib/core/zip-fs.js +39 -32
  42. package/lib/core/zip-reader.js +100 -38
  43. package/lib/core/zip-writer.js +301 -177
  44. package/lib/core/zlib-streams-inline.js +1 -1
  45. package/lib/zip-core-base.js +6 -1
  46. package/lib/zip-core-reader.js +1 -0
  47. package/lib/zip-core-writer.js +5 -0
  48. package/package.json +8 -2
@@ -32,8 +32,15 @@ import {
32
32
  UNDEFINED_VALUE,
33
33
  UNDEFINED_TYPE
34
34
  } from "./constants.js";
35
+ import {
36
+ checkFunctionOption,
37
+ toNumber
38
+ } from "./options.js";
35
39
 
40
+ const DEFAULT_CHUNK_SIZE = 64 * 1024;
36
41
  const MINIMUM_CHUNK_SIZE = 64;
42
+ const MINIMUM_PROPERTY_VALUE = 1;
43
+ const ERR_INVALID_MAX_WORKERS = "Invalid maxWorkers (must be an integer greater than 0)";
37
44
  let maxWorkers = 2;
38
45
  try {
39
46
  if (typeof navigator != UNDEFINED_TYPE && navigator.hardwareConcurrency) {
@@ -45,7 +52,7 @@ try {
45
52
  const DEFAULT_CONFIGURATION = {
46
53
  workerURI: "./core/web-worker-wasm.js",
47
54
  wasmURI: "./core/streams/zlib-wasm/zlib-streams.wasm",
48
- chunkSize: 64 * 1024,
55
+ chunkSize: DEFAULT_CHUNK_SIZE,
49
56
  maxWorkers,
50
57
  terminateWorkerTimeout: 5000,
51
58
  workerStarvationTimeout: 5000,
@@ -57,24 +64,38 @@ const DEFAULT_CONFIGURATION = {
57
64
  DecompressionStream: typeof DecompressionStream != UNDEFINED_TYPE && DecompressionStream
58
65
  };
59
66
 
60
- const CONFIGURABLE_PROPERTY_NAMES = [
67
+ const PROPERTY_NAME_MAX_WORKERS = "maxWorkers";
68
+
69
+ const STRING_PROPERTY_NAMES = [
61
70
  "baseURI",
62
71
  "wasmURI",
63
- "workerURI",
64
- "createWorker",
72
+ "workerURI"
73
+ ];
74
+ const BOOLEAN_PROPERTY_NAMES = [
75
+ "useCompressionStream",
76
+ "useWebWorkers",
77
+ "transferStreams"
78
+ ];
79
+ const NUMBER_PROPERTY_NAMES = [
65
80
  "chunkSize",
66
- "maxWorkers",
81
+ PROPERTY_NAME_MAX_WORKERS,
67
82
  "terminateWorkerTimeout",
68
83
  "workerStarvationTimeout",
69
- "workerStartupTimeout",
70
- "useCompressionStream",
71
- "useWebWorkers",
72
- "transferStreams",
84
+ "workerStartupTimeout"
85
+ ];
86
+ const FUNCTION_PROPERTY_NAMES = [
87
+ "createWorker",
73
88
  "CompressionStream",
74
89
  "DecompressionStream",
75
90
  "CompressionStreamFallback",
76
91
  "DecompressionStreamFallback"
77
92
  ];
93
+ const CONFIGURABLE_PROPERTY_NAMES = [
94
+ ...STRING_PROPERTY_NAMES,
95
+ ...BOOLEAN_PROPERTY_NAMES,
96
+ ...NUMBER_PROPERTY_NAMES,
97
+ ...FUNCTION_PROPERTY_NAMES
98
+ ];
78
99
 
79
100
  const config = { ...DEFAULT_CONFIGURATION };
80
101
 
@@ -83,7 +104,9 @@ export {
83
104
  setDefaultConfiguration,
84
105
  resetConfiguration,
85
106
  getConfiguration,
86
- getChunkSize
107
+ getChunkSize,
108
+ normalizeChunkSize,
109
+ ERR_INVALID_MAX_WORKERS
87
110
  };
88
111
 
89
112
  function getConfiguration() {
@@ -91,20 +114,43 @@ function getConfiguration() {
91
114
  }
92
115
 
93
116
  function getChunkSize(config) {
94
- return Math.max(config.chunkSize, MINIMUM_CHUNK_SIZE);
117
+ return normalizeChunkSize(config.chunkSize);
118
+ }
119
+
120
+ function normalizeChunkSize(chunkSize) {
121
+ chunkSize = toNumber(chunkSize);
122
+ return Number.isInteger(chunkSize) && chunkSize >= MINIMUM_PROPERTY_VALUE ? Math.max(chunkSize, MINIMUM_CHUNK_SIZE) : DEFAULT_CHUNK_SIZE;
95
123
  }
96
124
 
97
125
  function configure(configuration) {
98
- configuration = normalizeConfiguration(configuration);
126
+ Object.assign(config, checkConfiguration(normalizeConfiguration(configuration)));
127
+ }
128
+
129
+ function checkConfiguration(configuration) {
130
+ const checkedConfiguration = {};
99
131
  for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
100
132
  const propertyValue = configuration[propertyName];
101
133
  if (propertyValue !== UNDEFINED_VALUE) {
102
- config[propertyName] = propertyValue;
134
+ checkedConfiguration[propertyName] = checkPropertyValue(propertyName, propertyValue);
103
135
  }
104
136
  }
137
+ return checkedConfiguration;
138
+ }
139
+
140
+ function checkPropertyValue(propertyName, propertyValue) {
141
+ if (NUMBER_PROPERTY_NAMES.includes(propertyName)) {
142
+ propertyValue = toNumber(propertyValue);
143
+ if (propertyName == PROPERTY_NAME_MAX_WORKERS && (!Number.isInteger(propertyValue) || propertyValue < MINIMUM_PROPERTY_VALUE)) {
144
+ throw new Error(ERR_INVALID_MAX_WORKERS);
145
+ }
146
+ } else if (FUNCTION_PROPERTY_NAMES.includes(propertyName)) {
147
+ checkFunctionOption(propertyValue);
148
+ }
149
+ return propertyValue;
105
150
  }
106
151
 
107
152
  function normalizeConfiguration(configuration) {
153
+ configuration = configuration || {};
108
154
  const { CompressionStreamZlib, DecompressionStreamZlib } = configuration;
109
155
  if (CompressionStreamZlib === UNDEFINED_VALUE && DecompressionStreamZlib === UNDEFINED_VALUE) {
110
156
  return configuration;
@@ -120,14 +166,9 @@ function normalizeConfiguration(configuration) {
120
166
  }
121
167
 
122
168
  function setDefaultConfiguration(configuration) {
123
- configuration = normalizeConfiguration(configuration);
124
- for (const propertyName of CONFIGURABLE_PROPERTY_NAMES) {
125
- const propertyValue = configuration[propertyName];
126
- if (propertyValue !== UNDEFINED_VALUE) {
127
- DEFAULT_CONFIGURATION[propertyName] = propertyValue;
128
- }
129
- }
130
- configure(configuration);
169
+ const checkedConfiguration = checkConfiguration(normalizeConfiguration(configuration));
170
+ Object.assign(DEFAULT_CONFIGURATION, checkedConfiguration);
171
+ Object.assign(config, checkedConfiguration);
131
172
  }
132
173
 
133
174
  function resetConfiguration() {
@@ -36,6 +36,7 @@ const COMPRESSION_METHOD_AES = 0x63;
36
36
 
37
37
  const LOCAL_FILE_HEADER_SIGNATURE = 0x04034b50;
38
38
  const SPLIT_ZIP_FILE_SIGNATURE = 0x08074b50;
39
+ const TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE = 0x30304b50;
39
40
  const DATA_DESCRIPTOR_RECORD_SIGNATURE = SPLIT_ZIP_FILE_SIGNATURE;
40
41
  const ARCHIVE_EXTRA_DATA_SIGNATURE = 0x08064b50;
41
42
  const DIGITAL_SIGNATURE_RECORD_SIGNATURE = 0x05054b50;
@@ -52,6 +53,7 @@ const ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH = END_OF_CENTRAL_DIR_LENGTH + ZIP64_
52
53
  const DATA_DESCRIPTOR_RECORD_LENGTH = 12;
53
54
  const DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH = 20;
54
55
  const DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH = 4;
56
+ const SPLIT_ZIP_FILE_SIGNATURE_LENGTH = 4;
55
57
 
56
58
  const EXTRAFIELD_TYPE_ZIP64 = 0x0001;
57
59
  const EXTRAFIELD_TYPE_AES = 0x9901;
@@ -74,6 +76,7 @@ const BITFLAG_LEVEL_SUPER_FAST_MASK = 0b110;
74
76
  const BITFLAG_DATA_DESCRIPTOR = 0b1000;
75
77
  const BITFLAG_STRONG_ENCRYPTION = 0b1000000;
76
78
  const BITFLAG_LANG_ENCODING_FLAG = 0b100000000000;
79
+ const BITFLAG_MASKED_LOCAL_HEADERS = 0b10000000000000;
77
80
  const FILE_ATTR_MSDOS_DIR_MASK = 0b10000;
78
81
  const FILE_ATTR_MSDOS_READONLY_MASK = 0x01;
79
82
  const FILE_ATTR_MSDOS_HIDDEN_MASK = 0x02;
@@ -103,6 +106,8 @@ const HEADER_OFFSET_VERSION = 0;
103
106
  const HEADER_OFFSET_SIGNATURE = 10;
104
107
  const HEADER_OFFSET_COMPRESSED_SIZE = 14;
105
108
  const HEADER_OFFSET_UNCOMPRESSED_SIZE = 18;
109
+ const HEADER_OFFSET_FILENAME_LENGTH = 22;
110
+ const HEADER_OFFSET_EXTRAFIELD_LENGTH = 24;
106
111
  const LOCAL_HEADER_COMMON_OFFSET = 4;
107
112
 
108
113
  const MAX_DATE = new Date(2107, 11, 31, 23, 59, 58);
@@ -115,6 +120,7 @@ const FUNCTION_TYPE = "function";
115
120
  const OBJECT_TYPE = "object";
116
121
  const STRING_TYPE = "string";
117
122
  const NUMBER_TYPE = "number";
123
+ const BOOLEAN_TYPE = "boolean";
118
124
 
119
125
  const EMPTY_UINT8_ARRAY = new Uint8Array();
120
126
 
@@ -128,6 +134,7 @@ export {
128
134
  COMPRESSION_METHOD_STORE,
129
135
  COMPRESSION_METHOD_AES,
130
136
  SPLIT_ZIP_FILE_SIGNATURE,
137
+ TEMPORARY_SPLIT_ZIP_FILE_SIGNATURE,
131
138
  ARCHIVE_EXTRA_DATA_SIGNATURE,
132
139
  DIGITAL_SIGNATURE_RECORD_SIGNATURE,
133
140
  LOCAL_FILE_HEADER_SIGNATURE,
@@ -140,6 +147,7 @@ export {
140
147
  DATA_DESCRIPTOR_RECORD_LENGTH,
141
148
  DATA_DESCRIPTOR_RECORD_ZIP_64_LENGTH,
142
149
  DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH,
150
+ SPLIT_ZIP_FILE_SIGNATURE_LENGTH,
143
151
  EXTRAFIELD_TYPE_ZIP64,
144
152
  EXTRAFIELD_TYPE_AES,
145
153
  EXTRAFIELD_TYPE_NTFS,
@@ -164,6 +172,7 @@ export {
164
172
  BITFLAG_DATA_DESCRIPTOR,
165
173
  BITFLAG_STRONG_ENCRYPTION,
166
174
  BITFLAG_LANG_ENCODING_FLAG,
175
+ BITFLAG_MASKED_LOCAL_HEADERS,
167
176
  FILE_ATTR_MSDOS_DIR_MASK,
168
177
  FILE_ATTR_MSDOS_READONLY_MASK,
169
178
  FILE_ATTR_MSDOS_HIDDEN_MASK,
@@ -188,6 +197,8 @@ export {
188
197
  HEADER_OFFSET_SIGNATURE,
189
198
  HEADER_OFFSET_COMPRESSED_SIZE,
190
199
  HEADER_OFFSET_UNCOMPRESSED_SIZE,
200
+ HEADER_OFFSET_FILENAME_LENGTH,
201
+ HEADER_OFFSET_EXTRAFIELD_LENGTH,
191
202
  LOCAL_HEADER_COMMON_OFFSET,
192
203
  DIRECTORY_SIGNATURE,
193
204
  MIN_DATE,
@@ -198,5 +209,6 @@ export {
198
209
  FUNCTION_TYPE,
199
210
  OBJECT_TYPE,
200
211
  STRING_TYPE,
201
- NUMBER_TYPE
212
+ NUMBER_TYPE,
213
+ BOOLEAN_TYPE
202
214
  };
package/lib/core/io.js CHANGED
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global Blob, atob, btoa, XMLHttpRequest, URL, fetch, ReadableStream, WritableStream, FileReader, TransformStream */
29
+ /* global Blob, atob, btoa, XMLHttpRequest, URL, fetch, ReadableStream, WritableStream, TransformStream */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import {
@@ -36,9 +36,10 @@ import {
36
36
  END_OF_CENTRAL_DIR_LENGTH,
37
37
  EMPTY_UINT8_ARRAY
38
38
  } from "./constants.js";
39
- import { getConfiguration, getChunkSize } from "./configuration.js";
39
+ import { getConfiguration, getChunkSize, normalizeChunkSize } from "./configuration.js";
40
40
  import { concat, toExactUint8Array } from "./util/array.js";
41
41
  import { toCompatibleReadable, toCompatibleWritable, streamToBlob } from "./util/compatible-streams.js";
42
+ import { decodeTextRemovingBOM } from "./util/decode-text.js";
42
43
 
43
44
  const ERR_HTTP_STATUS = "HTTP error ";
44
45
  const ERR_HTTP_RANGE = "HTTP Range not supported";
@@ -83,6 +84,7 @@ class Reader extends Stream {
83
84
  createReadable({ offset = 0, size, chunkSize = getChunkSize(getConfiguration()) } = {}) {
84
85
  const reader = this;
85
86
  let chunkOffset = 0;
87
+ chunkSize = normalizeChunkSize(chunkSize);
86
88
  return new ReadableStream({
87
89
  async pull(controller) {
88
90
  const dataSize = size === UNDEFINED_VALUE ? chunkSize : Math.min(chunkSize, size - chunkOffset);
@@ -90,7 +92,7 @@ class Reader extends Stream {
90
92
  if (data.length) {
91
93
  controller.enqueue(data);
92
94
  }
93
- if ((chunkOffset + chunkSize >= size) || (size === UNDEFINED_VALUE && !data.length && dataSize)) {
95
+ if ((chunkOffset + chunkSize >= size) || (!data.length && dataSize)) {
94
96
  controller.close();
95
97
  } else {
96
98
  chunkOffset += chunkSize;
@@ -170,31 +172,31 @@ class Data64URIWriter extends Writer {
170
172
  Object.assign(this, {
171
173
  contentType,
172
174
  data: "data:" + (contentType || "") + ";base64,",
173
- pending: []
175
+ pendingCharacters: ""
174
176
  });
175
177
  }
176
178
 
177
179
  writeUint8Array(array) {
178
180
  const writer = this;
179
181
  let indexArray;
180
- let dataString = writer.pending;
181
- const delta = writer.pending.length;
182
- writer.pending = "";
182
+ let dataString = writer.pendingCharacters;
183
+ const delta = writer.pendingCharacters.length;
184
+ writer.pendingCharacters = "";
183
185
  for (indexArray = 0; indexArray < (Math.floor((delta + array.length) / 3) * 3) - delta; indexArray++) {
184
186
  dataString += String.fromCharCode(array[indexArray]);
185
187
  }
186
188
  for (; indexArray < array.length; indexArray++) {
187
- writer.pending += String.fromCharCode(array[indexArray]);
189
+ writer.pendingCharacters += String.fromCharCode(array[indexArray]);
188
190
  }
189
191
  if (dataString.length > 2) {
190
192
  writer.data += btoa(dataString);
191
193
  } else {
192
- writer.pending = dataString + writer.pending;
194
+ writer.pendingCharacters = dataString + writer.pendingCharacters;
193
195
  }
194
196
  }
195
197
 
196
198
  getData() {
197
- return this.data + btoa(this.pending);
199
+ return this.data + btoa(this.pendingCharacters);
198
200
  }
199
201
  }
200
202
 
@@ -224,7 +226,7 @@ class BlobReader extends Reader {
224
226
  constructor(blob) {
225
227
  super();
226
228
  Object.assign(this, {
227
- blob,
229
+ sourceBlob: blob,
228
230
  size: blob.size
229
231
  });
230
232
  if (!blobSliceProbe) {
@@ -234,13 +236,13 @@ class BlobReader extends Reader {
234
236
 
235
237
  createReadable(options) {
236
238
  const reader = this;
237
- const { blob, size } = reader;
239
+ const { sourceBlob, size } = reader;
238
240
  const { offset = 0, size: readSize = size - offset } = options || {};
239
241
  if (!offset && readSize >= size) {
240
- return toCompatibleReadable(blob.stream());
242
+ return toCompatibleReadable(sourceBlob.stream());
241
243
  }
242
244
  if (blobSliceReliable) {
243
- return toCompatibleReadable(blob.slice(offset, offset + readSize).stream());
245
+ return toCompatibleReadable(sourceBlob.slice(offset, offset + readSize).stream());
244
246
  }
245
247
  return super.createReadable(options);
246
248
  }
@@ -249,7 +251,7 @@ class BlobReader extends Reader {
249
251
  const reader = this;
250
252
  const offsetEnd = offset + length;
251
253
  const readsWholeBlob = !offset && offsetEnd >= reader.size;
252
- const blob = readsWholeBlob ? reader.blob : reader.blob.slice(offset, offsetEnd);
254
+ const blob = readsWholeBlob ? reader.sourceBlob : reader.sourceBlob.slice(offset, offsetEnd);
253
255
  let arrayBuffer = await blob.arrayBuffer();
254
256
  const sliceIgnoredByBuggyImplementation = arrayBuffer.byteLength > length;
255
257
  if (sliceIgnoredByBuggyImplementation) {
@@ -271,12 +273,12 @@ class BlobWriter extends Stream {
271
273
  }
272
274
  });
273
275
  writer.contentType = contentType;
274
- writer.blob = streamToBlob(transformStream.readable, contentType);
275
- writer.blob.catch(() => { });
276
+ writer.blobPromise = streamToBlob(transformStream.readable, contentType);
277
+ writer.blobPromise.catch(() => { });
276
278
  }
277
279
 
278
280
  getData() {
279
- return this.blob;
281
+ return this.blobPromise;
280
282
  }
281
283
  }
282
284
 
@@ -310,7 +312,7 @@ function getTextSize(text) {
310
312
  class TextWriter extends BlobWriter {
311
313
 
312
314
  constructor(encoding) {
313
- super(encoding);
315
+ super();
314
316
  Object.assign(this, {
315
317
  encoding,
316
318
  utf8: !encoding || encoding.toLowerCase() == "utf-8"
@@ -326,14 +328,7 @@ class TextWriter extends BlobWriter {
326
328
  if (blob.text && utf8) {
327
329
  return blob.text();
328
330
  } else {
329
- const reader = new FileReader();
330
- return new Promise((resolve, reject) => {
331
- Object.assign(reader, {
332
- onload: ({ target }) => resolve(target.result),
333
- onerror: () => reject(reader.error)
334
- });
335
- reader.readAsText(blob, encoding);
336
- });
331
+ return decodeTextRemovingBOM(new Uint8Array(await blob.arrayBuffer()), encoding);
337
332
  }
338
333
  }
339
334
  }
@@ -1001,8 +996,19 @@ function readUint8Array(reader, offset, size) {
1001
996
  return reader.readUint8Array(offset, size);
1002
997
  }
1003
998
 
999
+ function createReadable(reader, options) {
1000
+ if (reader.createReadable) {
1001
+ return reader.createReadable(options);
1002
+ } else if (reader.readUint8Array) {
1003
+ return Reader.prototype.createReadable.call(reader, options);
1004
+ } else {
1005
+ return reader.readable;
1006
+ }
1007
+ }
1008
+
1004
1009
  export {
1005
1010
  initStream,
1011
+ createReadable,
1006
1012
  GenericReader,
1007
1013
  GenericWriter,
1008
1014
  ownsWritable,
@@ -26,6 +26,13 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
+ import {
30
+ BOOLEAN_TYPE,
31
+ FUNCTION_TYPE,
32
+ STRING_TYPE,
33
+ UNDEFINED_VALUE
34
+ } from "./constants.js";
35
+
29
36
  const OPTION_FILENAME_ENCODING = "filenameEncoding";
30
37
  const OPTION_COMMENT_ENCODING = "commentEncoding";
31
38
  const OPTION_DECODE_TEXT = "decodeText";
@@ -75,6 +82,10 @@ const STRICTNESS_STRICT = "strict";
75
82
  const STRICTNESS_BALANCED = "balanced";
76
83
  const STRICTNESS_TOLERANT = "tolerant";
77
84
 
85
+ const ERR_INVALID_FUNCTION_OPTION = "Invalid option (must be a function)";
86
+ const ERR_INVALID_SIGNAL = "Invalid signal (must be an AbortSignal instance)";
87
+ const ERR_INVALID_PASSWORD_TYPE = "Invalid password (password must be a string, rawPassword must be a Uint8Array)";
88
+
78
89
  export {
79
90
  OPTION_FILENAME_ENCODING,
80
91
  OPTION_COMMENT_ENCODING,
@@ -123,5 +134,36 @@ export {
123
134
  TEXT_TYPE_COMMENT,
124
135
  STRICTNESS_STRICT,
125
136
  STRICTNESS_BALANCED,
126
- STRICTNESS_TOLERANT
127
- };
137
+ STRICTNESS_TOLERANT,
138
+ ERR_INVALID_FUNCTION_OPTION,
139
+ ERR_INVALID_SIGNAL,
140
+ ERR_INVALID_PASSWORD_TYPE,
141
+ checkFunctionOption,
142
+ checkSignalOption,
143
+ checkPasswordOption,
144
+ toNumber
145
+ };
146
+
147
+ function checkFunctionOption(value) {
148
+ if (value && typeof value != FUNCTION_TYPE) {
149
+ throw new Error(ERR_INVALID_FUNCTION_OPTION);
150
+ }
151
+ return value;
152
+ }
153
+
154
+ function checkSignalOption(signal) {
155
+ if (signal && (typeof signal.addEventListener != FUNCTION_TYPE || typeof signal.aborted != BOOLEAN_TYPE)) {
156
+ throw new Error(ERR_INVALID_SIGNAL);
157
+ }
158
+ return signal || UNDEFINED_VALUE;
159
+ }
160
+
161
+ function checkPasswordOption(password, rawPassword) {
162
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
163
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
164
+ }
165
+ }
166
+
167
+ function toNumber(value) {
168
+ return typeof value == STRING_TYPE && value.trim() ? Number(value) : value;
169
+ }
@@ -102,13 +102,13 @@ class AESDecryptionStream extends TransformStream {
102
102
  const {
103
103
  ctr,
104
104
  hmac,
105
- pending,
105
+ pendingInput,
106
106
  ready
107
107
  } = this;
108
108
  if (hmac && ctr) {
109
109
  await ready;
110
- const chunkToDecrypt = subarray(pending, 0, pending.length - AUTHENTICATION_CODE_LENGTH);
111
- const originalAuthenticationCode = subarray(pending, pending.length - AUTHENTICATION_CODE_LENGTH);
110
+ const chunkToDecrypt = subarray(pendingInput, 0, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
111
+ const originalAuthenticationCode = subarray(pendingInput, pendingInput.length - AUTHENTICATION_CODE_LENGTH);
112
112
  let decryptedChunkArray = EMPTY_UINT8_ARRAY;
113
113
  if (chunkToDecrypt.length) {
114
114
  const encryptedChunk = toBits(codecBytes, chunkToDecrypt);
@@ -117,7 +117,7 @@ class AESDecryptionStream extends TransformStream {
117
117
  decryptedChunkArray = fromBits(codecBytes, decryptedChunk);
118
118
  }
119
119
  const authenticationCode = subarray(fromBits(codecBytes, hmac.digest()), 0, AUTHENTICATION_CODE_LENGTH);
120
- let invalidAuthenticationCode = pending.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
120
+ let invalidAuthenticationCode = pendingInput.length < AUTHENTICATION_CODE_LENGTH ? 1 : 0;
121
121
  for (let indexByte = 0; indexByte < AUTHENTICATION_CODE_LENGTH; indexByte++) {
122
122
  invalidAuthenticationCode |= authenticationCode[indexByte] ^ originalAuthenticationCode[indexByte];
123
123
  }
@@ -161,14 +161,14 @@ class AESEncryptionStream extends TransformStream {
161
161
  const {
162
162
  ctr,
163
163
  hmac,
164
- pending,
164
+ pendingInput,
165
165
  ready
166
166
  } = this;
167
167
  if (hmac && ctr) {
168
168
  await ready;
169
169
  let encryptedChunkArray = EMPTY_UINT8_ARRAY;
170
- if (pending.length) {
171
- const encryptedChunk = ctr.update(toBits(codecBytes, pending));
170
+ if (pendingInput.length) {
171
+ const encryptedChunk = ctr.update(toBits(codecBytes, pendingInput));
172
172
  hmac.update(encryptedChunk);
173
173
  encryptedChunkArray = fromBits(codecBytes, encryptedChunk);
174
174
  }
@@ -190,7 +190,7 @@ function initAesCrypto(aesCrypto, password, rawPassword, encryptionStrength) {
190
190
  ready: new Promise(resolve => aesCrypto.resolveReady = resolve),
191
191
  password: encodePassword(password, rawPassword),
192
192
  strength: encryptionStrength - 1,
193
- pending: EMPTY_UINT8_ARRAY
193
+ pendingInput: EMPTY_UINT8_ARRAY
194
194
  });
195
195
  }
196
196
 
@@ -198,10 +198,10 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthen
198
198
  const {
199
199
  ctr,
200
200
  hmac,
201
- pending
201
+ pendingInput
202
202
  } = aesCrypto;
203
- if (pending.length) {
204
- input = concat(pending, input);
203
+ if (pendingInput.length) {
204
+ input = concat(pendingInput, input);
205
205
  }
206
206
  const inputLength = input.length - paddingEnd;
207
207
  output = expand(output, paddingStart + (inputLength - (inputLength % BLOCK_LENGTH)));
@@ -217,7 +217,7 @@ function append(aesCrypto, input, output, paddingStart, paddingEnd, verifyAuthen
217
217
  }
218
218
  output.set(fromBits(codecBytes, outputChunk), offset + paddingStart);
219
219
  }
220
- aesCrypto.pending = subarray(input, offset);
220
+ aesCrypto.pendingInput = subarray(input, offset);
221
221
  return output;
222
222
  }
223
223
 
@@ -31,13 +31,22 @@
31
31
  import { decodeCP437 } from "./decode-cp437.js";
32
32
 
33
33
  export {
34
- decodeText
34
+ decodeText,
35
+ decodeTextRemovingBOM
35
36
  };
36
37
 
37
38
  function decodeText(value, encoding) {
39
+ return decode(value, encoding, true);
40
+ }
41
+
42
+ function decodeTextRemovingBOM(value, encoding) {
43
+ return decode(value, encoding, false);
44
+ }
45
+
46
+ function decode(value, encoding, ignoreBOM) {
38
47
  if (encoding && encoding.trim().toLowerCase() == "cp437") {
39
48
  return decodeCP437(value);
40
49
  } else {
41
- return new TextDecoder(encoding, { ignoreBOM: true }).decode(value);
50
+ return new TextDecoder(encoding, { ignoreBOM }).decode(value);
42
51
  }
43
52
  }
@@ -44,6 +44,7 @@ import {
44
44
  MESSAGE_READY
45
45
  } from "./streams/codec-stream.js";
46
46
  import { getChunkSize } from "./configuration.js";
47
+ import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-streams.js";
47
48
  import { toExactUint8Array } from "./util/array.js";
48
49
  import { ensureCodecStreams } from "./codec-registry.js";
49
50
 
@@ -138,7 +139,7 @@ async function init(message) {
138
139
  config.DecompressionStreamFallback = config.DecompressionStreamZlib;
139
140
  }
140
141
  const strategy = { highWaterMark: 1 };
141
- const readable = message.readable || new ReadableStream({
142
+ const readable = message.readable ? toCompatibleReadable(message.readable) : new ReadableStream({
142
143
  async pull(controller) {
143
144
  const result = new Promise(resolve => pendingPullMessages.set(messageId, resolve));
144
145
  sendMessage({ type: MESSAGE_PULL, messageId });
@@ -150,7 +151,7 @@ async function init(message) {
150
151
  }
151
152
  }
152
153
  }, strategy);
153
- writable = message.writable || new WritableStream({
154
+ writable = message.writable ? toCompatibleWritable(message.writable) : new WritableStream({
154
155
  async write(value) {
155
156
  let resolveAckData;
156
157
  const ackData = new Promise(resolve => resolveAckData = resolve);