@zip.js/zip.js 2.8.44 → 2.8.45

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 (51) hide show
  1. package/deno.json +21 -1
  2. package/dist/zip-core-external.js +138 -123
  3. package/dist/zip-core-external.min.js +1 -1
  4. package/dist/zip-core.js +137 -96
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core-external.js +190 -131
  7. package/dist/zip-fs-core-external.min.js +1 -1
  8. package/dist/zip-fs-core.js +189 -104
  9. package/dist/zip-fs-core.min.js +1 -1
  10. package/dist/zip-fs-external.js +211 -1725
  11. package/dist/zip-fs-external.min.js +1 -1
  12. package/dist/zip-fs-native.js +212 -1700
  13. package/dist/zip-fs-native.min.js +1 -1
  14. package/dist/zip-fs.js +211 -1699
  15. package/dist/zip-fs.min.js +1 -1
  16. package/dist/zip-legacy.js +139 -98
  17. package/dist/zip-legacy.min.js +1 -1
  18. package/dist/zip-native.js +139 -98
  19. package/dist/zip-native.min.js +1 -1
  20. package/dist/zip-web-worker-native.js +1 -1
  21. package/dist/zip-web-worker.js +1 -1
  22. package/dist/zip.js +138 -97
  23. package/dist/zip.min.js +1 -1
  24. package/eslint.config.mjs +31 -2
  25. package/index-native.cjs +212 -1700
  26. package/index-native.min.js +1 -1
  27. package/index.cjs +211 -1699
  28. package/index.d.cts +49 -1
  29. package/index.d.ts +49 -1
  30. package/index.min.js +1 -1
  31. package/lib/core/codec-worker.js +2 -2
  32. package/lib/core/constants.js +4 -0
  33. package/lib/core/options.js +2 -0
  34. package/lib/core/streams/aes-crypto-stream.js +15 -18
  35. package/lib/core/streams/codec-stream.js +2 -2
  36. package/lib/core/streams/zip-entry-stream.js +5 -10
  37. package/lib/core/util/mime-type-data.js +3 -0
  38. package/lib/core/util/mime-type.js +23 -1596
  39. package/lib/core/web-worker-base.js +2 -2
  40. package/lib/core/web-worker-inline-native.js +1 -1
  41. package/lib/core/web-worker-inline-wasm.js +1 -1
  42. package/lib/core/zip-entry.js +8 -1
  43. package/lib/core/zip-fs.js +62 -5
  44. package/lib/core/zip-reader.js +45 -17
  45. package/lib/core/zip-writer.js +58 -44
  46. package/lib/zip-core-external.js +2 -0
  47. package/lib/zip-fs-core-external.js +2 -0
  48. package/lib/zip-fs-external.js +2 -0
  49. package/lib/zip-mime-types.js +2 -0
  50. package/package.json +9 -3
  51. package/worker-message-property-names.js +1 -1
@@ -208,7 +208,8 @@ import {
208
208
  OPTION_ENCODE_TEXT,
209
209
  OPTION_OFFSET,
210
210
  OPTION_USDZ,
211
- OPTION_UNIX_EXTRA_FIELD_TYPE
211
+ OPTION_UNIX_EXTRA_FIELD_TYPE,
212
+ OPTION_LOCAL_EXTRA_FIELD
212
213
  } from "./options.js";
213
214
 
214
215
  const ERR_DUPLICATED_NAME = "File already exists";
@@ -238,6 +239,8 @@ const ERR_INVALID_MSDOS_ATTRIBUTES = "Invalid msdosAttributesRaw (must be intege
238
239
  const ERR_INVALID_MSDOS_DATA = "Invalid msdosAttributes (must be an object with boolean flags)";
239
240
 
240
241
  const EXTRAFIELD_DATA_AES = new Uint8Array([0x07, 0x00, 0x02, 0x00, 0x41, 0x45, 0x03, 0x00, 0x00]);
242
+ const EXTRAFIELD_OFFSET_AES_VENDOR_VERSION = 4;
243
+ const VENDOR_VERSION_AE_1 = 1;
241
244
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
242
245
  const UNIX_EXTRA_FIELD_TYPE = "unix";
243
246
 
@@ -332,9 +335,9 @@ class ZipWriter {
332
335
  zip64UncompressedSize,
333
336
  extraFieldLength
334
337
  });
