xbintsc 0.3.87 → 0.5.20

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 (458) hide show
  1. package/AGENTS.md +23 -11
  2. package/README.md +11 -9
  3. package/README.zh-CN.md +7 -7
  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 +17 -4
  14. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  15. package/dist/src/codegen/generator/calls/closures.js +13 -1
  16. package/dist/src/codegen/generator/calls/closures.js.map +1 -1
  17. package/dist/src/codegen/generator/calls/invocation.js +4 -3
  18. package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
  19. package/dist/src/codegen/generator/context.d.ts +8 -0
  20. package/dist/src/codegen/generator/context.js +22 -3
  21. package/dist/src/codegen/generator/context.js.map +1 -1
  22. package/dist/src/codegen/generator/expressions/operators.js +17 -15
  23. package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
  24. package/dist/src/codegen/generator/expressions/primary.js +11 -1
  25. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  26. package/dist/src/codegen/generator/module.d.ts +0 -1
  27. package/dist/src/codegen/generator/module.js +10 -17
  28. package/dist/src/codegen/generator/module.js.map +1 -1
  29. package/dist/src/codegen/generator/numeric.d.ts +6 -3
  30. package/dist/src/codegen/generator/numeric.js +54 -11
  31. package/dist/src/codegen/generator/numeric.js.map +1 -1
  32. package/dist/src/codegen/generator/state.js +27 -0
  33. package/dist/src/codegen/generator/state.js.map +1 -1
  34. package/dist/src/codegen/generator/statements/control-flow.js +2 -7
  35. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
  36. package/dist/src/codegen/generator/statements/loops.js +48 -16
  37. package/dist/src/codegen/generator/statements/loops.js.map +1 -1
  38. package/dist/src/codegen/generator/tables.d.ts +9 -0
  39. package/dist/src/codegen/generator/tables.js +100 -3
  40. package/dist/src/codegen/generator/tables.js.map +1 -1
  41. package/dist/src/diagnostics/diagnostic.d.ts +3 -1
  42. package/dist/src/diagnostics/diagnostic.js +23 -3
  43. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  44. package/dist/src/driver/app-artifacts.d.ts +42 -0
  45. package/dist/src/driver/app-artifacts.js +53 -0
  46. package/dist/src/driver/app-artifacts.js.map +1 -0
  47. package/dist/src/driver/build-key.d.ts +29 -0
  48. package/dist/src/driver/build-key.js +35 -0
  49. package/dist/src/driver/build-key.js.map +1 -0
  50. package/dist/src/driver/bundler/graph.js +61 -12
  51. package/dist/src/driver/bundler/graph.js.map +1 -1
  52. package/dist/src/driver/bundler/merge.js +7 -1
  53. package/dist/src/driver/bundler/merge.js.map +1 -1
  54. package/dist/src/driver/compiler.d.ts +10 -67
  55. package/dist/src/driver/compiler.js +94 -230
  56. package/dist/src/driver/compiler.js.map +1 -1
  57. package/dist/src/driver/config.d.ts +3 -0
  58. package/dist/src/driver/config.js +8 -0
  59. package/dist/src/driver/config.js.map +1 -1
  60. package/dist/src/driver/frontend.d.ts +37 -0
  61. package/dist/src/driver/frontend.js +92 -0
  62. package/dist/src/driver/frontend.js.map +1 -0
  63. package/dist/src/driver/index.d.ts +1 -1
  64. package/dist/src/driver/index.js.map +1 -1
  65. package/dist/src/driver/options.d.ts +64 -0
  66. package/dist/src/driver/options.js +9 -0
  67. package/dist/src/driver/options.js.map +1 -0
  68. package/dist/src/driver/runtime-objects.d.ts +38 -0
  69. package/dist/src/driver/runtime-objects.js +111 -0
  70. package/dist/src/driver/runtime-objects.js.map +1 -0
  71. package/dist/src/driver/toolchain-provider.d.ts +4 -0
  72. package/dist/src/driver/toolchain-provider.js +4 -0
  73. package/dist/src/driver/toolchain-provider.js.map +1 -1
  74. package/dist/src/driver/toolchain.d.ts +32 -1
  75. package/dist/src/driver/toolchain.js +115 -11
  76. package/dist/src/driver/toolchain.js.map +1 -1
  77. package/dist/src/driver/version.d.ts +12 -0
  78. package/dist/src/driver/version.js +13 -0
  79. package/dist/src/driver/version.js.map +1 -0
  80. package/dist/src/driver/win-icon.d.ts +7 -9
  81. package/dist/src/driver/win-icon.js +37 -35
  82. package/dist/src/driver/win-icon.js.map +1 -1
  83. package/dist/src/parser/declarations/classes.js +5 -0
  84. package/dist/src/parser/declarations/classes.js.map +1 -1
  85. package/dist/src/parser/declarations/functions.js +13 -1
  86. package/dist/src/parser/declarations/functions.js.map +1 -1
  87. package/dist/src/parser/modules.js +8 -3
  88. package/dist/src/parser/modules.js.map +1 -1
  89. package/dist/src/parser/parser.d.ts +1 -0
  90. package/dist/src/parser/parser.js +23 -0
  91. package/dist/src/parser/parser.js.map +1 -1
  92. package/dist/tests/cli/check.test.d.ts +6 -0
  93. package/dist/tests/cli/check.test.js +68 -0
  94. package/dist/tests/cli/check.test.js.map +1 -0
  95. package/dist/tests/cli/main.test.js +19 -0
  96. package/dist/tests/cli/main.test.js.map +1 -1
  97. package/dist/tests/cli/watch.test.d.ts +6 -0
  98. package/dist/tests/cli/watch.test.js +72 -0
  99. package/dist/tests/cli/watch.test.js.map +1 -0
  100. package/dist/tests/codegen/closures.test.js +8 -0
  101. package/dist/tests/codegen/closures.test.js.map +1 -1
  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.d.ts +10 -0
  136. package/dist/tests/e2e/async-await.test.js +247 -0
  137. package/dist/tests/e2e/async-await.test.js.map +1 -0
  138. package/dist/tests/e2e/async-generators.test.d.ts +1 -0
  139. package/dist/tests/e2e/async-generators.test.js +154 -0
  140. package/dist/tests/e2e/async-generators.test.js.map +1 -0
  141. package/dist/tests/e2e/await-ordering.test.d.ts +5 -0
  142. package/dist/tests/e2e/await-ordering.test.js +37 -0
  143. package/dist/tests/e2e/await-ordering.test.js.map +1 -0
  144. package/dist/tests/e2e/compile-builtins.test.js +1 -1
  145. package/dist/tests/e2e/compile-modules.test.js +7 -0
  146. package/dist/tests/e2e/compile-modules.test.js.map +1 -1
  147. package/dist/tests/e2e/date-parse.test.d.ts +8 -0
  148. package/dist/tests/e2e/date-parse.test.js +38 -0
  149. package/dist/tests/e2e/date-parse.test.js.map +1 -0
  150. package/dist/tests/e2e/default-anonymous-exports.test.d.ts +7 -0
  151. package/dist/tests/e2e/default-anonymous-exports.test.js +23 -0
  152. package/dist/tests/e2e/default-anonymous-exports.test.js.map +1 -0
  153. package/dist/tests/e2e/globals-microtask.test.d.ts +9 -0
  154. package/dist/tests/e2e/globals-microtask.test.js +37 -0
  155. package/dist/tests/e2e/globals-microtask.test.js.map +1 -0
  156. package/dist/tests/e2e/gui-media.test.js +8 -1
  157. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  158. package/dist/tests/e2e/inspect-builtins.test.d.ts +10 -0
  159. package/dist/tests/e2e/inspect-builtins.test.js +43 -0
  160. package/dist/tests/e2e/inspect-builtins.test.js.map +1 -0
  161. package/dist/tests/e2e/json-builtin-objects.test.d.ts +9 -0
  162. package/dist/tests/e2e/json-builtin-objects.test.js +23 -0
  163. package/dist/tests/e2e/json-builtin-objects.test.js.map +1 -0
  164. package/dist/tests/e2e/json-circular.test.d.ts +6 -0
  165. package/dist/tests/e2e/json-circular.test.js +43 -0
  166. package/dist/tests/e2e/json-circular.test.js.map +1 -0
  167. package/dist/tests/e2e/json-parse-reviver.test.d.ts +6 -0
  168. package/dist/tests/e2e/json-parse-reviver.test.js +29 -0
  169. package/dist/tests/e2e/json-parse-reviver.test.js.map +1 -0
  170. package/dist/tests/e2e/json-stringify-replacer.test.d.ts +6 -0
  171. package/dist/tests/e2e/json-stringify-replacer.test.js +27 -0
  172. package/dist/tests/e2e/json-stringify-replacer.test.js.map +1 -0
  173. package/dist/tests/e2e/json-stringify-space.test.d.ts +6 -0
  174. package/dist/tests/e2e/json-stringify-space.test.js +23 -0
  175. package/dist/tests/e2e/json-stringify-space.test.js.map +1 -0
  176. package/dist/tests/e2e/method-dispatch-errors.test.d.ts +9 -0
  177. package/dist/tests/e2e/method-dispatch-errors.test.js +38 -0
  178. package/dist/tests/e2e/method-dispatch-errors.test.js.map +1 -0
  179. package/dist/tests/e2e/native-extensions.test.js +1 -1
  180. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  181. package/dist/tests/e2e/promise-with-resolvers.test.d.ts +5 -0
  182. package/dist/tests/e2e/promise-with-resolvers.test.js +20 -0
  183. package/dist/tests/e2e/promise-with-resolvers.test.js.map +1 -0
  184. package/dist/tests/e2e/property-descriptors.test.d.ts +5 -0
  185. package/dist/tests/e2e/property-descriptors.test.js +25 -0
  186. package/dist/tests/e2e/property-descriptors.test.js.map +1 -0
  187. package/dist/tests/e2e/property-ic.test.d.ts +1 -0
  188. package/dist/tests/e2e/property-ic.test.js +55 -0
  189. package/dist/tests/e2e/property-ic.test.js.map +1 -0
  190. package/dist/tests/e2e/runtime-coverage-globals.test.js +46 -0
  191. package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -1
  192. package/dist/tests/e2e/runtime-errors.test.d.ts +10 -0
  193. package/dist/tests/e2e/runtime-errors.test.js +52 -0
  194. package/dist/tests/e2e/runtime-errors.test.js.map +1 -0
  195. package/dist/tests/e2e/string-utf16.test.d.ts +6 -0
  196. package/dist/tests/e2e/string-utf16.test.js +133 -0
  197. package/dist/tests/e2e/string-utf16.test.js.map +1 -0
  198. package/dist/tests/e2e/structured-clone.test.d.ts +6 -0
  199. package/dist/tests/e2e/structured-clone.test.js +49 -0
  200. package/dist/tests/e2e/structured-clone.test.js.map +1 -0
  201. package/dist/tests/e2e/text-codec.test.d.ts +6 -0
  202. package/dist/tests/e2e/text-codec.test.js +24 -0
  203. package/dist/tests/e2e/text-codec.test.js.map +1 -0
  204. package/dist/tests/e2e/typed-array-views.test.d.ts +6 -0
  205. package/dist/tests/e2e/typed-array-views.test.js +39 -0
  206. package/dist/tests/e2e/typed-array-views.test.js.map +1 -0
  207. package/dist/tests/e2e/url-search-params.test.d.ts +5 -0
  208. package/dist/tests/e2e/url-search-params.test.js +30 -0
  209. package/dist/tests/e2e/url-search-params.test.js.map +1 -0
  210. package/dist/tests/e2e/weak-collections.test.d.ts +1 -0
  211. package/dist/tests/e2e/weak-collections.test.js +88 -0
  212. package/dist/tests/e2e/weak-collections.test.js.map +1 -0
  213. package/dist/tests/parser/declarations.test.js +12 -0
  214. package/dist/tests/parser/declarations.test.js.map +1 -1
  215. package/dist/tests/parser/module-syntax.test.js +9 -0
  216. package/dist/tests/parser/module-syntax.test.js.map +1 -1
  217. package/dist/tests/parser/parser.test.js +7 -0
  218. package/dist/tests/parser/parser.test.js.map +1 -1
  219. package/dist/tests/version.test.js +5 -1
  220. package/dist/tests/version.test.js.map +1 -1
  221. package/doc/ai/README.md +4 -3
  222. package/doc/ai/cli.md +41 -0
  223. package/doc/ai/contributing.md +26 -21
  224. package/doc/ai/extensions.md +12 -9
  225. package/doc/ai/language-support.md +26 -19
  226. package/doc/ai/troubleshooting.md +15 -12
  227. package/doc/ai/zh-CN/README.md +3 -2
  228. package/doc/ai/zh-CN/cli.md +35 -0
  229. package/doc/ai/zh-CN/contributing.md +19 -18
  230. package/doc/ai/zh-CN/extensions.md +10 -7
  231. package/doc/ai/zh-CN/language-support.md +26 -20
  232. package/doc/ai/zh-CN/troubleshooting.md +12 -10
  233. package/doc/gui/build.md +13 -4
  234. package/doc/gui/known-issues.md +9 -5
  235. package/doc/gui/rendering.md +3 -1
  236. package/doc/gui.md +4 -3
  237. package/doc/icon.md +5 -4
  238. package/doc/implemented/async.md +38 -0
  239. package/doc/implemented/binder.md +13 -0
  240. package/doc/implemented/cli.md +47 -0
  241. package/doc/implemented/codegen.md +33 -0
  242. package/doc/implemented/collections.md +26 -0
  243. package/doc/implemented/driver.md +19 -0
  244. package/doc/implemented/extensions.md +19 -0
  245. package/doc/implemented/fetch.md +12 -0
  246. package/doc/implemented/lexer.md +23 -0
  247. package/doc/implemented/modules.md +28 -0
  248. package/doc/implemented/node/assert.md +17 -0
  249. package/doc/implemented/node/buffer.md +29 -0
  250. package/doc/implemented/node/child-process.md +29 -0
  251. package/doc/implemented/node/crypto.md +9 -0
  252. package/doc/implemented/node/dgram.md +15 -0
  253. package/doc/implemented/node/events.md +37 -0
  254. package/doc/implemented/node/fs-promises.md +38 -0
  255. package/doc/implemented/node/fs.md +112 -0
  256. package/doc/implemented/node/http.md +21 -0
  257. package/doc/implemented/node/net.md +17 -0
  258. package/doc/implemented/node/os.md +22 -0
  259. package/doc/implemented/node/path.md +33 -0
  260. package/doc/implemented/node/process.md +23 -0
  261. package/doc/implemented/node/querystring.md +20 -0
  262. package/doc/implemented/node/stream-promises.md +8 -0
  263. package/doc/implemented/node/stream.md +19 -0
  264. package/doc/implemented/node/test.md +10 -0
  265. package/doc/implemented/node/url.md +8 -0
  266. package/doc/implemented/node/util.md +25 -0
  267. package/doc/implemented/node/worker-threads.md +10 -0
  268. package/doc/implemented/node/zlib.md +8 -0
  269. package/doc/implemented/node.md +48 -0
  270. package/doc/implemented/operators.md +38 -0
  271. package/doc/implemented/parser.md +58 -0
  272. package/doc/implemented/pipeline.md +28 -0
  273. package/doc/implemented/runtime-core.md +32 -0
  274. package/doc/implemented/stdlib.md +78 -0
  275. package/doc/implemented/strings.md +27 -0
  276. package/doc/implemented/tests.md +10 -0
  277. package/doc/implemented/typed-arrays.md +26 -0
  278. package/doc/implemented/value-model.md +18 -0
  279. package/doc/implemented.md +54 -352
  280. package/doc/node-implemented.md +3 -585
  281. package/doc/node-unimplemented.md +3 -164
  282. package/doc/requirements.md +23 -8
  283. package/doc/unimplemented/classes.md +22 -0
  284. package/doc/unimplemented/deviations.md +27 -0
  285. package/doc/unimplemented/expressions.md +26 -0
  286. package/doc/unimplemented/functions.md +21 -0
  287. package/doc/unimplemented/modules.md +22 -0
  288. package/doc/unimplemented/node/async.md +17 -0
  289. package/doc/unimplemented/node/bun.md +9 -0
  290. package/doc/unimplemented/node/fs-promises.md +16 -0
  291. package/doc/unimplemented/node/fs.md +31 -0
  292. package/doc/unimplemented/node/globals.md +23 -0
  293. package/doc/unimplemented/node/modules.md +21 -0
  294. package/doc/unimplemented/node.md +21 -0
  295. package/doc/unimplemented/statements.md +18 -0
  296. package/doc/unimplemented/stdlib.md +54 -0
  297. package/doc/unimplemented/toolchain.md +14 -0
  298. package/doc/unimplemented/types.md +12 -0
  299. package/doc/unimplemented.md +18 -274
  300. package/doc/xbintsc.config.schema.json +12 -0
  301. package/doc/zh-CN/gui/build.md +11 -3
  302. package/doc/zh-CN/gui/known-issues.md +9 -4
  303. package/doc/zh-CN/gui/rendering.md +2 -1
  304. package/doc/zh-CN/gui.md +3 -2
  305. package/doc/zh-CN/icon.md +5 -4
  306. package/doc/zh-CN/implemented/async.md +38 -0
  307. package/doc/zh-CN/implemented/binder.md +13 -0
  308. package/doc/zh-CN/implemented/cli.md +46 -0
  309. package/doc/zh-CN/implemented/codegen.md +33 -0
  310. package/doc/zh-CN/implemented/collections.md +26 -0
  311. package/doc/zh-CN/implemented/driver.md +19 -0
  312. package/doc/zh-CN/implemented/extensions.md +19 -0
  313. package/doc/zh-CN/implemented/fetch.md +12 -0
  314. package/doc/zh-CN/implemented/lexer.md +23 -0
  315. package/doc/zh-CN/implemented/modules.md +28 -0
  316. package/doc/zh-CN/implemented/node/assert.md +17 -0
  317. package/doc/zh-CN/implemented/node/buffer.md +25 -0
  318. package/doc/zh-CN/implemented/node/child-process.md +27 -0
  319. package/doc/zh-CN/implemented/node/crypto.md +9 -0
  320. package/doc/zh-CN/implemented/node/dgram.md +15 -0
  321. package/doc/zh-CN/implemented/node/events.md +36 -0
  322. package/doc/zh-CN/implemented/node/fs-promises.md +27 -0
  323. package/doc/zh-CN/implemented/node/fs.md +105 -0
  324. package/doc/zh-CN/implemented/node/http.md +17 -0
  325. package/doc/zh-CN/implemented/node/net.md +17 -0
  326. package/doc/zh-CN/implemented/node/os.md +21 -0
  327. package/doc/zh-CN/implemented/node/path.md +26 -0
  328. package/doc/zh-CN/implemented/node/process.md +23 -0
  329. package/doc/zh-CN/implemented/node/querystring.md +20 -0
  330. package/doc/zh-CN/implemented/node/stream-promises.md +8 -0
  331. package/doc/zh-CN/implemented/node/stream.md +15 -0
  332. package/doc/zh-CN/implemented/node/test.md +10 -0
  333. package/doc/zh-CN/implemented/node/url.md +8 -0
  334. package/doc/zh-CN/implemented/node/util.md +25 -0
  335. package/doc/zh-CN/implemented/node/worker-threads.md +9 -0
  336. package/doc/zh-CN/implemented/node/zlib.md +8 -0
  337. package/doc/zh-CN/implemented/node.md +45 -0
  338. package/doc/zh-CN/implemented/operators.md +38 -0
  339. package/doc/zh-CN/implemented/parser.md +58 -0
  340. package/doc/zh-CN/implemented/pipeline.md +25 -0
  341. package/doc/zh-CN/implemented/runtime-core.md +31 -0
  342. package/doc/zh-CN/implemented/stdlib.md +76 -0
  343. package/doc/zh-CN/implemented/strings.md +27 -0
  344. package/doc/zh-CN/implemented/tests.md +10 -0
  345. package/doc/zh-CN/implemented/typed-arrays.md +26 -0
  346. package/doc/zh-CN/implemented/value-model.md +18 -0
  347. package/doc/zh-CN/implemented.md +50 -347
  348. package/doc/zh-CN/node-implemented.md +4 -531
  349. package/doc/zh-CN/node-unimplemented.md +4 -139
  350. package/doc/zh-CN/plan-require-node-modules.md +4 -4
  351. package/doc/zh-CN/requirements.md +20 -6
  352. package/doc/zh-CN/unimplemented/classes.md +22 -0
  353. package/doc/zh-CN/unimplemented/deviations.md +24 -0
  354. package/doc/zh-CN/unimplemented/expressions.md +24 -0
  355. package/doc/zh-CN/unimplemented/functions.md +21 -0
  356. package/doc/zh-CN/unimplemented/modules.md +19 -0
  357. package/doc/zh-CN/unimplemented/node/async.md +17 -0
  358. package/doc/zh-CN/unimplemented/node/bun.md +8 -0
  359. package/doc/zh-CN/unimplemented/node/fs-promises.md +12 -0
  360. package/doc/zh-CN/unimplemented/node/fs.md +24 -0
  361. package/doc/zh-CN/unimplemented/node/globals.md +14 -0
  362. package/doc/zh-CN/unimplemented/node/modules.md +15 -0
  363. package/doc/zh-CN/unimplemented/node.md +18 -0
  364. package/doc/zh-CN/unimplemented/statements.md +15 -0
  365. package/doc/zh-CN/unimplemented/stdlib.md +54 -0
  366. package/doc/zh-CN/unimplemented/toolchain.md +14 -0
  367. package/doc/zh-CN/unimplemented/types.md +11 -0
  368. package/doc/zh-CN/unimplemented.md +14 -236
  369. package/llms.txt +32 -4
  370. package/package.json +1 -1
  371. package/runtime/ext_gui/renderer_shaders.h +2 -2
  372. package/runtime/ext_gui/stb_image.h +1 -17
  373. package/runtime/ext_node/child_process/child_process.c +173 -73
  374. package/runtime/rt.h +47 -0
  375. package/runtime/rt_internal.h +205 -10
  376. package/runtime/xt_alloc.c +49 -7
  377. package/runtime/xt_array_buffer.c +284 -0
  378. package/runtime/xt_async.c +222 -0
  379. package/runtime/xt_bigint/helpers.inc +3 -3
  380. package/runtime/xt_builtins.c +59 -51
  381. package/runtime/xt_constructors.c +399 -0
  382. package/runtime/xt_containers/access.inc +195 -14
  383. package/runtime/xt_containers/arrays.inc +26 -2
  384. package/runtime/xt_containers/objects.inc +226 -5
  385. package/runtime/xt_containers/shapes.inc +71 -0
  386. package/runtime/xt_containers.c +1 -0
  387. package/runtime/xt_coroutine.c +229 -0
  388. package/runtime/xt_generator.c +325 -167
  389. package/runtime/xt_io/inspect.inc +147 -2
  390. package/runtime/xt_loop.c +35 -4
  391. package/runtime/xt_performance.c +37 -0
  392. package/runtime/xt_promise.c +125 -18
  393. package/runtime/xt_stdlib/arrays.inc +1 -1
  394. package/runtime/xt_stdlib/dispatch.inc +64 -13
  395. package/runtime/xt_stdlib/strings.inc +74 -17
  396. package/runtime/xt_stdlib2/array-statics.inc +28 -3
  397. package/runtime/xt_stdlib2/arrays.inc +5 -3
  398. package/runtime/xt_stdlib2/container.inc +5 -0
  399. package/runtime/xt_stdlib2/date.inc +111 -3
  400. package/runtime/xt_stdlib2/error.inc +35 -0
  401. package/runtime/xt_stdlib2/json.inc +353 -33
  402. package/runtime/xt_stdlib2/number-string-statics.inc +24 -15
  403. package/runtime/xt_stdlib2/objects.inc +123 -1
  404. package/runtime/xt_stdlib2/regexp-match.inc +2 -2
  405. package/runtime/xt_stdlib2/set.inc +7 -1
  406. package/runtime/xt_stdlib2/strings.inc +70 -40
  407. package/runtime/xt_structured_clone.c +159 -0
  408. package/runtime/xt_symbol.c +2 -2
  409. package/runtime/xt_text_codec.c +69 -0
  410. package/runtime/xt_typed_array/construction.inc +78 -7
  411. package/runtime/xt_typed_array/elements.inc +159 -0
  412. package/runtime/xt_typed_array/methods.inc +21 -5
  413. package/runtime/xt_typed_array.c +11 -10
  414. package/runtime/xt_url.c +375 -0
  415. package/runtime/xt_values/arithmetic.inc +2 -2
  416. package/runtime/xt_values/constructors.inc +8 -0
  417. package/runtime/xt_values/conversions.inc +1 -1
  418. package/runtime/xt_values/strings.inc +19 -3
  419. package/runtime/xt_values/utf16.inc +340 -0
  420. package/runtime/xt_values.c +1 -0
  421. package/runtime/xt_weak.c +281 -0
  422. package/scripts/build-gui.ts +133 -60
  423. package/scripts/check-version.ts +3 -3
  424. package/src/binder/declarations.ts +14 -3
  425. package/src/cli/hints.ts +8 -1
  426. package/src/cli/main.ts +119 -18
  427. package/src/cli/watch.ts +101 -0
  428. package/src/codegen/generator/calls/access.ts +17 -4
  429. package/src/codegen/generator/calls/closures.ts +12 -1
  430. package/src/codegen/generator/calls/invocation.ts +4 -3
  431. package/src/codegen/generator/context.ts +23 -3
  432. package/src/codegen/generator/expressions/operators.ts +27 -13
  433. package/src/codegen/generator/expressions/primary.ts +10 -1
  434. package/src/codegen/generator/module.ts +10 -19
  435. package/src/codegen/generator/numeric.ts +85 -11
  436. package/src/codegen/generator/state.ts +27 -0
  437. package/src/codegen/generator/statements/control-flow.ts +2 -6
  438. package/src/codegen/generator/statements/loops.ts +50 -16
  439. package/src/codegen/generator/tables.ts +110 -3
  440. package/src/diagnostics/diagnostic.ts +23 -3
  441. package/src/driver/app-artifacts.ts +77 -0
  442. package/src/driver/build-key.ts +55 -0
  443. package/src/driver/bundler/graph.ts +63 -13
  444. package/src/driver/bundler/merge.ts +4 -1
  445. package/src/driver/compiler.ts +93 -324
  446. package/src/driver/config.ts +11 -0
  447. package/src/driver/frontend.ts +120 -0
  448. package/src/driver/index.ts +0 -1
  449. package/src/driver/options.ts +70 -0
  450. package/src/driver/runtime-objects.ts +133 -0
  451. package/src/driver/toolchain-provider.ts +4 -0
  452. package/src/driver/toolchain.ts +154 -10
  453. package/src/driver/version.ts +12 -0
  454. package/src/driver/win-icon.ts +36 -36
  455. package/src/parser/declarations/classes.ts +4 -0
  456. package/src/parser/declarations/functions.ts +12 -1
  457. package/src/parser/modules.ts +8 -4
  458. package/src/parser/parser.ts +28 -0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * xbintsc runtime — stackful generators.
