@zip.js/zip.js 2.8.44 → 2.8.46

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 (61) hide show
  1. package/README.md +28 -2
  2. package/deno.json +32 -2
  3. package/dist/zip-core-external.js +199 -149
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +196 -120
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +251 -157
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +227 -126
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +272 -1751
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +273 -1726
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +273 -1726
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +198 -122
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +200 -124
  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 +200 -124
  24. package/dist/zip.min.js +1 -1
  25. package/eslint.config.mjs +31 -2
  26. package/index-native.cjs +273 -1726
  27. package/index-native.min.js +1 -1
  28. package/index.cjs +273 -1726
  29. package/index.d.cts +140 -2
  30. package/index.d.ts +140 -2
  31. package/index.min.js +1 -1
  32. package/lib/core/codec-pool.js +3 -2
  33. package/lib/core/codec-worker.js +30 -14
  34. package/lib/core/configuration.js +20 -2
  35. package/lib/core/constants.js +4 -0
  36. package/lib/core/options.js +2 -0
  37. package/lib/core/streams/aes-crypto-stream.js +15 -18
  38. package/lib/core/streams/codec-stream.js +2 -2
  39. package/lib/core/streams/zip-entry-stream.js +13 -18
  40. package/lib/core/util/mime-type-data.js +3 -0
  41. package/lib/core/util/mime-type.js +23 -1596
  42. package/lib/core/web-worker-base.js +29 -2
  43. package/lib/core/web-worker-inline-native.js +1 -1
  44. package/lib/core/web-worker-inline-wasm.js +1 -1
  45. package/lib/core/web-worker-native.js +7 -9
  46. package/lib/core/web-worker-wasm.js +9 -12
  47. package/lib/core/zip-entry.js +8 -1
  48. package/lib/core/zip-fs.js +62 -5
  49. package/lib/core/zip-reader.js +45 -17
  50. package/lib/core/zip-writer.js +58 -44
  51. package/lib/{core/web-worker-inline-template.js → zip-core-custom.js} +13 -20
  52. package/lib/zip-core-external.js +2 -0
  53. package/lib/zip-fs-core-external.js +2 -0
  54. package/lib/zip-fs-external.js +2 -0
  55. package/lib/zip-mime-types.js +2 -0
  56. package/lib/zip-module-native.js +3 -3
  57. package/lib/zip-module-wasm-base.js +3 -3
  58. package/package.json +28 -4
  59. package/worker-message-property-names.js +1 -1
  60. package/lib/core/web-worker-inline-template-native.js +0 -48
  61. package/lib/core/zlib-streams-inline-template.js +0 -45
