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

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 +0 -31
  2. package/dist/browser/index.browser.d.ts +1 -0
  3. package/dist/browser/index.browser.js +12 -0
  4. package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.base.js +1 -1
  5. package/dist/{types/modules/archive → browser/modules/archive/compression}/compress.browser.d.ts +2 -8
  6. package/dist/browser/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  7. package/dist/browser/modules/archive/{compress.d.ts → compression/compress.d.ts} +2 -2
  8. package/dist/{esm/modules/archive → browser/modules/archive/compression}/compress.js +1 -1
  9. package/dist/browser/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +1 -1
  10. package/dist/browser/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +1 -1
  11. package/dist/browser/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  12. package/dist/browser/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  13. package/dist/browser/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +2 -2
  14. package/dist/browser/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  15. package/dist/browser/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +2 -2
  16. package/dist/browser/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  17. package/dist/browser/modules/archive/defaults.d.ts +1 -0
  18. package/dist/browser/modules/archive/defaults.js +6 -3
  19. package/dist/browser/modules/archive/index.base.d.ts +4 -4
  20. package/dist/browser/modules/archive/index.base.js +3 -6
  21. package/dist/browser/modules/archive/index.browser.d.ts +3 -4
  22. package/dist/browser/modules/archive/index.browser.js +3 -7
  23. package/dist/browser/modules/archive/index.d.ts +3 -4
  24. package/dist/browser/modules/archive/index.js +3 -5
  25. package/dist/browser/modules/archive/internal/byte-queue.d.ts +33 -0
  26. package/dist/browser/modules/archive/internal/byte-queue.js +407 -0
  27. package/dist/browser/modules/archive/io/archive-sink.d.ts +9 -0
  28. package/dist/browser/modules/archive/io/archive-sink.js +77 -0
  29. package/dist/browser/modules/archive/io/archive-source.d.ts +8 -0
  30. package/dist/browser/modules/archive/io/archive-source.js +107 -0
  31. package/dist/browser/modules/archive/{extract.d.ts → unzip/extract.d.ts} +2 -2
  32. package/dist/browser/modules/archive/unzip/index.d.ts +40 -0
  33. package/dist/browser/modules/archive/unzip/index.js +164 -0
  34. package/dist/browser/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +36 -2
  35. package/dist/browser/modules/archive/unzip/stream.base.js +1022 -0
  36. package/dist/browser/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +1 -1
  37. package/dist/browser/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
  38. package/dist/browser/modules/archive/{parse.d.ts → unzip/stream.d.ts} +2 -2
  39. package/dist/{esm/modules/archive/parse.js → browser/modules/archive/unzip/stream.js} +6 -5
  40. package/dist/browser/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
  41. package/dist/{esm/modules/archive → browser/modules/archive/unzip}/zip-parser.js +38 -24
  42. package/dist/browser/modules/archive/utils/async-queue.d.ts +7 -0
  43. package/dist/browser/modules/archive/utils/async-queue.js +103 -0
  44. package/dist/browser/modules/archive/utils/bytes.js +16 -16
  45. package/dist/browser/modules/archive/utils/compressibility.d.ts +10 -0
  46. package/dist/browser/modules/archive/utils/compressibility.js +57 -0
  47. package/dist/browser/modules/archive/utils/parse-buffer.js +21 -23
  48. package/dist/browser/modules/archive/utils/pattern-scanner.d.ts +21 -0
  49. package/dist/browser/modules/archive/utils/pattern-scanner.js +27 -0
  50. package/dist/browser/modules/archive/utils/timestamps.js +62 -1
  51. package/dist/browser/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  52. package/dist/browser/modules/archive/utils/zip-extra-fields.js +26 -14
  53. package/dist/browser/modules/archive/zip/index.d.ts +42 -0
  54. package/dist/browser/modules/archive/zip/index.js +157 -0
  55. package/dist/browser/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +28 -5
  56. package/dist/browser/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  57. package/dist/browser/modules/archive/zip/zip-bytes.d.ts +73 -0
  58. package/dist/browser/modules/archive/zip/zip-bytes.js +239 -0
  59. package/dist/{esm/modules/archive → browser/modules/archive/zip}/zip-entry-metadata.js +3 -3
  60. package/dist/browser/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  61. package/dist/browser/modules/archive/zip-spec/zip-records.js +126 -0
  62. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +1 -1
  63. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  64. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +1 -1
  65. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +3 -6
  66. package/dist/browser/modules/excel/xlsx/xlsx.js +1 -1
  67. package/dist/browser/modules/stream/streams.browser.d.ts +28 -30
  68. package/dist/browser/modules/stream/streams.browser.js +830 -710
  69. package/dist/browser/modules/stream/streams.js +140 -58
  70. package/dist/cjs/modules/archive/{compress.base.js → compression/compress.base.js} +1 -1
  71. package/dist/cjs/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  72. package/dist/cjs/modules/archive/{compress.js → compression/compress.js} +1 -1
  73. package/dist/cjs/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  74. package/dist/cjs/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  75. package/dist/cjs/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  76. package/dist/cjs/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  77. package/dist/cjs/modules/archive/defaults.js +7 -4
  78. package/dist/cjs/modules/archive/index.base.js +9 -19
  79. package/dist/cjs/modules/archive/index.browser.js +4 -10
  80. package/dist/cjs/modules/archive/index.js +4 -8
  81. package/dist/cjs/modules/archive/internal/byte-queue.js +411 -0
  82. package/dist/cjs/modules/archive/io/archive-sink.js +82 -0
  83. package/dist/cjs/modules/archive/io/archive-source.js +114 -0
  84. package/dist/cjs/modules/archive/unzip/index.js +170 -0
  85. package/dist/cjs/modules/archive/unzip/stream.base.js +1044 -0
  86. package/dist/cjs/modules/archive/{parse.browser.js → unzip/stream.browser.js} +372 -111
  87. package/dist/cjs/modules/archive/{parse.js → unzip/stream.js} +9 -8
  88. package/dist/cjs/modules/archive/{zip-parser.js → unzip/zip-parser.js} +47 -33
  89. package/dist/cjs/modules/archive/utils/async-queue.js +106 -0
  90. package/dist/cjs/modules/archive/utils/bytes.js +16 -16
  91. package/dist/cjs/modules/archive/utils/compressibility.js +60 -0
  92. package/dist/cjs/modules/archive/utils/parse-buffer.js +21 -23
  93. package/dist/cjs/modules/archive/utils/pattern-scanner.js +31 -0
  94. package/dist/cjs/modules/archive/utils/timestamps.js +64 -3
  95. package/dist/cjs/modules/archive/utils/zip-extra-fields.js +26 -14
  96. package/dist/cjs/modules/archive/zip/index.js +162 -0
  97. package/dist/cjs/modules/archive/{streaming-zip.js → zip/stream.js} +194 -50
  98. package/dist/cjs/modules/archive/zip/zip-bytes.js +242 -0
  99. package/dist/cjs/modules/archive/{zip-entry-metadata.js → zip/zip-entry-metadata.js} +5 -5
  100. package/dist/cjs/modules/archive/zip-spec/zip-records.js +136 -0
  101. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +2 -2
  102. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +4 -4
  103. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +6 -9
  104. package/dist/cjs/modules/excel/xlsx/xlsx.js +2 -2
  105. package/dist/cjs/modules/stream/streams.browser.js +830 -710
  106. package/dist/cjs/modules/stream/streams.js +140 -58
  107. package/dist/esm/index.browser.js +12 -0
  108. package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.base.js +1 -1
  109. package/dist/esm/modules/archive/{compress.browser.js → compression/compress.browser.js} +3 -11
  110. package/dist/{browser/modules/archive → esm/modules/archive/compression}/compress.js +1 -1
  111. package/dist/esm/modules/archive/{crc32.js → compression/crc32.js} +1 -1
  112. package/dist/esm/modules/archive/{deflate-fallback.js → compression/deflate-fallback.js} +1 -1
  113. package/dist/esm/modules/archive/{streaming-compress.browser.js → compression/streaming-compress.browser.js} +3 -3
  114. package/dist/esm/modules/archive/{streaming-compress.js → compression/streaming-compress.js} +2 -2
  115. package/dist/esm/modules/archive/defaults.js +6 -3
  116. package/dist/esm/modules/archive/index.base.js +3 -6
  117. package/dist/esm/modules/archive/index.browser.js +3 -7
  118. package/dist/esm/modules/archive/index.js +3 -5
  119. package/dist/esm/modules/archive/internal/byte-queue.js +407 -0
  120. package/dist/esm/modules/archive/io/archive-sink.js +77 -0
  121. package/dist/esm/modules/archive/io/archive-source.js +107 -0
  122. package/dist/esm/modules/archive/unzip/index.js +164 -0
  123. package/dist/esm/modules/archive/unzip/stream.base.js +1022 -0
  124. package/dist/esm/modules/archive/{parse.browser.js → unzip/stream.browser.js} +371 -110
  125. package/dist/{browser/modules/archive/parse.js → esm/modules/archive/unzip/stream.js} +6 -5
  126. package/dist/{browser/modules/archive → esm/modules/archive/unzip}/zip-parser.js +38 -24
  127. package/dist/esm/modules/archive/utils/async-queue.js +103 -0
  128. package/dist/esm/modules/archive/utils/bytes.js +16 -16
  129. package/dist/esm/modules/archive/utils/compressibility.js +57 -0
  130. package/dist/esm/modules/archive/utils/parse-buffer.js +21 -23
  131. package/dist/esm/modules/archive/utils/pattern-scanner.js +27 -0
  132. package/dist/esm/modules/archive/utils/timestamps.js +62 -1
  133. package/dist/esm/modules/archive/utils/zip-extra-fields.js +26 -14
  134. package/dist/esm/modules/archive/zip/index.js +157 -0
  135. package/dist/esm/modules/archive/{streaming-zip.js → zip/stream.js} +192 -48
  136. package/dist/esm/modules/archive/zip/zip-bytes.js +239 -0
  137. package/dist/{browser/modules/archive → esm/modules/archive/zip}/zip-entry-metadata.js +3 -3
  138. package/dist/esm/modules/archive/zip-spec/zip-records.js +126 -0
  139. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +1 -1
  140. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +1 -1
  141. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +3 -6
  142. package/dist/esm/modules/excel/xlsx/xlsx.js +1 -1
  143. package/dist/esm/modules/stream/streams.browser.js +830 -710
  144. package/dist/esm/modules/stream/streams.js +140 -58
  145. package/dist/iife/THIRD_PARTY_NOTICES.md +0 -31
  146. package/dist/iife/excelts.iife.js +6190 -4400
  147. package/dist/iife/excelts.iife.js.map +1 -1
  148. package/dist/iife/excelts.iife.min.js +103 -31
  149. package/dist/types/index.browser.d.ts +1 -0
  150. package/dist/{browser/modules/archive → types/modules/archive/compression}/compress.browser.d.ts +2 -8
  151. package/dist/types/modules/archive/{streaming-compress.browser.d.ts → compression/streaming-compress.browser.d.ts} +1 -1
  152. package/dist/types/modules/archive/defaults.d.ts +1 -0
  153. package/dist/types/modules/archive/index.base.d.ts +4 -4
  154. package/dist/types/modules/archive/index.browser.d.ts +3 -4
  155. package/dist/types/modules/archive/index.d.ts +3 -4
  156. package/dist/types/modules/archive/internal/byte-queue.d.ts +33 -0
  157. package/dist/types/modules/archive/io/archive-sink.d.ts +9 -0
  158. package/dist/types/modules/archive/io/archive-source.d.ts +8 -0
  159. package/dist/types/modules/archive/unzip/index.d.ts +40 -0
  160. package/dist/types/modules/archive/{parse.base.d.ts → unzip/stream.base.d.ts} +38 -4
  161. package/dist/types/modules/archive/{parse.browser.d.ts → unzip/stream.browser.d.ts} +2 -2
  162. package/dist/types/modules/archive/{parse.d.ts → unzip/stream.d.ts} +3 -3
  163. package/dist/types/modules/archive/{zip-parser.d.ts → unzip/zip-parser.d.ts} +1 -1
  164. package/dist/types/modules/archive/utils/async-queue.d.ts +7 -0
  165. package/dist/types/modules/archive/utils/compressibility.d.ts +10 -0
  166. package/dist/types/modules/archive/utils/pattern-scanner.d.ts +21 -0
  167. package/dist/types/modules/archive/utils/zip-extra-fields.d.ts +1 -1
  168. package/dist/types/modules/archive/zip/index.d.ts +42 -0
  169. package/dist/types/modules/archive/{streaming-zip.d.ts → zip/stream.d.ts} +29 -6
  170. package/dist/types/modules/archive/zip/zip-bytes.d.ts +73 -0
  171. package/dist/types/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +1 -1
  172. package/dist/types/modules/archive/{zip-records.d.ts → zip-spec/zip-records.d.ts} +20 -0
  173. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +1 -1
  174. package/dist/types/modules/stream/streams.browser.d.ts +28 -30
  175. package/package.json +5 -1
  176. package/dist/browser/modules/archive/byte-queue.d.ts +0 -18
  177. package/dist/browser/modules/archive/byte-queue.js +0 -125
  178. package/dist/browser/modules/archive/parse.base.js +0 -644
  179. package/dist/browser/modules/archive/utils/zip-extra.d.ts +0 -18
  180. package/dist/browser/modules/archive/utils/zip-extra.js +0 -68
  181. package/dist/browser/modules/archive/zip-builder.d.ts +0 -117
  182. package/dist/browser/modules/archive/zip-builder.js +0 -292
  183. package/dist/browser/modules/archive/zip-constants.d.ts +0 -18
  184. package/dist/browser/modules/archive/zip-constants.js +0 -23
  185. package/dist/browser/modules/archive/zip-records.js +0 -84
  186. package/dist/cjs/modules/archive/byte-queue.js +0 -129
  187. package/dist/cjs/modules/archive/parse.base.js +0 -666
  188. package/dist/cjs/modules/archive/utils/zip-extra.js +0 -74
  189. package/dist/cjs/modules/archive/zip-builder.js +0 -297
  190. package/dist/cjs/modules/archive/zip-constants.js +0 -26
  191. package/dist/cjs/modules/archive/zip-records.js +0 -90
  192. package/dist/esm/modules/archive/byte-queue.js +0 -125
  193. package/dist/esm/modules/archive/parse.base.js +0 -644
  194. package/dist/esm/modules/archive/utils/zip-extra.js +0 -68
  195. package/dist/esm/modules/archive/zip-builder.js +0 -292
  196. package/dist/esm/modules/archive/zip-constants.js +0 -23
  197. package/dist/esm/modules/archive/zip-records.js +0 -84
  198. package/dist/types/modules/archive/byte-queue.d.ts +0 -18
  199. package/dist/types/modules/archive/utils/zip-extra.d.ts +0 -18
  200. package/dist/types/modules/archive/zip-builder.d.ts +0 -117
  201. package/dist/types/modules/archive/zip-constants.d.ts +0 -18
  202. /package/dist/browser/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
  203. /package/dist/browser/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  204. /package/dist/browser/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  205. /package/dist/browser/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  206. /package/dist/browser/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  207. /package/dist/browser/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  208. /package/dist/browser/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  209. /package/dist/browser/modules/archive/{extract.js → unzip/extract.js} +0 -0
  210. /package/dist/browser/modules/archive/{zip-entry-metadata.d.ts → zip/zip-entry-metadata.d.ts} +0 -0
  211. /package/dist/browser/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
  212. /package/dist/browser/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  213. /package/dist/cjs/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  214. /package/dist/cjs/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  215. /package/dist/cjs/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  216. /package/dist/cjs/modules/archive/{extract.js → unzip/extract.js} +0 -0
  217. /package/dist/cjs/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  218. /package/dist/esm/modules/archive/{crc32.base.js → compression/crc32.base.js} +0 -0
  219. /package/dist/esm/modules/archive/{crc32.browser.js → compression/crc32.browser.js} +0 -0
  220. /package/dist/esm/modules/archive/{streaming-compress.base.js → compression/streaming-compress.base.js} +0 -0
  221. /package/dist/esm/modules/archive/{extract.js → unzip/extract.js} +0 -0
  222. /package/dist/esm/modules/archive/{zip-entry-info.js → zip-spec/zip-entry-info.js} +0 -0
  223. /package/dist/types/modules/archive/{compress.base.d.ts → compression/compress.base.d.ts} +0 -0
  224. /package/dist/types/modules/archive/{compress.d.ts → compression/compress.d.ts} +0 -0
  225. /package/dist/types/modules/archive/{crc32.base.d.ts → compression/crc32.base.d.ts} +0 -0
  226. /package/dist/types/modules/archive/{crc32.browser.d.ts → compression/crc32.browser.d.ts} +0 -0
  227. /package/dist/types/modules/archive/{crc32.d.ts → compression/crc32.d.ts} +0 -0
  228. /package/dist/types/modules/archive/{deflate-fallback.d.ts → compression/deflate-fallback.d.ts} +0 -0
  229. /package/dist/types/modules/archive/{streaming-compress.base.d.ts → compression/streaming-compress.base.d.ts} +0 -0
  230. /package/dist/types/modules/archive/{streaming-compress.d.ts → compression/streaming-compress.d.ts} +0 -0
  231. /package/dist/types/modules/archive/{extract.d.ts → unzip/extract.d.ts} +0 -0
  232. /package/dist/types/modules/archive/{zip-entry-info.d.ts → zip-spec/zip-entry-info.d.ts} +0 -0