2
+ * xbintsc runtime — stackful generators and async generators.
3
3
  *
4
4
  * A generator function object carries `is_generator`. Calling it does not run
5
5
  * the body; it creates an `xt_generator` that owns a private stack. `.next()`
@@ -8,27 +8,30 @@
8
8
  * `finally` and nested loops work across suspension points without a state
9
9
  * machine transform.
10
10
  *
11
- * POSIX uses `ucontext` (`swapcontext`); Windows uses fibers. The generator's
12
- * exception stack is swapped alongside it so a `throw` inside the body still
13
- * targets the body's own `try` frames.
11
+ * An `async function*` uses the same coroutine, but every `.next()` /
12
+ * `.throw()` / `.return()` returns a promise. The body may also suspend at an
13
+ * `await`: `xt_generator_await` parks the coroutine on the awaited promise and
14
+ * leaves the current `.next()` promise pending until the body yields or
15
+ * completes. This is what makes `for await...of` work without a state machine.
16
+ *
17
+ * The private stack and the context switch come from `xt_coroutine.c`, which
18
+ * `async` functions use as well. The generator's exception stack is swapped
19
+ * alongside it so a `throw` inside the body still targets the body's own
20
+ * `try` frames.
14
21
  */
15
22
 
16
- #define _XOPEN_SOURCE 700
17
-
18
23
  #include "rt_internal.h"