@@ -57,6 +57,8 @@ import {
57
57
  EXTRAFIELD_TYPE_EXTENDED_TIMESTAMP,
58
58
  EXTRAFIELD_TYPE_INFOZIP,
59
59
  EXTRAFIELD_TYPE_UNIX,
60
+ EXTRAFIELD_TYPE_UNIX_TYPE1,
61
+ EXTRAFIELD_TYPE_PKWARE_UNIX,
60
62
  EXTRAFIELD_TYPE_USDZ,
61
63
  END_OF_CENTRAL_DIR_LENGTH,
62
64
  ZIP64_END_OF_CENTRAL_DIR_LOCATOR_LENGTH,
@@ -590,7 +592,7 @@ class ZipEntry {
590
592
  config,
591
593
  bitFlag,
592
594
  rawBitFlag,
593
- signature,
595
+ crc32,
594
596
  rawLastModDate,
595
597
  uncompressedSize,
596
598
  compressedSize
@@ -691,9 +693,9 @@ class ZipEntry {
691
693
  encryptionStrength: extraFieldAES && extraFieldAES.strength,
692
694
  checkCrc32,
693
695
  checkAuthenticationCode: getOptionValue(zipEntry, options, OPTION_CHECK_AUTHENTICATION_CODE),
694
- passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((signature >>> 24) & MAX_8_BITS)),
696
+ passwordVerification: zipCrypto && (dataDescriptor ? ((rawLastModDate >>> 8) & MAX_8_BITS) : ((crc32 >>> 24) & MAX_8_BITS)),
695
697
  outputSize: passThrough ? compressedSize : uncompressedSize,
696
- signature,
698
+ crc32,
697
699
  compressed: compressionMethod != 0 && !passThrough,
698
700
  encrypted,
699
701
  useWebWorkers: getOptionValue(zipEntry, options, OPTION_USE_WEB_WORKERS),
@@ -715,7 +717,7 @@ class ZipEntry {
715
717
  fileEntry,
716
718
  index,
717
719
  offset: localHeaderOffset,
718
- signature,
720
+ crc32,
719
721
  compressedSize,
720
722
  uncompressedSize,
721
723
  dataOffset,
@@ -832,6 +834,16 @@ function readCommonFooter(fileEntry, directory, dataView, offset, localDirectory
832
834
  } else {
833
835
  directory.compressionMethod = compressionMethod;
834
836
  }
837
+ const extraFieldPkwareUnix = extraField.get(EXTRAFIELD_TYPE_PKWARE_UNIX);
838
+ if (extraFieldPkwareUnix) {
839
+ readExtraFieldUnixDates(extraFieldPkwareUnix, directory);
840
+ directory.extraFieldPkwareUnix = extraFieldPkwareUnix;
841
+ }
842
+ const extraFieldUnixType1 = extraField.get(EXTRAFIELD_TYPE_UNIX_TYPE1);
843
+ if (extraFieldUnixType1) {
844
+ readExtraFieldUnixDates(extraFieldUnixType1, directory);
845
+ directory.extraFieldUnixType1 = extraFieldUnixType1;
846
+ }
835
847
  const extraFieldNTFS = extraField.get(EXTRAFIELD_TYPE_NTFS);
836
848
  if (extraFieldNTFS) {
837
849
  readExtraFieldNTFS(extraFieldNTFS, directory);
@@ -881,15 +893,15 @@ function readExtraFieldUnicode(extraFieldUnicode, propertyName, rawPropertyName,
881
893
  return;
882
894
  }
883
895
  const extraFieldView = getDataView(extraFieldUnicode.data);
884
- const crc32 = new Crc32();
885
- crc32.append(fileEntry[rawPropertyName]);
886
- const dataViewSignature = getDataView(new Uint8Array(4));
887
- dataViewSignature.setUint32(0, crc32.get(), true);
888
- const signature = getUint32(extraFieldView, 1);
896
+ const computedCrc32 = new Crc32();
897
+ computedCrc32.append(fileEntry[rawPropertyName]);
898
+ const computedCrc32View = getDataView(new Uint8Array(4));
899
+ computedCrc32View.setUint32(0, computedCrc32.get(), true);
900
+ const nameCrc32 = getUint32(extraFieldView, 1);
889
901
  Object.assign(extraFieldUnicode, {
890
902
  version: getUint8(extraFieldView, 0),
891
903
  [propertyName]: decodeText(extraFieldUnicode.data.subarray(5)),
892
- valid: !fileEntry.bitFlag.languageEncodingFlag && signature == getUint32(dataViewSignature, 0)
904
+ valid: !fileEntry.bitFlag.languageEncodingFlag && nameCrc32 == getUint32(computedCrc32View, 0)
893
905
  });
894
906
  if (extraFieldUnicode.valid) {
895
907
  directory[propertyName] = extraFieldUnicode[propertyName];
@@ -948,6 +960,22 @@ function readExtraFieldNTFS(extraFieldNTFS, directory) {
948
960
  }
949
961
  }
950
962
 
963
+ function readExtraFieldUnixDates(extraField, directory) {
964
+ if (extraField.data.length < 8) {
965
+ return;
966
+ }
967
+ const extraFieldView = getDataView(extraField.data);
968
+ const lastAccessDate = new Date(getUint32(extraFieldView, 0) * 1000);
969
+ const lastModDate = new Date(getUint32(extraFieldView, 4) * 1000);
970
+ const extraFieldData = { lastAccessDate, lastModDate };
971
+ if (extraField.data.length >= 12) {
972
+ extraFieldData.uid = getUint16(extraFieldView, 8);
973
+ extraFieldData.gid = getUint16(extraFieldView, 10);
974
+ }
975
+ Object.assign(extraField, extraFieldData);
976
+ Object.assign(directory, extraFieldData);
977
+ }
978
+
951
979
  function readExtraFieldUnix(extraField, directory, isInfoZip) {
952
980
  try {
953
981
  const view = getDataView(extraField.data);
@@ -1026,7 +1054,7 @@ async function detectOverlappingEntry({
1026
1054
  fileEntry,
1027
1055
  index,
1028
1056
  offset,
1029
- signature,
1057
+ crc32,
1030
1058
  compressedSize,
1031
1059
  uncompressedSize,
1032
1060
  dataOffset,
@@ -1047,7 +1075,7 @@ async function detectOverlappingEntry({
1047
1075
  const dataDescriptorSignature = dataDescriptorArray.length == dataDescriptorLength + DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH &&
1048
1076
  getUint32(getDataView(dataDescriptorArray), 0) == DATA_DESCRIPTOR_RECORD_SIGNATURE;
1049
1077
  if (dataDescriptorSignature) {
1050
- const readSignature = getUint32(getDataView(dataDescriptorArray), 4);
1078
+ const readCrc32 = getUint32(getDataView(dataDescriptorArray), 4);
1051
1079
  let readCompressedSize;
1052
1080
  let readUncompressedSize;
1053
1081
  if (extraFieldZip64) {
@@ -1057,8 +1085,8 @@ async function detectOverlappingEntry({
1057
1085
  readCompressedSize = getUint32(getDataView(dataDescriptorArray), 8);
1058
1086
  readUncompressedSize = getUint32(getDataView(dataDescriptorArray), 12);
1059
1087
  }
1060
- const matchSignature = (fileEntry.encrypted && !fileEntry.zipCrypto) || readSignature == signature;
1061
- if (matchSignature &&
1088
+ const matchCrc32 = (fileEntry.encrypted && !fileEntry.zipCrypto) || readCrc32 == crc32;
1089
+ if (matchCrc32 &&
1062
1090
  readCompressedSize == compressedSize &&
1063
1091
  readUncompressedSize == uncompressedSize) {
1064
1092
  dataDescriptorLength += DATA_DESCRIPTOR_RECORD_SIGNATURE_LENGTH;
@@ -1227,11 +1255,11 @@ function checkLocalDirectory(zipEntry, localDirectory, rawLocalFilename) {
1227
1255
  throwAmbiguousArchive("mismatched local file header (compression method)");
1228
1256
  }
1229
1257
  if (!localDirectory.bitFlag.dataDescriptor &&
1230
- (localDirectory.signature || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
1231
- (localDirectory.signature != zipEntry.signature ||
1258
+ (localDirectory.crc32 || localDirectory.compressedSize || localDirectory.uncompressedSize) &&
1259
+ (localDirectory.crc32 != zipEntry.crc32 ||
1232
1260
  localDirectory.compressedSize != zipEntry.compressedSize ||
1233
1261
  localDirectory.uncompressedSize != zipEntry.uncompressedSize)) {
1234
- throwAmbiguousArchive("mismatched local file header (signature or sizes)");
1262
+ throwAmbiguousArchive("mismatched local file header (crc32 or sizes)");
1235
1263
  }
1236
1264
  }
1237
1265
 
@@ -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
 
@@ -7,8 +9,8 @@
7
9
  1. Redistributions of source code must retain the above copyright notice,
8
10
  this list of conditions and the following disclaimer.
9
11
 
10
- 2. Redistributions in binary form must reproduce the above copyright
11
- notice, this list of conditions and the following disclaimer in
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in
12
14
  the documentation and/or other materials provided with the distribution.
13
15
 
14
16
  3. The names of the authors may not be used to endorse or promote products
@@ -26,21 +28,12 @@
26
28
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
29
  */
28
30
 
29
- /* global Blob, URL */
30
- /* eslint-disable quotes */
31
-
32
- export function configureWebWorker(configure) {
33
- const code = `__workerCode__`;
34
-
35
- configure({
36
- workerURI: (useBlobURI) => {
37
- const type = "text/javascript";
38
- if (useBlobURI) {
39
- const blob = new Blob([code], { type });
40
- return URL.createObjectURL(blob);
41
- } else {
42
- return "data:" + type + "," + encodeURIComponent(code);
43
- }
44
- }
45
- });
46
- }
31
+ import { setDefaultConfiguration } from "./core/configuration.js";
32
+
33
+ setDefaultConfiguration({
34
+ workerURI: null,
35
+ wasmURI: null
36
+ });
37
+
38
+ export * from "./zip-core-base.js";
39
+ export { terminateWorkers } from "./core/codec-pool.js";
@@ -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
 
@@ -27,13 +27,13 @@
27
27
  */
28
28
 
29
29
  import { setDefaultConfiguration } from "./core/configuration.js";
30
- import { CompressionStreamZlib, DecompressionStreamZlib } from "./core/streams/zlib-js/zlib-streams.min.js";
30
+ import { CompressionStreamZlib as CompressionStreamFallback, DecompressionStreamZlib as DecompressionStreamFallback } from "./core/streams/zlib-js/zlib-streams.min.js";
31
31
 
32
32
  setDefaultConfiguration({
33
33
  workerURI: "./core/web-worker-native.js",
34
34
  wasmURI: null,
35
- CompressionStreamZlib,
36
- DecompressionStreamZlib
35
+ CompressionStreamFallback,
36
+ DecompressionStreamFallback
37
37
  });
38
38
 
39
39
  export { terminateWorkers } from "./core/codec-pool.js";
@@ -30,7 +30,7 @@ import { FUNCTION_TYPE } from "./core/constants.js";
30
30
  import { setDefaultConfiguration } from "./core/configuration.js";
31
31
  import { configureWorker } from "./core/codec-worker.js";
32
32
  import { terminateWorkers } from "./core/codec-pool.js";
33
- import { initModule, resetWasmModule, CompressionStreamZlib, DecompressionStreamZlib } from "./core/streams/zlib-wasm/zlib-streams-loader.js";
33
+ import { initModule, resetWasmModule, CompressionStreamZlib as CompressionStreamFallback, DecompressionStreamZlib as DecompressionStreamFallback } from "./core/streams/zlib-wasm/zlib-streams-loader.js";
34
34
 
35
35
  let modulePromise;
36
36
 
@@ -51,8 +51,8 @@ configureWorker({
51
51
  }
52
52
  });
53
53
  setDefaultConfiguration({
54
- CompressionStreamZlib,
55
- DecompressionStreamZlib
54
+ CompressionStreamFallback,
55
+ DecompressionStreamFallback
56
56
  });
57
57
 
58
58
  export { terminateWorkersAndModule as terminateWorkers };
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.46",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -34,8 +34,12 @@
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
- "build-dev": "npx rollup -c rollup.config.dev.js",
42
+ "build-dev": "npx rollup -c --environment DEV",
39
43
  "build-doc-api": "npx typedoc",
40
44
  "build-doc-markdown": "npx typedoc --plugin typedoc-plugin-markdown --out ./docs",
41
45
  "test-deno": "cd ./tests && deno test --allow-read ./deno-runner.js",
@@ -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",
@@ -83,6 +88,12 @@
83
88
  "default": "./lib/zip-mime-types.js"
84
89
  }
85
90
  },
91
+ "./worker": {
92
+ "import": {
93
+ "types": "./index.d.ts",
94
+ "default": "./lib/core/web-worker-base.js"
95
+ }
96
+ },
86
97
  "./lib/zip-core-external.js": {
87
98
  "import": {
88
99
  "types": "./index.d.ts",
@@ -95,6 +106,12 @@
95
106
  "default": "./lib/zip-fs-core-external.js"
96
107
  }
97
108
  },
109
+ "./lib/zip-core-custom.js": {
110
+ "import": {
111
+ "types": "./index.d.ts",
112
+ "default": "./lib/zip-core-custom.js"
113
+ }
114
+ },
98
115
  "./dist/zip-fs-external.js": {
99
116
  "import": {
100
117
  "types": "./index.d.ts",
@@ -220,6 +237,12 @@
220
237
  "types": "./index.d.ts",
221
238
  "default": "./lib/zip-native.js"
222
239
  }
240
+ },
241
+ "./lib/core/web-worker-base.js": {
242
+ "import": {
243
+ "types": "./index.d.ts",
244
+ "default": "./lib/core/web-worker-base.js"
245
+ }
223
246
  }
224
247
  },
225
248
  "repository": {
@@ -236,6 +259,7 @@
236
259
  "@rollup/plugin-terser": "^1.0.0",
237
260
  "eslint": "^10.8.1",
238
261
  "http-server": "^14.1.1",
262
+ "playwright": "^1.62.1",
239
263
  "rollup": "^4.62.4",
240
264
  "typedoc": "^0.28.20",
241
265
  "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 };
@@ -1,48 +0,0 @@
1
- /*
2
- Copyright (c) 2025 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
- /* global Blob, URL */
30
- /* eslint-disable quotes */
31
- import { inflateRaw } from "./util/inflate.js";
32
- import { base64Decode, base64Encode } from "./util/base64.js";
33
-
34
- export function configureWebWorker(configure) {
35
- const code = `__workerCode__`;
36
- configure({
37
- workerURI: (useBlobURI) => {
38
- const type = "text/javascript";
39
- const source = inflateRaw(base64Decode(code));
40
- if (useBlobURI) {
41
- const blob = new Blob([source], { type });
42
- return URL.createObjectURL(blob);
43
- } else {
44
- return "data:" + type + ";base64," + base64Encode(source);
45
- }
46
- }
47
- });
48
- }