@zip.js/zip.js 2.8.51 → 2.8.53

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 (41) hide show
  1. package/README.md +8 -3
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +241 -95
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +243 -94
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +564 -199
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +551 -194
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +564 -199
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +567 -198
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +567 -198
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +243 -94
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +243 -94
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip.js +243 -94
  22. package/dist/zip.min.js +1 -1
  23. package/eslint.config.mjs +1 -1
  24. package/index-native.cjs +567 -198
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +567 -198
  27. package/index.d.cts +551 -45
  28. package/index.d.ts +551 -45
  29. package/index.min.js +1 -1
  30. package/lib/core/codec-worker-web.js +13 -4
  31. package/lib/core/codec-worker.js +2 -0
  32. package/lib/core/constants.js +9 -0
  33. package/lib/core/io.js +43 -4
  34. package/lib/core/options.js +2 -0
  35. package/lib/core/util/compatible-streams.js +3 -8
  36. package/lib/core/zip-entry.js +16 -0
  37. package/lib/core/zip-fs.js +236 -107
  38. package/lib/core/zip-reader.js +106 -40
  39. package/lib/core/zip-writer.js +171 -41
  40. package/lib/zip-core-writer.js +3 -0
  41. package/package.json +9 -7
@@ -34,26 +34,31 @@ import {
34
34
  Reader,
35
35
  TextReader,
36
36
  TextWriter,
37
+ getTextSize,
37
38
  Data64URIReader,
38
39
  Data64URIWriter,
39
40
  Uint8ArrayReader,
40
41
  Uint8ArrayWriter,
41
42
  BlobReader,
42
43
  BlobWriter,
43
- HttpReader
44
+ HttpReader,
45
+ ownsWritable
44
46
  } from "./io.js";
45
47
  import {
46
48
  ZipReader,
47
49
  ERR_INVALID_PASSWORD
48
50
  } from "./zip-reader.js";
49
51
  import {
50
- ZipWriter
52
+ ZipWriter,
53
+ getEntriesSize
51
54
  } from "./zip-writer.js";
52
55
  import {
53
56
  Entry
54
57
  } from "./zip-entry.js";
58
+ import { ProgressWatcherStream, callHandler } from "./codec-worker.js";
55
59
  import {
56
60
  UNDEFINED_VALUE,
61
+ FUNCTION_TYPE,
57
62
  EXTRAFIELD_TYPE_ZIP64,
58
63
  EXTRAFIELD_TYPE_AES,
59
64
  EXTRAFIELD_TYPE_NTFS,
@@ -71,6 +76,7 @@ import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-st
71
76
 
72
77
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
73
78
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
79
+ const ERR_INVALID_PASS_THROUGH = "Invalid passThrough option (use readerOptions.passThrough or set uncompressedSize for each entry)";
74
80
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
75
81
  const ERR_ABORTED = "The operation was aborted";
76
82
  const ABORT_ERROR_NAME = "AbortError";
@@ -108,6 +114,7 @@ class ZipEntry {
108
114
  parent,
109
115
  children: [],
110
116
  uncompressedSize: params.uncompressedSize || 0,
117
+ undeterminedSize: params.undeterminedSize || params.uncompressedSize === UNDEFINED_VALUE,
111
118
  passThrough: params.passThrough
112
119
  });