19
24
 
20
25
  #include <stdlib.h>
21
26
  #include <string.h>
22
27
 
23
- #if defined(__APPLE__)
24
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
25
- #endif
26
-
27
- #ifdef _WIN32
28
- #include <windows.h>
29
- #else
30
- #include <ucontext.h>
31
- #endif
28
+ /* One queued async-generator request. Requests are processed in call order, so
29
+ * two `.next()` calls before the body yields do not overwrite each other. */
30
+ typedef struct {
31
+ xt_value promise;
32
+ xt_value sent;
33
+ int kind; /* 0 = next, 1 = throw, 2 = return */
34
+ } xt_async_request;
32
35
 
33
36
  typedef struct xt_generator {
34
37
  xt_header header;
@@ -44,41 +47,43 @@ typedef struct xt_generator {
44
47
  int started;
45
48
  int done;
46
49
  int threw;
47
- int booted;
48
- /* Private stack bounds, registered as an active stack region while the
49
- * generator runs and scanned conservatively while it is suspended. */
50
- char *stack;
51
- size_t stack_size;
52
- int stack_pushed;
53
- void *saved_try_top;
54
- #ifdef _WIN32
55
- void *fiber;
56
- void *caller_fiber;
57
- /* `SwitchToFiber` keeps the resumer's callee-saved registers in an opaque
58
- * fiber context (POSIX stores them in `caller`), so snapshot them for the
59
- * collector before switching away. */
60
- jmp_buf caller_regs;
61
- int has_caller_regs;
62
- #else
63
- ucontext_t ctx;
64
- ucontext_t caller;
65
- #endif
50
+ /* Async-generator state. `pending_promise` belongs to the request currently
51
+ * executing; `requests` holds calls made while it is pending. */
52
+ int is_async;
53
+ xt_value pending_promise;
54
+ xt_value resume_value;
55
+ int await_threw;
56
+ xt_async_request *requests;
57
+ uint32_t request_count;
58
+ uint32_t request_capacity;
59
+ /* Private stack, context switch and GC region bookkeeping live in
60
+ * xt_coroutine.c; `NULL` once the body has finished. */
61
+ xt_coroutine *coroutine;
66
62
  } xt_generator;
67
63
 
64
+ /* Resolved async iterator for a *synchronous* iterable (`for await` over an
65
+ * array). The source uses the ordinary index protocol; each step is wrapped in
66
+ * an already-settled promise. */
67
+ typedef struct {
68
+ xt_header header;
69
+ xt_value iterator;
70
+ xt_value index;
71
+ int done;
72
+ } xt_async_iterator_state;
73
+
68
74
  /* The generator whose coroutine is running, if any. */
69
75
  static xt_generator *g_active_generator = NULL;
70
- /* Filled in just before a coroutine is first entered (POSIX has no portable
71
- * way to pass a pointer to `makecontext`). */
72
- static xt_generator *g_boot_generator = NULL;
73
- #ifdef _WIN32
74
- static void *g_main_fiber = NULL;
75
- #endif
76
76
 
77
77
  int xt_is_generator(xt_value value) {
78
78
  if (!XT_IS_OBJECT(value)) return 0;
79
79
  return ((xt_header *)XT_GET_PTR(value))->kind == XT_OBJECT_KIND_GENERATOR;
80
80
  }
81
81
 
82
+ int xt_is_async_generator(xt_value value) {
83
+ if (!xt_is_generator(value)) return 0;
84
+ return ((xt_generator *)XT_GET_PTR(value))->is_async;
85
+ }
86
+
82
87
  static xt_generator *xt_as_generator(xt_value value) {
83
88
  if (!xt_is_generator(value)) return NULL;
84
89
  return (xt_generator *)XT_GET_PTR(value);
@@ -91,38 +96,13 @@ static xt_value xt_generator_result_object(xt_value value, int done) {
91
96
  return result;
92
97
  }
93
98
 
94
- static void xt_generator_suspend(xt_generator *gen) {
95
- gen->saved_try_top = xt_try_mark();
96
- #ifdef _WIN32
97
- SwitchToFiber(gen->caller_fiber);
98
- #else
99
- swapcontext(&gen->ctx, &gen->caller);
100
- #endif
99
+ static xt_value xt_generator_done_promise(xt_value value) {
100
+ return xt_promise_resolve(xt_generator_result_object(value, 1));
101
101
  }
102
102
 
103
103
  /* Runs on the generator's private stack. */
104
- static void xt_generator_run(xt_generator *gen) {
105
- #ifdef _WIN32
106
- /* The fiber stack is not observable from the outside; capture its bounds
107
- * here (before the body allocates anything) so a collection during the body
108
- * has a valid scan region. */
109
- if (!gen->stack) {
110
- MEMORY_BASIC_INFORMATION info;
111
- uintptr_t here = (uintptr_t)&info;
112
- if (VirtualQuery((LPCVOID)here, &info, sizeof(info))) {
113
- /* Use the *committed* region containing the current frame: a Windows
114
- * stack reserves more than it commits, and `AllocationBase + RegionSize`
115
- * can fall in uncommitted memory. `BaseAddress + RegionSize` is the
116
- * stack top. */
117
- gen->stack = (char *)info.BaseAddress;
118
- gen->stack_size = info.RegionSize;
119
- }
120
- }
121
- #endif
122
- if (gen->stack && gen->stack_size && !gen->stack_pushed) {
123
- xt_gc_push_stack((uintptr_t)gen->stack, (uintptr_t)gen->stack + gen->stack_size);
124
- gen->stack_pushed = 1;
125
- }
104
+ static void xt_generator_run(void *arg) {
105
+ xt_generator *gen = (xt_generator *)arg;
126
106
  void *boundary = xt_try_enter();
127
107
  if (xt_try_setjmp(boundary) == 0) {
128
108
  xt_function *function = (xt_function *)XT_GET_PTR(gen->function);
@@ -133,92 +113,105 @@ static void xt_generator_run(xt_generator *gen) {
133
113
  gen->threw = 1;
134
114
  }
135
115
  gen->done = 1;
136
- xt_generator_suspend(gen);
116
+ xt_coroutine_leave(gen->coroutine);
137
117
  }
138
118
 
139
- #ifndef _WIN32
140
- static void xt_generator_entry(void) {
141
- xt_generator *gen = g_boot_generator;
142
- g_boot_generator = NULL;
143
- xt_generator_run(gen);
119
+ /* Release the private stack once the coroutine has finished. The generator
120
+ * object itself stays valid; later `.next()` calls just report `done`. */
121
+ static void xt_generator_dispose(xt_generator *gen) {
122
+ xt_coroutine_release(gen->coroutine);
123
+ gen->coroutine = NULL;
144
124
  }
145
- #else
146
- static void CALLBACK xt_generator_entry(void *param) {
147
- xt_generator_run((xt_generator *)param);
125
+
126
+ static void xt_generator_boot(xt_generator *gen);
127
+
128
+ /* Enter the coroutine. Returns with the coroutine suspended (yield/await) or
129
+ * finished. */
130
+ static void xt_generator_enter(xt_generator *gen) {
131
+ if (!gen->coroutine) xt_generator_boot(gen);
132
+ xt_generator *previous = g_active_generator;
133
+ g_active_generator = gen;
134
+ xt_coroutine_enter(gen->coroutine);
135
+ if (gen->done) xt_generator_dispose(gen);
136
+ g_active_generator = previous;
148
137
  }
149
- #endif
150
138
 
151
- static void xt_generator_boot(xt_generator *gen) {
152
- #ifdef _WIN32
153
- if (!g_main_fiber) g_main_fiber = ConvertThreadToFiber(NULL);
154
- gen->fiber = CreateFiber(1 << 20, xt_generator_entry, gen);
155
- if (!gen->fiber) abort();
156
- #else
157
- size_t size = 1 << 20;
158
- gen->stack = (char *)malloc(size);
159
- if (!gen->stack) abort();
160
- gen->stack_size = size;
161
- if (getcontext(&gen->ctx) != 0) abort();
162
- gen->ctx.uc_stack.ss_sp = gen->stack;
163
- gen->ctx.uc_stack.ss_size = size;
164
- gen->ctx.uc_link = NULL;
165
- g_boot_generator = gen;
166
- makecontext(&gen->ctx, xt_generator_entry, 0);
167
- #endif
168
- gen->booted = 1;
139
+ /* Settle the promise of the request that just finished. */
140
+ static void xt_generator_settle_pending(xt_generator *gen) {
141
+ if (!gen->is_async || gen->pending_promise == XT_UNDEFINED) return;
142
+ xt_value promise = gen->pending_promise;
143
+ gen->pending_promise = XT_UNDEFINED;
144
+ if (gen->threw) xt_promise_reject_value(promise, gen->result);
145
+ else xt_promise_fulfill(promise, xt_generator_result_object(gen->result, 1));
169
146
  }
170
147
 
171
- /* Release the private stack once the coroutine has finished. The generator
172
- * object itself stays valid; later `.next()` calls just report `done`. */
173
- static void xt_generator_dispose(xt_generator *gen) {
174
- #ifdef _WIN32
175
- if (gen->fiber) {
176
- DeleteFiber(gen->fiber);
177
- gen->fiber = NULL;
148
+ static xt_value xt_async_enqueue(xt_generator *gen, xt_value sent, int kind);
149
+
150
+ static void xt_generator_start_next(xt_generator *gen) {
151
+ if (gen->request_count == 0) return;
152
+ xt_async_request request = gen->requests[0];
153
+ for (uint32_t i = 1; i < gen->request_count; i++) gen->requests[i - 1] = gen->requests[i];
154
+ gen->request_count--;
155
+ gen->pending_promise = request.promise;
156
+ gen->sent = request.sent;
157
+ gen->resume_kind = request.kind;
158
+
159
+ if (gen->done) {
160
+ if (request.kind == 1) xt_promise_reject_value(request.promise, request.sent);
161
+ else xt_promise_fulfill(request.promise, xt_generator_result_object(request.sent, 1));
162
+ gen->pending_promise = XT_UNDEFINED;
163
+ return;
178
164
  }
179
- gen->caller_fiber = NULL;
180
- /* `DeleteFiber` releases the stack: never scan it again. */
181
- gen->stack = NULL;
182
- gen->stack_size = 0;
183
- #else
184
- if (gen->stack) {
185
- free(gen->stack);
186
- gen->stack = NULL;
165
+ /* A `.throw()` before the body starts rejects the request; a `.return()`
166
+ * before it starts completes the generator without running the body. */
167
+ if (!gen->started) {
168
+ if (request.kind == 1) {
169
+ gen->done = 1;
170
+ gen->threw = 1;
171
+ gen->result = request.sent;
172
+ xt_promise_reject_value(request.promise, request.sent);
173
+ gen->pending_promise = XT_UNDEFINED;
174
+ return;
175
+ }
176
+ if (request.kind == 2) {
177
+ gen->done = 1;
178
+ gen->threw = 0;
179
+ gen->result = request.sent;
180
+ xt_promise_fulfill(request.promise, xt_generator_result_object(request.sent, 1));
181
+ gen->pending_promise = XT_UNDEFINED;
182
+ return;
183
+ }
187
184
  }
188
- #endif
185
+ gen->started = 1;
186
+ xt_generator_enter(gen);
187
+ if (gen->done) xt_generator_settle_pending(gen);
189
188
  }
190
189
 
191
- static void xt_generator_resume(xt_generator *gen) {
192
- if (!gen->booted) xt_generator_boot(gen);
193
- xt_generator *previous = g_active_generator;
194
- g_active_generator = gen;
195
- /* Record where the current (calling) stack suspends before switching away.
196
- * On Windows the first push happens inside the fiber once its stack bounds
197
- * are known, so the caller's region must be marked suspended here, on the
198
- * caller's own stack. */
199
- xt_gc_suspend((uintptr_t)&gen);
200
- if (gen->stack && gen->stack_size && !gen->stack_pushed) {
201
- xt_gc_push_stack((uintptr_t)gen->stack, (uintptr_t)gen->stack + gen->stack_size);
202
- gen->stack_pushed = 1;
190
+ /* Drain queued requests whose predecessor has already finished. */
191
+ static void xt_generator_drain_requests(xt_generator *gen) {
192
+ while (gen->pending_promise == XT_UNDEFINED && gen->request_count > 0) {
193
+ xt_generator_start_next(gen);
203
194
  }
204
- void *caller_try = xt_try_mark();
205
- xt_try_restore(gen->saved_try_top);
206
- #ifdef _WIN32
207
- _setjmp(gen->caller_regs);
208
- gen->has_caller_regs = 1;
209
- gen->caller_fiber = GetCurrentFiber();
210
- SwitchToFiber(gen->fiber);
211
- #else
212
- swapcontext(&gen->caller, &gen->ctx);
213
- #endif
214
- gen->saved_try_top = xt_try_mark();
215
- xt_try_restore(caller_try);
216
- if (gen->stack_pushed) {
217
- xt_gc_pop_stack();
218
- gen->stack_pushed = 0;
195
+ }
196
+
197
+ static xt_value xt_async_enqueue(xt_generator *gen, xt_value sent, int kind) {
198
+ if (gen->done) {
199
+ if (kind == 1) return xt_promise_reject(sent);
200
+ return xt_generator_done_promise(kind == 2 ? sent : XT_UNDEFINED);
219
201
  }
220
- if (gen->done) xt_generator_dispose(gen);
221
- g_active_generator = previous;
202
+ xt_value promise = xt_promise_create();
203
+ if (gen->request_count >= gen->request_capacity) {
204
+ uint32_t capacity = gen->request_capacity == 0 ? 4 : gen->request_capacity * 2;
205
+ gen->requests = (xt_async_request *)realloc(gen->requests, sizeof(xt_async_request) * capacity);
206
+ if (!gen->requests) abort();
207
+ gen->request_capacity = capacity;
208
+ }
209
+ gen->requests[gen->request_count].promise = promise;
210
+ gen->requests[gen->request_count].sent = sent;
211
+ gen->requests[gen->request_count].kind = kind;
212
+ gen->request_count++;
213
+ if (gen->pending_promise == XT_UNDEFINED) xt_generator_drain_requests(gen);
214
+ return promise;
222
215
  }
223
216
 
224
217
  /* The active generator is only reachable through this static pointer, and its
@@ -237,42 +230,57 @@ static void xt_generator_gc_register(void) {
237
230
 
238
231
  void xt_generator_gc_trace(xt_header *header) {
239
232
  xt_generator *gen = (xt_generator *)header;
240
- size_t payload = header->size > sizeof(xt_header) ? header->size - sizeof(xt_header) : 0;
241
- xt_gc_scan_region((const char *)header + sizeof(xt_header), payload);
233
+ xt_gc_mark_value(gen->function);
234
+ xt_gc_mark_value(gen->this_value);
235
+ xt_gc_mark_value(gen->sent);
236
+ xt_gc_mark_value(gen->result);
237
+ xt_gc_mark_value(gen->iter_value);
238
+ xt_gc_mark_value(gen->pending_promise);
239
+ xt_gc_mark_value(gen->resume_value);
242
240
  if (gen->args && gen->argc > 0) {
243
241
  xt_gc_scan_region(gen->args, sizeof(xt_value) * (size_t)gen->argc);
244
242
  }
245
- if (gen->stack && gen->stack_size) xt_gc_scan_region(gen->stack, gen->stack_size);
246
- #ifndef _WIN32
247
- /* Registers saved by `swapcontext` at the last yield are not on the stack. */
248
- xt_gc_scan_region(&gen->ctx, sizeof(gen->ctx));
249
- #else
250
- if (gen->has_caller_regs) xt_gc_scan_region(&gen->caller_regs, sizeof(gen->caller_regs));
251
- #endif
243
+ for (uint32_t i = 0; i < gen->request_count; i++) {
244
+ xt_gc_mark_value(gen->requests[i].promise);
245
+ xt_gc_mark_value(gen->requests[i].sent);
246
+ }
247
+ xt_coroutine_gc_trace(gen->coroutine);
252
248
  }
253
249
 
254
250
  void xt_generator_gc_release(xt_header *header) {
255
251
  xt_generator *gen = (xt_generator *)header;
256
252
  free(gen->args);
257
- #ifdef _WIN32
258
- if (gen->fiber) DeleteFiber(gen->fiber);
259
- #else
260
- free(gen->stack);
261
- #endif
253
+ free(gen->requests);
254
+ xt_coroutine_release(gen->coroutine);
255
+ gen->coroutine = NULL;
256
+ }
257
+
258
+ static void xt_generator_boot(xt_generator *gen) {
259
+ gen->coroutine = xt_coroutine_create(xt_generator_run, gen);
262
260
  }
263
261
 
264
262
  xt_value xt_generator_new(xt_value function, xt_value thisValue, int32_t argc, xt_value *argv) {
265
263
  xt_generator *gen = (xt_generator *)xt_alloc(sizeof(xt_generator), XT_OBJECT_KIND_GENERATOR);
264
+ xt_function *fn = (xt_function *)XT_GET_PTR(function);
266
265
  gen->function = function;
267
266
  gen->this_value = thisValue;
268
267
  gen->argc = argc;
269
268
  gen->args = NULL;
270
- gen->stack = NULL;
271
- gen->stack_size = 0;
272
- gen->stack_pushed = 0;
269
+ gen->coroutine = NULL;
273
270
  gen->result = XT_UNDEFINED;
274
271
  gen->sent = XT_UNDEFINED;
275
272
  gen->iter_value = XT_UNDEFINED;
273
+ gen->resume_kind = 0;
274
+ gen->started = 0;
275
+ gen->done = 0;
276
+ gen->threw = 0;
277
+ gen->is_async = fn->is_async_generator;
278
+ gen->pending_promise = XT_UNDEFINED;
279
+ gen->resume_value = XT_UNDEFINED;
280
+ gen->await_threw = 0;
281
+ gen->requests = NULL;
282
+ gen->request_count = 0;
283
+ gen->request_capacity = 0;
276
284
  if (argc > 0 && argv) {
277
285
  gen->args = (xt_value *)malloc(sizeof(xt_value) * (size_t)argc);
278
286
  if (!gen->args) abort();
@@ -285,13 +293,15 @@ xt_value xt_generator_new(xt_value function, xt_value thisValue, int32_t argc, x
285
293
  xt_value xt_generator_next(xt_value generator, xt_value sent) {
286
294
  xt_generator *gen = xt_as_generator(generator);
287
295
  if (!gen) {
288
- xt_throw(xt_string_from_cstr("TypeError: not a generator"));
296
+ xt_throw(xt_error_from_message("TypeError: not a generator"));
289
297
  return XT_UNDEFINED;
290
298
  }
299
+ if (gen->is_async) return xt_async_enqueue(gen, sent, 0);
291
300
  if (gen->done) return xt_generator_result_object(XT_UNDEFINED, 1);
292
301
  gen->sent = sent;
293
302
  gen->resume_kind = 0;
294
- xt_generator_resume(gen);
303
+ gen->started = 1;
304
+ xt_generator_enter(gen);
295
305
  if (gen->done) {
296
306
  if (gen->threw) xt_throw(gen->result);
297
307
  return xt_generator_result_object(gen->result, 1);
@@ -302,16 +312,18 @@ xt_value xt_generator_next(xt_value generator, xt_value sent) {
302
312
  xt_value xt_generator_throw(xt_value generator, xt_value error) {
303
313
  xt_generator *gen = xt_as_generator(generator);
304
314
  if (!gen) {
305
- xt_throw(xt_string_from_cstr("TypeError: not a generator"));
315
+ xt_throw(xt_error_from_message("TypeError: not a generator"));
306
316
  return XT_UNDEFINED;
307
317
  }
318
+ if (gen->is_async) return xt_async_enqueue(gen, error, 1);
308
319
  if (gen->done) {
309
320
  xt_throw(error);
310
321
  return XT_UNDEFINED;
311
322
  }
312
323
  gen->sent = error;
313
324
  gen->resume_kind = 1;
314
- xt_generator_resume(gen);
325
+ gen->started = 1;
326
+ xt_generator_enter(gen);
315
327
  if (gen->done) {
316
328
  if (gen->threw) xt_throw(gen->result);
317
329
  return xt_generator_result_object(gen->result, 1);
@@ -322,9 +334,10 @@ xt_value xt_generator_throw(xt_value generator, xt_value error) {
322
334
  xt_value xt_generator_return(xt_value generator, xt_value value) {
323
335
  xt_generator *gen = xt_as_generator(generator);
324
336
  if (!gen) {
325
- xt_throw(xt_string_from_cstr("TypeError: not a generator"));
337
+ xt_throw(xt_error_from_message("TypeError: not a generator"));
326
338
  return XT_UNDEFINED;
327
339
  }
340
+ if (gen->is_async) return xt_async_enqueue(gen, value, 2);
328
341
  /* Abandon the coroutine without resuming: finally blocks are not run. */
329
342
  gen->done = 1;
330
343
  gen->threw = 0;
@@ -339,21 +352,84 @@ xt_value xt_yield(xt_value value) {
339
352
  xt_generator *gen = g_active_generator;
340
353
  if (!gen || gen->done) return XT_UNDEFINED;
341
354
  gen->result = value;
342
- xt_generator_suspend(gen);
355
+ /* Settle the async `.next()` request that produced this yield. A pending
356
+ * `.throw(e)` must *not* settle it: if the body catches the error it may
357
+ * yield again, and only that next yield (or the escaped exception) settles
358
+ * the request. */
359
+ if (gen->is_async && gen->resume_kind != 1 && gen->pending_promise != XT_UNDEFINED) {
360
+ xt_value promise = gen->pending_promise;
361
+ gen->pending_promise = XT_UNDEFINED;
362
+ xt_promise_fulfill(promise, xt_generator_result_object(value, gen->resume_kind == 2));
363
+ }
364
+ /* The resume kind may change while suspended: control returns here only
365
+ * when the next `.next()` / `.throw()` / `.return()` resumes the coroutine,
366
+ * so the checks below must sit after the context switch. */
367
+ xt_coroutine_leave(gen->coroutine);
343
368
  if (gen->resume_kind == 1) {
369
+ gen->resume_kind = 0;
344
370
  xt_throw(gen->sent);
345
371
  return XT_UNDEFINED;
346
372
  }
347
373
  if (gen->resume_kind == 2) {
374
+ gen->resume_kind = 0;
348
375
  gen->done = 1;
349
376
  gen->threw = 0;
350
377
  gen->result = gen->sent;
351
- xt_generator_suspend(gen);
378
+ if (gen->is_async && gen->pending_promise != XT_UNDEFINED) {
379
+ xt_value promise = gen->pending_promise;
380
+ gen->pending_promise = XT_UNDEFINED;
381
+ xt_promise_fulfill(promise, xt_generator_result_object(gen->sent, 1));
382
+ }
383
+ xt_coroutine_leave(gen->coroutine);
352
384
  return XT_UNDEFINED;
353
385
  }
354
386
  return gen->sent;
355
387
  }
356
388
 
389
+ /* `await value` inside an async generator. The generator's current `.next()`
390
+ * promise stays pending; when the awaited promise settles the coroutine is
391
+ * resumed and this function returns the settlement (or throws a rejection). */
392
+ int xt_generator_await(xt_value value, xt_value *result) {
393
+ xt_generator *gen = g_active_generator;
394
+ if (!gen || !gen->is_async || gen->done || !gen->coroutine) return 0;
395
+ /* A nested async function inside the generator runs on its own coroutine;
396
+ * its awaits must not suspend the generator. */
397
+ if (!xt_coroutine_is_current(gen->coroutine)) return 0;
398
+ int state = xt_promise_state_of(value);
399
+ if (state == XT_PROMISE_PENDING) {
400
+ gen->await_threw = 0;
401
+ gen->resume_value = XT_UNDEFINED;
402
+ xt_promise_add_async_waiter(value, gen);
403
+ xt_coroutine_leave(gen->coroutine);
404
+ } else {
405
+ int rejected = state == XT_PROMISE_REJECTED;
406
+ xt_value settled = (state == XT_PROMISE_FULFILLED || rejected)
407
+ ? xt_promise_value_of(value)
408
+ : value;
409
+ gen->await_threw = rejected;
410
+ gen->resume_value = settled;
411
+ xt_promise_queue_async_wake(gen, settled, rejected);
412
+ xt_coroutine_leave(gen->coroutine);
413
+ }
414
+ if (gen->await_threw) {
415
+ gen->await_threw = 0;
416
+ xt_throw(gen->resume_value);
417
+ return 1;
418
+ }
419
+ *result = gen->resume_value;
420
+ return 1;
421
+ }
422
+
423
+ void xt_generator_wake(void *pointer, xt_value value, int rejected) {
424
+ xt_generator *gen = (xt_generator *)pointer;
425
+ if (!gen || gen->done || !gen->coroutine) return;
426
+ gen->resume_value = value;
427
+ gen->await_threw = rejected;
428
+ xt_generator_enter(gen);
429
+ if (gen->done) xt_generator_settle_pending(gen);
430
+ else xt_generator_drain_requests(gen);
431
+ }
432
+
357
433
  /* `yield* delegate`: relay every value the delegate produces. */
358
434
  xt_value xt_yield_star(xt_value delegate) {
359
435
  xt_value nextName = xt_string_from_cstr("next");
@@ -385,7 +461,7 @@ xt_value xt_yield_star(xt_value delegate) {
385
461
  /* `for...of` step for generators: pull and cache the next value. */
386
462
  int xt_generator_has_next(xt_value generator) {
387
463
  xt_generator *gen = xt_as_generator(generator);
388
- if (!gen || gen->done) return 0;
464
+ if (!gen || gen->done || gen->is_async) return 0;
389
465
  xt_value step = xt_generator_next(generator, XT_UNDEFINED);
390
466
  if (xt_truthy(xt_get(step, xt_string_from_cstr("done")))) return 0;
391
467
  gen->iter_value = xt_get(step, xt_string_from_cstr("value"));
@@ -396,3 +472,85 @@ xt_value xt_generator_iter_value(xt_value generator) {
396
472
  xt_generator *gen = xt_as_generator(generator);
397
473
  return gen ? gen->iter_value : XT_UNDEFINED;
398
474
  }
475
+
476
+ xt_value xt_function_set_generator(xt_value value) {
477
+ if (XT_IS_FUNCTION(value)) ((xt_function *)XT_GET_PTR(value))->is_generator = 1;
478
+ return value;
479
+ }
480
+
481
+ xt_value xt_function_set_async_generator(xt_value value) {
482
+ if (XT_IS_FUNCTION(value)) {
483
+ xt_function *function = (xt_function *)XT_GET_PTR(value);
484
+ function->is_generator = 1;
485
+ function->is_async_generator = 1;
486
+ }
487
+ return value;
488
+ }
489
+
490
+ /* -- async iteration ------------------------------------------------------ */
491
+
492
+ static xt_value xt_async_iterator_self(xt_value thisValue, xt_value env, int32_t argc,
493
+ xt_value *argv) {
494
+ (void)env;
495
+ (void)argc;
496
+ (void)argv;
497
+ return thisValue;
498
+ }
499
+
500
+ xt_value xt_async_iterator_method(void) {
501
+ static xt_value method = XT_UNDEFINED;
502
+ if (!XT_IS_FUNCTION(method)) {
503
+ method = xt_closure_new((void *)xt_async_iterator_self, 0, NULL);
504
+ xt_gc_add_root(&method);
505
+ }
506
+ return method;
507
+ }
508
+
509
+ xt_value xt_async_iter_open(xt_value value) {
510
+ if (xt_is_async_generator(value)) return value;
511
+ /* A user object may implement `[Symbol.asyncIterator]()`. */
512
+ if (XT_IS_OBJECT(value) || XT_IS_ARRAY(value) || XT_IS_FUNCTION(value)) {
513
+ xt_value method = xt_get(value, xt_symbol_well_known("asyncIterator"));
514
+ if (XT_IS_FUNCTION(method)) {
515
+ xt_value iterator = xt_call_with_this(method, value, 0, NULL);
516
+ if (XT_IS_OBJECT(iterator) || XT_IS_FUNCTION(iterator)) return iterator;
517
+ }
518
+ }
519
+ /* Fall back to the synchronous protocol and adapt each step. */
520
+ xt_async_iterator_state *state =
521
+ (xt_async_iterator_state *)xt_alloc(sizeof(xt_async_iterator_state),
522
+ XT_OBJECT_KIND_ASYNC_ITERATOR);
523
+ state->iterator = xt_iter_open(value);
524
+ state->index = xt_number(0);
525
+ state->done = 0;
526
+ return XT_FROM_PTR(XT_TAG_OBJECT, state);
527
+ }
528
+
529
+ static int xt_is_async_iterator_state(xt_value value) {
530
+ return XT_IS_OBJECT(value) &&
531
+ ((xt_header *)XT_GET_PTR(value))->kind == XT_OBJECT_KIND_ASYNC_ITERATOR;
532
+ }
533
+
534
+ xt_value xt_async_iter_next(xt_value iterator) {
535
+ if (xt_is_async_generator(iterator)) return xt_generator_next(iterator, XT_UNDEFINED);
536
+ if (xt_is_async_iterator_state(iterator)) {
537
+ xt_async_iterator_state *state = (xt_async_iterator_state *)XT_GET_PTR(iterator);
538
+ if (state->done) return xt_promise_resolve(xt_generator_result_object(XT_UNDEFINED, 1));
539
+ if (!xt_truthy(xt_iter_has(state->iterator, state->index))) {
540
+ state->done = 1;
541
+ return xt_promise_resolve(xt_generator_result_object(XT_UNDEFINED, 1));
542
+ }
543
+ xt_value value = xt_iter_value(state->iterator, state->index);
544
+ state->index = xt_add(state->index, xt_number(1));
545
+ return xt_promise_resolve(xt_generator_result_object(value, 0));
546
+ }
547
+ xt_value step = xt_call_method(iterator, xt_string_from_cstr("next"), 0, NULL);
548
+ if (xt_promise_state_of(step) >= 0) return step;
549
+ return xt_promise_resolve(step);
550
+ }
551
+
552
+ void xt_async_iterator_gc_trace(xt_header *header) {
553
+ xt_async_iterator_state *state = (xt_async_iterator_state *)header;
554
+ xt_gc_mark_value(state->iterator);
555
+ xt_gc_mark_value(state->index);
556
+ }