@cj-tech-master/excelts 4.2.1-canary.20260111102127.f808a37 → 4.2.1

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 (232) hide show
  1. package/THIRD_PARTY_NOTICES.md +31 -0
  2. package/dist/browser/index.browser.d.ts +0 -1
  3. package/dist/browser/index.browser.js +0 -12
  4. package/dist/browser/modules/archive/byte-queue.d.ts +18 -0
  5. package/dist/browser/modules/archive/byte-queue.js +125 -0
  6. package/dist/browser/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
  7. package/dist/browser/modules/archive/{compression/compress.browser.d.ts → compress.browser.d.ts} +8 -2
  8. package/dist/{esm/modules/archive/compression → browser/modules/archive}/compress.browser.js +11 -3
  9. package/dist/browser/modules/archive/{compression/compress.d.ts → compress.d.ts} +2 -2
  10. package/dist/{esm/modules/archive/compression → browser/modules/archive}/compress.js +1 -1
  11. package/dist/browser/modules/archive/{compression/crc32.browser.d.ts → crc32.browser.d.ts} +1 -1
  12. package/dist/browser/modules/archive/{compression/crc32.d.ts → crc32.d.ts} +1 -1
  13. package/dist/browser/modules/archive/{compression/crc32.js → crc32.js} +1 -1
  14. package/dist/browser/modules/archive/defaults.d.ts +0 -1
  15. package/dist/browser/modules/archive/defaults.js +3 -6
  16. package/dist/browser/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
  17. package/dist/browser/modules/archive/{unzip/extract.d.ts → extract.d.ts} +2 -2
  18. package/dist/browser/modules/archive/index.base.d.ts +4 -4
  19. package/dist/browser/modules/archive/index.base.js +6 -3
  20. package/dist/browser/modules/archive/index.browser.d.ts +4 -3
  21. package/dist/browser/modules/archive/index.browser.js +7 -3
  22. package/dist/browser/modules/archive/index.d.ts +4 -3
  23. package/dist/browser/modules/archive/index.js +5 -3
  24. package/dist/browser/modules/archive/{unzip/stream.base.d.ts → parse.base.d.ts} +2 -36
  25. package/dist/browser/modules/archive/parse.base.js +644 -0
  26. package/dist/browser/modules/archive/{unzip/stream.browser.d.ts → parse.browser.d.ts} +1 -1
  27. package/dist/{esm/modules/archive/unzip/stream.browser.js → browser/modules/archive/parse.browser.js} +110 -371
  28. package/dist/browser/modules/archive/{unzip/stream.d.ts → parse.d.ts} +2 -2
  29. package/dist/{esm/modules/archive/unzip/stream.js → browser/modules/archive/parse.js} +5 -6
  30. package/dist/browser/modules/archive/{compression/streaming-compress.browser.d.ts → streaming-compress.browser.d.ts} +2 -2
  31. package/dist/browser/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
  32. package/dist/browser/modules/archive/{compression/streaming-compress.d.ts → streaming-compress.d.ts} +2 -2
  33. package/dist/browser/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
  34. package/dist/browser/modules/archive/{zip/stream.d.ts → streaming-zip.d.ts} +5 -28
  35. package/dist/{esm/modules/archive/zip/stream.js → browser/modules/archive/streaming-zip.js} +48 -192
  36. package/dist/browser/modules/archive/utils/bytes.js +16 -16
  37. package/dist/browser/modules/archive/utils/parse-buffer.js +23 -21
  38. package/dist/browser/modules/archive/utils/timestamps.js +1 -62
  39. package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  40. package/dist/browser/modules/archive/utils/zip-extra-fields.js +14 -26
  41. package/dist/browser/modules/archive/utils/zip-extra.d.ts +18 -0
  42. package/dist/browser/modules/archive/utils/zip-extra.js +68 -0
  43. package/dist/browser/modules/archive/zip-builder.d.ts +117 -0
  44. package/dist/browser/modules/archive/zip-builder.js +292 -0
  45. package/dist/browser/modules/archive/zip-constants.d.ts +18 -0
  46. package/dist/browser/modules/archive/zip-constants.js +23 -0
  47. package/dist/{esm/modules/archive/zip → browser/modules/archive}/zip-entry-metadata.js +3 -3
  48. package/dist/{types/modules/archive/unzip → browser/modules/archive}/zip-parser.d.ts +1 -1
  49. package/dist/{esm/modules/archive/unzip → browser/modules/archive}/zip-parser.js +24 -38
  50. package/dist/browser/modules/archive/{zip-spec/zip-records.d.ts → zip-records.d.ts} +0 -20
  51. package/dist/browser/modules/archive/zip-records.js +84 -0
  52. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
  53. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  54. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
  55. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +6 -3
  56. package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
  57. package/dist/browser/modules/stream/streams.browser.d.ts +30 -28
  58. package/dist/browser/modules/stream/streams.browser.js +710 -830
  59. package/dist/browser/modules/stream/streams.js +58 -140
  60. package/dist/cjs/modules/archive/byte-queue.js +129 -0
  61. package/dist/cjs/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
  62. package/dist/cjs/modules/archive/{compression/compress.browser.js → compress.browser.js} +11 -3
  63. package/dist/cjs/modules/archive/{compression/compress.js → compress.js} +1 -1
  64. package/dist/cjs/modules/archive/{compression/crc32.js → crc32.js} +1 -1
  65. package/dist/cjs/modules/archive/defaults.js +4 -7
  66. package/dist/cjs/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
  67. package/dist/cjs/modules/archive/index.base.js +19 -9
  68. package/dist/cjs/modules/archive/index.browser.js +10 -4
  69. package/dist/cjs/modules/archive/index.js +8 -4
  70. package/dist/cjs/modules/archive/parse.base.js +666 -0
  71. package/dist/cjs/modules/archive/{unzip/stream.browser.js → parse.browser.js} +111 -372
  72. package/dist/cjs/modules/archive/{unzip/stream.js → parse.js} +8 -9
  73. package/dist/cjs/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
  74. package/dist/cjs/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
  75. package/dist/cjs/modules/archive/{zip/stream.js → streaming-zip.js} +50 -194
  76. package/dist/cjs/modules/archive/utils/bytes.js +16 -16
  77. package/dist/cjs/modules/archive/utils/parse-buffer.js +23 -21
  78. package/dist/cjs/modules/archive/utils/timestamps.js +3 -64
  79. package/dist/cjs/modules/archive/utils/zip-extra-fields.js +14 -26
  80. package/dist/cjs/modules/archive/utils/zip-extra.js +74 -0
  81. package/dist/cjs/modules/archive/zip-builder.js +297 -0
  82. package/dist/cjs/modules/archive/zip-constants.js +26 -0
  83. package/dist/cjs/modules/archive/{zip/zip-entry-metadata.js → zip-entry-metadata.js} +5 -5
  84. package/dist/cjs/modules/archive/{unzip/zip-parser.js → zip-parser.js} +33 -47
  85. package/dist/cjs/modules/archive/zip-records.js +90 -0
  86. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
  87. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
  88. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +9 -6
  89. package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
  90. package/dist/cjs/modules/stream/streams.browser.js +710 -830
  91. package/dist/cjs/modules/stream/streams.js +58 -140
  92. package/dist/esm/index.browser.js +0 -12
  93. package/dist/esm/modules/archive/byte-queue.js +125 -0
  94. package/dist/esm/modules/archive/{compression/compress.base.js → compress.base.js} +1 -1
  95. package/dist/{browser/modules/archive/compression → esm/modules/archive}/compress.browser.js +11 -3
  96. package/dist/{browser/modules/archive/compression → esm/modules/archive}/compress.js +1 -1
  97. package/dist/esm/modules/archive/{compression/crc32.js → crc32.js} +1 -1
  98. package/dist/esm/modules/archive/defaults.js +3 -6
  99. package/dist/esm/modules/archive/{compression/deflate-fallback.js → deflate-fallback.js} +1 -1
  100. package/dist/esm/modules/archive/index.base.js +6 -3
  101. package/dist/esm/modules/archive/index.browser.js +7 -3
  102. package/dist/esm/modules/archive/index.js +5 -3
  103. package/dist/esm/modules/archive/parse.base.js +644 -0
  104. package/dist/{browser/modules/archive/unzip/stream.browser.js → esm/modules/archive/parse.browser.js} +110 -371
  105. package/dist/{browser/modules/archive/unzip/stream.js → esm/modules/archive/parse.js} +5 -6
  106. package/dist/esm/modules/archive/{compression/streaming-compress.browser.js → streaming-compress.browser.js} +3 -3
  107. package/dist/esm/modules/archive/{compression/streaming-compress.js → streaming-compress.js} +2 -2
  108. package/dist/{browser/modules/archive/zip/stream.js → esm/modules/archive/streaming-zip.js} +48 -192
  109. package/dist/esm/modules/archive/utils/bytes.js +16 -16
  110. package/dist/esm/modules/archive/utils/parse-buffer.js +23 -21
  111. package/dist/esm/modules/archive/utils/timestamps.js +1 -62
  112. package/dist/esm/modules/archive/utils/zip-extra-fields.js +14 -26
  113. package/dist/esm/modules/archive/utils/zip-extra.js +68 -0
  114. package/dist/esm/modules/archive/zip-builder.js +292 -0
  115. package/dist/esm/modules/archive/zip-constants.js +23 -0
  116. package/dist/{browser/modules/archive/zip → esm/modules/archive}/zip-entry-metadata.js +3 -3
  117. package/dist/{browser/modules/archive/unzip → esm/modules/archive}/zip-parser.js +24 -38
  118. package/dist/esm/modules/archive/zip-records.js +84 -0
  119. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
  120. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
  121. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +6 -3
  122. package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
  123. package/dist/esm/modules/stream/streams.browser.js +710 -830
  124. package/dist/esm/modules/stream/streams.js +58 -140
  125. package/dist/iife/THIRD_PARTY_NOTICES.md +31 -0
  126. package/dist/iife/excelts.iife.js +4425 -6215
  127. package/dist/iife/excelts.iife.js.map +1 -1
  128. package/dist/iife/excelts.iife.min.js +31 -103
  129. package/dist/types/index.browser.d.ts +0 -1
  130. package/dist/types/modules/archive/byte-queue.d.ts +18 -0
  131. package/dist/types/modules/archive/{compression/compress.browser.d.ts → compress.browser.d.ts} +8 -2
  132. package/dist/types/modules/archive/defaults.d.ts +0 -1
  133. package/dist/types/modules/archive/index.base.d.ts +4 -4
  134. package/dist/types/modules/archive/index.browser.d.ts +4 -3
  135. package/dist/types/modules/archive/index.d.ts +4 -3
  136. package/dist/types/modules/archive/{unzip/stream.base.d.ts → parse.base.d.ts} +4 -38
  137. package/dist/types/modules/archive/{unzip/stream.browser.d.ts → parse.browser.d.ts} +2 -2
  138. package/dist/types/modules/archive/{unzip/stream.d.ts → parse.d.ts} +3 -3
  139. package/dist/types/modules/archive/{compression/streaming-compress.browser.d.ts → streaming-compress.browser.d.ts} +1 -1
  140. package/dist/types/modules/archive/{zip/stream.d.ts → streaming-zip.d.ts} +6 -29
  141. package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  142. package/dist/types/modules/archive/utils/zip-extra.d.ts +18 -0
  143. package/dist/types/modules/archive/zip-builder.d.ts +117 -0
  144. package/dist/types/modules/archive/zip-constants.d.ts +18 -0
  145. package/dist/types/modules/archive/{zip/zip-entry-metadata.d.ts → zip-entry-metadata.d.ts} +1 -1
  146. package/dist/{browser/modules/archive/unzip → types/modules/archive}/zip-parser.d.ts +1 -1
  147. package/dist/types/modules/archive/{zip-spec/zip-records.d.ts → zip-records.d.ts} +0 -20
  148. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  149. package/dist/types/modules/stream/streams.browser.d.ts +30 -28
  150. package/package.json +1 -5
  151. package/dist/browser/modules/archive/internal/byte-queue.d.ts +0 -33
  152. package/dist/browser/modules/archive/internal/byte-queue.js +0 -407
  153. package/dist/browser/modules/archive/io/archive-sink.d.ts +0 -9
  154. package/dist/browser/modules/archive/io/archive-sink.js +0 -77
  155. package/dist/browser/modules/archive/io/archive-source.d.ts +0 -8
  156. package/dist/browser/modules/archive/io/archive-source.js +0 -107
  157. package/dist/browser/modules/archive/unzip/index.d.ts +0 -40
  158. package/dist/browser/modules/archive/unzip/index.js +0 -164
  159. package/dist/browser/modules/archive/unzip/stream.base.js +0 -1022
  160. package/dist/browser/modules/archive/utils/async-queue.d.ts +0 -7
  161. package/dist/browser/modules/archive/utils/async-queue.js +0 -103
  162. package/dist/browser/modules/archive/utils/compressibility.d.ts +0 -10
  163. package/dist/browser/modules/archive/utils/compressibility.js +0 -57
  164. package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +0 -21
  165. package/dist/browser/modules/archive/utils/pattern-scanner.js +0 -27
  166. package/dist/browser/modules/archive/zip/index.d.ts +0 -42
  167. package/dist/browser/modules/archive/zip/index.js +0 -157
  168. package/dist/browser/modules/archive/zip/zip-bytes.d.ts +0 -73
  169. package/dist/browser/modules/archive/zip/zip-bytes.js +0 -239
  170. package/dist/browser/modules/archive/zip-spec/zip-records.js +0 -126
  171. package/dist/cjs/modules/archive/internal/byte-queue.js +0 -411
  172. package/dist/cjs/modules/archive/io/archive-sink.js +0 -82
  173. package/dist/cjs/modules/archive/io/archive-source.js +0 -114
  174. package/dist/cjs/modules/archive/unzip/index.js +0 -170
  175. package/dist/cjs/modules/archive/unzip/stream.base.js +0 -1044
  176. package/dist/cjs/modules/archive/utils/async-queue.js +0 -106
  177. package/dist/cjs/modules/archive/utils/compressibility.js +0 -60
  178. package/dist/cjs/modules/archive/utils/pattern-scanner.js +0 -31
  179. package/dist/cjs/modules/archive/zip/index.js +0 -162
  180. package/dist/cjs/modules/archive/zip/zip-bytes.js +0 -242
  181. package/dist/cjs/modules/archive/zip-spec/zip-records.js +0 -136
  182. package/dist/esm/modules/archive/internal/byte-queue.js +0 -407
  183. package/dist/esm/modules/archive/io/archive-sink.js +0 -77
  184. package/dist/esm/modules/archive/io/archive-source.js +0 -107
  185. package/dist/esm/modules/archive/unzip/index.js +0 -164
  186. package/dist/esm/modules/archive/unzip/stream.base.js +0 -1022
  187. package/dist/esm/modules/archive/utils/async-queue.js +0 -103
  188. package/dist/esm/modules/archive/utils/compressibility.js +0 -57
  189. package/dist/esm/modules/archive/utils/pattern-scanner.js +0 -27
  190. package/dist/esm/modules/archive/zip/index.js +0 -157
  191. package/dist/esm/modules/archive/zip/zip-bytes.js +0 -239
  192. package/dist/esm/modules/archive/zip-spec/zip-records.js +0 -126
  193. package/dist/types/modules/archive/internal/byte-queue.d.ts +0 -33
  194. package/dist/types/modules/archive/io/archive-sink.d.ts +0 -9
  195. package/dist/types/modules/archive/io/archive-source.d.ts +0 -8
  196. package/dist/types/modules/archive/unzip/index.d.ts +0 -40
  197. package/dist/types/modules/archive/utils/async-queue.d.ts +0 -7
  198. package/dist/types/modules/archive/utils/compressibility.d.ts +0 -10
  199. package/dist/types/modules/archive/utils/pattern-scanner.d.ts +0 -21
  200. package/dist/types/modules/archive/zip/index.d.ts +0 -42
  201. package/dist/types/modules/archive/zip/zip-bytes.d.ts +0 -73
  202. /package/dist/browser/modules/archive/{compression/compress.base.d.ts → compress.base.d.ts} +0 -0
  203. /package/dist/browser/modules/archive/{compression/crc32.base.d.ts → crc32.base.d.ts} +0 -0
  204. /package/dist/browser/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
  205. /package/dist/browser/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
  206. /package/dist/browser/modules/archive/{compression/deflate-fallback.d.ts → deflate-fallback.d.ts} +0 -0
  207. /package/dist/browser/modules/archive/{unzip/extract.js → extract.js} +0 -0
  208. /package/dist/browser/modules/archive/{compression/streaming-compress.base.d.ts → streaming-compress.base.d.ts} +0 -0
  209. /package/dist/browser/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
  210. /package/dist/browser/modules/archive/{zip-spec/zip-entry-info.d.ts → zip-entry-info.d.ts} +0 -0
  211. /package/dist/browser/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
  212. /package/dist/browser/modules/archive/{zip/zip-entry-metadata.d.ts → zip-entry-metadata.d.ts} +0 -0
  213. /package/dist/cjs/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
  214. /package/dist/cjs/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
  215. /package/dist/cjs/modules/archive/{unzip/extract.js → extract.js} +0 -0
  216. /package/dist/cjs/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
  217. /package/dist/cjs/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
  218. /package/dist/esm/modules/archive/{compression/crc32.base.js → crc32.base.js} +0 -0
  219. /package/dist/esm/modules/archive/{compression/crc32.browser.js → crc32.browser.js} +0 -0
  220. /package/dist/esm/modules/archive/{unzip/extract.js → extract.js} +0 -0
  221. /package/dist/esm/modules/archive/{compression/streaming-compress.base.js → streaming-compress.base.js} +0 -0
  222. /package/dist/esm/modules/archive/{zip-spec/zip-entry-info.js → zip-entry-info.js} +0 -0
  223. /package/dist/types/modules/archive/{compression/compress.base.d.ts → compress.base.d.ts} +0 -0
  224. /package/dist/types/modules/archive/{compression/compress.d.ts → compress.d.ts} +0 -0
  225. /package/dist/types/modules/archive/{compression/crc32.base.d.ts → crc32.base.d.ts} +0 -0
  226. /package/dist/types/modules/archive/{compression/crc32.browser.d.ts → crc32.browser.d.ts} +0 -0
  227. /package/dist/types/modules/archive/{compression/crc32.d.ts → crc32.d.ts} +0 -0
  228. /package/dist/types/modules/archive/{compression/deflate-fallback.d.ts → deflate-fallback.d.ts} +0 -0
  229. /package/dist/types/modules/archive/{unzip/extract.d.ts → extract.d.ts} +0 -0
  230. /package/dist/types/modules/archive/{compression/streaming-compress.base.d.ts → streaming-compress.base.d.ts} +0 -0
  231. /package/dist/types/modules/archive/{compression/streaming-compress.d.ts → streaming-compress.d.ts} +0 -0
  232. /package/dist/types/modules/archive/{zip-spec/zip-entry-info.d.ts → zip-entry-info.d.ts} +0 -0
