xbintsc 0.5.6 → 0.5.21

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 (490) hide show
  1. package/AGENTS.md +20 -10
  2. package/README.md +8 -7
  3. package/README.zh-CN.md +6 -6
  4. package/dist/src/binder/declarations.js +14 -3
  5. package/dist/src/binder/declarations.js.map +1 -1
  6. package/dist/src/cli/hints.js +7 -1
  7. package/dist/src/cli/hints.js.map +1 -1
  8. package/dist/src/cli/main.js +115 -15
  9. package/dist/src/cli/main.js.map +1 -1
  10. package/dist/src/cli/watch.d.ts +25 -0
  11. package/dist/src/cli/watch.js +93 -0
  12. package/dist/src/cli/watch.js.map +1 -0
  13. package/dist/src/codegen/generator/calls/access.js +11 -2
  14. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  15. package/dist/src/codegen/generator/calls/closures.js +12 -4
  16. package/dist/src/codegen/generator/calls/closures.js.map +1 -1
  17. package/dist/src/codegen/generator/context.d.ts +8 -0
  18. package/dist/src/codegen/generator/context.js +22 -3
  19. package/dist/src/codegen/generator/context.js.map +1 -1
  20. package/dist/src/codegen/generator/expressions/operators.js +17 -15
  21. package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
  22. package/dist/src/codegen/generator/expressions/primary.js +5 -0
  23. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  24. package/dist/src/codegen/generator/module.js +0 -7
  25. package/dist/src/codegen/generator/module.js.map +1 -1
  26. package/dist/src/codegen/generator/numeric.d.ts +6 -3
  27. package/dist/src/codegen/generator/numeric.js +54 -11
  28. package/dist/src/codegen/generator/numeric.js.map +1 -1
  29. package/dist/src/codegen/generator/state.js +23 -0
  30. package/dist/src/codegen/generator/state.js.map +1 -1
  31. package/dist/src/codegen/generator/statements/control-flow.js +1 -4
  32. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
  33. package/dist/src/codegen/generator/statements/loops.js +48 -16
  34. package/dist/src/codegen/generator/statements/loops.js.map +1 -1
  35. package/dist/src/codegen/generator/tables.js +26 -1
  36. package/dist/src/codegen/generator/tables.js.map +1 -1
  37. package/dist/src/diagnostics/diagnostic.d.ts +3 -1
  38. package/dist/src/diagnostics/diagnostic.js +23 -3
  39. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  40. package/dist/src/driver/app-artifacts.d.ts +42 -0
  41. package/dist/src/driver/app-artifacts.js +53 -0
  42. package/dist/src/driver/app-artifacts.js.map +1 -0
  43. package/dist/src/driver/build-key.d.ts +29 -0
  44. package/dist/src/driver/build-key.js +35 -0
  45. package/dist/src/driver/build-key.js.map +1 -0
  46. package/dist/src/driver/bundler/graph.js +61 -12
  47. package/dist/src/driver/bundler/graph.js.map +1 -1
  48. package/dist/src/driver/bundler/merge.js +7 -1
  49. package/dist/src/driver/bundler/merge.js.map +1 -1
  50. package/dist/src/driver/compiler.d.ts +10 -67
  51. package/dist/src/driver/compiler.js +95 -234
  52. package/dist/src/driver/compiler.js.map +1 -1
  53. package/dist/src/driver/config.d.ts +3 -0
  54. package/dist/src/driver/config.js +8 -0
  55. package/dist/src/driver/config.js.map +1 -1
  56. package/dist/src/driver/frontend.d.ts +37 -0
  57. package/dist/src/driver/frontend.js +92 -0
  58. package/dist/src/driver/frontend.js.map +1 -0
  59. package/dist/src/driver/index.d.ts +1 -1
  60. package/dist/src/driver/index.js.map +1 -1
  61. package/dist/src/driver/options.d.ts +64 -0
  62. package/dist/src/driver/options.js +9 -0
  63. package/dist/src/driver/options.js.map +1 -0
  64. package/dist/src/driver/runtime-objects.d.ts +38 -0
  65. package/dist/src/driver/runtime-objects.js +112 -0
  66. package/dist/src/driver/runtime-objects.js.map +1 -0
  67. package/dist/src/driver/toolchain-provider.d.ts +4 -0
  68. package/dist/src/driver/toolchain-provider.js +4 -0
  69. package/dist/src/driver/toolchain-provider.js.map +1 -1
  70. package/dist/src/driver/toolchain.d.ts +32 -1
  71. package/dist/src/driver/toolchain.js +115 -11
  72. package/dist/src/driver/toolchain.js.map +1 -1
  73. package/dist/src/driver/version.d.ts +12 -0
  74. package/dist/src/driver/version.js +13 -0
  75. package/dist/src/driver/version.js.map +1 -0
  76. package/dist/src/driver/win-icon.d.ts +7 -9
  77. package/dist/src/driver/win-icon.js +37 -35
  78. package/dist/src/driver/win-icon.js.map +1 -1
  79. package/dist/src/extensions/node/fs/index.d.ts +4 -3
  80. package/dist/src/extensions/node/fs/index.js +12 -3
  81. package/dist/src/extensions/node/fs/index.js.map +1 -1
  82. package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
  83. package/dist/src/extensions/node/fs-promises/index.js +15 -6
  84. package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
  85. package/dist/src/parser/declarations/classes.js +5 -0
  86. package/dist/src/parser/declarations/classes.js.map +1 -1
  87. package/dist/src/parser/declarations/functions.js +13 -1
  88. package/dist/src/parser/declarations/functions.js.map +1 -1
  89. package/dist/src/parser/modules.js +8 -3
  90. package/dist/src/parser/modules.js.map +1 -1
  91. package/dist/src/parser/parser.d.ts +1 -0
  92. package/dist/src/parser/parser.js +23 -0
  93. package/dist/src/parser/parser.js.map +1 -1
  94. package/dist/tests/cli/check.test.d.ts +6 -0
  95. package/dist/tests/cli/check.test.js +68 -0
  96. package/dist/tests/cli/check.test.js.map +1 -0
  97. package/dist/tests/cli/main.test.js +19 -0
  98. package/dist/tests/cli/main.test.js.map +1 -1
  99. package/dist/tests/cli/watch.test.d.ts +6 -0
  100. package/dist/tests/cli/watch.test.js +72 -0
  101. package/dist/tests/cli/watch.test.js.map +1 -0
  102. package/dist/tests/codegen/expressions.test.js +15 -3
  103. package/dist/tests/codegen/expressions.test.js.map +1 -1
  104. package/dist/tests/codegen/llvm.test.js +16 -0
  105. package/dist/tests/codegen/llvm.test.js.map +1 -1
  106. package/dist/tests/diagnostics/diagnostic.test.js +8 -0
  107. package/dist/tests/diagnostics/diagnostic.test.js.map +1 -1
  108. package/dist/tests/docs/structure.test.d.ts +1 -0
  109. package/dist/tests/docs/structure.test.js +92 -0
  110. package/dist/tests/docs/structure.test.js.map +1 -0
  111. package/dist/tests/driver/compiler.test.js +6 -0
  112. package/dist/tests/driver/compiler.test.js.map +1 -1
  113. package/dist/tests/driver/config.test.js +9 -0
  114. package/dist/tests/driver/config.test.js.map +1 -1
  115. package/dist/tests/driver/icon.test.js +19 -32
  116. package/dist/tests/driver/icon.test.js.map +1 -1
  117. package/dist/tests/driver/invalid-input.test.d.ts +10 -0
  118. package/dist/tests/driver/invalid-input.test.js +29 -0
  119. package/dist/tests/driver/invalid-input.test.js.map +1 -0
  120. package/dist/tests/driver/modules.test.js +42 -3
  121. package/dist/tests/driver/modules.test.js.map +1 -1
  122. package/dist/tests/driver/toolchain-provider.test.js +27 -1
  123. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  124. package/dist/tests/driver/toolchain.test.js +60 -2
  125. package/dist/tests/driver/toolchain.test.js.map +1 -1
  126. package/dist/tests/e2e/array-buffer.test.d.ts +5 -0
  127. package/dist/tests/e2e/array-buffer.test.js +38 -0
  128. package/dist/tests/e2e/array-buffer.test.js.map +1 -0
  129. package/dist/tests/e2e/array-from-iterables.test.d.ts +7 -0
  130. package/dist/tests/e2e/array-from-iterables.test.js +34 -0
  131. package/dist/tests/e2e/array-from-iterables.test.js.map +1 -0
  132. package/dist/tests/e2e/array-symbol-iterator.test.d.ts +8 -0
  133. package/dist/tests/e2e/array-symbol-iterator.test.js +42 -0
  134. package/dist/tests/e2e/array-symbol-iterator.test.js.map +1 -0
  135. package/dist/tests/e2e/async-await.test.js +1 -1
  136. package/dist/tests/e2e/async-fs.test.d.ts +9 -0
  137. package/dist/tests/e2e/async-fs.test.js +119 -0
  138. package/dist/tests/e2e/async-fs.test.js.map +1 -0
  139. package/dist/tests/e2e/async-generators.test.d.ts +1 -0
  140. package/dist/tests/e2e/async-generators.test.js +154 -0
  141. package/dist/tests/e2e/async-generators.test.js.map +1 -0
  142. package/dist/tests/e2e/await-ordering.test.d.ts +5 -0
  143. package/dist/tests/e2e/await-ordering.test.js +37 -0
  144. package/dist/tests/e2e/await-ordering.test.js.map +1 -0
  145. package/dist/tests/e2e/compile-builtins.test.js +1 -1
  146. package/dist/tests/e2e/compile-modules.test.js +7 -0
  147. package/dist/tests/e2e/compile-modules.test.js.map +1 -1
  148. package/dist/tests/e2e/date-parse.test.d.ts +8 -0
  149. package/dist/tests/e2e/date-parse.test.js +38 -0
  150. package/dist/tests/e2e/date-parse.test.js.map +1 -0
  151. package/dist/tests/e2e/default-anonymous-exports.test.d.ts +7 -0
  152. package/dist/tests/e2e/default-anonymous-exports.test.js +23 -0
  153. package/dist/tests/e2e/default-anonymous-exports.test.js.map +1 -0
  154. package/dist/tests/e2e/fetch.test.js +24 -0
  155. package/dist/tests/e2e/fetch.test.js.map +1 -1
  156. package/dist/tests/e2e/globals-microtask.test.d.ts +9 -0
  157. package/dist/tests/e2e/globals-microtask.test.js +37 -0
  158. package/dist/tests/e2e/globals-microtask.test.js.map +1 -0
  159. package/dist/tests/e2e/gui-inline-svg.test.d.ts +11 -0
  160. package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
  161. package/dist/tests/e2e/gui-inline-svg.test.js.map +1 -0
  162. package/dist/tests/e2e/gui-media.test.js +8 -1
  163. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  164. package/dist/tests/e2e/inspect-builtins.test.d.ts +10 -0
  165. package/dist/tests/e2e/inspect-builtins.test.js +43 -0
  166. package/dist/tests/e2e/inspect-builtins.test.js.map +1 -0
  167. package/dist/tests/e2e/json-builtin-objects.test.d.ts +9 -0
  168. package/dist/tests/e2e/json-builtin-objects.test.js +23 -0
  169. package/dist/tests/e2e/json-builtin-objects.test.js.map +1 -0
  170. package/dist/tests/e2e/json-circular.test.d.ts +6 -0
  171. package/dist/tests/e2e/json-circular.test.js +43 -0
  172. package/dist/tests/e2e/json-circular.test.js.map +1 -0
  173. package/dist/tests/e2e/json-parse-reviver.test.d.ts +6 -0
  174. package/dist/tests/e2e/json-parse-reviver.test.js +29 -0
  175. package/dist/tests/e2e/json-parse-reviver.test.js.map +1 -0
  176. package/dist/tests/e2e/json-stringify-replacer.test.d.ts +6 -0
  177. package/dist/tests/e2e/json-stringify-replacer.test.js +27 -0
  178. package/dist/tests/e2e/json-stringify-replacer.test.js.map +1 -0
  179. package/dist/tests/e2e/json-stringify-space.test.d.ts +6 -0
  180. package/dist/tests/e2e/json-stringify-space.test.js +23 -0
  181. package/dist/tests/e2e/json-stringify-space.test.js.map +1 -0
  182. package/dist/tests/e2e/method-dispatch-errors.test.d.ts +9 -0
  183. package/dist/tests/e2e/method-dispatch-errors.test.js +38 -0
  184. package/dist/tests/e2e/method-dispatch-errors.test.js.map +1 -0
  185. package/dist/tests/e2e/native-extensions.test.js +1 -1
  186. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  187. package/dist/tests/e2e/promise-with-resolvers.test.d.ts +5 -0
  188. package/dist/tests/e2e/promise-with-resolvers.test.js +20 -0
  189. package/dist/tests/e2e/promise-with-resolvers.test.js.map +1 -0
  190. package/dist/tests/e2e/property-descriptors.test.d.ts +5 -0
  191. package/dist/tests/e2e/property-descriptors.test.js +25 -0
  192. package/dist/tests/e2e/property-descriptors.test.js.map +1 -0
  193. package/dist/tests/e2e/property-ic.test.d.ts +1 -0
  194. package/dist/tests/e2e/property-ic.test.js +55 -0
  195. package/dist/tests/e2e/property-ic.test.js.map +1 -0
  196. package/dist/tests/e2e/runtime-errors.test.d.ts +10 -0
  197. package/dist/tests/e2e/runtime-errors.test.js +52 -0
  198. package/dist/tests/e2e/runtime-errors.test.js.map +1 -0
  199. package/dist/tests/e2e/structured-clone.test.d.ts +6 -0
  200. package/dist/tests/e2e/structured-clone.test.js +49 -0
  201. package/dist/tests/e2e/structured-clone.test.js.map +1 -0
  202. package/dist/tests/e2e/text-codec.test.d.ts +6 -0
  203. package/dist/tests/e2e/text-codec.test.js +24 -0
  204. package/dist/tests/e2e/text-codec.test.js.map +1 -0
  205. package/dist/tests/e2e/typed-array-views.test.d.ts +6 -0
  206. package/dist/tests/e2e/typed-array-views.test.js +39 -0
  207. package/dist/tests/e2e/typed-array-views.test.js.map +1 -0
  208. package/dist/tests/e2e/url-search-params.test.d.ts +5 -0
  209. package/dist/tests/e2e/url-search-params.test.js +30 -0
  210. package/dist/tests/e2e/url-search-params.test.js.map +1 -0
  211. package/dist/tests/e2e/weak-collections.test.d.ts +1 -0
  212. package/dist/tests/e2e/weak-collections.test.js +88 -0
  213. package/dist/tests/e2e/weak-collections.test.js.map +1 -0
  214. package/dist/tests/parser/declarations.test.js +12 -0
  215. package/dist/tests/parser/declarations.test.js.map +1 -1
  216. package/dist/tests/parser/module-syntax.test.js +9 -0
  217. package/dist/tests/parser/module-syntax.test.js.map +1 -1
  218. package/dist/tests/parser/parser.test.js +7 -0
  219. package/dist/tests/parser/parser.test.js.map +1 -1
  220. package/dist/tests/version.test.js +5 -1
  221. package/dist/tests/version.test.js.map +1 -1
  222. package/doc/ai/README.md +4 -3
  223. package/doc/ai/cli.md +41 -0
  224. package/doc/ai/contributing.md +20 -16
  225. package/doc/ai/extensions.md +13 -10
  226. package/doc/ai/language-support.md +19 -14
  227. package/doc/ai/troubleshooting.md +11 -9
  228. package/doc/ai/zh-CN/README.md +3 -2
  229. package/doc/ai/zh-CN/cli.md +35 -0
  230. package/doc/ai/zh-CN/contributing.md +16 -15
  231. package/doc/ai/zh-CN/extensions.md +12 -9
  232. package/doc/ai/zh-CN/language-support.md +19 -15
  233. package/doc/ai/zh-CN/troubleshooting.md +9 -8
  234. package/doc/gui/api.md +8 -0
  235. package/doc/gui/build.md +13 -4
  236. package/doc/gui/known-issues.md +19 -14
  237. package/doc/gui/media.md +32 -3
  238. package/doc/gui/rendering.md +3 -1
  239. package/doc/gui.md +28 -5
  240. package/doc/icon.md +5 -4
  241. package/doc/implemented/async.md +51 -0
  242. package/doc/implemented/binder.md +13 -0
  243. package/doc/implemented/cli.md +47 -0
  244. package/doc/implemented/codegen.md +33 -0
  245. package/doc/implemented/collections.md +26 -0
  246. package/doc/implemented/driver.md +19 -0
  247. package/doc/implemented/extensions.md +19 -0
  248. package/doc/implemented/fetch.md +44 -0
  249. package/doc/implemented/lexer.md +23 -0
  250. package/doc/implemented/modules.md +28 -0
  251. package/doc/implemented/node/assert.md +17 -0
  252. package/doc/implemented/node/buffer.md +29 -0
  253. package/doc/implemented/node/child-process.md +29 -0
  254. package/doc/implemented/node/crypto.md +9 -0
  255. package/doc/implemented/node/dgram.md +15 -0
  256. package/doc/implemented/node/events.md +37 -0
  257. package/doc/implemented/node/fs-promises.md +49 -0
  258. package/doc/implemented/node/fs.md +112 -0
  259. package/doc/implemented/node/http.md +21 -0
  260. package/doc/implemented/node/net.md +17 -0
  261. package/doc/implemented/node/os.md +22 -0
  262. package/doc/implemented/node/path.md +33 -0
  263. package/doc/implemented/node/process.md +23 -0
  264. package/doc/implemented/node/querystring.md +20 -0
  265. package/doc/implemented/node/stream-promises.md +8 -0
  266. package/doc/implemented/node/stream.md +19 -0
  267. package/doc/implemented/node/test.md +10 -0
  268. package/doc/implemented/node/url.md +8 -0
  269. package/doc/implemented/node/util.md +25 -0
  270. package/doc/implemented/node/worker-threads.md +10 -0
  271. package/doc/implemented/node/zlib.md +8 -0
  272. package/doc/implemented/node.md +48 -0
  273. package/doc/implemented/operators.md +38 -0
  274. package/doc/implemented/parser.md +58 -0
  275. package/doc/implemented/pipeline.md +28 -0
  276. package/doc/implemented/runtime-core.md +32 -0
  277. package/doc/implemented/stdlib.md +78 -0
  278. package/doc/implemented/strings.md +27 -0
  279. package/doc/implemented/tests.md +10 -0
  280. package/doc/implemented/typed-arrays.md +26 -0
  281. package/doc/implemented/value-model.md +18 -0
  282. package/doc/implemented.md +54 -355
  283. package/doc/node-implemented.md +3 -585
  284. package/doc/node-unimplemented.md +3 -164
  285. package/doc/requirements.md +23 -8
  286. package/doc/unimplemented/classes.md +22 -0
  287. package/doc/unimplemented/deviations.md +27 -0
  288. package/doc/unimplemented/expressions.md +26 -0
  289. package/doc/unimplemented/functions.md +21 -0
  290. package/doc/unimplemented/modules.md +22 -0
  291. package/doc/unimplemented/node/async.md +20 -0
  292. package/doc/unimplemented/node/bun.md +9 -0
  293. package/doc/unimplemented/node/fs-promises.md +20 -0
  294. package/doc/unimplemented/node/fs.md +30 -0
  295. package/doc/unimplemented/node/globals.md +23 -0
  296. package/doc/unimplemented/node/modules.md +21 -0
  297. package/doc/unimplemented/node.md +21 -0
  298. package/doc/unimplemented/statements.md +18 -0
  299. package/doc/unimplemented/stdlib.md +54 -0
  300. package/doc/unimplemented/toolchain.md +14 -0
  301. package/doc/unimplemented/types.md +12 -0
  302. package/doc/unimplemented.md +18 -275
  303. package/doc/xbintsc.config.schema.json +12 -0
  304. package/doc/zh-CN/gui/api.md +7 -0
  305. package/doc/zh-CN/gui/build.md +11 -3
  306. package/doc/zh-CN/gui/known-issues.md +17 -11
  307. package/doc/zh-CN/gui/media.md +26 -2
  308. package/doc/zh-CN/gui/rendering.md +2 -1
  309. package/doc/zh-CN/gui.md +21 -3
  310. package/doc/zh-CN/icon.md +5 -4
  311. package/doc/zh-CN/implemented/async.md +49 -0
  312. package/doc/zh-CN/implemented/binder.md +13 -0
  313. package/doc/zh-CN/implemented/cli.md +46 -0
  314. package/doc/zh-CN/implemented/codegen.md +33 -0
  315. package/doc/zh-CN/implemented/collections.md +26 -0
  316. package/doc/zh-CN/implemented/driver.md +19 -0
  317. package/doc/zh-CN/implemented/extensions.md +19 -0
  318. package/doc/zh-CN/implemented/fetch.md +31 -0
  319. package/doc/zh-CN/implemented/lexer.md +23 -0
  320. package/doc/zh-CN/implemented/modules.md +28 -0
  321. package/doc/zh-CN/implemented/node/assert.md +17 -0
  322. package/doc/zh-CN/implemented/node/buffer.md +25 -0
  323. package/doc/zh-CN/implemented/node/child-process.md +27 -0
  324. package/doc/zh-CN/implemented/node/crypto.md +9 -0
  325. package/doc/zh-CN/implemented/node/dgram.md +15 -0
  326. package/doc/zh-CN/implemented/node/events.md +36 -0
  327. package/doc/zh-CN/implemented/node/fs-promises.md +30 -0
  328. package/doc/zh-CN/implemented/node/fs.md +105 -0
  329. package/doc/zh-CN/implemented/node/http.md +17 -0
  330. package/doc/zh-CN/implemented/node/net.md +17 -0
  331. package/doc/zh-CN/implemented/node/os.md +21 -0
  332. package/doc/zh-CN/implemented/node/path.md +26 -0
  333. package/doc/zh-CN/implemented/node/process.md +23 -0
  334. package/doc/zh-CN/implemented/node/querystring.md +20 -0
  335. package/doc/zh-CN/implemented/node/stream-promises.md +8 -0
  336. package/doc/zh-CN/implemented/node/stream.md +15 -0
  337. package/doc/zh-CN/implemented/node/test.md +10 -0
  338. package/doc/zh-CN/implemented/node/url.md +8 -0
  339. package/doc/zh-CN/implemented/node/util.md +25 -0
  340. package/doc/zh-CN/implemented/node/worker-threads.md +9 -0
  341. package/doc/zh-CN/implemented/node/zlib.md +8 -0
  342. package/doc/zh-CN/implemented/node.md +45 -0
  343. package/doc/zh-CN/implemented/operators.md +38 -0
  344. package/doc/zh-CN/implemented/parser.md +58 -0
  345. package/doc/zh-CN/implemented/pipeline.md +25 -0
  346. package/doc/zh-CN/implemented/runtime-core.md +31 -0
  347. package/doc/zh-CN/implemented/stdlib.md +76 -0
  348. package/doc/zh-CN/implemented/strings.md +27 -0
  349. package/doc/zh-CN/implemented/tests.md +10 -0
  350. package/doc/zh-CN/implemented/typed-arrays.md +26 -0
  351. package/doc/zh-CN/implemented/value-model.md +18 -0
  352. package/doc/zh-CN/implemented.md +50 -350
  353. package/doc/zh-CN/node-implemented.md +4 -531
  354. package/doc/zh-CN/node-unimplemented.md +4 -139
  355. package/doc/zh-CN/plan-require-node-modules.md +4 -4
  356. package/doc/zh-CN/requirements.md +20 -6
  357. package/doc/zh-CN/unimplemented/classes.md +22 -0
  358. package/doc/zh-CN/unimplemented/deviations.md +24 -0
  359. package/doc/zh-CN/unimplemented/expressions.md +24 -0
  360. package/doc/zh-CN/unimplemented/functions.md +21 -0
  361. package/doc/zh-CN/unimplemented/modules.md +19 -0
  362. package/doc/zh-CN/unimplemented/node/async.md +20 -0
  363. package/doc/zh-CN/unimplemented/node/bun.md +8 -0
  364. package/doc/zh-CN/unimplemented/node/fs-promises.md +12 -0
  365. package/doc/zh-CN/unimplemented/node/fs.md +24 -0
  366. package/doc/zh-CN/unimplemented/node/globals.md +14 -0
  367. package/doc/zh-CN/unimplemented/node/modules.md +15 -0
  368. package/doc/zh-CN/unimplemented/node.md +18 -0
  369. package/doc/zh-CN/unimplemented/statements.md +15 -0
  370. package/doc/zh-CN/unimplemented/stdlib.md +54 -0
  371. package/doc/zh-CN/unimplemented/toolchain.md +14 -0
  372. package/doc/zh-CN/unimplemented/types.md +11 -0
  373. package/doc/zh-CN/unimplemented.md +14 -237
  374. package/llms.txt +32 -4
  375. package/package.json +1 -1
  376. package/runtime/ext_gui/inline_svg.cpp +219 -0
  377. package/runtime/ext_gui/inline_svg.h +41 -0
  378. package/runtime/ext_gui/layout.cpp +18 -0
  379. package/runtime/ext_gui/layout.h +7 -0
  380. package/runtime/ext_gui/layout_flow.cpp +4 -3
  381. package/runtime/ext_gui/paint.cpp +14 -0
  382. package/runtime/ext_gui/paint.h +5 -1
  383. package/runtime/ext_gui/renderer_image.cpp +53 -25
  384. package/runtime/ext_gui/renderer_shaders.h +2 -2
  385. package/runtime/ext_gui/stb_image.h +1 -17
  386. package/runtime/ext_gui/style_ua.cpp +3 -0
  387. package/runtime/ext_gui/svg.cpp +122 -39
  388. package/runtime/ext_gui/svg.h +14 -3
  389. package/runtime/ext_gui/window.cpp +28 -0
  390. package/runtime/ext_node/child_process/child_process.c +173 -73
  391. package/runtime/ext_node/fs/async_api.c +314 -0
  392. package/runtime/ext_node/fs/async_complete.c +99 -0
  393. package/runtime/ext_node/fs/async_fh.c +206 -0
  394. package/runtime/ext_node/fs/async_job.c +81 -0
  395. package/runtime/ext_node/fs/async_job.h +132 -0
  396. package/runtime/ext_node/fs/async_worker.c +534 -0
  397. package/runtime/ext_node/fs/async_worker_dir.c +439 -0
  398. package/runtime/ext_node/fs/async_worker_dir.h +33 -0
  399. package/runtime/ext_node/fs/async_worker_fd.c +74 -0
  400. package/runtime/ext_node/fs/dir.c +60 -15
  401. package/runtime/ext_node/fs/fs_common.h +9 -0
  402. package/runtime/ext_node/fs/fs_ops.c +18 -29
  403. package/runtime/ext_node/fs/parts/builtins.inc +34 -0
  404. package/runtime/ext_node/fs/parts/platform.inc +66 -0
  405. package/runtime/ext_node/fs/promises.c +44 -234
  406. package/runtime/rt.h +15 -0
  407. package/runtime/rt_internal.h +108 -0
  408. package/runtime/xt_alloc.c +43 -7
  409. package/runtime/xt_array_buffer.c +284 -0
  410. package/runtime/xt_async.c +46 -21
  411. package/runtime/xt_async_io.c +333 -0
  412. package/runtime/xt_async_io.h +47 -0
  413. package/runtime/xt_bigint/helpers.inc +3 -3
  414. package/runtime/xt_builtins.c +21 -17
  415. package/runtime/xt_constructors.c +12 -2
  416. package/runtime/xt_containers/access.inc +148 -3
  417. package/runtime/xt_containers/objects.inc +26 -2
  418. package/runtime/xt_containers/shapes.inc +71 -0
  419. package/runtime/xt_containers.c +1 -0
  420. package/runtime/xt_coroutine.c +17 -0
  421. package/runtime/xt_fetch/async.inc +295 -0
  422. package/runtime/xt_fetch/request.inc +6 -183
  423. package/runtime/xt_fetch/socket.inc +5 -4
  424. package/runtime/xt_fetch.c +6 -4
  425. package/runtime/xt_generator.c +299 -10
  426. package/runtime/xt_io/inspect.inc +112 -0
  427. package/runtime/xt_loop.c +79 -7
  428. package/runtime/xt_performance.c +37 -0
  429. package/runtime/xt_promise.c +63 -1
  430. package/runtime/xt_stdlib/arrays.inc +1 -1
  431. package/runtime/xt_stdlib/dispatch.inc +46 -11
  432. package/runtime/xt_stdlib/strings.inc +1 -1
  433. package/runtime/xt_stdlib2/array-statics.inc +25 -0
  434. package/runtime/xt_stdlib2/arrays.inc +5 -3
  435. package/runtime/xt_stdlib2/container.inc +5 -0
  436. package/runtime/xt_stdlib2/date.inc +111 -3
  437. package/runtime/xt_stdlib2/error.inc +24 -0
  438. package/runtime/xt_stdlib2/json.inc +310 -19
  439. package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
  440. package/runtime/xt_stdlib2/objects.inc +122 -0
  441. package/runtime/xt_stdlib2/set.inc +1 -1
  442. package/runtime/xt_structured_clone.c +159 -0
  443. package/runtime/xt_symbol.c +2 -2
  444. package/runtime/xt_text_codec.c +69 -0
  445. package/runtime/xt_typed_array/construction.inc +35 -5
  446. package/runtime/xt_typed_array/elements.inc +159 -0
  447. package/runtime/xt_typed_array/methods.inc +21 -5
  448. package/runtime/xt_typed_array.c +7 -10
  449. package/runtime/xt_url.c +375 -0
  450. package/runtime/xt_values/arithmetic.inc +2 -2
  451. package/runtime/xt_values/conversions.inc +1 -1
  452. package/runtime/xt_weak.c +281 -0
  453. package/scripts/build-gui.ts +133 -60
  454. package/scripts/check-version.ts +3 -3
  455. package/src/binder/declarations.ts +14 -3
  456. package/src/cli/hints.ts +8 -1
  457. package/src/cli/main.ts +119 -18
  458. package/src/cli/watch.ts +101 -0
  459. package/src/codegen/generator/calls/access.ts +10 -2
  460. package/src/codegen/generator/calls/closures.ts +12 -4
  461. package/src/codegen/generator/context.ts +23 -3
  462. package/src/codegen/generator/expressions/operators.ts +27 -13
  463. package/src/codegen/generator/expressions/primary.ts +4 -0
  464. package/src/codegen/generator/module.ts +0 -7
  465. package/src/codegen/generator/numeric.ts +85 -11
  466. package/src/codegen/generator/state.ts +23 -0
  467. package/src/codegen/generator/statements/control-flow.ts +1 -4
  468. package/src/codegen/generator/statements/loops.ts +50 -16
  469. package/src/codegen/generator/tables.ts +26 -1
  470. package/src/diagnostics/diagnostic.ts +23 -3
  471. package/src/driver/app-artifacts.ts +77 -0
  472. package/src/driver/build-key.ts +55 -0
  473. package/src/driver/bundler/graph.ts +63 -13
  474. package/src/driver/bundler/merge.ts +4 -1
  475. package/src/driver/compiler.ts +94 -328
  476. package/src/driver/config.ts +11 -0
  477. package/src/driver/frontend.ts +120 -0
  478. package/src/driver/index.ts +0 -1
  479. package/src/driver/options.ts +70 -0
  480. package/src/driver/runtime-objects.ts +134 -0
  481. package/src/driver/toolchain-provider.ts +4 -0
  482. package/src/driver/toolchain.ts +154 -10
  483. package/src/driver/version.ts +12 -0
  484. package/src/driver/win-icon.ts +36 -36
  485. package/src/extensions/node/fs/index.ts +12 -3
  486. package/src/extensions/node/fs-promises/index.ts +15 -6
  487. package/src/parser/declarations/classes.ts +4 -0
  488. package/src/parser/declarations/functions.ts +12 -1
  489. package/src/parser/modules.ts +8 -4
  490. package/src/parser/parser.ts +28 -0