335
- const { signature } = entry;
336
- if (signature !== UNDEFINED_VALUE) {
337
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
338
+ const { crc32 } = entry;
339
+ if (crc32 !== UNDEFINED_VALUE) {
340
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
338
341
  }
339
342
  Object.assign(entry, {
340
343
  zip64UncompressedSize,
@@ -537,6 +540,7 @@ async function addFile(zipWriter, name, reader, options) {
537
540
  internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
538
541
  externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
539
542
  signature: options[PROPERTY_NAME_SIGNATURE],
543
+ crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
540
544
  offset: zipWriter.offset - diskOffset,
541
545
  diskNumberStart: diskNumber
542
546
  });
@@ -753,27 +757,8 @@ function resolveMetadata(zipWriter, name, options) {
753
757
  if (!zipCrypto && (password !== UNDEFINED_VALUE || rawPassword !== UNDEFINED_VALUE) && !(encryptionStrength >= 1 && encryptionStrength <= 3)) {
754
758
  throw new Error(ERR_INVALID_ENCRYPTION_STRENGTH);
755
759
  }
756
- let rawExtraField = EMPTY_UINT8_ARRAY;
757
- const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
758
- if (extraField) {
759
- let extraFieldSize = 0;
760
- let offset = 0;
761
- extraField.forEach(data => extraFieldSize += 4 + getLength(data));
762
- rawExtraField = new Uint8Array(extraFieldSize);
763
- const rawExtraFieldView = getDataView(rawExtraField);
764
- extraField.forEach((data, type) => {
765
- if (type > MAX_16_BITS) {
766
- throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
767
- }
768
- if (getLength(data) > MAX_16_BITS) {
769
- throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
770
- }
771
- setUint16(rawExtraFieldView, offset, type);
772
- setUint16(rawExtraFieldView, offset + 2, getLength(data));
773
- arraySet(rawExtraField, data, offset + 4);
774
- offset += 4 + getLength(data);
775
- });
776
- }
760
+ const rawExtraField = serializeExtraField(options[PROPERTY_NAME_EXTRA_FIELD]);
761
+ const rawLocalExtraField = serializeExtraField(options[OPTION_LOCAL_EXTRA_FIELD]);
777
762
  return {
778
763
  comment,
779
764
  resolvedOptions: {
@@ -807,11 +792,36 @@ function resolveMetadata(zipWriter, name, options) {
807
792
  useCompressionStream,
808
793
  dataDescriptor,
809
794
  zip64,
810
- rawExtraField
795
+ rawExtraField,
796
+ rawLocalExtraField
811
797
  }
812
798
  };
813
799
  }
814
800
 
801
+ function serializeExtraField(extraField) {
802
+ if (!extraField) {
803
+ return EMPTY_UINT8_ARRAY;
804
+ }
805
+ let extraFieldSize = 0;
806
+ let offset = 0;
807
+ extraField.forEach(data => extraFieldSize += 4 + getLength(data));
808
+ const rawExtraField = new Uint8Array(extraFieldSize);
809
+ const rawExtraFieldView = getDataView(rawExtraField);
810
+ extraField.forEach((data, type) => {
811
+ if (type > MAX_16_BITS) {
812
+ throw new Error(ERR_INVALID_EXTRAFIELD_TYPE);
813
+ }
814
+ if (getLength(data) > MAX_16_BITS) {
815
+ throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
816
+ }
817
+ setUint16(rawExtraFieldView, offset, type);
818
+ setUint16(rawExtraFieldView, offset + 2, getLength(data));
819
+ arraySet(rawExtraField, data, offset + 4);
820
+ offset += 4 + getLength(data);
821
+ });
822
+ return rawExtraField;
823
+ }
824
+
815
825
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
816
826
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
817
827
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
@@ -1136,12 +1146,9 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1136
1146
  msdosAttributes
1137
1147
  };
1138
1148
  let {
1139
- crc32: signature,
1149
+ crc32,
1140
1150
  uncompressedSize
1141
1151
  } = options;
1142
- if (signature === UNDEFINED_VALUE) {
1143
- ({ signature } = options);
1144
- }
1145
1152
  let compressedSize = 0;
1146
1153
  if (!passThrough) {
1147
1154
  uncompressedSize = 0;
@@ -1179,7 +1186,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1179
1186
  if (!passThrough) {
1180
1187
  uncompressedSize = result.inputSize;
1181
1188
  if (!encrypted || zipCrypto) {
1182
- signature = result.signature;
1189
+ crc32 = result.crc32;
1183
1190
  }
1184
1191
  }
1185
1192
  if ((!zip64CompressedSize && compressedSize >= MAX_32_BITS) ||
@@ -1195,7 +1202,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1195
1202
 
1196
1203
  }
1197
1204
  setEntryInfo({
1198
- signature,
1205
+ crc32,
1199
1206
  compressedSize,
1200
1207
  uncompressedSize,
1201
1208
  headerInfo,
@@ -1218,8 +1225,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1218
1225
  version,
1219
1226
  headerArray,
1220
1227
  headerView,
1221
- signature,
1222
- crc32: encrypted && !zipCrypto ? UNDEFINED_VALUE : signature,
1228
+ signature: crc32,
1229
+ crc32: encrypted && !zipCrypto && !passThrough ? UNDEFINED_VALUE : crc32,
1223
1230
  extraFieldExtendedTimestampFlag,
1224
1231
  zip64UncompressedSize,
1225
1232
  zip64CompressedSize
@@ -1240,6 +1247,7 @@ function getHeaderInfo(options) {
1240
1247
  dataDescriptor,
1241
1248
  directory,
1242
1249
  rawExtraField,
1250
+ rawLocalExtraField,
1243
1251
  encryptionStrength,
1244
1252
  extendedTimestamp,
1245
1253
  ntfsTimestamp,
@@ -1247,7 +1255,8 @@ function getHeaderInfo(options) {
1247
1255
  encrypted,
1248
1256
  zip64UncompressedSize,
1249
1257
  zip64CompressedSize,
1250
- uncompressedSize
1258
+ uncompressedSize,
1259
+ crc32
1251
1260
  } = options;
1252
1261
  let { version, compressionMethod } = options;
1253
1262
  const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
@@ -1373,11 +1382,14 @@ function getHeaderInfo(options) {
1373
1382
  }
1374
1383
  if (encrypted && !zipCrypto) {
1375
1384
  version = version > VERSION_AES ? version : VERSION_AES;
1385
+ if (passThrough && crc32 !== UNDEFINED_VALUE) {
1386
+ rawExtraFieldAES[EXTRAFIELD_OFFSET_AES_VENDOR_VERSION] = VENDOR_VERSION_AE_1;
1387
+ }
1376
1388
  rawExtraFieldAES[9] = compressionMethod;
1377
1389
  compressionMethod = COMPRESSION_METHOD_AES;
1378
1390
  }
1379
1391
  const localExtraFieldZip64Length = writeLocalExtraFieldZip64 ? getLength(rawLocalExtraFieldZip64) : 0;
1380
- const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField);
1392
+ const extraFieldLength = localExtraFieldZip64Length + getLength(rawExtraFieldAES, rawExtraFieldExtendedTimestamp, rawExtraFieldNTFS, rawExtraFieldUnix, rawExtraField, rawLocalExtraField);
1381
1393
  if (extraFieldLength > MAX_16_BITS) {
1382
1394
  throw new Error(ERR_INVALID_EXTRAFIELD_DATA);
1383
1395
  }
@@ -1411,6 +1423,7 @@ function getHeaderInfo(options) {
1411
1423
  localHeader.bytes(rawExtraFieldNTFS);
1412
1424
  localHeader.bytes(rawExtraFieldUnix);
1413
1425
  localHeader.bytes(rawExtraField);
1426
+ localHeader.bytes(rawLocalExtraField);
1414
1427
  if (dataDescriptor) {
1415
1428
  if (!zip64CompressedSize) {
1416
1429
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, 0);
@@ -1529,7 +1542,7 @@ function getDataDescriptorInfo({
1529
1542
  }
1530
1543
 
1531
1544
  function setEntryInfo({
1532
- signature,
1545
+ crc32,
1533
1546
  compressedSize,
1534
1547
  uncompressedSize,
1535
1548
  headerInfo,
@@ -1537,6 +1550,7 @@ function setEntryInfo({
1537
1550
  }, {
1538
1551
  zip64,
1539
1552
  zipCrypto,
1553
+ passThrough,
1540
1554
  dataDescriptor
1541
1555
  }) {
1542
1556
  const {
@@ -1547,10 +1561,10 @@ function setEntryInfo({
1547
1561
  dataDescriptorView,
1548
1562
  dataDescriptorOffset
1549
1563
  } = dataDescriptorInfo;
1550
- if ((!encrypted || zipCrypto) && signature !== UNDEFINED_VALUE) {
1551
- setUint32(headerView, HEADER_OFFSET_SIGNATURE, signature);
1564
+ if ((!encrypted || zipCrypto || passThrough) && crc32 !== UNDEFINED_VALUE) {
1565
+ setUint32(headerView, HEADER_OFFSET_SIGNATURE, crc32);
1552
1566
  if (dataDescriptor) {
1553
- setUint32(dataDescriptorView, dataDescriptorOffset, signature);
1567
+ setUint32(dataDescriptorView, dataDescriptorOffset, crc32);
1554
1568
  }
1555
1569
  }
1556
1570
  if (zip64) {
@@ -1573,15 +1587,15 @@ function updateLocalHeader({
1573
1587
  encrypted,
1574
1588
  zip64,
1575
1589
  localExtraFieldZip64Length,
1576
- signature,
1590
+ crc32,
1577
1591
  compressedSize,
1578
1592
  uncompressedSize,
1579
1593
  zip64UncompressedSize,
1580
1594
  zip64CompressedSize
1581
- }, localHeaderView, { dataDescriptor }) {
1595
+ }, localHeaderView, { dataDescriptor, passThrough }) {
1582
1596
  if (!dataDescriptor) {
1583
- if (!encrypted) {
1584
- setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, signature);
1597
+ if (!encrypted || (passThrough && crc32 !== UNDEFINED_VALUE)) {
1598
+ setUint32(localHeaderView, HEADER_OFFSET_SIGNATURE + LOCAL_HEADER_COMMON_OFFSET, crc32);
1585
1599
  }
1586
1600
  if (!zip64CompressedSize) {
1587
1601
  setUint32(localHeaderView, HEADER_OFFSET_COMPRESSED_SIZE + LOCAL_HEADER_COMMON_OFFSET, compressedSize);
@@ -1,3 +1,5 @@
1
+ /// <reference types="../index.d.ts" />
2
+
1
3
  /*
2
4
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
5
 
@@ -1,3 +1,5 @@
1
+ /// <reference types="../index.d.ts" />
2
+
1
3
  /*
2
4
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
5
 
@@ -1,3 +1,5 @@
1
+ /// <reference types="../index.d.ts" />
2
+
1
3
  /*
2
4
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
5
 
@@ -1,3 +1,5 @@
1
+ /// <reference types="../index.d.ts" />
2
+
1
3
  /*
2
4
  Copyright (c) 2025 Gildas Lormeau. All rights reserved.
3
5
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.8.44",
6
+ "version": "2.8.45",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -34,6 +34,10 @@
34
34
  "bun": ">=0.7.0"
35
35
  },
36
36
  "scripts": {
37
+ "lint": "npx eslint . && deno lint",
38
+ "test": "npm run test-node && npm run test-deno && npm run test-bun && npm run test-node-dist && npm run test-deno-dist && npm run test-bun-dist && npm run test-web-streams-polyfill && npm run test-types",
39
+ "test-browsers": "npm run test-chrome && npm run test-firefox && npm run test-webkit",
40
+ "test-all": "npm run lint && npm run test && npm run test-browsers",
37
41
  "build": "npx rollup -c",
38
42
  "build-dev": "npx rollup -c rollup.config.dev.js",
39
43
  "build-doc-api": "npx typedoc",
@@ -46,8 +50,9 @@
46
50
  "test-node-dist": "./tests/dist-runner.sh node",
47
51
  "test-bun-dist": "./tests/dist-runner.sh bun",
48
52
  "test-types": "tsc -p ./tests/types/tsconfig.json",
49
- "test-firefox": "firefox http://localhost:8081/tests/ & npx http-server -p=8081 & wait $!",
50
- "test-chrome": "google-chrome http://localhost:8081/tests/ & npx http-server -p=8081 & wait $!"
53
+ "test-firefox": "node ./tests/browser-runner.js firefox",
54
+ "test-chrome": "node ./tests/browser-runner.js chrome",
55
+ "test-webkit": "node ./tests/browser-runner.js webkit"
51
56
  },
52
57
  "main": "./index.cjs",
53
58
  "module": "./index.js",
@@ -236,6 +241,7 @@
236
241
  "@rollup/plugin-terser": "^1.0.0",
237
242
  "eslint": "^10.8.1",
238
243
  "http-server": "^14.1.1",
244
+ "playwright": "^1.62.1",
239
245
  "rollup": "^4.62.4",
240
246
  "typedoc": "^0.28.20",
241
247
  "typedoc-plugin-markdown": "^4.12.0",
@@ -1,3 +1,3 @@
1
- const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkAuthenticationCode", "checkCrc32", "checkPasswordOnly", "chunkSize", "code", "codecType", "codecURI", "compressed", "compressionMethod", "computeCrc32", "config", "deflate64", "done", "encrypted", "encryptionStrength", "error", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "readable", "result", "signature", "stack", "transferStreams", "type", "useCompressionStream", "useWebWorkers", "value", "wasmURI", "workerStartupTimeout", "writable", "zipCrypto"];
1
+ const WORKER_MESSAGE_PROPERTY_NAMES = ["baseURI", "cause", "checkAuthenticationCode", "checkCrc32", "checkPasswordOnly", "chunkSize", "code", "codecType", "codecURI", "compressed", "compressionMethod", "computeCrc32", "config", "crc32", "deflate64", "done", "encrypted", "encryptionStrength", "error", "format", "inputSize", "level", "message", "messageId", "name", "options", "outputSize", "password", "passwordVerification", "rawBitFlag", "rawPassword", "readable", "result", "stack", "transferStreams", "type", "useCompressionStream", "useWebWorkers", "value", "wasmURI", "workerStartupTimeout", "writable", "zipCrypto"];
2
2
 
3
3
  export { WORKER_MESSAGE_PROPERTY_NAMES };