@@ -3,11 +3,11 @@
3
3
  * Works in both Node.js and browser environments
4
4
  * No dependency on Node.js stream module
5
5
  */
6
- import { decompress, decompressSync } from "./compress.browser.js";
7
- import { BinaryReader } from "./utils/binary.js";
8
- import { resolveZipLastModifiedDateFromUnixSeconds } from "./utils/timestamps.js";
9
- import { parseZipExtraFields } from "./utils/zip-extra-fields.js";
10
- import { CENTRAL_DIR_HEADER_SIG, COMPRESSION_DEFLATE, COMPRESSION_STORE, END_OF_CENTRAL_DIR_SIG, LOCAL_FILE_HEADER_SIG, UINT16_MAX, UINT32_MAX, ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG, ZIP64_END_OF_CENTRAL_DIR_SIG } from "./zip-constants.js";
6
+ import { decompress, decompressSync } from "../compression/compress.js";
7
+ import { BinaryReader } from "../utils/binary.js";
8
+ import { resolveZipLastModifiedDateFromUnixSeconds } from "../utils/timestamps.js";
9
+ import { parseZipExtraFields } from "../utils/zip-extra-fields.js";
10
+ import { CENTRAL_DIR_HEADER_SIG, COMPRESSION_DEFLATE, COMPRESSION_STORE, LOCAL_FILE_HEADER_SIG, UINT16_MAX, UINT32_MAX, ZIP64_END_OF_CENTRAL_DIR_SIG } from "../zip-spec/zip-records.js";
11
11
  /**
12
12
  * Find the End of Central Directory record
13
13
  * Searches backwards from the end of the file
@@ -16,9 +16,13 @@ function findEndOfCentralDir(data) {
16
16
  // EOCD is at least 22 bytes, search backwards
17
17
  // Comment can be up to 65535 bytes
18
18
  const minOffset = Math.max(0, data.length - 65557);
19
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
19
+ // Signature bytes (little-endian): 0x06054b50 -> 50 4b 05 06
20
+ const b0 = 0x50;
21
+ const b1 = 0x4b;
22
+ const b2 = 0x05;
23
+ const b3 = 0x06;
20
24
  for (let i = data.length - 22; i >= minOffset; i--) {
21
- if (view.getUint32(i, true) === END_OF_CENTRAL_DIR_SIG) {
25
+ if (data[i] === b0 && data[i + 1] === b1 && data[i + 2] === b2 && data[i + 3] === b3) {
22
26
  return i;
23
27
  }
24
28
  }
@@ -33,8 +37,11 @@ function findZip64EOCDLocator(data, eocdOffset) {
33
37
  if (locatorOffset < 0) {
34
38
  return -1;
35
39
  }
36
- const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
37
- if (view.getUint32(locatorOffset, true) === ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
40
+ // Signature bytes (little-endian): 0x07064b50 -> 50 4b 06 07
41
+ if (data[locatorOffset] === 0x50 &&
42
+ data[locatorOffset + 1] === 0x4b &&
43
+ data[locatorOffset + 2] === 0x06 &&
44
+ data[locatorOffset + 3] === 0x07) {
38
45
  return locatorOffset;
39
46
  }
40
47
  return -1;
@@ -44,7 +51,7 @@ function findZip64EOCDLocator(data, eocdOffset) {
44
51
  */