@@ -0,0 +1,295 @@
1
+ /* -- asynchronous request/response exchange ------------------------------- */
2
+
3
+ /*
4
+ * `fetch` is a state machine over the async I/O pool. The main thread validates
5
+ * the URL, turns `init.headers` into a `Headers` object and serialises the
6
+ * request; a worker performs the blocking `getaddrinfo`/connect/send/recv
7
+ * exchange; the main thread parses the raw response, follows redirects and
8
+ * builds the `Response`. Nothing observed from JavaScript blocks the reactor, so
9
+ * timers and sockets keep running while a request is in flight.
10
+ *
11
+ * The worker only sees plain C memory. The values that must survive across the
12
+ * suspension (`promise`, `headers`) are held in the job's `roots` slots and
13
+ * scanned by the collector.
14
+ */
15
+
16
+ typedef struct xt_fetch_state xt_fetch_state;
17
+
18
+ typedef struct {
19
+ xt_async_job base;
20
+ xt_fetch_state *state;
21
+ char *request;
22
+ size_t request_length;
23
+ xt_fetch_buffer raw;
24
+ int failed;
25
+ } xt_fetch_hop;
26
+
27
+ struct xt_fetch_state {
28
+ xt_value promise;
29
+ xt_value headers_source;
30
+ char *url;
31
+ char method[16];
32
+ char redirect[16];
33
+ xt_fetch_buffer body;
34
+ int redirects;
35
+ };
36
+
37
+ static void xt_fetch_start(xt_fetch_state *state);
38
+
39
+ static void xt_fetch_state_free(xt_fetch_state *state) {
40
+ if (!state) return;
41
+ free(state->url);
42
+ xt_fetch_buffer_free(&state->body);
43
+ free(state);
44
+ }
45
+
46
+ static void xt_fetch_state_reject(xt_fetch_state *state, const char *message) {
47
+ xt_value argument = xt_string_from_cstr(message);
48
+ xt_value error = xt_type_error_ctor(1, &argument);
49
+ xt_value promise = state->promise;
50
+ xt_fetch_state_free(state);
51
+ xt_promise_reject_value(promise, error);
52
+ }
53
+
54
+ static void xt_fetch_hop_release(xt_async_job *job) {
55
+ xt_fetch_hop *hop = (xt_fetch_hop *)job;
56
+ free(hop->request);
57
+ xt_fetch_buffer_free(&hop->raw);
58
+ free(hop);
59
+ }
60
+
61
+ /* Worker thread: connect, write the request, read until the response is
62
+ * complete (or the peer closes). Only plain C memory is touched here. */
63
+ static void xt_fetch_hop_run(xt_async_job *job) {
64
+ xt_fetch_hop *hop = (xt_fetch_hop *)job;
65
+ xt_fetch_url parsed;
66
+ if (xt_fetch_parse_url(hop->state->url, &parsed) != 0) {
67
+ hop->failed = 1;
68
+ return;
69
+ }
70
+ int fd = xt_fetch_connect(&parsed);
71
+ if (fd < 0) {
72
+ hop->failed = 1;
73
+ return;
74
+ }
75
+ if (xt_fetch_send_all(fd, hop->request, hop->request_length) != 0) {
76
+ xt_fetch_close_socket(fd);
77
+ hop->failed = 1;
78
+ return;
79
+ }
80
+
81
+ char chunk[16384];
82
+ for (;;) {
83
+ int headEnd = xt_fetch_head_end(&hop->raw);
84
+ if (headEnd > 0) {
85
+ int status = 0;
86
+ char statusText[256];
87
+ size_t headerStart = 0;
88
+ if (xt_fetch_parse_status_line(hop->raw.data, hop->raw.length, &status, statusText, sizeof(statusText),
89
+ &headerStart) == 0) {
90
+ int stop = 0;
91
+ if (status == 204 || status == 304 || (status >= 100 && status < 200) ||
92
+ strcmp(hop->state->method, "HEAD") == 0) {
93
+ stop = 1;
94
+ } else {
95
+ size_t contentLength = 0;
96
+ int hasContentLength = 0;
97
+ int chunked = 0;
98
+ xt_fetch_scan_headers(hop->raw.data, headerStart, (size_t)headEnd - 2, &contentLength, &hasContentLength,
99
+ &chunked);
100
+ if (chunked) {
101
+ size_t decoded = 0;
102
+ if (xt_fetch_chunked_complete(hop->raw.data, hop->raw.length, (size_t)headEnd, &decoded) == 1) stop = 1;
103
+ } else if (hasContentLength && hop->raw.length - (size_t)headEnd >= contentLength) {
104
+ stop = 1;
105
+ }
106
+ }
107
+ if (stop) break;
108
+ }
109
+ }
110
+ int count = xt_fetch_recv(fd, chunk, sizeof(chunk));
111
+ if (count > 0) {
112
+ xt_fetch_buffer_append(&hop->raw, chunk, (size_t)count);
113
+ continue;
114
+ }
115
+ break;
116
+ }
117
+ xt_fetch_close_socket(fd);
118
+ }
119
+
120
+ #define XT_FETCH_HOP(c) ((xt_fetch_hop *)(c))
121
+
122
+ /* Main thread: parse the raw response and either follow a redirect (starting a
123
+ * fresh hop) or build the `Response` and settle the promise. */
124
+ static void xt_fetch_hop_complete(xt_async_job *job) {
125
+ xt_fetch_hop *hop = XT_FETCH_HOP(job);
126
+ xt_fetch_state *state = hop->state;
127
+ if (hop->failed) {
128
+ xt_fetch_state_reject(state, "fetch failed");
129
+ return;
130
+ }
131
+
132
+ xt_fetch_buffer *raw = &hop->raw;
133
+ int headEnd = xt_fetch_head_end(raw);
134
+ int status = 0;
135
+ char statusText[256];
136
+ size_t headerStart = 0;
137
+ if (headEnd <= 0 ||
138
+ xt_fetch_parse_status_line(raw->data, raw->length, &status, statusText, sizeof(statusText), &headerStart) != 0) {
139
+ xt_fetch_state_reject(state, "fetch failed: invalid response");
140
+ return;
141
+ }
142
+
143
+ xt_value responseHeaders = xt_headers_new();
144
+ xt_headers_parse_block(responseHeaders, raw->data + headerStart, (size_t)headEnd - 2 - headerStart);
145
+
146
+ int isRedirect = status == 301 || status == 302 || status == 303 || status == 307 || status == 308;
147
+ if (isRedirect && strcmp(state->redirect, "error") == 0) {
148
+ xt_fetch_state_reject(state, "fetch failed: redirect not allowed");
149
+ return;
150
+ }
151
+ if (isRedirect && strcmp(state->redirect, "manual") != 0 && state->redirects < 20) {
152
+ xt_fetch_url parsed;
153
+ if (xt_fetch_parse_url(state->url, &parsed) == 0) {
154
+ const char *location = xt_headers_lookup(responseHeaders, "location");
155
+ char resolved[4096];
156
+ if (location && xt_fetch_resolve_location(&parsed, location, resolved, sizeof(resolved)) == 0) {
157
+ if (status == 303 || ((status == 301 || status == 302) && strcmp(state->method, "POST") == 0)) {
158
+ snprintf(state->method, sizeof(state->method), "GET");
159
+ state->body.length = 0;
160
+ }
161
+ free(state->url);
162
+ size_t length = strlen(resolved);
163
+ state->url = (char *)malloc(length + 1);
164
+ if (!state->url) {
165
+ xt_fetch_state_reject(state, "fetch failed");
166
+ return;
167
+ }
168
+ memcpy(state->url, resolved, length + 1);
169
+ state->redirects++;
170
+ xt_fetch_start(state);
171
+ return;
172
+ }
173
+ }
174
+ }
175
+
176
+ size_t contentLength = 0;
177
+ int hasContentLength = 0;
178
+ int chunked = 0;
179
+ xt_fetch_scan_headers(raw->data, headerStart, (size_t)headEnd - 2, &contentLength, &hasContentLength, &chunked);
180
+ xt_fetch_buffer responseBody;
181
+ xt_fetch_buffer_init(&responseBody);
182
+ if (status == 204 || status == 304 || (status >= 100 && status < 200) || strcmp(state->method, "HEAD") == 0) {
183
+ /* No body by definition. */
184
+ } else if (chunked) {
185
+ xt_fetch_decode_chunked(raw->data, raw->length, (size_t)headEnd, &responseBody);
186
+ } else if (hasContentLength) {
187
+ size_t available = raw->length - (size_t)headEnd;
188
+ size_t take = contentLength < available ? contentLength : available;
189
+ xt_fetch_buffer_append(&responseBody, raw->data + headEnd, take);
190
+ } else {
191
+ xt_fetch_buffer_append(&responseBody, raw->data + headEnd, raw->length - (size_t)headEnd);
192
+ }
193
+
194
+ xt_value response = xt_response_new(responseHeaders, status, statusText, state->url,
195
+ responseBody.data ? responseBody.data : "", responseBody.length);
196
+ xt_fetch_buffer_free(&responseBody);
197
+ xt_value promise = state->promise;
198
+ xt_fetch_state_free(state);
199
+ xt_promise_fulfill(promise, response);
200
+ }
201
+
202
+ /* Main thread: validate the current URL and queue one exchange. */
203
+ static void xt_fetch_start(xt_fetch_state *state) {
204
+ xt_fetch_url parsed;
205
+ if (xt_fetch_parse_url(state->url, &parsed) != 0) {
206
+ xt_fetch_state_reject(state, "Failed to parse URL");
207
+ return;
208
+ }
209
+ if (parsed.secure) {
210
+ xt_fetch_state_reject(state, "fetch failed: https is not supported");
211
+ return;
212
+ }
213
+
214
+ xt_value requestHeaders = xt_headers_from_source(state->headers_source);
215
+ xt_fetch_buffer request;
216
+ xt_fetch_buffer_init(&request);
217
+ xt_fetch_build_request(state->method, &parsed, requestHeaders, state->body.length > 0 ? &state->body : NULL,
218
+ &request);
219
+
220
+ xt_fetch_hop *hop = (xt_fetch_hop *)calloc(1, sizeof(xt_fetch_hop));
221
+ if (!hop) abort();
222
+ hop->base.roots[0] = state->promise;
223
+ hop->base.roots[1] = state->headers_source;
224
+ hop->base.run = xt_fetch_hop_run;
225
+ hop->base.complete = xt_fetch_hop_complete;
226
+ hop->base.release = xt_fetch_hop_release;
227
+ hop->state = state;
228
+ hop->request = request.data;
229
+ hop->request_length = request.length;
230
+ xt_fetch_buffer_init(&hop->raw);
231
+ xt_async_submit(&hop->base);
232
+ }
233
+
234
+ /** Implements the global `fetch(input, init)`. The returned promise settles
235
+ * once a worker has completed the exchange and the reactor dispatches it. */
236
+ xt_value xt_fetch(int32_t argc, xt_value *argv) {
237
+ xt_value input = xt_arg_at(argc, argv, 0);
238
+ xt_value init = xt_arg_at(argc, argv, 1);
239
+ if (input == XT_UNDEFINED || input == XT_NULL) {
240
+ xt_value argument = xt_string_from_cstr("Failed to parse URL from undefined");
241
+ return xt_promise_reject(xt_type_error_ctor(1, &argument));
242
+ }
243
+
244
+ xt_value urlValue = input;
245
+ if (XT_IS_OBJECT(input)) {
246
+ xt_value candidate = xt_object_get_cstr(input, "url");
247
+ if (XT_IS_STRING(candidate)) urlValue = candidate;
248
+ }
249
+ const char *urlText = xt_string_data(xt_to_string(urlValue));
250
+ if (!urlText) {
251
+ xt_value argument = xt_string_from_cstr("Failed to parse URL");
252
+ return xt_promise_reject(xt_type_error_ctor(1, &argument));
253
+ }
254
+
255
+ xt_fetch_state *state = (xt_fetch_state *)calloc(1, sizeof(xt_fetch_state));
256
+ if (!state) abort();
257
+ size_t urlLength = strlen(urlText);
258
+ state->url = (char *)malloc(urlLength + 1);
259
+ if (!state->url) abort();
260
+ memcpy(state->url, urlText, urlLength + 1);
261
+ snprintf(state->method, sizeof(state->method), "GET");
262
+ snprintf(state->redirect, sizeof(state->redirect), "follow");
263
+ xt_fetch_buffer_init(&state->body);
264
+ state->headers_source = XT_UNDEFINED;
265
+ state->redirects = 0;
266
+
267
+ if (XT_IS_OBJECT(init)) {
268
+ xt_value methodValue = xt_object_get_cstr(init, "method");
269
+ if (XT_IS_STRING(methodValue)) {
270
+ const char *text = xt_string_data(methodValue);
271
+ size_t i = 0;
272
+ for (; text && text[i] && i + 1 < sizeof(state->method); i++) {
273
+ char c = text[i];
274
+ state->method[i] = (c >= 'a' && c <= 'z') ? (char)(c - 32) : c;
275
+ }
276
+ state->method[i] = '\0';
277
+ }
278
+ state->headers_source = xt_object_get_cstr(init, "headers");
279
+ xt_value bodySource = xt_object_get_cstr(init, "body");
280
+ if (bodySource != XT_UNDEFINED && bodySource != XT_NULL) {
281
+ xt_value text = xt_to_string(bodySource);
282
+ const char *data = xt_string_data(text);
283
+ if (data) xt_fetch_buffer_append(&state->body, data, (size_t)xt_string_length_value(text));
284
+ }
285
+ xt_value redirectValue = xt_object_get_cstr(init, "redirect");
286
+ if (XT_IS_STRING(redirectValue)) {
287
+ snprintf(state->redirect, sizeof(state->redirect), "%s", xt_string_data(redirectValue));
288
+ }
289
+ }
290
+
291
+ state->promise = xt_promise_create();
292
+ xt_value promise = state->promise;
293
+ xt_fetch_start(state);
294
+ return promise;
295
+ }
@@ -1,9 +1,10 @@
1
1
  /* -- request / response exchange ------------------------------------------ */
