@scriptc/compiler 0.4.0 → 0.4.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 (433) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +35 -5
  2. package/dist/backend/executable-features.js +7 -0
  3. package/dist/backend/executable-features.js.map +1 -1
  4. package/dist/backend/library-pack.js +3 -0
  5. package/dist/backend/library-pack.js.map +1 -1
  6. package/dist/backend/link-plan-core.d.ts +2 -0
  7. package/dist/backend/link-plan-core.js +2 -0
  8. package/dist/backend/link-plan-core.js.map +1 -1
  9. package/dist/backend/link-plan.d.ts +1 -0
  10. package/dist/backend/link-plan.js +1 -0
  11. package/dist/backend/link-plan.js.map +1 -1
  12. package/dist/backend/llvm/array-search.js +3 -1
  13. package/dist/backend/llvm/array-search.js.map +1 -1
  14. package/dist/backend/llvm/classes.d.ts +27 -1
  15. package/dist/backend/llvm/classes.js +115 -22
  16. package/dist/backend/llvm/classes.js.map +1 -1
  17. package/dist/backend/llvm/classes.test.js +21 -9
  18. package/dist/backend/llvm/classes.test.js.map +1 -1
  19. package/dist/backend/llvm/common.d.ts +21 -3
  20. package/dist/backend/llvm/common.js +50 -3
  21. package/dist/backend/llvm/common.js.map +1 -1
  22. package/dist/backend/llvm/dense-array-access.d.ts +3 -1
  23. package/dist/backend/llvm/dense-array-access.js +61 -38
  24. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  25. package/dist/backend/llvm/dense-array-access.test.js +4 -0
  26. package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
  27. package/dist/backend/llvm/dense-array-loops.js +3 -3
  28. package/dist/backend/llvm/dense-array-loops.js.map +1 -1
  29. package/dist/backend/llvm/dyn.d.ts +9 -0
  30. package/dist/backend/llvm/dyn.js +62 -6
  31. package/dist/backend/llvm/dyn.js.map +1 -1
  32. package/dist/backend/llvm/emit-function.js +5 -2
  33. package/dist/backend/llvm/emit-function.js.map +1 -1
  34. package/dist/backend/llvm/emit-module.js +54 -32
  35. package/dist/backend/llvm/emit-module.js.map +1 -1
  36. package/dist/backend/llvm/emit-statements.d.ts +3 -2
  37. package/dist/backend/llvm/emit-statements.js +90 -13
  38. package/dist/backend/llvm/emit-statements.js.map +1 -1
  39. package/dist/backend/llvm/emitter.d.ts +20 -9
  40. package/dist/backend/llvm/emitter.js +42 -31
  41. package/dist/backend/llvm/emitter.js.map +1 -1
  42. package/dist/backend/llvm/expr-calls.js +17 -4
  43. package/dist/backend/llvm/expr-calls.js.map +1 -1
  44. package/dist/backend/llvm/expr-containers.js +6 -9
  45. package/dist/backend/llvm/expr-containers.js.map +1 -1
  46. package/dist/backend/llvm/expr-dynamic.js +46 -4
  47. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  48. package/dist/backend/llvm/expr-primitives.js +3 -3
  49. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  50. package/dist/backend/llvm/expr-primitives.test.js +55 -0
  51. package/dist/backend/llvm/expr-primitives.test.js.map +1 -1
  52. package/dist/backend/llvm/expr-stream-bridges.js +11 -15
  53. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  54. package/dist/backend/llvm/integer-clones.js +3 -3
  55. package/dist/backend/llvm/integer-clones.js.map +1 -1
  56. package/dist/backend/llvm/js-ic.d.ts +18 -0
  57. package/dist/backend/llvm/js-ic.js +712 -0
  58. package/dist/backend/llvm/js-ic.js.map +1 -0
  59. package/dist/backend/llvm/jsval.js +139 -11
  60. package/dist/backend/llvm/jsval.js.map +1 -1
  61. package/dist/backend/llvm/lib-process.js +4 -3
  62. package/dist/backend/llvm/lib-process.js.map +1 -1
  63. package/dist/backend/llvm/lib-shared.js +22 -0
  64. package/dist/backend/llvm/lib-shared.js.map +1 -1
  65. package/dist/backend/llvm/local-array-reads.js +40 -31
  66. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  67. package/dist/backend/llvm/map-number-lookup.d.ts +20 -4
  68. package/dist/backend/llvm/map-number-lookup.js +43 -7
  69. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  70. package/dist/backend/llvm/narrow-guards.js +64 -0
  71. package/dist/backend/llvm/narrow-guards.js.map +1 -1
  72. package/dist/backend/llvm/publish.d.ts +3 -0
  73. package/dist/backend/llvm/publish.js +36 -17
  74. package/dist/backend/llvm/publish.js.map +1 -1
  75. package/dist/backend/llvm/regions.js +2 -2
  76. package/dist/backend/llvm/regions.js.map +1 -1
  77. package/dist/backend/llvm/regions.test.js +7 -1
  78. package/dist/backend/llvm/regions.test.js.map +1 -1
  79. package/dist/backend/llvm/shapes.d.ts +8 -2
  80. package/dist/backend/llvm/shapes.js +9 -7
  81. package/dist/backend/llvm/shapes.js.map +1 -1
  82. package/dist/backend/llvm/speculative-integers.d.ts +20 -1
  83. package/dist/backend/llvm/speculative-integers.js +94 -6
  84. package/dist/backend/llvm/speculative-integers.js.map +1 -1
  85. package/dist/backend/llvm/speculative-integers.test.js +55 -1
  86. package/dist/backend/llvm/speculative-integers.test.js.map +1 -1
  87. package/dist/backend/llvm/string-reads.d.ts +1 -1
  88. package/dist/backend/llvm/string-reads.js +4 -4
  89. package/dist/backend/llvm/string-reads.js.map +1 -1
  90. package/dist/backend/llvm/thread-slots.test.js +5 -4
  91. package/dist/backend/llvm/thread-slots.test.js.map +1 -1
  92. package/dist/backend/mangle.d.ts +5 -0
  93. package/dist/backend/mangle.js +7 -0
  94. package/dist/backend/mangle.js.map +1 -1
  95. package/dist/backend/native/contracts.d.ts +20 -0
  96. package/dist/backend/native/executable.js +20 -3
  97. package/dist/backend/native/executable.js.map +1 -1
  98. package/dist/backend/native/library.js +2 -1
  99. package/dist/backend/native/library.js.map +1 -1
  100. package/dist/backend/native-codegen.d.ts +6 -0
  101. package/dist/backend/native-codegen.js +19 -0
  102. package/dist/backend/native-codegen.js.map +1 -1
  103. package/dist/backend/native-codegen.test.js +27 -0
  104. package/dist/backend/native-codegen.test.js.map +1 -1
  105. package/dist/backend/native-link-info-core.d.ts +18 -0
  106. package/dist/backend/native-link-info-core.js.map +1 -1
  107. package/dist/backend/native-profile.d.ts +32 -0
  108. package/dist/backend/native-profile.js +39 -0
  109. package/dist/backend/native-profile.js.map +1 -0
  110. package/dist/backend/native-profile.test.d.ts +1 -0
  111. package/dist/backend/native-profile.test.js +58 -0
  112. package/dist/backend/native-profile.test.js.map +1 -0
  113. package/dist/backend/native-tools.d.ts +14 -0
  114. package/dist/backend/native-tools.js +13 -0
  115. package/dist/backend/native-tools.js.map +1 -1
  116. package/dist/backend/runtime-abi.d.ts +2 -2
  117. package/dist/backend/runtime-abi.js +2 -2
  118. package/dist/backend/runtime-pack-core.d.ts +4 -0
  119. package/dist/backend/runtime-pack-core.js +4 -0
  120. package/dist/backend/runtime-pack-core.js.map +1 -1
  121. package/dist/backend/runtime-pack-targets.test.js +4 -1
  122. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  123. package/dist/backend/runtime-pack.test.js +4 -1
  124. package/dist/backend/runtime-pack.test.js.map +1 -1
  125. package/dist/backend/target-diagnostics.js +7 -0
  126. package/dist/backend/target-diagnostics.js.map +1 -1
  127. package/dist/backend/warm-cache.js +3 -0
  128. package/dist/backend/warm-cache.js.map +1 -1
  129. package/dist/cli/command.js +63 -1
  130. package/dist/cli/command.js.map +1 -1
  131. package/dist/cli/host.d.ts +3 -0
  132. package/dist/cli/output-options.d.ts +2 -0
  133. package/dist/cli/output-options.js +9 -0
  134. package/dist/cli/output-options.js.map +1 -1
  135. package/dist/cli/usage.d.ts +11 -1
  136. package/dist/cli/usage.js +23 -0
  137. package/dist/cli/usage.js.map +1 -1
  138. package/dist/compile-types.d.ts +9 -0
  139. package/dist/contracts/check.js +1 -2
  140. package/dist/contracts/check.js.map +1 -1
  141. package/dist/executable/executable-cache.d.ts +10 -0
  142. package/dist/executable/executable-cache.js +6 -0
  143. package/dist/executable/executable-cache.js.map +1 -1
  144. package/dist/executable/executable-cache.test.js +5 -0
  145. package/dist/executable/executable-cache.test.js.map +1 -1
  146. package/dist/frontend/arguments-usage.d.ts +8 -0
  147. package/dist/frontend/arguments-usage.js +98 -0
  148. package/dist/frontend/arguments-usage.js.map +1 -1
  149. package/dist/frontend/arguments-usage.test.d.ts +1 -0
  150. package/dist/frontend/arguments-usage.test.js +32 -0
  151. package/dist/frontend/arguments-usage.test.js.map +1 -0
  152. package/dist/frontend/builtin-package-aliases.d.ts +24 -0
  153. package/dist/frontend/builtin-package-aliases.js +133 -0
  154. package/dist/frontend/builtin-package-aliases.js.map +1 -0
  155. package/dist/frontend/builtin-package-aliases.test.d.ts +1 -0
  156. package/dist/frontend/builtin-package-aliases.test.js +48 -0
  157. package/dist/frontend/builtin-package-aliases.test.js.map +1 -0
  158. package/dist/frontend/dts-paths.d.ts +4 -0
  159. package/dist/frontend/dts-paths.js +9 -1
  160. package/dist/frontend/dts-paths.js.map +1 -1
  161. package/dist/frontend/lowering/builtins/builtin-class-dyn.d.ts +8 -0
  162. package/dist/frontend/lowering/builtins/builtin-class-dyn.js +50 -1
  163. package/dist/frontend/lowering/builtins/builtin-class-dyn.js.map +1 -1
  164. package/dist/frontend/lowering/builtins/callable-aliases.js +3 -2
  165. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
  166. package/dist/frontend/lowering/builtins/crypto.d.ts +3 -0
  167. package/dist/frontend/lowering/builtins/crypto.js +4 -1
  168. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  169. package/dist/frontend/lowering/builtins/ecdh.d.ts +10 -0
  170. package/dist/frontend/lowering/builtins/ecdh.js +208 -0
  171. package/dist/frontend/lowering/builtins/ecdh.js.map +1 -0
  172. package/dist/frontend/lowering/builtins/json.js +52 -0
  173. package/dist/frontend/lowering/builtins/json.js.map +1 -1
  174. package/dist/frontend/lowering/builtins/process.d.ts +9 -0
  175. package/dist/frontend/lowering/builtins/process.js +44 -0
  176. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  177. package/dist/frontend/lowering/builtins/promisify-callback.d.ts +3 -0
  178. package/dist/frontend/lowering/builtins/promisify-callback.js +21 -3
  179. package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -1
  180. package/dist/frontend/lowering/builtins/reflection.js +26 -0
  181. package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
  182. package/dist/frontend/lowering/builtins/timers.js +5 -1
  183. package/dist/frontend/lowering/builtins/timers.js.map +1 -1
  184. package/dist/frontend/lowering/builtins/typed-array-members.d.ts +7 -0
  185. package/dist/frontend/lowering/builtins/typed-array-members.js +160 -0
  186. package/dist/frontend/lowering/builtins/typed-array-members.js.map +1 -0
  187. package/dist/frontend/lowering/call-signatures.d.ts +4 -0
  188. package/dist/frontend/lowering/call-signatures.js +126 -9
  189. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  190. package/dist/frontend/lowering/cjs-exports-object.js +34 -1
  191. package/dist/frontend/lowering/cjs-exports-object.js.map +1 -1
  192. package/dist/frontend/lowering/class-dynamic-dispatch.js +9 -1
  193. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  194. package/dist/frontend/lowering/class-protocols.d.ts +10 -0
  195. package/dist/frontend/lowering/class-protocols.js +53 -3
  196. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  197. package/dist/frontend/lowering/class-prototypes.js +6 -1
  198. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  199. package/dist/frontend/lowering/class-to-primitive.d.ts +2 -2
  200. package/dist/frontend/lowering/class-to-primitive.js +6 -3
  201. package/dist/frontend/lowering/class-to-primitive.js.map +1 -1
  202. package/dist/frontend/lowering/coercions/fresh-spread.d.ts +13 -0
  203. package/dist/frontend/lowering/coercions/fresh-spread.js +95 -0
  204. package/dist/frontend/lowering/coercions/fresh-spread.js.map +1 -0
  205. package/dist/frontend/lowering/coercions/function-adapters.js +99 -70
  206. package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
  207. package/dist/frontend/lowering/containers/array-callbacks.d.ts +8 -0
  208. package/dist/frontend/lowering/containers/array-callbacks.js +22 -19
  209. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  210. package/dist/frontend/lowering/containers/array-construction.js +7 -0
  211. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  212. package/dist/frontend/lowering/containers/array-methods.js +5 -0
  213. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  214. package/dist/frontend/lowering/containers/bytes.d.ts +9 -0
  215. package/dist/frontend/lowering/containers/bytes.js +493 -17
  216. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  217. package/dist/frontend/lowering/containers/collection-methods.js +72 -3
  218. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  219. package/dist/frontend/lowering/containers/string-and-regexp.js +49 -13
  220. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  221. package/dist/frontend/lowering/cycle-initialization.d.ts +26 -10
  222. package/dist/frontend/lowering/cycle-initialization.js +152 -35
  223. package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
  224. package/dist/frontend/lowering/expressions/array-literals.js +33 -13
  225. package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
  226. package/dist/frontend/lowering/expressions/binary.js +79 -5
  227. package/dist/frontend/lowering/expressions/binary.js.map +1 -1
  228. package/dist/frontend/lowering/expressions/element-access.js +13 -6
  229. package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
  230. package/dist/frontend/lowering/expressions/keyed-field-targets.d.ts +14 -2
  231. package/dist/frontend/lowering/expressions/keyed-field-targets.js +91 -10
  232. package/dist/frontend/lowering/expressions/keyed-field-targets.js.map +1 -1
  233. package/dist/frontend/lowering/expressions/narrowing.js +17 -2
  234. package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
  235. package/dist/frontend/lowering/expressions/object-literals.js +48 -1
  236. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  237. package/dist/frontend/lowering/expressions/optional-chains.d.ts +1 -1
  238. package/dist/frontend/lowering/expressions/optional-chains.js +12 -3
  239. package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
  240. package/dist/frontend/lowering/expressions/property-access.d.ts +5 -0
  241. package/dist/frontend/lowering/expressions/property-access.js +252 -9
  242. package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
  243. package/dist/frontend/lowering/expressions/relational.js +49 -4
  244. package/dist/frontend/lowering/expressions/relational.js.map +1 -1
  245. package/dist/frontend/lowering/expressions/typeof.js +13 -0
  246. package/dist/frontend/lowering/expressions/typeof.js.map +1 -1
  247. package/dist/frontend/lowering/expressions/updates.js +1 -1
  248. package/dist/frontend/lowering/expressions/updates.js.map +1 -1
  249. package/dist/frontend/lowering/generator-delegation.d.ts +8 -0
  250. package/dist/frontend/lowering/generator-delegation.js +191 -1
  251. package/dist/frontend/lowering/generator-delegation.js.map +1 -1
  252. package/dist/frontend/lowering/generic-functions.d.ts +4 -0
  253. package/dist/frontend/lowering/generic-functions.js +213 -56
  254. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  255. package/dist/frontend/lowering/handle-properties.d.ts +24 -0
  256. package/dist/frontend/lowering/handle-properties.js +281 -0
  257. package/dist/frontend/lowering/handle-properties.js.map +1 -0
  258. package/dist/frontend/lowering/iterable-spelling.d.ts +7 -0
  259. package/dist/frontend/lowering/iterable-spelling.js +38 -0
  260. package/dist/frontend/lowering/iterable-spelling.js.map +1 -0
  261. package/dist/frontend/lowering/lower-array-sort.d.ts +33 -15
  262. package/dist/frontend/lowering/lower-array-sort.js +117 -21
  263. package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
  264. package/dist/frontend/lowering/lower-array-sort.test.js +93 -14
  265. package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
  266. package/dist/frontend/lowering/lower-builtin-values.js +1 -0
  267. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  268. package/dist/frontend/lowering/lower-calls.js +166 -7
  269. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  270. package/dist/frontend/lowering/lower-classes.d.ts +4 -0
  271. package/dist/frontend/lowering/lower-classes.js +59 -7
  272. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  273. package/dist/frontend/lowering/lower-dgram.js +62 -13
  274. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  275. package/dist/frontend/lowering/lower-exprs.js +32 -1
  276. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  277. package/dist/frontend/lowering/lower-functions.js +4 -0
  278. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  279. package/dist/frontend/lowering/lower-generators.js +10 -4
  280. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  281. package/dist/frontend/lowering/lower-inspect.js +569 -11
  282. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  283. package/dist/frontend/lowering/lower-modules.d.ts +11 -3
  284. package/dist/frontend/lowering/lower-modules.js +212 -67
  285. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  286. package/dist/frontend/lowering/lower-namespaces.js +20 -0
  287. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  288. package/dist/frontend/lowering/lower-server.js +26 -1
  289. package/dist/frontend/lowering/lower-server.js.map +1 -1
  290. package/dist/frontend/lowering/lower-stdlib.js +28 -9
  291. package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
  292. package/dist/frontend/lowering/lower-stmts.d.ts +7 -10
  293. package/dist/frontend/lowering/lower-stmts.js +418 -51
  294. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  295. package/dist/frontend/lowering/lower-timers.js +17 -1
  296. package/dist/frontend/lowering/lower-timers.js.map +1 -1
  297. package/dist/frontend/lowering/lowerer.d.ts +29 -5
  298. package/dist/frontend/lowering/lowerer.js +172 -25
  299. package/dist/frontend/lowering/lowerer.js.map +1 -1
  300. package/dist/frontend/lowering/rebindable-functions.d.ts +8 -0
  301. package/dist/frontend/lowering/rebindable-functions.js +54 -0
  302. package/dist/frontend/lowering/rebindable-functions.js.map +1 -0
  303. package/dist/frontend/lowering/static-typeof.d.ts +26 -0
  304. package/dist/frontend/lowering/static-typeof.js +133 -0
  305. package/dist/frontend/lowering/static-typeof.js.map +1 -0
  306. package/dist/frontend/lowering/string-index-bounds.js +3 -2
  307. package/dist/frontend/lowering/string-index-bounds.js.map +1 -1
  308. package/dist/frontend/lowering/surfaces.js +30 -4
  309. package/dist/frontend/lowering/surfaces.js.map +1 -1
  310. package/dist/frontend/lowering/thenables.d.ts +16 -0
  311. package/dist/frontend/lowering/thenables.js +124 -0
  312. package/dist/frontend/lowering/thenables.js.map +1 -0
  313. package/dist/frontend/npm-static-builtin-aliases.d.ts +8 -0
  314. package/dist/frontend/npm-static-builtin-aliases.js +65 -0
  315. package/dist/frontend/npm-static-builtin-aliases.js.map +1 -0
  316. package/dist/frontend/npm-static-bundled-chunks.d.ts +8 -1
  317. package/dist/frontend/npm-static-bundled-chunks.js +173 -2
  318. package/dist/frontend/npm-static-bundled-chunks.js.map +1 -1
  319. package/dist/frontend/npm-static-bundled-chunks.test.js +112 -0
  320. package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -1
  321. package/dist/frontend/npm-static-bundled-esm.js +224 -4
  322. package/dist/frontend/npm-static-bundled-esm.js.map +1 -1
  323. package/dist/frontend/npm-static-bundled-esm.test.js +129 -0
  324. package/dist/frontend/npm-static-bundled-esm.test.js.map +1 -1
  325. package/dist/frontend/npm-static-enum-iife.d.ts +6 -0
  326. package/dist/frontend/npm-static-enum-iife.js +280 -0
  327. package/dist/frontend/npm-static-enum-iife.js.map +1 -0
  328. package/dist/frontend/npm-static-enum-iife.test.d.ts +1 -0
  329. package/dist/frontend/npm-static-enum-iife.test.js +116 -0
  330. package/dist/frontend/npm-static-enum-iife.test.js.map +1 -0
  331. package/dist/frontend/npm-static.d.ts +8 -0
  332. package/dist/frontend/npm-static.js +46 -1
  333. package/dist/frontend/npm-static.js.map +1 -1
  334. package/dist/frontend/npm.js +13 -0
  335. package/dist/frontend/npm.js.map +1 -1
  336. package/dist/frontend/package-shims.d.ts +47 -0
  337. package/dist/frontend/package-shims.js +300 -0
  338. package/dist/frontend/package-shims.js.map +1 -0
  339. package/dist/frontend/pipeline.js +67 -1
  340. package/dist/frontend/pipeline.js.map +1 -1
  341. package/dist/frontend/program.d.ts +8 -0
  342. package/dist/frontend/program.js +72 -9
  343. package/dist/frontend/program.js.map +1 -1
  344. package/dist/frontend/resolve.js +13 -0
  345. package/dist/frontend/resolve.js.map +1 -1
  346. package/dist/frontend/services.d.ts +6 -0
  347. package/dist/frontend/services.js +19 -0
  348. package/dist/frontend/services.js.map +1 -1
  349. package/dist/frontend/ts7/program-host.d.ts +6 -5
  350. package/dist/frontend/ts7/program-host.js +7 -0
  351. package/dist/frontend/ts7/program-host.js.map +1 -1
  352. package/dist/frontend/ts7/semantic-model.d.ts +3 -0
  353. package/dist/frontend/ts7/semantic-model.js +26 -0
  354. package/dist/frontend/ts7/semantic-model.js.map +1 -1
  355. package/dist/frontend/ts7/session.d.ts +19 -4
  356. package/dist/frontend/ts7/session.js.map +1 -1
  357. package/dist/frontend/type-mapper.js +201 -15
  358. package/dist/frontend/type-mapper.js.map +1 -1
  359. package/dist/index.d.ts +1 -0
  360. package/dist/index.js +58 -6
  361. package/dist/index.js.map +1 -1
  362. package/dist/ir/array-length-stability.d.ts +3 -2
  363. package/dist/ir/array-length-stability.js +15 -2
  364. package/dist/ir/array-length-stability.js.map +1 -1
  365. package/dist/ir/array-length-stability.test.js +22 -1
  366. package/dist/ir/array-length-stability.test.js.map +1 -1
  367. package/dist/ir/builtin-effects.js +13 -0
  368. package/dist/ir/builtin-effects.js.map +1 -1
  369. package/dist/ir/builtin-signatures.d.ts +1 -1
  370. package/dist/ir/builtin-signatures.js +46 -4
  371. package/dist/ir/builtin-signatures.js.map +1 -1
  372. package/dist/ir/integer-loop-facts.d.ts +5 -0
  373. package/dist/ir/integer-loop-facts.js +79 -14
  374. package/dist/ir/integer-loop-facts.js.map +1 -1
  375. package/dist/ir/integer-ranges.d.ts +10 -1
  376. package/dist/ir/integer-ranges.js +122 -25
  377. package/dist/ir/integer-ranges.js.map +1 -1
  378. package/dist/ir/integer-ranges.test.js +191 -1
  379. package/dist/ir/integer-ranges.test.js.map +1 -1
  380. package/dist/ir/ir.js +8 -0
  381. package/dist/ir/ir.js.map +1 -1
  382. package/dist/ir/js-ic.d.ts +52 -0
  383. package/dist/ir/js-ic.js +199 -0
  384. package/dist/ir/js-ic.js.map +1 -0
  385. package/dist/ir/js-ic.test.d.ts +1 -0
  386. package/dist/ir/js-ic.test.js +148 -0
  387. package/dist/ir/js-ic.test.js.map +1 -0
  388. package/dist/ir/jsval.js +38 -4
  389. package/dist/ir/jsval.js.map +1 -1
  390. package/dist/ir/runtime-features.d.ts +39 -4
  391. package/dist/ir/runtime-features.js +229 -99
  392. package/dist/ir/runtime-features.js.map +1 -1
  393. package/dist/ir/traverse.js +110 -68
  394. package/dist/ir/traverse.js.map +1 -1
  395. package/dist/ir/validate.js +21 -8
  396. package/dist/ir/validate.js.map +1 -1
  397. package/dist/ir/validate.test.js +15 -2
  398. package/dist/ir/validate.test.js.map +1 -1
  399. package/dist/library/ir-policy.js +1 -0
  400. package/dist/library/ir-policy.js.map +1 -1
  401. package/dist/native/cli.js +17 -0
  402. package/dist/native/cli.js.map +1 -1
  403. package/dist/native/compiler.js +33 -4
  404. package/dist/native/compiler.js.map +1 -1
  405. package/dist/native/executable-cache.js +3 -0
  406. package/dist/native/executable-cache.js.map +1 -1
  407. package/dist/native/prepare.js +3 -0
  408. package/dist/native/prepare.js.map +1 -1
  409. package/dist/native/sanitizer.test.js +7 -0
  410. package/dist/native/sanitizer.test.js.map +1 -1
  411. package/package.json +21 -20
  412. package/shims/fs-extra/core/api.ts +1192 -0
  413. package/shims/fs-extra/index.ts +9 -0
  414. package/shims/undici/core/agent.ts +163 -0
  415. package/shims/undici/core/api.ts +93 -0
  416. package/shims/undici/core/client.ts +1304 -0
  417. package/shims/undici/core/connector.ts +157 -0
  418. package/shims/undici/core/diagnostics-types.ts +68 -0
  419. package/shims/undici/core/diagnostics.ts +16 -0
  420. package/shims/undici/core/dispatcher.ts +574 -0
  421. package/shims/undici/core/errors-v5.ts +22 -0
  422. package/shims/undici/core/errors-v7.ts +25 -0
  423. package/shims/undici/core/errors.ts +255 -0
  424. package/shims/undici/core/fetch.ts +635 -0
  425. package/shims/undici/core/pool.ts +280 -0
  426. package/shims/undici/core/readable.ts +268 -0
  427. package/shims/undici/core/request.ts +313 -0
  428. package/shims/undici/core/timers.ts +80 -0
  429. package/shims/undici/core/types.ts +167 -0
  430. package/shims/undici/core/util.ts +67 -0
  431. package/shims/undici/v5.ts +119 -0
  432. package/shims/undici/v7.ts +119 -0
  433. package/surface-manifest.json +2 -4