@@ -6,11 +6,11 @@
6
6
  *
7
7
  * API compatible with Node.js version - supports .on("data"), .on("end"), .write(callback), .end()
8
8
  */
9
- import { EventEmitter } from "../../stream/index.js";
9
+ import { EventEmitter } from "../stream/index.js";
10
10
  import { deflateRawCompressed, inflateRaw } from "./deflate-fallback.js";
11
11
  import { hasDeflateRawWebStreams } from "./compress.base.js";
12
- import { concatUint8Arrays } from "../utils/bytes.js";
13
- import { DEFAULT_COMPRESS_LEVEL } from "../defaults.js";
12
+ import { concatUint8Arrays } from "./utils/bytes.js";
13
+ import { DEFAULT_COMPRESS_LEVEL } from "./defaults.js";
14
14
  import { asError } from "./streaming-compress.base.js";
15
15
  /**
16
16
  * Check if deflate-raw streaming compression is supported by this library.
@@ -5,8 +5,8 @@
5
5
  * Each write() immediately produces compressed output without waiting for end().
6
6
  */
7
7
  import { createDeflateRaw, createInflateRaw, constants } from "zlib";
8
- import { Transform } from "../../stream/index.js";
9
- import { DEFAULT_COMPRESS_LEVEL } from "../defaults.js";
8
+ import { Transform } from "../stream/index.js";
9
+ import { DEFAULT_COMPRESS_LEVEL } from "./defaults.js";
10
10
  /**
11
11
  * Wrapper around zlib DeflateRaw that flushes after every write
12
12
  * This ensures true streaming behavior - data is emitted immediately, not buffered
@@ -2,16 +2,15 @@
2
2
  * True Streaming ZIP creator - shared implementation.
3
3
  *
4
4
  * This module is intentionally platform-agnostic.
5
- * - In Node builds it uses `./compression/crc32` + `./compression/streaming-compress` (zlib-backed).
5
+ * - In Node builds it uses `./crc32` + `./streaming-compress` (zlib-backed).
6
6
  * - In browser builds the bundler aliases those imports to their browser variants.
7
7
  */