45
52
  function parseZipEntries(data, options = {}) {
46
53
  const { decodeStrings = true } = options;
47
- const entries = [];
54
+ let entries = [];
48
55
  // Find End of Central Directory
49
56
  const eocdOffset = findEndOfCentralDir(data);
50
57
  if (eocdOffset === -1) {
@@ -96,6 +103,10 @@ function parseZipEntries(data, options = {}) {
96
103
  }
97
104
  }
98
105
  }
106
+ // Preallocate to avoid repeated array growth on large archives.
107
+ if (totalEntries > 0) {
108
+ entries = new Array(totalEntries);
109
+ }
99
110
  // Read Central Directory entries
100
111
  const centralReader = new BinaryReader(data, centralDirOffset);
101
112
  for (let i = 0; i < totalEntries; i++) {
@@ -144,23 +155,26 @@ function parseZipEntries(data, options = {}) {
144
155
  // Check for UTF-8 flag (bit 11)
145
156
  const isUtf8 = (flags & 0x800) !== 0;
146
157
  const useUtf8 = decodeStrings && isUtf8;
147
- const fileName = centralReader.readString(fileNameLength, useUtf8);
148
- const extraField = centralReader.readBytes(extraFieldLength);
149
- const comment = centralReader.readString(commentLength, useUtf8);
150
- const vars = {
151
- compressedSize,
152
- uncompressedSize,
153
- offsetToLocalFileHeader: localHeaderOffset
154
- };
155
- const extraFields = extraFieldLength > 0 ? parseZipExtraFields(extraField, vars) : {};
156
- compressedSize = vars.compressedSize;
157
- uncompressedSize = vars.uncompressedSize;
158
- localHeaderOffset = vars.offsetToLocalFileHeader ?? localHeaderOffset;
158
+ const fileName = fileNameLength > 0 ? centralReader.readString(fileNameLength, useUtf8) : "";
159
+ let extraFields = {};
160
+ if (extraFieldLength > 0) {
161
+ const extraField = centralReader.readBytes(extraFieldLength);
162
+ const vars = {
163
+ compressedSize,
164
+ uncompressedSize,
165
+ offsetToLocalFileHeader: localHeaderOffset
166
+ };
167
+ extraFields = parseZipExtraFields(extraField, vars);
168
+ compressedSize = vars.compressedSize;
169
+ uncompressedSize = vars.uncompressedSize;
170
+ localHeaderOffset = vars.offsetToLocalFileHeader ?? localHeaderOffset;
171
+ }
172
+ const comment = commentLength > 0 ? centralReader.readString(commentLength, useUtf8) : "";
159
173
  const isDirectory = fileName.endsWith("/") || (externalAttributes & 0x10) !== 0;
160
174
  const isEncrypted = (flags & 0x01) !== 0;
161
175
  const unixSecondsMtime = extraFields.mtimeUnixSeconds;
162
176
  const lastModified = resolveZipLastModifiedDateFromUnixSeconds(lastModDate, lastModTime, unixSecondsMtime);
163
- entries.push({
177
+ entries[i] = {
164
178
  path: fileName,
165
179
  isDirectory,
166
180
  compressedSize,
@@ -172,7 +186,7 @@ function parseZipEntries(data, options = {}) {
172
186
  comment,
173
187
  externalAttributes,
174
188
  isEncrypted
175
- });
189
+ };
176
190
  }
177
191
  return entries;
178
192
  }
@@ -0,0 +1,103 @@
1
+ export function createAsyncQueue() {
2
+ const values = [];
3
+ let valuesHead = 0;
4
+ const waiters = [];
5
+ let waitersHead = 0;
6
+ let done = false;
7
+ let error = null;
8
+ const maybeCompact = () => {
9
+ // Prevent unbounded growth of the underlying arrays.
10
+ if (valuesHead > 1024 && valuesHead * 2 > values.length) {
11
+ values.splice(0, valuesHead);
12
+ valuesHead = 0;
13
+ }
14
+ if (waitersHead > 1024 && waitersHead * 2 > waiters.length) {
15
+ waiters.splice(0, waitersHead);
16
+ waitersHead = 0;
17
+ }
18
+ };
19
+ const shiftWaiter = () => {
20
+ while (waitersHead < waiters.length) {
21
+ const w = waiters[waitersHead];
22
+ waiters[waitersHead] = undefined;
23
+ waitersHead++;
24
+ if (w) {
25
+ maybeCompact();
26
+ return w;
27
+ }
28
+ }
29
+ maybeCompact();
30
+ return undefined;
31
+ };
32
+ const shiftValue = () => {
33
+ while (valuesHead < values.length) {
34
+ const v = values[valuesHead];
35
+ values[valuesHead] = undefined;
36
+ valuesHead++;
37
+ if (v !== undefined) {
38
+ maybeCompact();
39
+ return v;
40
+ }
41
+ }
42
+ maybeCompact();
43
+ return undefined;
44
+ };
45
+ const push = (value) => {
46
+ if (done || error) {
47
+ return;
48
+ }
49
+ const waiter = shiftWaiter();
50
+ if (waiter) {
51
+ waiter.resolve({ value, done: false });
52
+ }
53
+ else {
54
+ values.push(value);
55
+ }
56
+ };
57
+ const fail = (err) => {
58
+ if (done || error) {
59
+ return;
60
+ }
61
+ error = err;
62
+ while (true) {
63
+ const waiter = shiftWaiter();
64
+ if (!waiter) {
65
+ break;
66
+ }
67
+ waiter.reject(err);
68
+ }
69
+ };
70
+ const close = () => {
71
+ if (done || error) {
72
+ return;
73
+ }
74
+ done = true;
75
+ while (true) {
76
+ const waiter = shiftWaiter();
77
+ if (!waiter) {
78
+ break;
79
+ }
80
+ waiter.resolve({ value: undefined, done: true });
81
+ }
82
+ };
83
+ const iterable = {
84
+ [Symbol.asyncIterator]() {
85
+ return {
86
+ next() {
87
+ if (error) {
88
+ return Promise.reject(error);
89
+ }
90
+ const value = shiftValue();
91
+ if (value !== undefined) {
92
+ return Promise.resolve({ value, done: false });
93
+ }
94
+ if (done) {
95
+ return Promise.resolve({ value: undefined, done: true });
96
+ }
97
+ return new Promise((resolve, reject) => waiters.push({ resolve, reject }));
98
+ }
99
+ };
100
+ }
101
+ };
102
+ return { push, fail, close, iterable };
103
+ }
@@ -45,21 +45,18 @@ 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
- 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;
48
+ return buffer.indexOf(pattern[0], start);
55
49
  }