@@ -0,0 +1,1304 @@
1
+ // undici's Client (lib/dispatcher/client.js + client-h1.js): HTTP/1.1 over
2
+ // one TCP/TLS connection at a time, with keep-alive reuse, a request queue,
3
+ // headers/body/idle timeouts and the same request lifecycle callbacks.
4
+ import type { Socket } from "node:net";
5
+ import { buildConnector } from "./connector.ts";
6
+ import { channels } from "./diagnostics.ts";
7
+ import { DispatcherBase } from "./dispatcher.ts";
8
+ import type { Dispatcher } from "./dispatcher.ts";
9
+ import {
10
+ BodyTimeoutError,
11
+ HeadersOverflowError,
12
+ HeadersTimeoutError,
13
+ HTTPParserError,
14
+ InformationalError,
15
+ InvalidArgumentError,
16
+ NotSupportedError,
17
+ RequestAbortedError,
18
+ RequestContentLengthMismatchError,
19
+ ResponseContentLengthMismatchError,
20
+ ResponseExceededMaxSizeError,
21
+ SocketError,
22
+ UndiciError,
23
+ } from "./errors.ts";
24
+ import type { SocketInfo } from "./errors.ts";
25
+ import { Request } from "./request.ts";
26
+ import { FastTimer } from "./timers.ts";
27
+ import { parseKeepAliveTimeout, parseOrigin } from "./util.ts";
28
+ import type {
29
+ ClientOptions,
30
+ Connector,
31
+ ConnectorOptions,
32
+ DispatchHandlers,
33
+ DispatchOptions,
34
+ Profile,
35
+ } from "./types.ts";
36
+
37
+ const TIMEOUT_NONE = 0;
38
+ const TIMEOUT_HEADERS = 1;
39
+ const TIMEOUT_BODY = 2;
40
+ const TIMEOUT_IDLE = 3;
41
+
42
+ export class Client extends DispatcherBase {
43
+ __url: URL;
44
+ __connector: Connector;
45
+ __socket: Socket | null;
46
+ __connecting: boolean;
47
+ __queue: (Request | null)[];
48
+ __runningIdx: number;
49
+ __pendingIdx: number;
50
+ __pipelining: number;
51
+ __hostHeader: string;
52
+ __maxHeaderSize: number;
53
+ __keepAliveDefaultTimeout: number;
54
+ __keepAliveMaxTimeout: number;
55
+ __keepAliveTimeoutThreshold: number;
56
+ __keepAliveTimeoutValue: number;
57
+ __headersTimeout: number;
58
+ __bodyTimeout: number;
59
+ __strictContentLength: boolean;
60
+ __maxRequests: number;
61
+ __maxResponseSize: number;
62
+ __resuming: number;
63
+ __needDrain: number;
64
+ __closedResolve: (() => void) | null;
65
+ __serverName: string | null;
66
+ __localAddress: string | null;
67
+ // Per-connection state (one socket at a time).
68
+ __sockNoRef: boolean;
69
+ __sockReset: boolean;
70
+ __sockBlocking: boolean;
71
+ __sockCounter: number;
72
+ __parser: ResponseParser | null;
73
+ __sockError: Error | null;
74
+ // The parser timer, held as closures over its handle (a nullable timer
75
+ // field does not compile under @types/node).
76
+ __timerCancel: (() => void) | null;
77
+ __timerRefresh: (() => void) | null;
78
+ __timerType: number;
79
+
80
+ constructor(url: string | URL, options: ClientOptions | undefined, profile: Profile) {
81
+ super(profile);
82
+ const opts: ClientOptions = options ?? {};
83
+ const pipelining = opts.pipelining ?? 1;
84
+ if (!Number.isInteger(pipelining) || pipelining < 0) {
85
+ throw new InvalidArgumentError("invalid pipelining");
86
+ }
87
+ if (pipelining > 1) {
88
+ throw new NotSupportedError(
89
+ "scriptc's undici client does not pipeline more than one request yet",
90
+ );
91
+ }
92
+ const maxHeaderSize = opts.maxHeaderSize ?? null;
93
+ if (maxHeaderSize !== null && !Number.isFinite(maxHeaderSize)) {
94
+ throw new InvalidArgumentError("invalid maxHeaderSize");
95
+ }
96
+ const connectTimeout = opts.connectTimeout ?? null;
97
+ if (connectTimeout !== null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) {
98
+ throw new InvalidArgumentError("invalid connectTimeout");
99
+ }
100
+ const keepAliveTimeout = opts.keepAliveTimeout ?? null;
101
+ if (
102
+ keepAliveTimeout !== null &&
103
+ (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)
104
+ ) {
105
+ throw new InvalidArgumentError("invalid keepAliveTimeout");
106
+ }
107
+ const keepAliveMaxTimeout = opts.keepAliveMaxTimeout ?? null;
108
+ if (
109
+ keepAliveMaxTimeout !== null &&
110
+ (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)
111
+ ) {
112
+ throw new InvalidArgumentError("invalid keepAliveMaxTimeout");
113
+ }
114
+ const keepAliveTimeoutThreshold = opts.keepAliveTimeoutThreshold ?? null;
115
+ if (keepAliveTimeoutThreshold !== null && !Number.isFinite(keepAliveTimeoutThreshold)) {
116
+ throw new InvalidArgumentError("invalid keepAliveTimeoutThreshold");
117
+ }
118
+ const headersTimeout = opts.headersTimeout ?? null;
119
+ if (headersTimeout !== null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) {
120
+ throw new InvalidArgumentError("headersTimeout must be a positive integer or zero");
121
+ }
122
+ const bodyTimeout = opts.bodyTimeout ?? null;
123
+ if (bodyTimeout !== null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) {
124
+ throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero");
125
+ }
126
+ const maxRequests = opts.maxRequestsPerClient ?? 0;
127
+ if (!Number.isInteger(maxRequests) || maxRequests < 0) {
128
+ throw new InvalidArgumentError("maxRequestsPerClient must be a positive number");
129
+ }
130
+ const maxResponseSize = opts.maxResponseSize ?? -1;
131
+ if (!Number.isInteger(maxResponseSize) || maxResponseSize < -1) {
132
+ throw new InvalidArgumentError("maxResponseSize must be a positive number");
133
+ }
134
+
135
+ const connect = opts.connect ?? null;
136
+ if (typeof connect === "function") {
137
+ this.__connector = connect;
138
+ } else {
139
+ this.__connector = buildConnector(
140
+ connect !== null
141
+ ? {
142
+ ...connect,
143
+ timeout: connect.timeout !== undefined ? connect.timeout : connectTimeout,
144
+ }
145
+ : { timeout: connectTimeout },
146
+ );
147
+ }
148
+ // 5.x composes `interceptors.Client` around dispatch; 7.x dropped the
149
+ // option and ignores it.
150
+ const interceptors = opts.interceptors;
151
+ if (profile.major < 7 && interceptors !== undefined && interceptors.Client !== undefined) {
152
+ this.__interceptors = interceptors.Client;
153
+ }
154
+
155
+ this.__url = parseOrigin(url, profile);
156
+ this.__socket = null;
157
+ this.__connecting = false;
158
+ this.__queue = [];
159
+ this.__runningIdx = 0;
160
+ this.__pendingIdx = 0;
161
+ this.__pipelining = pipelining;
162
+ this.__hostHeader = `host: ${this.__url.hostname}${this.__url.port ? `:${this.__url.port}` : ""}\r\n`;
163
+ this.__maxHeaderSize = maxHeaderSize !== null && maxHeaderSize !== 0 ? maxHeaderSize : 16384;
164
+ this.__keepAliveDefaultTimeout = keepAliveTimeout ?? 4e3;
165
+ this.__keepAliveMaxTimeout = keepAliveMaxTimeout ?? 600e3;
166
+ this.__keepAliveTimeoutThreshold =
167
+ keepAliveTimeoutThreshold ?? (profile.major >= 7 ? 2e3 : 1e3);
168
+ this.__keepAliveTimeoutValue = this.__keepAliveDefaultTimeout;
169
+ const defaultTimeout = profile.major >= 7 ? 300e3 : 30e3;
170
+ this.__headersTimeout = headersTimeout ?? defaultTimeout;
171
+ this.__bodyTimeout = bodyTimeout ?? defaultTimeout;
172
+ this.__strictContentLength = opts.strictContentLength ?? true;
173
+ this.__maxRequests = maxRequests;
174
+ this.__maxResponseSize = maxResponseSize;
175
+ this.__resuming = 0;
176
+ this.__needDrain = 0;
177
+ this.__closedResolve = null;
178
+ this.__serverName = null;
179
+ this.__localAddress = opts.localAddress ?? null;
180
+ this.__sockNoRef = false;
181
+ this.__sockReset = false;
182
+ this.__sockBlocking = false;
183
+ this.__sockCounter = 0;
184
+ this.__parser = null;
185
+ this.__sockError = null;
186
+ this.__timerCancel = null;
187
+ this.__timerRefresh = null;
188
+ this.__timerType = TIMEOUT_NONE;
189
+ }
190
+
191
+ get pipelining(): number {
192
+ return this.__pipelining;
193
+ }
194
+
195
+ __pendingCount(): number {
196
+ return this.__queue.length - this.__pendingIdx;
197
+ }
198
+
199
+ __runningCount(): number {
200
+ return this.__pendingIdx - this.__runningIdx;
201
+ }
202
+
203
+ __sizeCount(): number {
204
+ return this.__queue.length - this.__runningIdx;
205
+ }
206
+
207
+ __connectedFlag(): boolean {
208
+ const socket = this.__socket;
209
+ return socket !== null && !this.__connecting && !socket.destroyed;
210
+ }
211
+
212
+ __busy(): boolean {
213
+ return (
214
+ (this.__socket !== null && (this.__sockReset || this.__sockBlocking)) ||
215
+ this.__sizeCount() >= (this.__pipelining || 1) ||
216
+ this.__pendingCount() > 0
217
+ );
218
+ }
219
+
220
+ __dispatch(opts: DispatchOptions, handler: DispatchHandlers): boolean {
221
+ const originValue = opts.origin;
222
+ const origin =
223
+ originValue === undefined || originValue === ""
224
+ ? this.__url.origin
225
+ : typeof originValue === "string"
226
+ ? originValue
227
+ : originValue.origin;
228
+ const request = new Request(origin, opts, handler, this.__profile);
229
+ this.__queue.push(request);
230
+ if (this.__resuming === 0) this.__resume(true);
231
+ if (this.__resuming !== 0 && this.__needDrain !== 2 && this.__busy()) this.__needDrain = 2;
232
+ return this.__needDrain < 2;
233
+ }
234
+
235
+ __close(): Promise<void> {
236
+ return new Promise<void>((resolve) => {
237
+ if (this.__sizeCount() === 0) {
238
+ this.destroy().then(() => resolve());
239
+ } else {
240
+ this.__closedResolve = resolve;
241
+ }
242
+ });
243
+ }
244
+
245
+ __destroy(err: Error): Promise<void> {
246
+ return new Promise<void>((resolve) => {
247
+ const requests = this.__queue.splice(this.__pendingIdx);
248
+ for (const request of requests) if (request !== null) this.__errorRequest(request, err);
249
+ const done = (): void => {
250
+ const closed = this.__closedResolve;
251
+ if (closed !== null) {
252
+ this.__closedResolve = null;
253
+ closed();
254
+ }
255
+ resolve();
256
+ };
257
+ const socket = this.__socket;
258
+ if (socket === null) {
259
+ queueMicrotask(done);
260
+ } else {
261
+ socket.on("close", () => done());
262
+ this.__destroySocket(socket, err);
263
+ }
264
+ this.__resume(false);
265
+ });
266
+ }
267
+
268
+ /** util.destroy(socket, err): remember the first error for 'close'. */
269
+ __destroySocket(socket: Socket, err: Error): void {
270
+ if (socket === this.__socket && this.__sockError === null) this.__sockError = err;
271
+ socket.destroy();
272
+ }
273
+
274
+ __errorRequest(request: Request, err: Error): void {
275
+ try {
276
+ request.onError(err);
277
+ } catch (e) {
278
+ this.emit("error", e as Error);
279
+ }
280
+ }
281
+
282
+ __socketInfo(): SocketInfo {
283
+ const socket = this.__socket;
284
+ if (socket === null) return {};
285
+ return {
286
+ localAddress: socket.localAddress,
287
+ localPort: socket.localPort,
288
+ remoteAddress: socket.remoteAddress,
289
+ remotePort: socket.remotePort,
290
+ remoteFamily: socket.remoteFamily,
291
+ timeout: undefined,
292
+ bytesWritten: socket.bytesWritten,
293
+ bytesRead: socket.bytesRead,
294
+ };
295
+ }
296
+
297
+ /** The parser timer: 5.x uses native timers throughout; 7.x drives the
298
+ * headers and body timeouts from its fast timers. */
299
+ __setTimeout(delay: number, type: number): void {
300
+ this.__clearTimer();
301
+ this.__timerType = type;
302
+ if (delay > 0) {
303
+ if (this.__profile.major >= 7 && (type === TIMEOUT_HEADERS || type === TIMEOUT_BODY)) {
304
+ const fast = new FastTimer(() => this.__onTimeout(), delay);
305
+ this.__timerCancel = () => fast.clear();
306
+ this.__timerRefresh = () => fast.refresh();
307
+ } else {
308
+ const timer = setTimeout(() => this.__onTimeout(), delay);
309
+ timer.unref();
310
+ this.__timerCancel = () => clearTimeout(timer);
311
+ this.__timerRefresh = () => {
312
+ timer.refresh();
313
+ };
314
+ }
315
+ }
316
+ }
317
+
318
+ __clearTimer(): void {
319
+ const cancel = this.__timerCancel;
320
+ this.__timerCancel = null;
321
+ this.__timerRefresh = null;
322
+ if (cancel !== null) cancel();
323
+ }
324
+
325
+ __refreshTimer(): void {
326
+ const refresh = this.__timerRefresh;
327
+ if (refresh !== null) refresh();
328
+ }
329
+
330
+ __onTimeout(): void {
331
+ const socket = this.__socket;
332
+ const parser = this.__parser;
333
+ // A body timeout that fires while the response is paused keeps its
334
+ // timer: resuming refreshes it, as undici's parser does.
335
+ if (this.__timerType === TIMEOUT_BODY && parser !== null && parser.paused) return;
336
+ this.__timerCancel = null;
337
+ this.__timerRefresh = null;
338
+ if (socket === null || parser === null) return;
339
+ if (this.__timerType === TIMEOUT_HEADERS) {
340
+ this.__destroySocket(socket, new HeadersTimeoutError());
341
+ } else if (this.__timerType === TIMEOUT_BODY) {
342
+ this.__destroySocket(socket, new BodyTimeoutError());
343
+ } else if (this.__timerType === TIMEOUT_IDLE) {
344
+ this.__destroySocket(socket, new InformationalError("socket idle timeout"));
345
+ }
346
+ }
347
+
348
+ __connect(): void {
349
+ const url = this.__url;
350
+ let hostname = url.hostname;
351
+ if (hostname.startsWith("[")) {
352
+ const idx = hostname.indexOf("]");
353
+ hostname = hostname.slice(1, idx);
354
+ }
355
+ this.__connecting = true;
356
+ const params: ConnectorOptions = {
357
+ host: url.host,
358
+ hostname,
359
+ protocol: url.protocol,
360
+ port: url.port,
361
+ servername: this.__serverName ?? undefined,
362
+ localAddress: this.__localAddress,
363
+ };
364
+ const connectParams = {
365
+ host: url.host,
366
+ hostname,
367
+ protocol: url.protocol,
368
+ port: url.port,
369
+ servername: this.__serverName,
370
+ localAddress: this.__localAddress,
371
+ };
372
+ if (channels.beforeConnect.hasSubscribers) {
373
+ channels.beforeConnect.publish({ connectParams });
374
+ }
375
+ let settled = false;
376
+ const onConnected = (err: Error | null, socket: Socket | null): void => {
377
+ if (settled) return;
378
+ settled = true;
379
+ // undici awaits the connector's promise: continue on a later tick.
380
+ queueMicrotask(() => {
381
+ if (err !== null || socket === null)
382
+ this.__onConnectError(err ?? new SocketError("connect failed"), connectParams);
383
+ else this.__onConnected(socket, connectParams);
384
+ });
385
+ };
386
+ try {
387
+ this.__connector(params, onConnected);
388
+ } catch (err) {
389
+ onConnected(err as Error, null);
390
+ }
391
+ }
392
+
393
+ __onConnected(
394
+ socket: Socket,
395
+ connectParams: {
396
+ host: string;
397
+ hostname: string;
398
+ protocol: string;
399
+ port: string;
400
+ servername: string | null;
401
+ localAddress: string | null;
402
+ },
403
+ ): void {
404
+ this.__connecting = false;
405
+ if (this.destroyed) {
406
+ socket.destroy();
407
+ this.__resume(false);
408
+ return;
409
+ }
410
+ this.__socket = socket;
411
+ this.__sockNoRef = false;
412
+ this.__sockReset = false;
413
+ this.__sockBlocking = false;
414
+ this.__sockCounter = 0;
415
+ this.__sockError = null;
416
+ const parser = new ResponseParser(this, socket);
417
+ this.__parser = parser;
418
+ socket.on("data", (chunk: Buffer) => {
419
+ if (this.__socket === socket) parser.execute(chunk);
420
+ });
421
+ socket.on("error", (err: Error) => {
422
+ if (this.__socket === socket) this.__onSocketError(socket, err);
423
+ });
424
+ socket.on("end", () => {
425
+ if (this.__socket === socket) this.__onSocketEnd(socket);
426
+ });
427
+ socket.on("close", () => {
428
+ if (this.__socket === socket) this.__onSocketClose(socket);
429
+ });
430
+ if (channels.connected.hasSubscribers) {
431
+ channels.connected.publish({ connectParams });
432
+ }
433
+ this.emit("connect", this.__url, [this as Dispatcher]);
434
+ this.__resume(false);
435
+ }
436
+
437
+ __onConnectError(
438
+ err: Error,
439
+ connectParams: {
440
+ host: string;
441
+ hostname: string;
442
+ protocol: string;
443
+ port: string;
444
+ servername: string | null;
445
+ localAddress: string | null;
446
+ },
447
+ ): void {
448
+ this.__connecting = false;
449
+ if (channels.connectError.hasSubscribers) {
450
+ channels.connectError.publish({ connectParams, error: err });
451
+ }
452
+ this.__onError(err);
453
+ this.emit("connectionError", this.__url, [this as Dispatcher], err);
454
+ this.__resume(false);
455
+ }
456
+
457
+ /** client.js onError: with nothing running, a connection-level failure
458
+ * fails every queued request. */
459
+ __onError(err: Error): void {
460
+ const code = errorCode(err);
461
+ if (this.__runningCount() === 0 && code !== "UND_ERR_INFO" && code !== "UND_ERR_SOCKET") {
462
+ const requests = this.__queue.splice(this.__runningIdx);
463
+ for (const request of requests) if (request !== null) this.__errorRequest(request, err);
464
+ }
465
+ }
466
+
467
+ __onSocketError(socket: Socket, err: Error): void {
468
+ const parser = this.__parser;
469
+ if (
470
+ errorCode(err) === "ECONNRESET" &&
471
+ parser !== null &&
472
+ parser.statusCode !== 0 &&
473
+ !parser.shouldKeepAlive
474
+ ) {
475
+ parser.finishOnEof();
476
+ return;
477
+ }
478
+ this.__destroySocket(socket, err);
479
+ this.__onError(err);
480
+ }
481
+
482
+ __onSocketEnd(socket: Socket): void {
483
+ const parser = this.__parser;
484
+ if (parser !== null && parser.statusCode !== 0 && !parser.shouldKeepAlive) {
485
+ parser.finishOnEof();
486
+ return;
487
+ }
488
+ this.__destroySocket(socket, new SocketError("other side closed", this.__socketInfo()));
489
+ }
490
+
491
+ __onSocketClose(_socket: Socket): void {
492
+ const parser = this.__parser;
493
+ const recorded = this.__sockError;
494
+ this.__sockError = null;
495
+ if (
496
+ recorded === null &&
497
+ parser !== null &&
498
+ parser.statusCode !== 0 &&
499
+ !parser.shouldKeepAlive
500
+ ) {
501
+ parser.finishOnEof();
502
+ }
503
+ const err = recorded ?? new SocketError("closed", this.__socketInfo());
504
+ this.__parser = null;
505
+ this.__socket = null;
506
+ this.__clearTimer();
507
+ this.__timerType = TIMEOUT_NONE;
508
+ if (this.destroyed) {
509
+ const requests = this.__queue.splice(this.__runningIdx);
510
+ for (const request of requests) if (request !== null) this.__errorRequest(request, err);
511
+ } else if (this.__runningCount() > 0 && errorCode(err) !== "UND_ERR_INFO") {
512
+ const request = this.__queue[this.__runningIdx];
513
+ this.__queue[this.__runningIdx++] = null;
514
+ if (request !== null && request !== undefined) this.__errorRequest(request, err);
515
+ }
516
+ this.__pendingIdx = this.__runningIdx;
517
+ this.emit("disconnect", this.__url, [this as Dispatcher], err);
518
+ this.__resume(false);
519
+ }
520
+
521
+ __emitDrain(): void {
522
+ this.__needDrain = 0;
523
+ this.emit("drain", this.__url, [this as Dispatcher]);
524
+ }
525
+
526
+ __resume(sync: boolean): void {
527
+ if (this.__resuming === 2) return;
528
+ this.__resuming = 2;
529
+ this.__resumeLoop(sync);
530
+ this.__resuming = 0;
531
+ if (this.__runningIdx > 256) {
532
+ this.__queue.splice(0, this.__runningIdx);
533
+ this.__pendingIdx -= this.__runningIdx;
534
+ this.__runningIdx = 0;
535
+ }
536
+ }
537
+
538
+ __resumeLoop(sync: boolean): void {
539
+ for (;;) {
540
+ if (this.destroyed) return;
541
+ if (this.closed && this.__sizeCount() === 0) {
542
+ this.destroy();
543
+ return;
544
+ }
545
+ const socket = this.__socket;
546
+ const parser = this.__parser;
547
+ if (socket !== null && parser !== null) {
548
+ if (this.__sizeCount() === 0) {
549
+ if (!this.__sockNoRef) {
550
+ socket.unref();
551
+ this.__sockNoRef = true;
552
+ }
553
+ } else if (this.__sockNoRef) {
554
+ socket.ref();
555
+ this.__sockNoRef = false;
556
+ }
557
+ if (this.__sizeCount() === 0) {
558
+ if (this.__timerType !== TIMEOUT_IDLE)
559
+ this.__setTimeout(this.__keepAliveTimeoutValue, TIMEOUT_IDLE);
560
+ } else if (this.__runningCount() > 0 && parser.statusCode < 200) {
561
+ if (this.__timerType !== TIMEOUT_HEADERS) {
562
+ const request = this.__queue[this.__runningIdx];
563
+ const headersTimeout =
564
+ request !== null && request !== undefined && request.headersTimeout !== null
565
+ ? request.headersTimeout
566
+ : this.__headersTimeout;
567
+ this.__setTimeout(headersTimeout, TIMEOUT_HEADERS);
568
+ }
569
+ }
570
+ }
571
+
572
+ if (this.__busy()) {
573
+ this.__needDrain = 2;
574
+ } else if (this.__needDrain === 2) {
575
+ if (sync) {
576
+ this.__needDrain = 1;
577
+ process.nextTick(() => this.__emitDrain());
578
+ } else {
579
+ this.__emitDrain();
580
+ }
581
+ continue;
582
+ }
583
+
584
+ if (this.__pendingCount() === 0) return;
585
+ if (this.__runningCount() >= (this.__pipelining || 1)) return;
586
+
587
+ const request = this.__queue[this.__pendingIdx]!;
588
+ if (this.__url.protocol === "https:" && this.__serverName !== request.servername) {
589
+ if (this.__runningCount() > 0) return;
590
+ this.__serverName = request.servername;
591
+ if (socket !== null) {
592
+ this.__destroySocket(socket, new InformationalError("servername changed"));
593
+ return;
594
+ }
595
+ }
596
+ if (this.__connecting) return;
597
+ if (socket === null) {
598
+ this.__connect();
599
+ continue;
600
+ }
601
+ if (socket.destroyed || this.__sockReset || this.__sockBlocking) return;
602
+ if (this.__runningCount() > 0 && !request.idempotent) return;
603
+
604
+ if (!request.aborted && this.__write(request, socket)) {
605
+ this.__pendingIdx++;
606
+ } else {
607
+ this.__queue.splice(this.__pendingIdx, 1);
608
+ }
609
+ }
610
+ }
611
+
612
+ __write(request: Request, socket: Socket): boolean {
613
+ const method = request.method;
614
+ const body = request.body;
615
+ const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
616
+ // util.bodyLength: a missing body has length 0.
617
+ let contentLength: number | null = body !== null ? body.length : 0;
618
+ if (contentLength === 0 && !expectsPayload) contentLength = null;
619
+ const declared = request.contentLength;
620
+ const sendsLength =
621
+ method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE";
622
+ const mismatch =
623
+ declared !== null &&
624
+ declared !== contentLength &&
625
+ (this.__profile.major < 7 || (sendsLength && contentLength !== null && contentLength > 0));
626
+ if (mismatch) {
627
+ if (this.__strictContentLength) {
628
+ this.__errorRequest(request, new RequestContentLengthMismatchError());
629
+ return false;
630
+ }
631
+ process.emitWarning(new RequestContentLengthMismatchError());
632
+ }
633
+
634
+ const abort = (err?: Error): void => {
635
+ if (request.aborted || request.completed) return;
636
+ this.__errorRequest(request, err ?? new RequestAbortedError());
637
+ this.__destroySocket(socket, new InformationalError("aborted"));
638
+ };
639
+ try {
640
+ request.onConnect(abort);
641
+ } catch (err) {
642
+ this.__errorRequest(request, err as Error);
643
+ }
644
+ if (request.aborted) return false;
645
+
646
+ if (method === "HEAD") this.__sockReset = true;
647
+ if (request.reset !== null) this.__sockReset = request.reset;
648
+ if (this.__maxRequests > 0 && this.__sockCounter++ >= this.__maxRequests)
649
+ this.__sockReset = true;
650
+ if (request.blocking) this.__sockBlocking = true;
651
+
652
+ let header = `${method} ${request.path} HTTP/1.1\r\n`;
653
+ header += request.host !== null ? `host: ${request.host}\r\n` : this.__hostHeader;
654
+ if (this.__pipelining !== 0 && !(this.__profile.major >= 7 && this.__sockReset)) {
655
+ header += "connection: keep-alive\r\n";
656
+ } else {
657
+ header += "connection: close\r\n";
658
+ }
659
+ header += request.headers;
660
+ if (channels.sendHeaders.hasSubscribers) {
661
+ channels.sendHeaders.publish({ request: request.diagnosticView(), headers: header });
662
+ }
663
+ if (body === null) {
664
+ if (contentLength === 0) socket.write(`${header}content-length: 0\r\n\r\n`);
665
+ else socket.write(`${header}\r\n`);
666
+ } else {
667
+ socket.write(`${header}content-length: ${contentLength}\r\n\r\n`);
668
+ socket.write(body);
669
+ request.onBodySent(body);
670
+ if (!expectsPayload && (this.__profile.major < 7 || request.reset !== false))
671
+ this.__sockReset = true;
672
+ }
673
+ request.onRequestSent();
674
+ return true;
675
+ }
676
+
677
+ // ResponseParser callbacks.
678
+
679
+ __onHeadersComplete(parser: ResponseParser, socket: Socket): number {
680
+ const request = this.__queue[this.__runningIdx];
681
+ if (request === null || request === undefined || socket.destroyed) return -1;
682
+ const statusCode = parser.statusCode;
683
+ if (statusCode === 100) {
684
+ this.__destroySocket(socket, new SocketError("bad response", this.__socketInfo()));
685
+ return -1;
686
+ }
687
+ if (statusCode >= 200) {
688
+ const bodyTimeout = request.bodyTimeout !== null ? request.bodyTimeout : this.__bodyTimeout;
689
+ this.__setTimeout(bodyTimeout, TIMEOUT_BODY);
690
+ }
691
+ if (parser.shouldKeepAlive && this.__pipelining !== 0) {
692
+ const hint =
693
+ parser.keepAliveHeader !== "" ? parseKeepAliveTimeout(parser.keepAliveHeader) : null;
694
+ if (hint !== null) {
695
+ const timeout = Math.min(
696
+ hint - this.__keepAliveTimeoutThreshold,
697
+ this.__keepAliveMaxTimeout,
698
+ );
699
+ if (timeout <= 0) this.__sockReset = true;
700
+ else this.__keepAliveTimeoutValue = timeout;
701
+ } else {
702
+ this.__keepAliveTimeoutValue = this.__keepAliveDefaultTimeout;
703
+ }
704
+ } else {
705
+ this.__sockReset = true;
706
+ }
707
+ let pause = false;
708
+ try {
709
+ pause =
710
+ request.onHeaders(statusCode, parser.headers, () => parser.resume(), parser.statusText) ===
711
+ false;
712
+ } catch (err) {
713
+ this.__destroySocket(socket, err as Error);
714
+ return -1;
715
+ }
716
+ if (request.method === "HEAD") return 1;
717
+ if (statusCode < 200) return 1;
718
+ if (this.__sockBlocking) {
719
+ this.__sockBlocking = false;
720
+ this.__resume(false);
721
+ }
722
+ return pause ? 2 : 0;
723
+ }
724
+
725
+ __onBody(parser: ResponseParser, socket: Socket, chunk: Buffer): boolean {
726
+ const request = this.__queue[this.__runningIdx];
727
+ if (request === null || request === undefined || socket.destroyed) return false;
728
+ if (this.__timerType === TIMEOUT_BODY) this.__refreshTimer();
729
+ if (this.__maxResponseSize > -1 && parser.bytesRead + chunk.length > this.__maxResponseSize) {
730
+ this.__destroySocket(socket, new ResponseExceededMaxSizeError());
731
+ return false;
732
+ }
733
+ parser.bytesRead += chunk.length;
734
+ try {
735
+ return request.onData(chunk) !== false;
736
+ } catch (err) {
737
+ this.__destroySocket(socket, err as Error);
738
+ return false;
739
+ }
740
+ }
741
+
742
+ /** Returns false when the socket was torn down (stop parsing). */
743
+ __onMessageComplete(parser: ResponseParser, socket: Socket, trailers: Buffer[]): boolean {
744
+ if (socket.destroyed && (parser.statusCode === 0 || parser.shouldKeepAlive)) return false;
745
+ const request = this.__queue[this.__runningIdx];
746
+ if (request === null || request === undefined) return false;
747
+ const statusCode = parser.statusCode;
748
+ const shouldKeepAlive = parser.shouldKeepAlive;
749
+ const contentLength = parser.contentLength;
750
+ const bytesRead = parser.bytesRead;
751
+ parser.reset();
752
+ if (statusCode < 200) return true;
753
+ if (request.method !== "HEAD" && contentLength >= 0 && bytesRead !== contentLength) {
754
+ this.__destroySocket(socket, new ResponseContentLengthMismatchError());
755
+ return false;
756
+ }
757
+ try {
758
+ request.onComplete(trailers);
759
+ } catch (err) {
760
+ this.__errorRequest(request, err as Error);
761
+ }
762
+ this.__queue[this.__runningIdx++] = null;
763
+ if (!shouldKeepAlive) {
764
+ this.__destroySocket(socket, new InformationalError("reset"));
765
+ return false;
766
+ }
767
+ if (this.__sockReset && this.__runningCount() === 0) {
768
+ this.__destroySocket(socket, new InformationalError("reset"));
769
+ return false;
770
+ }
771
+ if (this.__pipelining === 1) setImmediate(() => this.__resume(false));
772
+ else this.__resume(false);
773
+ return true;
774
+ }
775
+
776
+ __onParseError(socket: Socket, err: Error): void {
777
+ this.__destroySocket(socket, err);
778
+ }
779
+ }
780
+
781
+ function errorCode(err: Error): string {
782
+ if (err instanceof UndiciError) return err.code;
783
+ return (err as NodeJS.ErrnoException).code ?? "";
784
+ }
785
+
786
+ const CRLF = Buffer.from("\r\n");
787
+
788
+ // Chunk-size line states (llhttp's chunk_size* and chunk_extension* nodes).
789
+ const SIZE_FIRST = 0;
790
+ const SIZE_DIGITS = 1;
791
+ const SIZE_AFTER = 2;
792
+ const SIZE_EXT = 3;
793
+ const SIZE_EXT_NAME = 4;
794
+ const SIZE_EXT_VALUE = 5;
795
+ const SIZE_EXT_QUOTED = 6;
796
+ const SIZE_EXT_PAIR = 7;
797
+ const SIZE_EXT_QUOTED_DONE = 8;
798
+ const SIZE_CR = 9;
799
+
800
+ function hexDigit(c: number): number {
801
+ if (c >= 0x30 && c <= 0x39) return c - 0x30;
802
+ if (c >= 0x41 && c <= 0x46) return c - 0x37;
803
+ if (c >= 0x61 && c <= 0x66) return c - 0x57;
804
+ return -1;
805
+ }
806
+
807
+ /** tchar: ALPHA, DIGIT and !#$%&'*+-.^_`|~. */
808
+ const TOKEN_BYTES = tokenBytes();
809
+
810
+ function tokenBytes(): Uint8Array {
811
+ const table = new Uint8Array(256);
812
+ const marks = "!#$%&'*+-.^_`|~";
813
+ for (let i = 0; i < marks.length; i++) table[marks.charCodeAt(i)] = 1;
814
+ for (let c = 0x30; c <= 0x39; c++) table[c] = 1;
815
+ for (let c = 0x41; c <= 0x5a; c++) {
816
+ table[c] = 1;
817
+ table[c + 0x20] = 1;
818
+ }
819
+ return table;
820
+ }
821
+
822
+ /** qdtext: HTAB, SP and 0x21-0xff but '"' and '\\'. */
823
+ function isQuotedByte(c: number): boolean {
824
+ return c === 0x09 || c === 0x20 || (c >= 0x21 && c !== 0x22 && c !== 0x5c);
825
+ }
826
+
827
+ /** The byte after '\\' in a quoted-pair: HTAB, SP, VCHAR or obs-text. */
828
+ function isQuotedPairByte(c: number): boolean {
829
+ return c === 0x09 || c === 0x20 || (c >= 0x21 && c !== 0x7f);
830
+ }
831
+
832
+ /** An incremental HTTP/1.1 response parser (the subset of llhttp undici
833
+ * relies on): status line, raw header pairs, Content-Length, chunked and
834
+ * read-until-close bodies, trailers, and pause/resume back-pressure. */
835
+ class ResponseParser {
836
+ client: Client;
837
+ socket: Socket;
838
+ /** Unconsumed bytes of the current arrival, then the later arrivals in
839
+ * order. */
840
+ buf: Buffer;
841
+ queue: Buffer[];
842
+ state: number;
843
+ paused: boolean;
844
+ statusCode: number;
845
+ statusText: string;
846
+ headers: Buffer[];
847
+ headersSize: number;
848
+ versionMinor: number;
849
+ contentLength: number;
850
+ chunked: boolean;
851
+ connectionHeader: string;
852
+ keepAliveHeader: string;
853
+ shouldKeepAlive: boolean;
854
+ remaining: number;
855
+ bytesRead: number;
856
+ trailers: Buffer[];
857
+ skipBody: boolean;
858
+ sizeState: number;
859
+ sizeDigits: number;
860
+ chunkSize: number;
861
+
862
+ constructor(client: Client, socket: Socket) {
863
+ this.client = client;
864
+ this.socket = socket;
865
+ this.buf = Buffer.alloc(0);
866
+ this.queue = [];
867
+ this.state = 0;
868
+ this.paused = false;
869
+ this.statusCode = 0;
870
+ this.statusText = "";
871
+ this.headers = [];
872
+ this.headersSize = 0;
873
+ this.versionMinor = 1;
874
+ this.contentLength = -1;
875
+ this.chunked = false;
876
+ this.connectionHeader = "";
877
+ this.keepAliveHeader = "";
878
+ this.shouldKeepAlive = true;
879
+ this.remaining = 0;
880
+ this.bytesRead = 0;
881
+ this.trailers = [];
882
+ this.skipBody = false;
883
+ this.sizeState = SIZE_FIRST;
884
+ this.sizeDigits = 0;
885
+ this.chunkSize = 0;
886
+ }
887
+
888
+ reset(): void {
889
+ this.state = 0;
890
+ this.statusCode = 0;
891
+ this.statusText = "";
892
+ this.headers = [];
893
+ this.headersSize = 0;
894
+ this.contentLength = -1;
895
+ this.chunked = false;
896
+ this.connectionHeader = "";
897
+ this.keepAliveHeader = "";
898
+ this.remaining = 0;
899
+ this.bytesRead = 0;
900
+ this.trailers = [];
901
+ this.skipBody = false;
902
+ }
903
+
904
+ execute(data: Buffer): void {
905
+ if (this.buf.length === 0 && this.queue.length === 0) this.buf = data;
906
+ else this.queue.push(data);
907
+ if (!this.paused) this.run();
908
+ }
909
+
910
+ /** Moves the next queued arrival into `buf`, after the bytes left in it;
911
+ * false when nothing is queued. Only a partial status, header or trailer
912
+ * line (bounded by maxHeaderSize) or a partial chunk-data CRLF is copied. */
913
+ more(): boolean {
914
+ const next = this.queue.shift();
915
+ if (next === undefined) return false;
916
+ this.buf = this.buf.length === 0 ? next : Buffer.concat([this.buf, next]);
917
+ return true;
918
+ }
919
+
920
+ resume(): void {
921
+ if (!this.paused) return;
922
+ if (this.client.__timerType === TIMEOUT_BODY) this.client.__refreshTimer();
923
+ this.paused = false;
924
+ this.socket.resume();
925
+ this.run();
926
+ }
927
+
928
+ pause(): void {
929
+ this.paused = true;
930
+ this.socket.pause();
931
+ }
932
+
933
+ /** EOF while reading a close-delimited body completes the message. */
934
+ finishOnEof(): void {
935
+ if (this.state === 6) {
936
+ this.client.__onMessageComplete(this, this.socket, []);
937
+ }
938
+ }
939
+
940
+ /** A parse error with llhttp's reason: undici 7 puts it inside its
941
+ * protocol message and, as its error table maps names to numbers only,
942
+ * sets no code; undici 5 uses the reason as the message and the code. */
943
+ fail(reason: string, code: string): void {
944
+ const err =
945
+ this.client.__profile.major >= 7
946
+ ? new HTTPParserError(`Response does not match the HTTP/1.1 protocol (${reason})`)
947
+ : new HTTPParserError(reason, code, "");
948
+ this.client.__onParseError(this.socket, err);
949
+ this.state = 99;
950
+ }
951
+
952
+ /** Reads the chunk-size line one byte at a time as llhttp does, so a line
953
+ * that never ends holds no memory: hex digits (past 16 significant ones
954
+ * the size overflows), then extensions, checked and dropped, then CRLF.
955
+ * The 7.x profile follows llhttp 9 (undici 7), the 5.x profile llhttp 8
956
+ * in its lenient mode (undici 5). Returns true when the line is complete
957
+ * and chunkSize holds its size; false when it needs more bytes or failed. */
958
+ chunkSizeLine(): boolean {
959
+ const buf = this.buf;
960
+ if (this.sizeState === SIZE_FIRST) {
961
+ // The common line, hex digits then CRLF in this buffer, in one pass;
962
+ // any other line takes the byte loop below from its start.
963
+ let size = 0;
964
+ let digits = 0;
965
+ let j = 0;
966
+ for (; j < buf.length && j < 32; j++) {
967
+ const d = hexDigit(buf[j]!);
968
+ if (d === -1) break;
969
+ if (digits > 0 || d !== 0) {
970
+ digits++;
971
+ size = size * 16 + d;
972
+ }
973
+ }
974
+ if (j > 0 && digits <= 16 && j + 1 < buf.length && buf[j] === 0x0d && buf[j + 1] === 0x0a) {
975
+ this.chunkSize = size;
976
+ this.buf = buf.subarray(j + 2);
977
+ return true;
978
+ }
979
+ }
980
+ const v7 = this.client.__profile.major >= 7;
981
+ let i = 0;
982
+ while (i < buf.length) {
983
+ const c = buf[i]!;
984
+ const state = this.sizeState;
985
+ if (state === SIZE_FIRST || state === SIZE_DIGITS) {
986
+ const d = hexDigit(c);
987
+ if (d === -1) {
988
+ if (state === SIZE_FIRST) {
989
+ this.fail("Invalid character in chunk size", "INVALID_CHUNK_SIZE");
990
+ return false;
991
+ }
992
+ this.sizeState = SIZE_AFTER;
993
+ continue;
994
+ }
995
+ if (state === SIZE_FIRST) {
996
+ this.chunkSize = 0;
997
+ this.sizeDigits = 0;
998
+ this.sizeState = SIZE_DIGITS;
999
+ }
1000
+ if (this.sizeDigits > 0 || d !== 0) {
1001
+ if (this.sizeDigits === 16) {
1002
+ this.fail("Chunk size overflow", "INVALID_CHUNK_SIZE");
1003
+ return false;
1004
+ }
1005
+ this.sizeDigits++;
1006
+ this.chunkSize = this.chunkSize * 16 + d;
1007
+ }
1008
+ } else if (state === SIZE_AFTER) {
1009
+ if (c === 0x0d) this.sizeState = SIZE_CR;
1010
+ else if (c === 0x3b) this.sizeState = SIZE_EXT;
1011
+ else if (c === 0x0a && v7) {
1012
+ this.fail("Missing expected CR after chunk size", "CR_EXPECTED");
1013
+ return false;
1014
+ } else {
1015
+ this.fail("Invalid character in chunk size", "INVALID_CHUNK_SIZE");
1016
+ return false;
1017
+ }
1018
+ } else if (state === SIZE_EXT) {
1019
+ if (c === 0x20 || c === 0x0d) {
1020
+ this.fail("Invalid character in chunk extensions", "STRICT");
1021
+ return false;
1022
+ }
1023
+ this.sizeState = SIZE_EXT_NAME;
1024
+ continue;
1025
+ } else if (state === SIZE_EXT_NAME) {
1026
+ if (c === 0x3d) this.sizeState = SIZE_EXT_VALUE;
1027
+ else if (c === 0x3b) this.sizeState = SIZE_EXT;
1028
+ else if (c === 0x0d) this.sizeState = SIZE_CR;
1029
+ else if (c === 0x0a && v7) {
1030
+ this.fail("Missing expected CR after chunk extension name", "CR_EXPECTED");
1031
+ return false;
1032
+ } else if (TOKEN_BYTES[c] !== 1) {
1033
+ this.fail("Invalid character in chunk extensions name", "STRICT");
1034
+ return false;
1035
+ }
1036
+ } else if (state === SIZE_EXT_VALUE) {
1037
+ if (c === 0x22) this.sizeState = SIZE_EXT_QUOTED;
1038
+ // llhttp 8 goes on with the chunk-size node after a value's ';'.
1039
+ else if (c === 0x3b) this.sizeState = v7 ? SIZE_EXT : SIZE_AFTER;
1040
+ else if (c === 0x0d) this.sizeState = SIZE_CR;
1041
+ else if (c === 0x0a && v7) {
1042
+ this.fail("Missing expected CR after chunk extension value", "CR_EXPECTED");
1043
+ return false;
1044
+ } else if (TOKEN_BYTES[c] !== 1) {
1045
+ this.fail("Invalid character in chunk extensions value", "STRICT");
1046
+ return false;
1047
+ }
1048
+ } else if (state === SIZE_EXT_QUOTED) {
1049
+ if (c === 0x22) this.sizeState = SIZE_EXT_QUOTED_DONE;
1050
+ else if (c === 0x5c && v7) this.sizeState = SIZE_EXT_PAIR;
1051
+ else if (!isQuotedByte(c)) {
1052
+ this.fail("Invalid character in chunk extensions quoted value", "STRICT");
1053
+ return false;
1054
+ }
1055
+ } else if (state === SIZE_EXT_PAIR) {
1056
+ if (!isQuotedPairByte(c)) {
1057
+ this.fail("Invalid quoted-pair in chunk extensions quoted value", "STRICT");
1058
+ return false;
1059
+ }
1060
+ this.sizeState = SIZE_EXT_QUOTED;
1061
+ } else if (state === SIZE_EXT_QUOTED_DONE) {
1062
+ if (c === 0x3b) this.sizeState = SIZE_EXT;
1063
+ else if (c === 0x0d) this.sizeState = SIZE_CR;
1064
+ else if (c === 0x0a && v7) {
1065
+ this.fail("Missing expected CR after chunk extension value", "CR_EXPECTED");
1066
+ return false;
1067
+ } else {
1068
+ this.fail("Invalid character in chunk extensions quote value", "STRICT");
1069
+ return false;
1070
+ }
1071
+ } else {
1072
+ // SIZE_CR: llhttp 9 needs the LF; llhttp 8's lenient mode skips
1073
+ // whatever byte follows the CR.
1074
+ if (c !== 0x0a && v7) {
1075
+ this.fail("Expected LF after chunk size", "STRICT");
1076
+ return false;
1077
+ }
1078
+ this.buf = buf.subarray(i + 1);
1079
+ this.sizeState = SIZE_FIRST;
1080
+ return true;
1081
+ }
1082
+ i++;
1083
+ }
1084
+ this.buf = Buffer.alloc(0);
1085
+ return false;
1086
+ }
1087
+
1088
+ line(): Buffer | null {
1089
+ const idx = this.buf.indexOf(CRLF);
1090
+ if (idx === -1) return null;
1091
+ const out = this.buf.subarray(0, idx);
1092
+ this.buf = this.buf.subarray(idx + 2);
1093
+ return out;
1094
+ }
1095
+
1096
+ run(): void {
1097
+ while (!this.paused && this.state !== 99) {
1098
+ if (this.state === 0) {
1099
+ // Status line.
1100
+ const line = this.line();
1101
+ if (line === null) {
1102
+ if (this.buf.length > this.client.__maxHeaderSize) {
1103
+ this.client.__onParseError(this.socket, new HeadersOverflowError());
1104
+ this.state = 99;
1105
+ return;
1106
+ }
1107
+ if (this.more()) continue;
1108
+ return;
1109
+ }
1110
+ if (line.length === 0) continue;
1111
+ const text = line.toString("latin1");
1112
+ const m = /^HTTP\/1\.([01]) (\d{3})(?: (.*))?$/.exec(text);
1113
+ if (m === null) {
1114
+ const v7 = this.client.__profile.major >= 7;
1115
+ if (!text.startsWith("HTTP/")) {
1116
+ this.fail(v7 ? "Expected HTTP/, RTSP/ or ICE/" : "Expected HTTP/", "INVALID_CONSTANT");
1117
+ } else {
1118
+ this.fail(v7 ? "Invalid status code" : "Invalid response status", "INVALID_STATUS");
1119
+ }
1120
+ return;
1121
+ }
1122
+ this.versionMinor = Number(m[1]);
1123
+ this.statusCode = Number(m[2]);
1124
+ this.statusText = m[3] ?? "";
1125
+ this.headersSize = line.length;
1126
+ this.state = 1;
1127
+ } else if (this.state === 1 || this.state === 5) {
1128
+ // Header (1) or trailer (5) lines.
1129
+ const line = this.line();
1130
+ if (line === null) {
1131
+ if (this.headersSize + this.buf.length > this.client.__maxHeaderSize) {
1132
+ this.client.__onParseError(this.socket, new HeadersOverflowError());
1133
+ this.state = 99;
1134
+ return;
1135
+ }
1136
+ if (this.more()) continue;
1137
+ return;
1138
+ }
1139
+ this.headersSize += line.length;
1140
+ if (this.headersSize > this.client.__maxHeaderSize) {
1141
+ this.client.__onParseError(this.socket, new HeadersOverflowError());
1142
+ this.state = 99;
1143
+ return;
1144
+ }
1145
+ if (line.length > 0) {
1146
+ const colon = line.indexOf(0x3a);
1147
+ if (colon <= 0) {
1148
+ this.fail("Invalid header token", "INVALID_HEADER_TOKEN");
1149
+ return;
1150
+ }
1151
+ const name = line.subarray(0, colon);
1152
+ let start = colon + 1;
1153
+ let end = line.length;
1154
+ while (start < end && (line[start] === 0x20 || line[start] === 0x09)) start++;
1155
+ while (end > start && (line[end - 1] === 0x20 || line[end - 1] === 0x09)) end--;
1156
+ const value = line.subarray(start, end);
1157
+ if (this.state === 5) {
1158
+ this.trailers.push(Buffer.from(name), Buffer.from(value));
1159
+ continue;
1160
+ }
1161
+ this.headers.push(Buffer.from(name), Buffer.from(value));
1162
+ const lower = name.toString("latin1").toLowerCase();
1163
+ if (lower === "content-length") {
1164
+ const n = Number(value.toString("latin1"));
1165
+ if (!Number.isInteger(n) || n < 0) {
1166
+ this.fail("Invalid character in Content-Length", "INVALID_CONTENT_LENGTH");
1167
+ return;
1168
+ }
1169
+ this.contentLength = n;
1170
+ } else if (lower === "transfer-encoding") {
1171
+ this.chunked = /(?:^|,)\s*chunked\s*$/i.test(value.toString("latin1"));
1172
+ } else if (lower === "connection") {
1173
+ this.connectionHeader = value.toString("latin1").toLowerCase();
1174
+ } else if (lower === "keep-alive") {
1175
+ this.keepAliveHeader = value.toString("latin1");
1176
+ }
1177
+ continue;
1178
+ }
1179
+ if (this.state === 5) {
1180
+ if (!this.complete()) return;
1181
+ continue;
1182
+ }
1183
+ // End of headers.
1184
+ const noBody = this.statusCode < 200 || this.statusCode === 204 || this.statusCode === 304;
1185
+ const closeRequested = /(?:^|,)\s*close\s*(?:,|$)/.test(this.connectionHeader);
1186
+ const keepAliveRequested = /(?:^|,)\s*keep-alive\s*(?:,|$)/.test(this.connectionHeader);
1187
+ this.shouldKeepAlive = this.versionMinor === 1 ? !closeRequested : keepAliveRequested;
1188
+ if (!noBody && !this.chunked && this.contentLength < 0) this.shouldKeepAlive = false;
1189
+ const ret = this.client.__onHeadersComplete(this, this.socket);
1190
+ if (ret === -1) {
1191
+ this.state = 99;
1192
+ return;
1193
+ }
1194
+ this.skipBody = ret === 1 || noBody;
1195
+ if (this.skipBody) {
1196
+ if (!this.complete()) return;
1197
+ continue;
1198
+ }
1199
+ if (this.chunked) {
1200
+ this.state = 3;
1201
+ } else if (this.contentLength >= 0) {
1202
+ this.remaining = this.contentLength;
1203
+ this.state = 2;
1204
+ if (this.remaining === 0) {
1205
+ if (ret === 2) this.pause();
1206
+ if (!this.complete()) return;
1207
+ continue;
1208
+ }
1209
+ } else {
1210
+ this.state = 6;
1211
+ }
1212
+ if (ret === 2) this.pause();
1213
+ } else if (this.state === 2) {
1214
+ // Content-Length body.
1215
+ if (this.buf.length === 0) {
1216
+ if (this.more()) continue;
1217
+ return;
1218
+ }
1219
+ const n = Math.min(this.remaining, this.buf.length);
1220
+ const chunk = this.buf.subarray(0, n);
1221
+ this.buf = this.buf.subarray(n);
1222
+ this.remaining -= n;
1223
+ const more = this.client.__onBody(this, this.socket, Buffer.from(chunk));
1224
+ if (this.socket.destroyed) {
1225
+ this.state = 99;
1226
+ return;
1227
+ }
1228
+ if (!more) this.pause();
1229
+ if (this.remaining === 0) {
1230
+ if (!this.complete()) return;
1231
+ }
1232
+ } else if (this.state === 3) {
1233
+ // Chunk size line; a partial one continues with the next arrival.
1234
+ if (!this.chunkSizeLine()) {
1235
+ if (this.state === 3 && this.more()) continue;
1236
+ return;
1237
+ }
1238
+ if (this.chunkSize === 0) {
1239
+ this.state = 5;
1240
+ } else {
1241
+ this.remaining = this.chunkSize;
1242
+ this.state = 4;
1243
+ }
1244
+ } else if (this.state === 4) {
1245
+ // Chunk data, then its CRLF.
1246
+ if (this.remaining > 0) {
1247
+ if (this.buf.length === 0) {
1248
+ if (this.more()) continue;
1249
+ return;
1250
+ }
1251
+ const n = Math.min(this.remaining, this.buf.length);
1252
+ const chunk = this.buf.subarray(0, n);
1253
+ this.buf = this.buf.subarray(n);
1254
+ this.remaining -= n;
1255
+ const more = this.client.__onBody(this, this.socket, Buffer.from(chunk));
1256
+ if (this.socket.destroyed) {
1257
+ this.state = 99;
1258
+ return;
1259
+ }
1260
+ if (!more) this.pause();
1261
+ continue;
1262
+ }
1263
+ if (this.buf.length < 2) {
1264
+ if (this.more()) continue;
1265
+ return;
1266
+ }
1267
+ if (this.buf[0] !== 0x0d || this.buf[1] !== 0x0a) {
1268
+ this.fail("Expected LF after chunk data", "STRICT");
1269
+ return;
1270
+ }
1271
+ this.buf = this.buf.subarray(2);
1272
+ this.state = 3;
1273
+ } else if (this.state === 6) {
1274
+ // Read until the connection closes.
1275
+ if (this.buf.length === 0) {
1276
+ if (this.more()) continue;
1277
+ return;
1278
+ }
1279
+ const chunk = this.buf;
1280
+ this.buf = Buffer.alloc(0);
1281
+ const more = this.client.__onBody(this, this.socket, Buffer.from(chunk));
1282
+ if (this.socket.destroyed) {
1283
+ this.state = 99;
1284
+ return;
1285
+ }
1286
+ if (!more) this.pause();
1287
+ } else {
1288
+ return;
1289
+ }
1290
+ }
1291
+ }
1292
+
1293
+ /** Message complete: hand the trailers over and get ready for the next
1294
+ * response on this connection. Returns false when parsing must stop. */
1295
+ complete(): boolean {
1296
+ const trailers = this.trailers;
1297
+ const ok = this.client.__onMessageComplete(this, this.socket, trailers);
1298
+ if (!ok) {
1299
+ this.state = 99;
1300
+ return false;
1301
+ }
1302
+ return true;
1303
+ }
1304
+ }