8
- import { crc32Update, crc32Finalize } from "../compression/crc32.browser.js";
9
- import { createDeflateStream } from "../compression/streaming-compress.browser.js";
10
- import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "../defaults.js";
11
- import { buildZipEntryMetadata, resolveZipCompressionMethod } from "./zip-entry-metadata.js";
12
- import { decodeUtf8, encodeUtf8 } from "../utils/text.js";
13
- import { isProbablyIncompressible } from "../utils/compressibility.js";
14
- import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader, VERSION_MADE_BY, VERSION_NEEDED } from "../zip-spec/zip-records.js";
8
+ import { crc32Update, crc32Finalize } from "./crc32.js";
9
+ import { createDeflateStream } from "./streaming-compress.js";
10
+ import { DEFAULT_ZIP_LEVEL, DEFAULT_ZIP_TIMESTAMPS } from "./defaults.js";
11
+ import { buildZipEntryMetadata } from "./zip-entry-metadata.js";
12
+ import { buildCentralDirectoryHeader, buildDataDescriptor, buildEndOfCentralDirectory, buildLocalFileHeader } from "./zip-records.js";
13
+ import { VERSION_MADE_BY, VERSION_NEEDED } from "./zip-constants.js";
15
14
  /**
16
15
  * True Streaming ZIP File - compresses chunk by chunk
17
16
  */