56
50
  if (patLen === 2) {
57
51
  const p0 = pattern[0];
58
52
  const p1 = pattern[1];
59
- for (let i = start; i <= bufLen - 2; i++) {
60
- if (buffer[i] === p0 && buffer[i + 1] === p1) {
53
+ const last = bufLen - 2;
54
+ let i = buffer.indexOf(p0, start);
55
+ while (i !== -1 && i <= last) {
56
+ if (buffer[i + 1] === p1) {
61
57
  return i;
62
58
  }
59
+ i = buffer.indexOf(p0, i + 1);
63
60
  }
64
61
  return -1;
65
62
  }
@@ -67,10 +64,13 @@ export function indexOfUint8ArrayPattern(buffer, pattern, startIndex = 0) {
67
64
  const p0 = pattern[0];
68
65
  const p1 = pattern[1];
69
66
  const p2 = pattern[2];
70
- for (let i = start; i <= bufLen - 3; i++) {
71
- if (buffer[i] === p0 && buffer[i + 1] === p1 && buffer[i + 2] === p2) {
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) {
72
71
  return i;
73
72
  }
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
- 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) {
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) {
87
86
  return i;
88
87
  }
88
+ i = buffer.indexOf(p0, i + 1);
89
89
  }
90
90
  return -1;
91
91
  }
@@ -0,0 +1,57 @@
1
+ const DEFAULT_SAMPLE_BYTES = 64 * 1024;
2
+ const MIN_DECISION_BYTES = 16 * 1024;
3
+ function log2(x) {
4
+ return Math.log(x) / Math.LN2;
5
+ }
6
+ function shannonEntropy(bytes) {
7
+ const counts = new Uint32Array(256);
8
+ for (let i = 0; i < bytes.length; i++) {
9
+ counts[bytes[i]] += 1;
10
+ }
11
+ let entropy = 0;
12
+ const total = bytes.length;
13
+ for (let i = 0; i < 256; i++) {
14
+ const count = counts[i];
15
+ if (count === 0) {
16
+ continue;
17
+ }
18
+ const p = count / total;
19
+ entropy -= p * log2(p);
20
+ }
21
+ return entropy;
22
+ }
23
+ /**
24
+ * Heuristic: detect incompressible (high-entropy) data.
25
+ *
26
+ * This is a performance optimization: if data looks random, DEFLATE usually
27
+ * wastes CPU and may even produce slightly larger output.
28
+ */
29
+ export function isProbablyIncompressible(data, options = {}) {
30
+ const sampleBytes = options.sampleBytes ?? DEFAULT_SAMPLE_BYTES;
31
+ const minDecisionBytes = options.minDecisionBytes ?? MIN_DECISION_BYTES;
32
+ const len = Math.min(data.length, sampleBytes);
33
+ if (len < minDecisionBytes) {
34
+ return false;
35
+ }
36
+ const sample = data.subarray(0, len);
37
+ // Fast-ish early filter: if there are too few unique bytes, it's probably compressible.
38
+ // (e.g. text, repeated patterns)
39
+ const seen = new Uint8Array(256);
40
+ let unique = 0;
41
+ for (let i = 0; i < sample.length; i++) {
42
+ const b = sample[i];
43
+ if (seen[b] === 0) {
44
+ seen[b] = 1;
45
+ unique += 1;
46
+ if (unique >= 200) {
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ if (unique < 200) {
52
+ return false;
53
+ }
54
+ // Shannon entropy in bits/byte; random tends to ~8.
55
+ // Threshold picked to be conservative.
56
+ return shannonEntropy(sample) >= 7.95;
57
+ }
@@ -1,25 +1,3 @@
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
- }
23
1
  /**
24
2
  * Parses sequential unsigned little endian numbers from the head of the passed buffer according to
25
3
  * the specified format passed. If the buffer is not large enough to satisfy the full format,
@@ -38,10 +16,30 @@ function readUIntLE(buffer, offset, size) {
38
16
  */
39
17
  export function parse(buffer, format) {
40
18
  const result = {};
19
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
41
20
  let offset = 0;
42
21
  for (const [key, size] of format) {
43
22
  if (buffer.length >= offset + size) {
44
- result[key] = readUIntLE(buffer, 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
+ }
45
43
  }
46
44
  else {
47
45
  result[key] = null;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Stateful helper for incremental pattern scanning in growing buffers.
3
+ *
4
+ * The scanner tracks a `searchFrom` cursor and an `overlap` region so callers
5
+ * can avoid rescanning bytes that cannot start a match.
6
+ */
7
+ export class PatternScanner {
8
+ constructor(pattern) {
9
+ this.searchFrom = 0;
10
+ this.pattern = pattern;
11
+ this.overlap = Math.max(0, pattern.length - 1);
12
+ }
13
+ /** Find the next match index starting at the current `searchFrom`. */
14
+ find(target) {
15
+ return target.indexOfPattern(this.pattern, this.searchFrom);
16
+ }
17
+ /** Update `searchFrom` after consuming `consumed` bytes from the front. */
18
+ onConsume(consumed) {
19
+ if (consumed > 0) {
20
+ this.searchFrom = Math.max(0, this.searchFrom - consumed);
21
+ }
22
+ }
23
+ /** Update `searchFrom` after a no-match scan on a buffer of length `bufferLength`. */
24
+ onNoMatch(bufferLength) {
25
+ this.searchFrom = Math.max(this.searchFrom, Math.max(0, bufferLength - this.overlap));
26
+ }
27
+ }
@@ -1,4 +1,65 @@
1
- import { buildExtendedTimestampExtraFieldFromDate, parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
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
+ }
2
63
  /**
3
64
  * DOS date/time helpers for ZIP files.
4
65
  */
@@ -1,10 +1,31 @@
1
1
  /**
2
2
  * ZIP extra field parsing helpers.
3
3
  *
4
- * Kept standalone so both streaming parser (`parse.base.ts`) and buffer parser
4
+ * Kept standalone so both streaming parser (`stream.base.ts`) and buffer parser
5
5
  * (`zip-parser.ts`) can share ZIP64 + Info-ZIP timestamp handling.
6
6
  */
7
- import { parseExtendedTimestampMtimeUnixSeconds } from "./zip-extra.js";
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
+ }
8
29
  function readUint64LE(view, offset) {
9
30
  // Convert to Number via 2x Uint32 to avoid BigInt requirements.
10
31
  const low = view.getUint32(offset, true);
@@ -43,18 +64,9 @@ export function parseZipExtraFields(extraField, vars) {
43
64
  }
44
65
  }
45
66
  else if (signature === 0x5455) {
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
- }
67
+ const unixSeconds = parseExtendedTimestampMtimeUnixSeconds(extraField.subarray(offset, dataEnd));
68
+ if (unixSeconds !== undefined) {
69
+ extra.mtimeUnixSeconds = unixSeconds;
58
70
  }
59
71
  }
60
72
  offset = dataEnd;