113
120
  if (parent || !fs.root) {
@@ -175,16 +182,17 @@ class ZipFileEntry extends ZipEntry {
175
182
 
176
183
  async getData(writer, options = {}) {
177
184
  const zipEntry = this;
178
- if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data)) {
185
+ if (!writer || (writer.constructor == zipEntry.Writer && zipEntry.data && keepsContentType(writer, zipEntry.data))) {
179
186
  return zipEntry.data;
180
187
  } else {
181
188
  const reader = zipEntry.reader = createReader(zipEntry.Reader, zipEntry.data, options);
182
- const uncompressedSize = zipEntry.data ? zipEntry.data.uncompressedSize : reader.size;
183
- await Promise.all([initStream(reader), initStream(writer, uncompressedSize)]);
184
- const { readable } = reader;
189
+ const dataSize = zipEntry.uncompressedSize || reader.size;
190
+ await Promise.all([initStream(reader), initStream(writer, dataSize)]);
185
191
  const { signal } = options;
192
+ const readable = createProgressReadable(zipEntry, reader, options, signal);
193
+ const preventClose = !ownsWritable(writer) && Boolean(options.preventClose);
186
194
  zipEntry.uncompressedSize = reader.size;
187
- await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal });
195
+ await toCompatibleReadable(readable).pipeTo(toCompatibleWritable(writer.writable), { signal, preventClose, preventAbort: preventClose });
188
196
  return writer.getData ? writer.getData() : writer.writable;
189
197
  }
190
198
  }
@@ -315,7 +323,7 @@ class ZipDirectoryEntry extends ZipEntry {
315
323
  Reader: TextReader,
316
324
  Writer: TextWriter,
317
325
  options,
318
- uncompressedSize: text.length
326
+ uncompressedSize: getTextSize(text)
319
327
  });
320
328
  }
321
329
 
@@ -444,10 +452,16 @@ class ZipDirectoryEntry extends ZipEntry {
444
452
  }
445
453
 
446
454
  async importZip(reader, options = {}) {
447
- await initStream(reader);
448
- const zipReader = new ZipReader(reader, options);
455
+ let zipReader;
456
+ if (reader && typeof reader.getEntries == FUNCTION_TYPE) {
457
+ zipReader = reader;
458
+ options = Object.assign({}, zipReader.options, options);
459
+ } else {
460
+ await initStream(reader);
461
+ zipReader = new ZipReader(reader, options);
462
+ }
449
463
  const importedEntries = [];
450
- const entries = await zipReader.getEntries();
464
+ const entries = await zipReader.getEntries(options);
451
465
  for (const entry of entries) {
452
466
  let parent = this;
453
467
  try {
@@ -469,7 +483,7 @@ class ZipDirectoryEntry extends ZipEntry {
469
483
  importedEntries.push(addChild(parent, name, {
470
484
  data: entry,
471
485
  Reader: getZipBlobReader(Object.assign({}, options)),
472
- uncompressedSize: entry.uncompressedSize,
486
+ uncompressedSize: options.passThrough ? entry.compressedSize : entry.uncompressedSize,
473
487
  passThrough: options.passThrough
474
488
  }));
475
489
  } else {
@@ -511,11 +525,25 @@ class ZipDirectoryEntry extends ZipEntry {
511
525
  }
512
526
  const [readers] = await Promise.all([initReaders(zipEntry, options.readerOptions), initStream(writer)]);
513
527
  const zipWriter = new ZipWriter(writer, options);
514
- await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], "uncompressedSize"), options, readers);
515
- await zipWriter.close();
528
+ await exportZip(zipWriter, zipEntry, getTotalSize([zipEntry], getUncompressedSize), options, readers);
529
+ await zipWriter.close(options.globalComment);
516
530
  return writer.getData ? writer.getData() : writer.writable;
517
531
  }
518
532
 