@@ -24,15 +23,9 @@ export class ZipDeflateFile {
24
23
  this._finalized = false;
25
24
  this._headerEmitted = false;
26
25
  this._ondata = null;
27
- this._onerror = null;
28
26
  this._centralDirEntryInfo = null;
29
27
  this._pendingEnd = false;
30
28
  this._emittedDataDescriptor = false;
31
- this._localHeader = null;
32
- // Smart STORE: delay method selection until we sample data.
33
- this._deflateWanted = null;
34
- this._pendingChunks = [];
35
- this._sampleLen = 0;
36
29
  // Promise resolution for completion (including data descriptor)
37
30
  this._completeResolve = null;
38
31
  this._completeReject = null;
@@ -41,70 +34,46 @@ export class ZipDeflateFile {
41
34
  // Queue for incoming data before ondata is set
42
35
  this._dataQueue = [];
43
36
  this._finalQueued = false;
44
- // Serialize push() calls so callers don't need to await to preserve ordering.
45
- this._pushChain = Promise.resolve();
46
37
  this.name = name;
47
38
  const modTime = options?.modTime ?? new Date();
48
39
  this._modTime = modTime;
49
40
  this.level = options?.level ?? DEFAULT_ZIP_LEVEL;
50
- this._smartStore = options?.smartStore ?? true;
51
- this._sampleBuffer = this._smartStore ? new Uint8Array(64 * 1024) : new Uint8Array(0);
52
41
  const metadata = buildZipEntryMetadata({
53
42
  name,
54
- comment: options?.comment ?? "",
43
+ comment: "",
55
44
  modTime,
56
45
  timestamps: options?.timestamps ?? DEFAULT_ZIP_TIMESTAMPS,
57
46
  useDataDescriptor: true,
58
- deflate: false
47
+ deflate: this.level > 0
59
48
  });
60
49
  this.nameBytes = metadata.nameBytes;
61
- this.commentBytes = metadata.commentBytes;
62
50
  this.dosTime = metadata.dosTime;
63
51
  this.dosDate = metadata.dosDate;
64
52
  this.extraField = metadata.extraField;
65
53
  this._flags = metadata.flags;
66
54
  this._compressionMethod = metadata.compressionMethod;
67
- // If smart store is disabled, decide method upfront and keep true streaming semantics.
68
- if (!this._smartStore) {
69
- const deflate = this.level > 0;
70
- this._deflateWanted = deflate;
71
- this._compressionMethod = this._buildCompressionMethod(deflate);
72
- if (deflate) {
73
- this._initDeflateStream();
74
- }
75
- return;
76
- }
77
- // Level 0: always STORE.
78
- if (this.level === 0) {
79
- this._deflateWanted = false;
80
- this._compressionMethod = this._buildCompressionMethod(false);
81
- }
82
- }
83
- _buildCompressionMethod(deflate) {
84
- return resolveZipCompressionMethod(deflate);
85
- }
86
- _initDeflateStream() {
87
- if (this._deflate) {
88
- return;
55
+ // Create deflate stream for compression
56
+ if (this.level > 0) {
57
+ this._deflate = createDeflateStream({ level: this.level });
58
+ this._deflate.on("error", (err) => {
59
+ this._rejectComplete(err);
60
+ });
61
+ // Handle compressed output - this is true streaming!
62
+ this._deflate.on("data", (chunk) => {
63
+ this._compressedSize += chunk.length;
64
+ this._enqueueData(chunk, false);
65
+ });
66
+ // Handle end - emit data descriptor
67
+ // IMPORTANT: Only use 'end' event, NOT 'finish'!
68
+ // Node.js zlib emits events in order: finish -> data -> end
69
+ this._deflate.on("end", () => {
70
+ if (this._pendingEnd && !this._emittedDataDescriptor) {
71
+ this._emittedDataDescriptor = true;
72
+ this._emitDataDescriptor();
73
+ }
74
+ });
89
75
  }
90
- this._deflate = createDeflateStream({ level: this.level });
91
- this._deflate.on("error", (err) => {
92
- this._rejectComplete(err);
93
- });
94
- // Handle compressed output - this is true streaming!
95
- this._deflate.on("data", (chunk) => {
96
- this._compressedSize += chunk.length;
97
- this._enqueueData(chunk, false);
98
- });
99
- // Handle end - emit data descriptor
100
- // IMPORTANT: Only use 'end' event, NOT 'finish'!
101
- // Node.js zlib emits events in order: finish -> data -> end
102
- this._deflate.on("end", () => {
103
- if (this._pendingEnd && !this._emittedDataDescriptor) {
104
- this._emittedDataDescriptor = true;
105
- this._emitDataDescriptor();
106
- }
107
- });
76
+ this._localHeader = this._buildLocalHeader();
108
77
  }
109
78
  _buildLocalHeader() {
110
79
  // CRC + sizes are written via data descriptor for true streaming.
@@ -121,63 +90,6 @@ export class ZipDeflateFile {
121
90
  versionNeeded: VERSION_NEEDED
122
91
  });
123
92
  }
124
- _accumulateSample(data) {
125
- if (this._deflateWanted !== null) {
126
- return;
127
- }
128
- if (this._sampleLen >= this._sampleBuffer.length) {
129
- return;
130
- }
131
- const take = Math.min(this._sampleBuffer.length - this._sampleLen, data.length);
132
- if (take <= 0) {
133
- return;
134
- }
135
- this._sampleBuffer.set(data.subarray(0, take), this._sampleLen);
136
- this._sampleLen += take;
137
- }
138
- _shouldDecide(final) {
139
- if (this._deflateWanted !== null) {
140
- return false;
141
- }
142
- return final || this._sampleLen >= 16 * 1024;
143
- }
144
- _decideCompressionIfNeeded(final) {
145
- if (this._deflateWanted !== null) {
146
- return;
147
- }
148
- // Match non-streaming builder semantics: empty files never need DEFLATE.
149
- if (final && this._sampleLen === 0) {
150
- this._deflateWanted = false;
151
- this._compressionMethod = this._buildCompressionMethod(false);
152
- this._localHeader = null;
153
- return;
154
- }
155
- // Default to DEFLATE unless heuristic says STORE.
156
- const sample = this._sampleBuffer.subarray(0, this._sampleLen);
157
- const store = isProbablyIncompressible(sample);
158
- this._deflateWanted = !store;
159
- this._compressionMethod = this._buildCompressionMethod(this._deflateWanted);
160
- this._localHeader = null;
161
- if (this._deflateWanted) {
162
- this._initDeflateStream();
163
- }
164
- }
165
- _emitHeaderIfNeeded() {
166
- if (this._headerEmitted) {
167
- return;
168
- }
169
- this._emitHeader();
170
- this._headerEmitted = true;
171
- }
172
- async _flushPendingChunks() {
173
- if (this._pendingChunks.length === 0) {
174
- return;
175
- }
176
- for (const chunk of this._pendingChunks) {
177
- await this._writeData(chunk);
178
- }
179
- this._pendingChunks = [];
180
- }
181
93
  _enqueueData(data, final) {
182
94
  if (this._ondata) {
183
95
  this._ondata(data, final);
@@ -209,29 +121,13 @@ export class ZipDeflateFile {
209
121
  // Flush any queued data
210
122
  this._flushQueue();
211
123
  }
212
- get onerror() {
213
- return this._onerror ?? undefined;
214
- }
215
- set onerror(cb) {
216
- this._onerror = cb;
217
- // If an error already occurred, surface it immediately.
218
- if (this._completeError) {
219
- cb(this._completeError);
220
- }
221
- }
222
124
  _resolveComplete() {
223
125
  if (this._completeResolve) {
224
126
  this._completeResolve();
225
127
  }
226
128
  }
227
129
  _rejectComplete(err) {
228
- if (this._completeError) {
229
- return;
230
- }
231
130
  this._completeError = err;
232
- if (this._onerror) {
233
- this._onerror(err);
234
- }
235
131
  if (this._completeReject) {
236
132
  this._completeReject(err);
237
133
  }
@@ -257,6 +153,13 @@ export class ZipDeflateFile {
257
153
  }
258
154
  promise.then(() => callback()).catch(err => callback(err));
259
155
  }
156
+ _emitHeaderIfNeeded() {
157
+ if (this._headerEmitted) {
158
+ return;
159
+ }
160
+ this._emitHeader();
161
+ this._headerEmitted = true;
162
+ }
260
163
  _writeData(data) {
261
164
  if (data.length === 0) {
262
165
  return Promise.resolve();
@@ -314,60 +217,27 @@ export class ZipDeflateFile {
314
217
  this._emitDataDescriptor();
315
218
  return completePromise;
316
219
  }
317
- _pushUnchained(data, final, callback) {
220
+ /**
221
+ * Push data - immediately compresses and outputs
222
+ * Returns a Promise that resolves when the write is complete.
223
+ * If final=true, it resolves after the data descriptor is emitted.
224
+ */
225
+ push(data, final = false, callback) {
318
226
  if (this._finalized) {
319
227
  const promise = Promise.reject(new Error("Cannot push to finalized ZipDeflateFile"));
320
228
  this._tapCallback(promise, callback);
321
229
  return promise;
322
230
  }
323
- if (this._deflateWanted === null) {
324
- this._accumulateSample(data);
325
- if (!this._shouldDecide(final)) {
326
- if (data.length > 0) {
327
- this._pendingChunks.push(data);
328
- }
329
- const promise = Promise.resolve();
330
- this._tapCallback(promise, callback);
331
- return promise;
332
- }
333
- this._decideCompressionIfNeeded(final);
334
- this._emitHeaderIfNeeded();
335
- const hadPendingChunks = this._pendingChunks.length > 0;
336
- const flushPromise = this._flushPendingChunks();
337
- let writePromise = flushPromise;
338
- if (data.length > 0) {
339
- writePromise = hadPendingChunks
340
- ? flushPromise.then(() => this._writeData(data))
341
- : this._writeData(data);
342
- }
343
- const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
344
- this._tapCallback(promise, callback);
345
- return promise;
346
- }
347
231
  this._emitHeaderIfNeeded();
348
232
  const writePromise = this._writeData(data);
349
233
  const promise = final ? this._finalizeAfterWrite(writePromise) : writePromise;
350
234
  this._tapCallback(promise, callback);
351
235
  return promise;
352
236
  }
353
- /**
354
- * Push data - immediately compresses and outputs
355
- * Returns a Promise that resolves when the write is complete.
356
- * If final=true, it resolves after the data descriptor is emitted.
357
- */
358
- push(data, final = false, callback) {
359
- const promise = (this._pushChain = this._pushChain.then(() => this._pushUnchained(data, final, callback)));
360
- // Prevent unhandled rejection when callers intentionally ignore the Promise.
361
- promise.catch(() => { });
362
- return promise;
363
- }
364
237
  /**
365
238
  * Emit local file header with Data Descriptor flag
366
239
  */
367
240
  _emitHeader() {
368
- if (!this._localHeader) {
369
- this._localHeader = this._buildLocalHeader();
370
- }
371
241
  this._enqueueData(this._localHeader, false);
372
242
  }
373
243
  /**
@@ -380,7 +250,6 @@ export class ZipDeflateFile {
380
250
  this._centralDirEntryInfo = {
381
251
  name: this.nameBytes,
382
252
  extraField: this.extraField,
383
- comment: this.commentBytes,
384
253
  flags: this._flags,
385
254
  crc: crcValue,
386
255
  compressedSize: this._compressedSize,
@@ -419,7 +288,7 @@ export class ZipDeflateFile {
419
288
  crc32: this._centralDirEntryInfo.crc,
420
289
  lastModified: this._modTime,
421
290
  localHeaderOffset: this._centralDirEntryInfo.offset,
422
- comment: decodeUtf8(this._centralDirEntryInfo.comment),
291
+ comment: "",
423
292
  externalAttributes: 0,
424
293
  isEncrypted: false
425
294
  };
@@ -436,7 +305,7 @@ export class ZipDeflateFile {
436
305
  * Streaming ZIP Creator - processes files sequentially
437
306
  */
438
307
  export class StreamingZip {
439
- constructor(callback, options) {
308
+ constructor(callback) {
440
309
  this.entries = [];
441
310
  this.currentOffset = 0;
442
311
  this.ended = false;
@@ -446,12 +315,10 @@ export class StreamingZip {
446
315
  this.fileQueueIndex = 0;
447
316
  this.activeFile = null;
448
317
  this.callback = callback;
449
- // Avoid per-instance TextEncoder allocations.
450
- this.zipComment = options?.comment ? encodeUtf8(options.comment) : new Uint8Array(0);
451
318
  }
452
319
  add(file) {
453
320
  if (this.ended) {
454
- throw new Error("Cannot add files after calling end() ");
321
+ throw new Error("Cannot add files after calling end()");
455
322
  }
456
323
  this.fileQueue.push(file);
457
324
  // If no active file, process this one
@@ -474,18 +341,7 @@ export class StreamingZip {
474
341
  const file = this.fileQueue[this.fileQueueIndex++];
475
342
  this.activeFile = file;
476
343
  const startOffset = this.currentOffset;
477
- const empty = new Uint8Array(0);
478
- file.onerror = (err) => {
479
- if (this.ended) {
480
- return;
481
- }
482
- this.ended = true;
483
- this.callback(err, empty, true);
484
- };
485
344
  file.ondata = (data, final) => {
486
- if (this.ended) {
487
- return;
488
- }
489
345
  this.currentOffset += data.length;
490
346
  this.callback(null, data, false);
491
347
  if (final) {
@@ -511,7 +367,7 @@ export class StreamingZip {
511
367
  const header = buildCentralDirectoryHeader({
512
368
  fileName: entry.name,
513
369
  extraField: entry.extraField,
514
- comment: entry.comment ?? empty,
370
+ comment: empty,
515
371
  flags: entry.flags,
516
372
  compressionMethod: entry.compressionMethod,
517
373
  dosTime: entry.dosTime,
@@ -530,7 +386,7 @@ export class StreamingZip {
530
386
  entryCount: this.entries.length,
531
387
  centralDirSize,
532
388
  centralDirOffset,
533
- comment: this.zipComment
389
+ comment: empty
534
390
  });
535
391
  this.callback(null, eocd, true);
536
392
  }
@@ -45,18 +45,21 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
45
45
  }
46
46
  // Fast paths for small patterns (very common in ZIP parsing: 2/3/4-byte signatures).
47
47
  if (patLen === 1) {
48
- return buffer.indexOf(pattern[0], start);
48
+ const p0 = pattern[0];
49
+ for (let i = start; i < bufLen; i++) {
50
+ if (buffer[i] === p0) {
51
+ return i;
52
+ }
53
+ }
54
+ return -1;
49
55
  }
50
56
  if (patLen === 2) {
51
57
  const p0 = pattern[0];
52
58
  const p1 = pattern[1];
53
- const last = bufLen - 2;
54
- let i = buffer.indexOf(p0, start);
55
- while (i !== -1 && i <= last) {
56
- if (buffer[i + 1] === p1) {
59
+ for (let i = start; i <= bufLen - 2; i++) {
60
+ if (buffer[i] === p0 && buffer[i + 1] === p1) {
57
61
  return i;
58
62
  }
59
- i = buffer.indexOf(p0, i + 1);
60
63
  }
61
64
  return -1;
62
65
  }
@@ -64,13 +67,10 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
64
67
  const p0 = pattern[0];
65
68
  const p1 = pattern[1];
66
69
  const p2 = pattern[2];
67
- const last = bufLen - 3;
68
- let i = buffer.indexOf(p0, start);
69
- while (i !== -1 && i <= last) {
70
- if (buffer[i + 1] === p1 && buffer[i + 2] === p2) {
70
+ for (let i = start; i <= bufLen - 3; i++) {
71
+ if (buffer[i] === p0 && buffer[i + 1] === p1 && buffer[i + 2] === p2) {
71
72
  return i;
72
73
  }
73
- i = buffer.indexOf(p0, i + 1);
74
74
  }
75
75
  return -1;
76
76
  }
@@ -79,13 +79,13 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
79
79
  const p1 = pattern[1];
80
80
  const p2 = pattern[2];
81
81
  const p3 = pattern[3];
82
- const last = bufLen - 4;
83
- let i = buffer.indexOf(p0, start);
84
- while (i !== -1 && i <= last) {
85
- if (buffer[i + 1] === p1 && buffer[i + 2] === p2 && buffer[i + 3] === p3) {
82
+ for (let i = start; i <= bufLen - 4; i++) {
83
+ if (buffer[i] === p0 &&
84
+ buffer[i + 1] === p1 &&
85
+ buffer[i + 2] === p2 &&
86
+ buffer[i + 3] === p3) {
86
87
  return i;
87
88
  }
88
- i = buffer.indexOf(p0, i + 1);
89
89
  }
90
90
  return -1;
91
91
  }
@@ -1,3 +1,25 @@
1
+ /**
2
+ * Read unsigned little-endian integer from Uint8Array
3
+ */
4
+ function readUIntLE(buffer, offset, size) {
5
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
6
+ switch (size) {
7
+ case 1:
8
+ return view.getUint8(offset);
9
+ case 2:
10
+ return view.getUint16(offset, true);
11
+ case 4:
12
+ return view.getUint32(offset, true);
13
+ case 8: {
14
+ // Read as BigUint64 and convert to Number
15
+ const low = view.getUint32(offset, true);
16
+ const high = view.getUint32(offset + 4, true);
17
+ return high * 0x100000000 + low;
18
+ }
19
+ default:
20
+ throw new Error("Unsupported UInt LE size!");
21
+ }
22
+ }
1
23
  /**
2
24
  * Parses sequential unsigned little endian numbers from the head of the passed buffer according to
3
25
  * the specified format passed. If the buffer is not large enough to satisfy the full format,
@@ -16,30 +38,10 @@
16
38
  */
17
39
  export function parse(buffer, format) {
18
40
  const result = {};
19
- const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
20
41
  let offset = 0;
21
42
  for (const [key, size] of format) {
22
43
  if (buffer.length >= offset + size) {
23
- switch (size) {
24
- case 1:
25
- result[key] = view.getUint8(offset);
26
- break;
27
- case 2:
28
- result[key] = view.getUint16(offset, true);
29
- break;
30
- case 4:
31
- result[key] = view.getUint32(offset, true);
32
- break;
33
- case 8: {
34
- // Keep behavior (Number) while avoiding BigInt costs.
35
- const low = view.getUint32(offset, true);
36
- const high = view.getUint32(offset + 4, true);
37
- result[key] = high * 0x100000000 + low;
38
- break;
39
- }
40
- default:
41
- throw new Error("Unsupported UInt LE size!");
42
- }
44
+ result[key] = readUIntLE(buffer, offset, size);
43
45
  }
44
46
  else {
45
47
  result[key] = null;
@@ -1,65 +1,4 @@
1
- const EXTENDED_TIMESTAMP_ID = 0x5455;
2
- function clampUint32(value) {
3
- if (!Number.isFinite(value)) {
4
- return 0;
5
- }
6
- if (value <= 0) {
7
- return 0;
8
- }
9
- // 0xFFFFFFFF fits JS safe integer.
10
- if (value >= 0xffffffff) {
11
- return 0xffffffff;
12
- }
13
- return value >>> 0;
14
- }
15
- function unixSecondsFromDate(date) {
16
- return clampUint32(Math.floor(date.getTime() / 1000));
17
- }
18
- /**
19
- * Parse Info-ZIP "Extended Timestamp" extra field (0x5455) and return mtime.
20
- * Returns Unix seconds (UTC) if present.
21
- */
22
- function parseExtendedTimestampMtimeUnixSeconds(extraField) {
23
- const view = new DataView(extraField.buffer, extraField.byteOffset, extraField.byteLength);
24
- let offset = 0;
25
- while (offset + 4 <= extraField.length) {
26
- const headerId = view.getUint16(offset, true);
27
- const dataSize = view.getUint16(offset + 2, true);
28
- const dataStart = offset + 4;
29
- const dataEnd = dataStart + dataSize;
30
- if (dataEnd > extraField.length) {
31
- break;
32
- }
33
- if (headerId === EXTENDED_TIMESTAMP_ID && dataSize >= 1) {
34
- const flags = extraField[dataStart];
35
- if ((flags & 0x01) !== 0 && dataSize >= 5) {
36
- // mtime is 4 bytes right after flags.
37
- return view.getUint32(dataStart + 1, true) >>> 0;
38
- }
39
- }
40
- offset = dataEnd;
41
- }
42
- return undefined;
43
- }
44
- /**
45
- * Build Info-ZIP "Extended Timestamp" extra field (0x5455).
46
- * We write only mtime (UTC, Unix seconds) to minimize size.
47
- */
48
- function buildExtendedTimestampExtraFieldFromUnixSeconds(unixSeconds) {
49
- const ts = clampUint32(unixSeconds);
50
- // flags(1) + mtime(4)
51
- const payloadSize = 5;
52
- const out = new Uint8Array(4 + payloadSize);
53
- const view = new DataView(out.buffer);
54
- view.setUint16(0, EXTENDED_TIMESTAMP_ID, true);
55
- view.setUint16(2, payloadSize, true);
56
- out[4] = 0x01; // mtime present
57
- view.setUint32(5, ts, true);
58
- return out;
59
- }
60
- function buildExtendedTimestampExtraFieldFromDate(date) {
61
- return buildExtendedTimestampExtraFieldFromUnixSeconds(unixSecondsFromDate(date));
62
- }
1
+ import { buildExtendedTimestampExtraFieldFromDate, parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
63
2
  /**
64
3
  * DOS date/time helpers for ZIP files.
65
4
  */
@@ -1,31 +1,10 @@
1
1
  /**
2
2
  * ZIP extra field parsing helpers.
3
3
  *
4
- * Kept standalone so both streaming parser (`stream.base.ts`) and buffer parser
4
+ * Kept standalone so both streaming parser (`parse.base.ts`) and buffer parser
5
5
  * (`zip-parser.ts`) can share ZIP64 + Info-ZIP timestamp handling.
6
6
  */
7
- const EXTENDED_TIMESTAMP_ID = 0x5455;
8
- function parseExtendedTimestampMtimeUnixSeconds(extraField) {
9
- const view = new DataView(extraField.buffer, extraField.byteOffset, extraField.byteLength);
10
- let offset = 0;
11
- while (offset + 4 <= extraField.length) {
12
- const headerId = view.getUint16(offset, true);
13
- const dataSize = view.getUint16(offset + 2, true);
14
- const dataStart = offset + 4;
15
- const dataEnd = dataStart + dataSize;
16
- if (dataEnd > extraField.length) {
17
- break;
18
- }
19
- if (headerId === EXTENDED_TIMESTAMP_ID && dataSize >= 1) {
20
- const flags = extraField[dataStart];
21
- if ((flags & 0x01) !== 0 && dataSize >= 5) {
22
- return view.getUint32(dataStart + 1, true) >>> 0;
23
- }
24
- }
25
- offset = dataEnd;
26
- }
27
- return undefined;
28
- }
7
+ import { parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
29
8
  function readUint64LE(view, offset) {
30
9
  // Convert to Number via 2x Uint32 to avoid BigInt requirements.
31
10
  const low = view.getUint32(offset, true);
@@ -64,9 +43,18 @@ export function parseZipExtraFields(extraField, vars) {
64
43
  }
65
44
  }
66
45
  else if (signature === 0x5455) {
67
- const unixSeconds = parseExtendedTimestampMtimeUnixSeconds(extraField.subarray(offset, dataEnd));
68
- if (unixSeconds !== undefined) {
69
- extra.mtimeUnixSeconds = unixSeconds;
46
+ // Fast-path parse for Info-ZIP extended timestamp (mtime only).
47
+ if (partSize >= 1) {
48
+ const flags = extraField[dataStart];
49
+ if ((flags & 0x01) !== 0 && partSize >= 5) {
50
+ extra.mtimeUnixSeconds = view.getUint32(dataStart + 1, true) >>> 0;
51
+ }
52
+ else {
53
+ const unixSeconds = parseExtendedTimestampMtimeUnixSeconds(extraField.subarray(offset, dataEnd));
54
+ if (unixSeconds !== undefined) {
55
+ extra.mtimeUnixSeconds = unixSeconds;
56
+ }
57
+ }
70
58
  }
71
59
  }
72
60
  offset = dataEnd;