2
2
 
3
3
  /*
4
- * The actual `fetch` implementation. Because the runtime has no event loop,
5
- * this is a synchronous, blocking HTTP/1.1 exchange; the promise it returns is
6
- * already settled, which is all the current `await` machinery needs.
4
+ * Request serialisation, response framing and header parsing for `fetch`. The
5
+ * blocking exchange itself runs on an async I/O worker (see `async.inc`); these
6
+ * helpers are shared by the main thread (building the request, parsing the
7
+ * completed response) and the worker (deciding when the response is complete).
7
8
  */
8
9
 
9
10
  /** Index just past the blank line that terminates the response headers. */
@@ -204,183 +205,5 @@ static void xt_fetch_build_request(const char *method, const xt_fetch_url *url,
204
205
  if (body && body->length > 0) xt_fetch_buffer_append(out, body->data, body->length);
205
206
  }
206
207
 
207
- static xt_value xt_fetch_reject(const char *message) {
208
- xt_value argument = xt_string_from_cstr(message);
209
- return xt_promise_reject(xt_type_error_ctor(1, &argument));
210
- }
211
-
212
- xt_value xt_fetch(int32_t argc, xt_value *argv) {
213
- xt_value input = xt_arg_at(argc, argv, 0);
214
- xt_value init = xt_arg_at(argc, argv, 1);
215
- if (input == XT_UNDEFINED || input == XT_NULL) return xt_fetch_reject("Failed to parse URL from undefined");
216
-
217
- xt_value urlValue = input;
218
- if (XT_IS_OBJECT(input)) {
219
- xt_value candidate = xt_object_get_cstr(input, "url");
220
- if (XT_IS_STRING(candidate)) urlValue = candidate;
221
- }
222
- const char *urlText = xt_string_data(xt_to_string(urlValue));
223
- if (!urlText) return xt_fetch_reject("Failed to parse URL");
224
-
225
- char currentUrl[4096];
226
- snprintf(currentUrl, sizeof(currentUrl), "%s", urlText);
227
-
228
- char method[16];
229
- snprintf(method, sizeof(method), "GET");
230
- xt_value headersSource = XT_UNDEFINED;
231
- xt_value bodySource = XT_UNDEFINED;
232
- const char *redirectMode = "follow";
233
- if (XT_IS_OBJECT(init)) {
234
- xt_value methodValue = xt_object_get_cstr(init, "method");
235
- if (XT_IS_STRING(methodValue)) {
236
- const char *text = xt_string_data(methodValue);
237
- size_t i = 0;
238
- for (; text && text[i] && i + 1 < sizeof(method); i++) {
239
- char c = text[i];
240
- method[i] = (c >= 'a' && c <= 'z') ? (char)(c - 32) : c;
241
- }
242
- method[i] = '\0';
243
- }
244
- headersSource = xt_object_get_cstr(init, "headers");
245
- bodySource = xt_object_get_cstr(init, "body");
246
- xt_value redirectValue = xt_object_get_cstr(init, "redirect");
247
- if (XT_IS_STRING(redirectValue)) redirectMode = xt_string_data(redirectValue);
248
- }
249
-
250
- xt_fetch_buffer body;
251
- xt_fetch_buffer_init(&body);
252
- if (bodySource != XT_UNDEFINED && bodySource != XT_NULL) {
253
- xt_value text = xt_to_string(bodySource);
254
- const char *data = xt_string_data(text);
255
- if (data) xt_fetch_buffer_append(&body, data, (size_t)xt_string_length_value(text));
256
- }
257
-
258
- for (int redirects = 0; redirects <= 20; redirects++) {
259
- xt_fetch_url parsed;
260
- if (xt_fetch_parse_url(currentUrl, &parsed) != 0) {
261
- xt_fetch_buffer_free(&body);
262
- return xt_fetch_reject("Failed to parse URL");
263
- }
264
- if (parsed.secure) {
265
- xt_fetch_buffer_free(&body);
266
- return xt_fetch_reject("fetch failed: https is not supported");
267
- }
268
-
269
- int fd = xt_fetch_connect(&parsed);
270
- if (fd < 0) {
271
- xt_fetch_buffer_free(&body);
272
- return xt_fetch_reject("fetch failed");
273
- }
274
-
275
- xt_value requestHeaders = xt_headers_from_source(headersSource);
276
- xt_fetch_buffer request;
277
- xt_fetch_buffer_init(&request);
278
- xt_fetch_build_request(method, &parsed, requestHeaders, body.length > 0 ? &body : NULL, &request);
279
- if (xt_fetch_send_all(fd, request.data, request.length) != 0) {
280
- xt_fetch_close_socket(fd);
281
- xt_fetch_buffer_free(&request);
282
- xt_fetch_buffer_free(&body);
283
- return xt_fetch_reject("fetch failed");
284
- }
285
- xt_fetch_buffer_free(&request);
286
-
287
- xt_fetch_buffer raw;
288
- xt_fetch_buffer_init(&raw);
289
- char chunk[16384];
290
- for (;;) {
291
- int headEnd = xt_fetch_head_end(&raw);
292
- if (headEnd > 0) {
293
- int status = 0;
294
- char statusText[256];
295
- size_t headerStart = 0;
296
- if (xt_fetch_parse_status_line(raw.data, raw.length, &status, statusText, sizeof(statusText), &headerStart) == 0) {
297
- int stop = 0;
298
- if (status == 204 || status == 304 || (status >= 100 && status < 200) || strcmp(method, "HEAD") == 0) {
299
- stop = 1;
300
- } else {
301
- size_t contentLength = 0;
302
- int hasContentLength = 0;
303
- int chunked = 0;
304
- xt_fetch_scan_headers(raw.data, headerStart, (size_t)headEnd - 2, &contentLength, &hasContentLength, &chunked);
305
- if (chunked) {
306
- size_t decoded = 0;
307
- if (xt_fetch_chunked_complete(raw.data, raw.length, (size_t)headEnd, &decoded) == 1) stop = 1;
308
- } else if (hasContentLength && raw.length - (size_t)headEnd >= contentLength) {
309
- stop = 1;
310
- }
311
- }
312
- if (stop) break;
313
- }
314
- }
315
- int count = xt_fetch_recv(fd, chunk, sizeof(chunk));
316
- if (count > 0) {
317
- xt_fetch_buffer_append(&raw, chunk, (size_t)count);
318
- continue;
319
- }
320
- break;
321
- }
322
- xt_fetch_close_socket(fd);
323
-
324
- int headEnd = xt_fetch_head_end(&raw);
325
- int status = 0;
326
- char statusText[256];
327
- size_t headerStart = 0;
328
- if (headEnd <= 0 ||
329
- xt_fetch_parse_status_line(raw.data, raw.length, &status, statusText, sizeof(statusText), &headerStart) != 0) {
330
- xt_fetch_buffer_free(&raw);
331
- xt_fetch_buffer_free(&body);
332
- return xt_fetch_reject("fetch failed: invalid response");
333
- }
334
-
335
- xt_value responseHeaders = xt_headers_new();
336
- xt_headers_parse_block(responseHeaders, raw.data + headerStart, (size_t)headEnd - 2 - headerStart);
337
-
338
- int isRedirect = status == 301 || status == 302 || status == 303 || status == 307 || status == 308;
339
- if (isRedirect && strcmp(redirectMode, "error") == 0) {
340
- xt_fetch_buffer_free(&raw);
341
- xt_fetch_buffer_free(&body);
342
- return xt_fetch_reject("fetch failed: redirect not allowed");
343
- }
344
- if (isRedirect && strcmp(redirectMode, "manual") != 0 && redirects < 20) {
345
- const char *location = xt_headers_lookup(responseHeaders, "location");
346
- char resolved[4096];
347
- if (location && xt_fetch_resolve_location(&parsed, location, resolved, sizeof(resolved)) == 0) {
348
- if (status == 303 || ((status == 301 || status == 302) && strcmp(method, "POST") == 0)) {
349
- snprintf(method, sizeof(method), "GET");
350
- body.length = 0;
351
- }
352
- snprintf(currentUrl, sizeof(currentUrl), "%s", resolved);
353
- xt_fetch_buffer_free(&raw);
354
- continue;
355
- }
356
- }
357
-
358
- size_t contentLength = 0;
359
- int hasContentLength = 0;
360
- int chunked = 0;
361
- xt_fetch_scan_headers(raw.data, headerStart, (size_t)headEnd - 2, &contentLength, &hasContentLength, &chunked);
362
- xt_fetch_buffer responseBody;
363
- xt_fetch_buffer_init(&responseBody);
364
- if (status == 204 || status == 304 || (status >= 100 && status < 200) || strcmp(method, "HEAD") == 0) {
365
- /* No body by definition. */
366
- } else if (chunked) {
367
- xt_fetch_decode_chunked(raw.data, raw.length, (size_t)headEnd, &responseBody);
368
- } else if (hasContentLength) {
369
- size_t available = raw.length - (size_t)headEnd;
370
- size_t take = contentLength < available ? contentLength : available;
371
- xt_fetch_buffer_append(&responseBody, raw.data + headEnd, take);
372
- } else {
373
- xt_fetch_buffer_append(&responseBody, raw.data + headEnd, raw.length - (size_t)headEnd);
374
- }
375
-
376
- xt_value response = xt_response_new(responseHeaders, status, statusText, currentUrl,
377
- responseBody.data ? responseBody.data : "", responseBody.length);
378
- xt_fetch_buffer_free(&responseBody);
379
- xt_fetch_buffer_free(&raw);
380
- xt_fetch_buffer_free(&body);
381
- return xt_promise_resolve(response);
382
- }
383
-
384
- xt_fetch_buffer_free(&body);
385
- return xt_fetch_reject("fetch failed: too many redirects");
386
- }
208
+ /* The async exchange itself lives in `async.inc`; it reuses the parsers and
209
+ * request builder above. */
@@ -1,10 +1,11 @@
1
1
  /* -- TCP socket helpers --------------------------------------------------- */