533
+ getExportedSize(options = {}) {
534
+ const zipEntry = this;
535
+ options = Object.assign({}, options);
536
+ if (options.bufferedWrite === UNDEFINED_VALUE) {
537
+ options.bufferedWrite = true;
538
+ }
539
+ const writeOrderGuaranteed = !options.bufferedWrite ||
540
+ (options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
541
+ return getEntriesSize(options, Array.from(zipEntry.getChildren({ recursive: true }), child => {
542
+ const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
543
+ return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
544
+ }), writeOrderGuaranteed, options.globalComment);
545
+ }
546
+
519
547
  getChildByName(name) {
520
548
  const children = this.children;
521
549
  for (let childIndex = 0; childIndex < children.length; childIndex++) {
@@ -723,6 +751,10 @@ class FS {
723
751
  return this.root.exportZip(writer, options);
724
752
  }
725
753
 
754
+ getExportedSize(options) {
755
+ return this.root.getExportedSize(options);
756
+ }
757
+
726
758
  isPasswordProtected() {
727
759
  return this.root.isPasswordProtected();
728
760
  }
@@ -733,14 +765,14 @@ class FS {
733
765
  }
734
766
 
735
767
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
736
- export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_ABORTED };
768
+ export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_INVALID_PASS_THROUGH, ERR_ABORTED };
737
769
 
738
- function getTotalSize(entries, propertyName) {
770
+ function getTotalSize(entries, getEntrySize) {
739
771
  let size = 0;
740
772
  const pendingEntries = Array.from(entries);
741
773
  while (pendingEntries.length) {
742
774
  const entry = pendingEntries.pop();
743
- size += entry[propertyName] || 0;
775
+ size += getEntrySize(entry) || 0;
744
776
  for (const child of entry.children) {
745
777
  pendingEntries.push(child);
746
778
  }
@@ -748,6 +780,15 @@ function getTotalSize(entries, propertyName) {
748
780
  return size;
749
781
  }
750
782
 
783
+ function getUncompressedSize(entry) {
784
+ return entry.uncompressedSize;
785
+ }
786
+
787
+ function getExtractedSize(entry, passThrough) {
788
+ const { data } = entry;
789
+ return passThrough && data instanceof Entry ? data.compressedSize : entry.uncompressedSize;
790
+ }
791
+
751
792
  function getReadableReader(readable) {
752
793
  let consumed;
753
794
  return function () {
@@ -770,10 +811,17 @@ function getZipBlobReader(options) {
770
811
 
771
812
  async init() {
772
813
  const zipBlobReader = this;
773
- zipBlobReader.size = zipBlobReader.entry.uncompressedSize;
774
- const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign({}, options, zipBlobReader.options));
814
+ const readerOptions = Object.assign({}, options, zipBlobReader.options);
815
+ const { checkOverlappingEntry, checkOverlappingEntryOnly } = readerOptions;
816
+ const data = await zipBlobReader.entry.getData(new BlobWriter(), Object.assign(readerOptions, {
817
+ checkPasswordOnly: false,
818
+ checkOverlappingEntry: checkOverlappingEntryOnly || checkOverlappingEntry,
819
+ checkOverlappingEntryOnly: false,
820
+ preventClose: false
821
+ }));
775
822
  zipBlobReader.data = data;
776
823
  zipBlobReader.blobReader = new BlobReader(data);
824
+ zipBlobReader.size = data.size;
777
825
  super.init();
778
826
  }
779
827
 
@@ -787,6 +835,30 @@ function createReader(Reader, data, options) {
787
835
  return Reader.prototype ? new Reader(data, options) : Reader(data, options);
788
836
  }
789
837
 
838
+ function keepsContentType(writer, data) {
839
+ const { contentType } = writer;
840
+ if (contentType === UNDEFINED_VALUE) {
841
+ return true;
842
+ } else if (writer.constructor == BlobWriter) {
843
+ return data.type == contentType;
844
+ } else if (writer.constructor == Data64URIWriter) {
845
+ return data.startsWith(writer.data);
846
+ } else {
847
+ return true;
848
+ }
849
+ }
850
+
851
+ function createProgressReadable(zipEntry, reader, options, signal) {
852
+ const { onstart, onprogress, onend } = options;
853
+ const { readable } = reader;
854
+ const coreReaderReportsProgress = zipEntry.data instanceof Entry;
855
+ if (coreReaderReportsProgress || (!onstart && !onprogress && !onend)) {
856
+ return readable;
857
+ } else {
858
+ return toCompatibleReadable(readable).pipeThrough(new ProgressWatcherStream({ onstart, onprogress, onend, size: reader.size }), { signal });
859
+ }
860
+ }
861
+
790
862
  async function initReaders(entry, options) {
791
863
  const fileEntries = [];
792
864
  const pendingEntries = [entry];
@@ -819,6 +891,7 @@ async function initReaders(entry, options) {
819
891
  }
820
892
  if (reader.size !== UNDEFINED_VALUE) {
821
893
  child.uncompressedSize = reader.size;
894
+ child.undeterminedSize = false;
822
895
  }
823
896
  }));
824
897
  return readers;
@@ -868,6 +941,90 @@ function aggregateEntryErrors(errors) {
868
941
  return error;
869
942
  }
870
943
 
944
+ function getChildEntryOptions(child, selectedEntry, options) {
945
+ const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
946
+ const childOptions = child.options || {};
947
+ let zipEntryMetadata = {};
948
+ let passThroughOptions = {};
949
+ if (child.data instanceof Entry) {
950
+ const {
951
+ externalFileAttributes,
952
+ versionMadeBy,
953
+ comment,
954
+ lastModDate,
955
+ creationDate,
956
+ lastAccessDate,
957
+ uncompressedSize,
958
+ encrypted,
959
+ zipCrypto,
960
+ crc32,
961
+ compressionMethod,
962
+ extraFieldAES,
963
+ internalFileAttributes,
964
+ extraField,
965
+ uid,
966
+ gid
967
+ } = child.data;
968
+ zipEntryMetadata = {
969
+ externalFileAttributes,
970
+ versionMadeBy,
971
+ comment,
972
+ lastModDate,
973
+ creationDate,
974
+ lastAccessDate,
975
+ internalFileAttributes
976
+ };
977
+ const userExtraField = getUserExtraField(extraField);
978
+ if (userExtraField) {
979
+ zipEntryMetadata.extraField = userExtraField;
980
+ }
981
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
982
+ Object.assign(zipEntryMetadata, {
983
+ uid,
984
+ gid,
985
+ unixExtraFieldType: INFOZIP_EXTRA_FIELD_TYPE
986
+ });
987
+ }
988
+ if (isPassThrough(child, options)) {
989
+ let level, encryptionStrength;
990
+ if (compressionMethod === 0) {
991
+ level = 0;
992
+ }
993
+ if (extraFieldAES) {
994
+ encryptionStrength = extraFieldAES.strength;
995
+ }
996
+ passThroughOptions = {
997
+ passThrough: true,
998
+ encrypted,
999
+ zipCrypto,
1000
+ crc32,
1001
+ uncompressedSize,
1002
+ level,
1003
+ encryptionStrength,
1004
+ compressionMethod
1005
+ };
1006
+ }
1007
+ }
1008
+ const entryOptions = Object.assign({}, zipEntryMetadata, options, passThroughOptions, childOptions, { directory: child.directory });
1009
+ if (!child.directory && entryOptions.passThrough && entryOptions.uncompressedSize === UNDEFINED_VALUE) {
1010
+ throw new Error(ERR_INVALID_PASS_THROUGH);
1011
+ }
1012
+ return { name, entryOptions };
1013
+ }
1014
+
1015
+ function getDeterminedSize(child, passThrough) {
1016
+ const { reader } = child;
1017
+ if (reader && reader.size !== UNDEFINED_VALUE) {
1018
+ return reader.size;
1019
+ }
1020
+ return child.undeterminedSize ? UNDEFINED_VALUE : getExtractedSize(child, passThrough);
1021
+ }
1022
+
1023
+ function isPassThrough(child, options) {
1024
+ const { readerOptions } = options;
1025
+ return Boolean(!child.directory && (child.passThrough || (readerOptions && readerOptions.passThrough)));
1026
+ }
1027
+
871
1028
  function getUserExtraField(extraField) {
872
1029
  if (extraField) {
873
1030
  const userExtraField = new Map();
@@ -883,8 +1040,14 @@ function getUserExtraField(extraField) {
883
1040
  }
884
1041
 
885
1042
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
1043
+ const { onstart, onprogress, onend, onentryprogress } = options;
886
1044
  const selectedEntry = entry;
887
- const entryOffsets = new Map();
1045
+ const totalEntries = getTotalSize(entry.children, () => 1);
1046
+ let writtenSize = 0;
1047
+ let writtenEntries = 0;
1048
+ if (onstart) {
1049
+ await callHandler(onstart, totalSize);
1050
+ }
888
1051
  if (options.bufferedWrite) {
889
1052
  await processChildren(entry);
890
1053
  } else {
@@ -892,6 +1055,9 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
892
1055
  await addChild(child);
893
1056
  }
894
1057
  }
1058
+ if (onend) {
1059
+ await callHandler(onend, writtenSize);
1060
+ }
895
1061
 
896
1062
  async function processChildren(entry) {
897
1063
  const results = await Promise.allSettled(entry.children.map(async child => {
@@ -905,81 +1071,23 @@ async function exportZip(zipWriter, entry, totalSize, options, readers) {
905
1071
  }
906
1072
 
907
1073
  async function addChild(child) {
908
- const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
909
- const childOptions = child.options || {};
910
- let zipEntryOptions = {};
911
- if (child.data instanceof Entry) {
912
- const {
913
- externalFileAttributes,
914
- versionMadeBy,
915
- comment,
916
- lastModDate,
917
- creationDate,
918
- lastAccessDate,
919
- uncompressedSize,
920
- encrypted,
921
- zipCrypto,
922
- crc32,
923
- compressionMethod,
924
- extraFieldAES,
925
- internalFileAttributes,
926
- extraField,
927
- uid,
928
- gid
929
- } = child.data;
930
- zipEntryOptions = {
931
- externalFileAttributes,
932
- versionMadeBy,
933
- comment,
934
- lastModDate,
935
- creationDate,
936
- lastAccessDate,
937
- internalFileAttributes
938
- };
939
- const userExtraField = getUserExtraField(extraField);
940
- if (userExtraField) {
941
- zipEntryOptions.extraField = userExtraField;
942
- }
943
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
944
- Object.assign(zipEntryOptions, {
945
- uid,
946
- gid,
947
- unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
948
- });
949
- }
950
- if (child.passThrough) {
951
- let level, encryptionStrength;
952
- if (compressionMethod === 0) {
953
- level = 0;
954
- }
955
- if (extraFieldAES) {
956
- encryptionStrength = extraFieldAES.strength;
957
- }
958
- zipEntryOptions = Object.assign(zipEntryOptions, {
959
- passThrough: true,
960
- encrypted,
961
- zipCrypto,
962
- crc32,
963
- uncompressedSize,
964
- level,
965
- encryptionStrength,
966
- compressionMethod
967
- });
968
- }
969
- }
970
- await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
971
- directory: child.directory,
1074
+ const { name, entryOptions } = getChildEntryOptions(child, selectedEntry, options);
1075
+ let entryWrittenSize = 0;
1076
+ const entryMetadata = await zipWriter.add(name, readers.get(child), Object.assign(entryOptions, {
1077
+ onstart: UNDEFINED_VALUE,
1078
+ onend: UNDEFINED_VALUE,
972
1079
  onprogress: async indexProgress => {
973
- if (options.onprogress) {
974
- entryOffsets.set(name, indexProgress);
975
- try {
976
- await options.onprogress(Array.from(entryOffsets.values()).reduce((previousValue, currentValue) => previousValue + currentValue), totalSize);
977
- } catch {
978
- // ignored
979
- }
1080
+ writtenSize += indexProgress - entryWrittenSize;
1081
+ entryWrittenSize = indexProgress;
1082
+ if (onprogress) {
1083
+ await callHandler(onprogress, writtenSize, totalSize);
980
1084
  }
981
1085
  }
982
1086
  }));
1087
+ writtenEntries++;
1088
+ if (onentryprogress) {
1089
+ await callHandler(onentryprogress, writtenEntries, totalEntries, entryMetadata);
1090
+ }
983
1091
  }
984
1092
  }
985
1093
 
@@ -1007,7 +1115,7 @@ function addFileSystemHandle(zipEntry, handle, options) {
1007
1115
  })
1008
1116
  );
1009
1117
  } else if (handle.kind == "directory") {
1010
- const directoryEntry = parentEntry.addDirectory(handle.name);
1118
+ const directoryEntry = parentEntry.addDirectory(handle.name, options);
1011
1119
  addedEntries.push(directoryEntry);
1012
1120
  for await (const childHandle of handle.values()) {
1013
1121
  await addFile(directoryEntry, childHandle, addedEntries, entryName);
@@ -1029,15 +1137,29 @@ function addFileSystemHandle(zipEntry, handle, options) {
1029
1137
  }
1030
1138
 
1031
1139
  async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1032
- const totalSize = getTotalSize([zipEntry], "uncompressedSize");
1033
- const writtenSizes = new Map();
1140
+ const { onstart, onprogress, onend } = options;
1034
1141
  const abortController = new AbortController();
1035
1142
  const { signal } = abortController;
1036
1143
  const releaseSignal = forwardAbort(options.signal, abortController);
1144
+ const getDataOptions = Object.assign({}, options, options.readerOptions, {
1145
+ signal,
1146
+ onstart: UNDEFINED_VALUE,
1147
+ onprogress: UNDEFINED_VALUE,
1148
+ onend: UNDEFINED_VALUE,
1149
+ preventClose: false
1150
+ });
1151
+ const totalSize = getTotalSize([zipEntry], entry => getExtractedSize(entry, getDataOptions.passThrough));
1037
1152
  const exportedEntryNames = [];
1038
1153
  let exportAborted = false;
1154
+ let writtenSize = 0;
1039
1155
  try {
1156
+ if (onstart) {
1157
+ await callHandler(onstart, totalSize);
1158
+ }
1040
1159
  await exportChildren(zipEntry, directoryHandle);
1160
+ if (onend) {
1161
+ await callHandler(onend, writtenSize);
1162
+ }
1041
1163
  } catch (error) {
1042
1164
  try {
1043
1165
  error.exportedEntryNames = exportedEntryNames;
@@ -1050,6 +1172,25 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1050
1172
  }
1051
1173
  return directoryHandle;
1052
1174
 
1175
+ function createProgressWritable(writable) {
1176
+ const writer = writable.getWriter();
1177
+ return new WritableStream({
1178
+ async write(chunk) {
1179
+ await writer.write(chunk);
1180
+ writtenSize += chunk.length;
1181
+ if (onprogress) {
1182
+ await callHandler(onprogress, writtenSize, totalSize);
1183
+ }
1184
+ },
1185
+ close() {
1186
+ return writer.close();
1187
+ },
1188
+ abort(reason) {
1189
+ return writer.abort(reason);
1190
+ }
1191
+ });
1192
+ }
1193
+
1053
1194
  async function exportChildren(entry, parentHandle) {
1054
1195
  if (options.concurrent) {
1055
1196
  const results = await Promise.allSettled(entry.children.map(child => exportChild(child, parentHandle)));
@@ -1081,19 +1222,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1081
1222
  const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
1082
1223
  const writable = await fileHandle.createWritable();
1083
1224
  try {
1084
- await child.getData({ writable }, Object.assign({}, options, {
1085
- signal,
1086
- onprogress: async progress => {
1087
- if (options.onprogress) {
1088
- writtenSizes.set(child.id, progress);
1089
- try {
1090
- await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
1091
- } catch {
1092
- // ignored
1093
- }
1094
- }
1095
- }
1096
- }));
1225
+ await child.getData({ writable: createProgressWritable(writable) }, getDataOptions);
1097
1226
  } catch (error) {
1098
1227
  throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
1099
1228
  }