2
2
 
3
3
  /*
4
- * `fetch` performs a conventional blocking request/response exchange: connect,
5
- * write the request, read until the response is complete (or the peer closes).
6
- * The socket carries a receive timeout so a stalled server cannot hang the
7
- * program forever; the timeout surfaces as a rejected promise.
4
+ * `fetch` performs a conventional blocking request/response exchange on an
5
+ * async I/O worker: connect, write the request, read until the response is
6
+ * complete (or the peer closes). The socket carries a receive timeout so a
7
+ * stalled server cannot pin a worker forever; the timeout surfaces as a
8
+ * rejected promise.
8
9
  */
9
10
  #define XT_FETCH_TIMEOUT_SECONDS 30
10
11
 
@@ -2,10 +2,11 @@
2
2
  * xbintsc runtime — the global `fetch` API.
3
3
  *
4
4
  * This is a small, dependency-free HTTP/1.1 client exposed as the platform
5
- * `fetch` global. The runtime has no event loop (promises are drained
6
- * synchronously by `await`), so the request is performed with blocking sockets
7
- * and the returned promise is already settled. TLS is not implemented, so only
8
- * `http://` URLs are accepted; `https://` rejects with a `TypeError`.
5
+ * `fetch` global. The blocking socket exchange runs on the async I/O pool
6
+ * (`xt_async_io.c`), so a request in flight does not stall the reactor: timers,
7
+ * sockets and other `await`s keep running until the response is dispatched on
8
+ * the main thread. TLS is not implemented, so only `http://` URLs are accepted;
9
+ * `https://` rejects with a `TypeError`.
9
10
  *
10
11
  * The implementation is grouped by concern under `xt_fetch/` and `#include`d
11
12
  * here as a single translation unit, following the other runtime modules.
@@ -37,3 +38,4 @@ typedef socklen_t xt_fetch_socklen_t;
37
38
  #include "xt_fetch/headers.inc"
38
39
  #include "xt_fetch/response.inc"
39
40
  #include "xt_fetch/request.inc"
41
+ #include "xt_fetch/async.inc"