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
@@ -26,6 +26,8 @@ static xt_value xt_error_proto_for(const char *name) {
26
26
  xt_string_from_cstr("Error"));
27
27
  xt_object_set(xt_error_root_proto, xt_string_from_cstr("message"),
28
28
  xt_string_from_cstr(""));
29
+ xt_value constructor = xt_error_constructor(xt_string_from_cstr("Error"));
30
+ xt_object_set(xt_error_root_proto, xt_string_from_cstr("constructor"), constructor);
29
31
  }
30
32
  if (strcmp(name, "Error") == 0) return xt_error_root_proto;
31
33
  xt_value key = xt_string_from_cstr(name);
@@ -41,6 +43,8 @@ static xt_value xt_error_proto_for(const char *name) {
41
43
  xt_object_set(proto, xt_string_from_cstr("name"), key);
42
44
  xt_object_set(proto, xt_string_from_cstr("message"), xt_string_from_cstr(""));
43
45
  xt_object_set(registry, key, proto);
46
+ xt_value constructor = xt_error_constructor(key);
47
+ xt_object_set(proto, xt_string_from_cstr("constructor"), constructor);
44
48
  return proto;
45
49
  }
46
50
 
@@ -108,6 +112,30 @@ xt_value xt_error_constructor(xt_value nameValue) {
108
112
  return closure;
109
113
  }
110
114
 
115
+ /* Build the value thrown by the runtime for an internal "Name: message"
116
+ * string. JavaScript code can observe anything thrown, so internal failures
117
+ * must be real Error instances (`instanceof Error`, `.name`, `.message`,
118
+ * `.stack`), exactly like `new TypeError("...")`; a bare string would make
119
+ * `catch` blocks silently misbehave. User `throw` expressions never go
120
+ * through this helper. */
121
+ xt_value xt_error_from_message(const char *message) {
122
+ const char *separator = strstr(message, ": ");
123
+ if (separator != NULL) {
124
+ size_t nameLength = (size_t)(separator - message);
125
+ char name[24];
126
+ if (nameLength > 0 && nameLength < sizeof(name)) {
127
+ memcpy(name, message, nameLength);
128
+ name[nameLength] = '\0';
129
+ if (xt_error_is_family(name)) {
130
+ xt_value argument = xt_string_from_cstr(separator + 2);
131
+ return xt_make_error(name, 1, &argument);
132
+ }
133
+ }
134
+ }
135
+ xt_value argument = xt_string_from_cstr(message);
136
+ return xt_make_error("Error", 1, &argument);
137
+ }
138
+
111
139
  xt_value xt_error_to_string(xt_value error) {
112
140
  xt_value name = xt_object_get(error, xt_string_from_cstr("name"));
113
141
  xt_value message = xt_object_get(error, xt_string_from_cstr("message"));
@@ -162,6 +190,13 @@ xt_value xt_aggregate_error_ctor(int32_t argc, xt_value *argv) {
162
190
  return xt_make_error("AggregateError", argc, argv);
163
191
  }
164
192
 
193
+ /* Dispatch used by the first-class constructor factory (`const E = TypeError`). */
194
+ xt_value xt_error_ctor_by_name(xt_value nameValue, int32_t argc, xt_value *argv) {
195
+ const char *name = XT_IS_STRING(nameValue) ? xt_string_data(nameValue) : "Error";
196
+ if (!xt_error_is_family(name)) name = "Error";
197
+ return xt_make_error(name, argc, argv);
198
+ }
199
+
165
200
  /* `super(message)` inside a subclass of the builtin Error family: initialize
166
201
  * the already-allocated instance instead of creating a fresh object. The
167
202
  * parent's name selects the default `name` (`TypeError`, ...). */
@@ -36,14 +36,31 @@ static xt_value xt_json_parse_string(xt_json_cursor *c) {
36
36
  else if (h >= 'a' && h <= 'f') code |= (unsigned)(h - 'a' + 10);
37
37
  else if (h >= 'A' && h <= 'F') code |= (unsigned)(h - 'A' + 10);
38
38
  }
39
+ /* A high surrogate followed by `\u` and a low surrogate denotes one
40
+ * supplementary code point, exactly like a JavaScript string. */
41
+ if (code >= 0xD800 && code <= 0xDBFF && c->pos + 5 < c->length &&
42
+ c->data[c->pos] == '\\' && c->data[c->pos + 1] == 'u') {
43
+ unsigned low = 0;
44
+ int valid = 1;
45
+ for (int i = 0; i < 4; i++) {
46
+ char h = c->data[c->pos + 2 + (size_t)i];
47
+ low <<= 4;
48
+ if (h >= '0' && h <= '9') low |= (unsigned)(h - '0');
49
+ else if (h >= 'a' && h <= 'f') low |= (unsigned)(h - 'a' + 10);
50
+ else if (h >= 'A' && h <= 'F') low |= (unsigned)(h - 'A' + 10);
51
+ else valid = 0;
52
+ }
53
+ if (valid && low >= 0xDC00 && low <= 0xDFFF) {
54
+ code = 0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
55
+ c->pos += 6;
56
+ }
57
+ }
39
58
  if (code >= 0x80) {
40
59
  char tmp[4];
41
- int bytes = 0;
42
- if (code < 0x800) { tmp[bytes++] = (char)(0xC0 | (code >> 6)); tmp[bytes++] = (char)(0x80 | (code & 0x3F)); }
43
- else { tmp[bytes++] = (char)(0xE0 | (code >> 12)); tmp[bytes++] = (char)(0x80 | ((code >> 6) & 0x3F)); tmp[bytes++] = (char)(0x80 | (code & 0x3F)); }
44
- if (length + (size_t)bytes + 1 > capacity) { capacity = (length + (size_t)bytes + 1) * 2; out = (char *)realloc(out, capacity); if (!out) abort(); }
45
- memcpy(out + length, tmp, (size_t)bytes);
46
- length += (size_t)bytes;
60
+ size_t bytes = xt_utf8_encode(code, tmp);
61
+ if (length + bytes + 1 > capacity) { capacity = (length + bytes + 1) * 2; out = (char *)realloc(out, capacity); if (!out) abort(); }
62
+ memcpy(out + length, tmp, bytes);
63
+ length += bytes;
47
64
  continue;
48
65
  }
49
66
  ch = (char)code;
@@ -116,50 +133,152 @@ static xt_value xt_json_parse_value(xt_json_cursor *c) {
116
133
  return xt_json_parse_number(c);
117
134
  }
118
135
 
136
+ /* Reviver walk: rebuild each container bottom-up, then pass the value to the
137
+ * user callback with its holder as `this`. Returning undefined deletes an
138
+ * object property / array element, exactly like the specification. */
139
+ static xt_value xt_json_revive(xt_value holder, xt_value key, xt_value reviver) {
140
+ xt_value value = xt_get(holder, key);
141
+ if (XT_IS_ARRAY(value)) {
142
+ xt_array *array = xt_as_array(value);
143
+ for (uint32_t i = 0; i < array->length; i++) {
144
+ /* Reviver keys are strings even for array indices. */
145
+ char keyBuffer[16];
146
+ snprintf(keyBuffer, sizeof(keyBuffer), "%u", i);
147
+ xt_value index = xt_string_from_cstr(keyBuffer);
148
+ xt_value updated = xt_json_revive(value, index, reviver);
149
+ if (updated == XT_UNDEFINED) xt_delete(value, index);
150
+ else xt_set(value, index, updated);
151
+ }
152
+ } else if (XT_IS_OBJECT(value)) {
153
+ xt_value keys = xt_object_keys(value);
154
+ xt_array *list = xt_as_array(keys);
155
+ if (list) {
156
+ for (uint32_t i = 0; i < list->length; i++) {
157
+ xt_value childKey = list->items[i];
158
+ xt_value updated = xt_json_revive(value, childKey, reviver);
159
+ if (updated == XT_UNDEFINED) xt_delete(value, childKey);
160
+ else xt_object_set(value, childKey, updated);
161
+ }
162
+ }
163
+ }
164
+ xt_value args[2] = {key, value};
165
+ return xt_call_with_this(reviver, holder, 2, args);
166
+ }
167
+
119
168
  xt_value xt_json_parse(int32_t argc, xt_value *argv) {
120
169
  xt_value input = xt_to_string(xt_arg_at(argc, argv, 0));
121
170
  xt_string *s = xt_as_string(input);
122
171
  if (!s) return XT_UNDEFINED;
123
172
  xt_json_cursor cursor = {xt_string_bytes(s), s->length, 0};
124
- return xt_json_parse_value(&cursor);
173
+ xt_value parsed = xt_json_parse_value(&cursor);
174
+ xt_value reviver = xt_arg_at(argc, argv, 1);
175
+ if (!XT_IS_FUNCTION(reviver)) return parsed;
176
+ xt_value holder = xt_object_new();
177
+ xt_object_set(holder, xt_string_from_cstr(""), parsed);
178
+ return xt_json_revive(holder, xt_string_from_cstr(""), reviver);
179
+ }
180
+
181
+ static void xt_json_stringify_value(xt_value value, xt_value indent, int depth, xt_value *out);
182
+
183
+ /* The indentation unit for the `space` argument: up to 10 spaces for a
184
+ * number, or the first 10 UTF-16 code units of a string (any characters,
185
+ * not just spaces), matching JSON.stringify. An empty string means compact. */
186
+ static xt_value xt_json_space_unit(xt_value space) {
187
+ if (XT_IS_NUMBER(space)) {
188
+ int count = xt_to_int32(space);
189
+ if (count < 0) count = 0;
190
+ if (count > 10) count = 10;
191
+ char spaces[10];
192
+ memset(spaces, ' ', (size_t)count);
193
+ return xt_string_new(spaces, (size_t)count);
194
+ }
195
+ if (XT_IS_STRING(space)) {
196
+ xt_string *s = xt_as_string(space);
197
+ const char *bytes = xt_string_bytes(s);
198
+ size_t offset = 0;
199
+ size_t end = 0;
200
+ uint32_t units = 0;
201
+ while (offset < s->length && units < 10) {
202
+ size_t width = 0;
203
+ uint32_t code = xt_utf8_decode(bytes + offset, s->length - offset, &width);
204
+ units += code >= 0x10000 ? 2 : 1;
205
+ offset += width;
206
+ if (units <= 10) end = offset;
207
+ }
208
+ return xt_string_new(bytes, end);
209
+ }
210
+ return xt_string_from_cstr("");
125
211
  }
126
212
 
127
- static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_value *out);
213
+ static int xt_json_indented(xt_value unit) {
214
+ return XT_IS_STRING(unit) && xt_as_string(unit)->length > 0;
215
+ }
128
216
 
129
- static void xt_json_indent(xt_value *out, int indent, int depth) {
130
- if (indent <= 0) return;
217
+ static void xt_json_indent(xt_value *out, xt_value unit, int depth) {
218
+ if (!xt_json_indented(unit)) return;
131
219
  *out = xt_add(*out, xt_string_from_cstr("\n"));
132
- for (int i = 0; i < indent * depth; i++) *out = xt_add(*out, xt_string_from_cstr(" "));
220
+ for (int i = 0; i < depth; i++) *out = xt_add(*out, unit);
133
221
  }
134
222
 
135
- static void xt_json_stringify_array(xt_value value, int indent, int depth, xt_value *out) {
223
+ /* Containers on the current serialization path. A repeated pointer is a cycle;
224
+ * serializing it would recurse until the native stack overflowed (a hard crash,
225
+ * not the TypeError the platform throws). */
226
+ static xt_value *xt_json_path = NULL;
227
+ static uint32_t xt_json_path_count = 0;
228
+ static uint32_t xt_json_path_capacity = 0;
229
+
230
+ static void xt_json_enter(xt_value value) {
231
+ for (uint32_t i = 0; i < xt_json_path_count; i++) {
232
+ if (xt_json_path[i] == value) {
233
+ xt_value message = xt_string_from_cstr("Converting circular structure to JSON");
234
+ xt_throw(xt_type_error_ctor(1, &message));
235
+ }
236
+ }
237
+ if (xt_json_path_count >= xt_json_path_capacity) {
238
+ uint32_t capacity = xt_json_path_capacity == 0 ? 16 : xt_json_path_capacity * 2;
239
+ xt_value *path = (xt_value *)realloc(xt_json_path, sizeof(xt_value) * capacity);
240
+ if (!path) abort();
241
+ xt_json_path = path;
242
+ xt_json_path_capacity = capacity;
243
+ }
244
+ xt_json_path[xt_json_path_count++] = value;
245
+ }
246
+
247
+ static void xt_json_leave(void) {
248
+ if (xt_json_path_count > 0) xt_json_path_count--;
249
+ }
250
+
251
+ static void xt_json_stringify_array(xt_value value, xt_value indent, int depth, xt_value *out) {
136
252
  xt_array *array = xt_as_array(value);
137
253
  if (!array || array->length == 0) { *out = xt_add(*out, xt_string_from_cstr("[]")); return; }
138
254
  *out = xt_add(*out, xt_string_from_cstr("["));
255
+ xt_json_enter(value);
139
256
  for (uint32_t i = 0; i < array->length; i++) {
140
257
  if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
141
258
  xt_json_indent(out, indent, depth + 1);
142
259
  xt_json_stringify_value(array->items[i], indent, depth + 1, out);
143
260
  }
144
261
  xt_json_indent(out, indent, depth);
262
+ xt_json_leave();
145
263
  *out = xt_add(*out, xt_string_from_cstr("]"));
146
264
  }
147
265
 
148
- static void xt_json_stringify_object(xt_value value, int indent, int depth, xt_value *out) {
266
+ static void xt_json_stringify_object(xt_value value, xt_value indent, int depth, xt_value *out) {
149
267
  xt_value keys = xt_object_keys(value);
150
268
  xt_array *array = xt_as_array(keys);
151
269
  if (!array) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
152
270
  int any = 0;
153
271
  for (uint32_t i = 0; i < array->length; i++) {
154
- xt_value item = xt_object_get(value, array->items[i]);
272
+ xt_value item = xt_get(value, array->items[i]);
155
273
  if (item != XT_UNDEFINED && !XT_IS_FUNCTION(item) && !xt_is_symbol(item)) { any = 1; break; }
156
274
  }
157
275
  if (!any) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
158
276
  *out = xt_add(*out, xt_string_from_cstr("{"));
277
+ xt_json_enter(value);
159
278
  int written = 0;
160
279
  for (uint32_t i = 0; i < array->length; i++) {
161
280
  xt_value key = array->items[i];
162
- xt_value item = xt_object_get(value, key);
281
+ xt_value item = xt_get(value, key);
163
282
  /* `undefined`, functions and symbols are omitted from objects. */
164
283
  if (item == XT_UNDEFINED || XT_IS_FUNCTION(item) || xt_is_symbol(item)) continue;
165
284
  if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
@@ -168,20 +287,21 @@ static void xt_json_stringify_object(xt_value value, int indent, int depth, xt_v
168
287
  *out = xt_add(*out, xt_string_from_cstr("\""));
169
288
  *out = xt_add(*out, key);
170
289
  *out = xt_add(*out, xt_string_from_cstr("\":"));
171
- if (indent > 0) *out = xt_add(*out, xt_string_from_cstr(" "));
290
+ if (xt_json_indented(indent)) *out = xt_add(*out, xt_string_from_cstr(" "));
172
291
  xt_json_stringify_value(item, indent, depth + 1, out);
173
292
  }
174
293
  xt_json_indent(out, indent, depth);
294
+ xt_json_leave();
175
295
  *out = xt_add(*out, xt_string_from_cstr("}"));
176
296
  }
177
297
 
178
- static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_value *out) {
298
+ static void xt_json_stringify_value(xt_value value, xt_value indent, int depth, xt_value *out) {
179
299
  if (value == XT_UNDEFINED || value == XT_NULL || XT_IS_FUNCTION(value) || xt_is_symbol(value)) {
180
300
  *out = xt_add(*out, xt_string_from_cstr("null"));
181
301
  return;
182
302
  }
183
303
  if (XT_IS_BIGINT(value)) {
184
- xt_throw(xt_string_from_cstr("TypeError: Do not know how to serialize a BigInt"));
304
+ xt_throw(xt_error_from_message("TypeError: Do not know how to serialize a BigInt"));
185
305
  return;
186
306
  }
187
307
  if (XT_IS_BOOL(value)) { *out = xt_add(*out, value == XT_TRUE ? xt_string_from_cstr("true") : xt_string_from_cstr("false")); return; }
@@ -195,32 +315,232 @@ static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_va
195
315
  xt_string *s = xt_as_string(value);
196
316
  const char *bytes = xt_string_bytes(s);
197
317
  *out = xt_add(*out, xt_string_from_cstr("\""));
198
- for (uint32_t i = 0; i < s->length; i++) {
199
- char ch = bytes[i];
200
- if (ch == '"') *out = xt_add(*out, xt_string_from_cstr("\\\""));
201
- else if (ch == '\\') *out = xt_add(*out, xt_string_from_cstr("\\\\"));
202
- else if (ch == '\n') *out = xt_add(*out, xt_string_from_cstr("\\n"));
203
- else if (ch == '\r') *out = xt_add(*out, xt_string_from_cstr("\\r"));
204
- else if (ch == '\t') *out = xt_add(*out, xt_string_from_cstr("\\t"));
205
- else *out = xt_add(*out, xt_string_new(&ch, 1));
318
+ size_t offset = 0;
319
+ while (offset < s->length) {
320
+ size_t width = 0;
321
+ uint32_t code = xt_utf8_decode(bytes + offset, s->length - offset, &width);
322
+ const char *escape = NULL;
323
+ char buffer[8];
324
+ if (code == '"') escape = "\\\"";
325
+ else if (code == '\\') escape = "\\\\";
326
+ else if (code == '\b') escape = "\\b";
327
+ else if (code == '\f') escape = "\\f";
328
+ else if (code == '\n') escape = "\\n";
329
+ else if (code == '\r') escape = "\\r";
330
+ else if (code == '\t') escape = "\\t";
331
+ else if (code < 0x20 || (code >= 0xD800 && code <= 0xDFFF)) {
332
+ snprintf(buffer, sizeof(buffer), "\\u%04x", (unsigned)code);
333
+ escape = buffer;
334
+ }
335
+ if (escape) *out = xt_add(*out, xt_string_from_cstr(escape));
336
+ else *out = xt_add(*out, xt_string_new(bytes + offset, width));
337
+ offset += width;
206
338
  }
207
339
  *out = xt_add(*out, xt_string_from_cstr("\""));
208
340
  return;
209
341
  }
210
342
  if (XT_IS_ARRAY(value)) { xt_json_stringify_array(value, indent, depth, out); return; }
211
- if (XT_IS_OBJECT(value)) { xt_json_stringify_object(value, indent, depth, out); return; }
343
+ if (XT_IS_OBJECT(value)) {
344
+ /* Map/Set/Date/RegExp/Promise/generators are not property-bag objects;
345
+ * handing them to xt_json_stringify_object reads their fields as a property
346
+ * table and crashed with an access violation. JSON sees no enumerable own
347
+ * properties on the first group and calls Date.prototype.toJSON. */
348
+ xt_object *object = (xt_object *)XT_GET_PTR(value);
349
+ switch (object->header.kind) {
350
+ case XT_OBJECT_KIND_MAP:
351
+ case XT_OBJECT_KIND_SET:
352
+ case XT_OBJECT_KIND_REGEXP:
353
+ case XT_OBJECT_KIND_PROMISE:
354
+ case XT_OBJECT_KIND_GENERATOR:
355
+ case XT_OBJECT_KIND_ITERATOR:
356
+ case XT_OBJECT_KIND_ASYNC:
357
+ *out = xt_add(*out, xt_string_from_cstr("{}"));
358
+ return;
359
+ case XT_OBJECT_KIND_DATE: {
360
+ xt_value time = xt_call_method(value, xt_string_from_cstr("getTime"), 0, NULL);
361
+ if (isnan(xt_to_number(time))) {
362
+ *out = xt_add(*out, xt_string_from_cstr("null"));
363
+ return;
364
+ }
365
+ xt_value text = xt_call_method(value, xt_string_from_cstr("toJSON"), 0, NULL);
366
+ xt_json_stringify_value(text, indent, depth, out);
367
+ return;
368
+ }
369
+ default:
370
+ break;
371
+ }
372
+ xt_json_stringify_object(value, indent, depth, out);
373
+ return;
374
+ }
212
375
  *out = xt_add(*out, xt_string_from_cstr("null"));
213
376
  }
214
377
 
378
+ /* -- replacer-aware stringify -------------------------------------------- */
379
+ /*
380
+ * The replacer overload needs the holder and key of every value, so it gets a
381
+ * separate walk instead of complicating the fast path. It also calls `toJSON`
382
+ * and filters object keys through an array replacer.
383
+ */
384
+ typedef struct {
385
+ xt_value replacer;
386
+ xt_value indent;
387
+ xt_value *path;
388
+ uint32_t path_count;
389
+ uint32_t path_capacity;
390
+ } xt_json_replacer_context;
391
+
392
+ static void xt_json_replacer_enter(xt_json_replacer_context *ctx, xt_value value) {
393
+ for (uint32_t i = 0; i < ctx->path_count; i++) {
394
+ if (ctx->path[i] == value) {
395
+ xt_value message = xt_string_from_cstr("Converting circular structure to JSON");
396
+ xt_throw(xt_type_error_ctor(1, &message));
397
+ }
398
+ }
399
+ if (ctx->path_count >= ctx->path_capacity) {
400
+ uint32_t capacity = ctx->path_capacity == 0 ? 16 : ctx->path_capacity * 2;
401
+ xt_value *path = (xt_value *)realloc(ctx->path, sizeof(xt_value) * capacity);
402
+ if (!path) abort();
403
+ ctx->path = path;
404
+ ctx->path_capacity = capacity;
405
+ }
406
+ ctx->path[ctx->path_count++] = value;
407
+ }
408
+
409
+ static void xt_json_replacer_leave(xt_json_replacer_context *ctx) {
410
+ if (ctx->path_count > 0) ctx->path_count--;
411
+ }
412
+
413
+ static void xt_json_replacer_indent(xt_json_replacer_context *ctx, int depth, xt_value *out) {
414
+ xt_json_indent(out, ctx->indent, depth);
415
+ }
416
+
417
+ static int xt_json_replacer_allows(xt_value replacer, xt_value key) {
418
+ if (!XT_IS_ARRAY(replacer)) return 1;
419
+ xt_array *allowed = xt_as_array(replacer);
420
+ for (uint32_t i = 0; i < allowed->length; i++) {
421
+ xt_value item = allowed->items[i];
422
+ if (!XT_IS_STRING(item) && !XT_IS_NUMBER(item)) continue;
423
+ xt_value text = xt_to_string(item);
424
+ xt_string *a = xt_as_string(text);
425
+ xt_string *b = xt_as_string(key);
426
+ if (a && b && xt_string_equals(a, b)) return 1;
427
+ }
428
+ return 0;
429
+ }
430
+
431
+ static int xt_json_replacer_write(xt_json_replacer_context *ctx, xt_value holder, xt_value key,
432
+ int depth, xt_value *out);
433
+
434
+ static int xt_json_replacer_container(xt_json_replacer_context *ctx, xt_value value, int depth,
435
+ xt_value *out) {
436
+ xt_json_replacer_enter(ctx, value);
437
+ if (XT_IS_ARRAY(value)) {
438
+ xt_array *array = xt_as_array(value);
439
+ *out = xt_add(*out, xt_string_from_cstr("["));
440
+ for (uint32_t i = 0; i < array->length; i++) {
441
+ if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
442
+ xt_json_replacer_indent(ctx, depth + 1, out);
443
+ char keyBuffer[16];
444
+ snprintf(keyBuffer, sizeof(keyBuffer), "%u", i);
445
+ xt_value temporary = xt_string_from_cstr("");
446
+ int wrote = xt_json_replacer_write(ctx, value, xt_string_from_cstr(keyBuffer), depth + 1,
447
+ &temporary);
448
+ *out = xt_add(*out, wrote ? temporary : xt_string_from_cstr("null"));
449
+ }
450
+ xt_json_replacer_indent(ctx, depth, out);
451
+ xt_json_replacer_leave(ctx);
452
+ *out = xt_add(*out, xt_string_from_cstr("]"));
453
+ return 1;
454
+ }
455
+
456
+ xt_value keys = xt_object_keys(value);
457
+ xt_array *list = xt_as_array(keys);
458
+ *out = xt_add(*out, xt_string_from_cstr("{"));
459
+ int written = 0;
460
+ if (list) {
461
+ for (uint32_t i = 0; i < list->length; i++) {
462
+ xt_value childKey = list->items[i];
463
+ if (!xt_json_replacer_allows(ctx->replacer, childKey)) continue;
464
+ xt_value temporary = xt_string_from_cstr("");
465
+ int wrote = xt_json_replacer_write(ctx, value, childKey, depth + 1, &temporary);
466
+ if (!wrote) continue;
467
+ if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
468
+ written++;
469
+ xt_json_replacer_indent(ctx, depth + 1, out);
470
+ *out = xt_add(*out, xt_string_from_cstr("\""));
471
+ *out = xt_add(*out, childKey);
472
+ *out = xt_add(*out, xt_string_from_cstr("\":"));
473
+ if (xt_json_indented(ctx->indent)) *out = xt_add(*out, xt_string_from_cstr(" "));
474
+ *out = xt_add(*out, temporary);
475
+ }
476
+ }
477
+ xt_json_replacer_indent(ctx, depth, out);
478
+ xt_json_replacer_leave(ctx);
479
+ *out = xt_add(*out, xt_string_from_cstr("}"));
480
+ return 1;
481
+ }
482
+
483
+ static int xt_json_replacer_write(xt_json_replacer_context *ctx, xt_value holder, xt_value key,
484
+ int depth, xt_value *out) {
485
+ xt_value value = xt_get(holder, key);
486
+ if (XT_IS_FUNCTION(ctx->replacer)) {
487
+ xt_value args[2] = {key, value};
488
+ value = xt_call_with_this(ctx->replacer, holder, 2, args);
489
+ }
490
+ if (xt_is_date(value)) {
491
+ value = xt_call_method(value, xt_string_from_cstr("toJSON"), 1, &key);
492
+ } else if (XT_IS_ARRAY(value) ||
493
+ (XT_IS_OBJECT(value) &&
494
+ (((xt_object *)XT_GET_PTR(value))->header.kind == XT_OBJECT_KIND_OBJECT ||
495
+ ((xt_object *)XT_GET_PTR(value))->header.kind == XT_OBJECT_KIND_ERROR))) {
496
+ xt_value toJSON = XT_IS_ARRAY(value) ? xt_get(value, xt_string_from_cstr("toJSON"))
497
+ : xt_object_get(value, xt_string_from_cstr("toJSON"));
498
+ if (XT_IS_FUNCTION(toJSON)) {
499
+ xt_value args[1] = {key};
500
+ value = xt_call_with_this(toJSON, value, 1, args);
501
+ }
502
+ }
503
+ if (value == XT_UNDEFINED || XT_IS_FUNCTION(value) || xt_is_symbol(value)) return 0;
504
+ if (XT_IS_BIGINT(value)) {
505
+ xt_value message = xt_string_from_cstr("Do not know how to serialize a BigInt");
506
+ xt_throw(xt_type_error_ctor(1, &message));
507
+ }
508
+ if (XT_IS_ARRAY(value)) return xt_json_replacer_container(ctx, value, depth, out);
509
+ if (XT_IS_OBJECT(value)) {
510
+ int kind = ((xt_object *)XT_GET_PTR(value))->header.kind;
511
+ if (kind == XT_OBJECT_KIND_MAP || kind == XT_OBJECT_KIND_SET ||
512
+ kind == XT_OBJECT_KIND_REGEXP || kind == XT_OBJECT_KIND_PROMISE ||
513
+ kind == XT_OBJECT_KIND_GENERATOR || kind == XT_OBJECT_KIND_ITERATOR ||
514
+ kind == XT_OBJECT_KIND_ASYNC) {
515
+ *out = xt_add(*out, xt_string_from_cstr("{}"));
516
+ return 1;
517
+ }
518
+ return xt_json_replacer_container(ctx, value, depth, out);
519
+ }
520
+ xt_json_stringify_value(value, ctx->indent, depth, out);
521
+ return 1;
522
+ }
523
+
215
524
  xt_value xt_json_stringify(int32_t argc, xt_value *argv) {
216
- int indent = 0;
217
- xt_value space = xt_arg_at(argc, argv, 1);
218
- if (XT_IS_NUMBER(space)) indent = xt_to_int32(space);
219
- else if (XT_IS_STRING(space)) indent = (int)((xt_string *)XT_GET_PTR(space))->length;
220
- if (indent < 0) indent = 0;
221
- if (indent > 10) indent = 10;
222
525
  xt_value value = xt_arg_at(argc, argv, 0);
223
526
  if (value == XT_UNDEFINED || XT_IS_FUNCTION(value) || xt_is_symbol(value)) return XT_UNDEFINED;
527
+ /* Signature: stringify(value, replacer, space). The replacer is argv[1] and
528
+ * the indentation is argv[2]; reading argv[1] as `space` silently ignored
529
+ * `JSON.stringify(value, null, 2)`. */
530
+ xt_value indent = xt_json_space_unit(xt_arg_at(argc, argv, 2));
531
+ xt_value replacer = xt_arg_at(argc, argv, 1);
532
+ if (XT_IS_FUNCTION(replacer) || XT_IS_ARRAY(replacer)) {
533
+ xt_json_replacer_context context = {replacer, indent, NULL, 0, 0};
534
+ xt_value wrapper = xt_object_new();
535
+ xt_object_set(wrapper, xt_string_from_cstr(""), value);
536
+ xt_value out = xt_string_from_cstr("");
537
+ int wrote = xt_json_replacer_write(&context, wrapper, xt_string_from_cstr(""), 0, &out);
538
+ free(context.path);
539
+ return wrote ? out : XT_UNDEFINED;
540
+ }
541
+ /* A caught circular-structure error longjmps past xt_json_leave; start every
542
+ * top-level serialization with a clean path. */
543
+ xt_json_path_count = 0;
224
544
  xt_value out = xt_string_from_cstr("");
225
545
  xt_json_stringify_value(value, indent, 0, &out);
226
546
  return out;
@@ -41,24 +41,33 @@ xt_value xt_number_static(xt_value name, int32_t argc, xt_value *argv) {
41
41
  xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv) {
42
42
  const char *fn = xt_string_data(name);
43
43
  if (!fn) return XT_UNDEFINED;
44
- if (strcmp(fn, "fromCharCode") == 0 || strcmp(fn, "fromCodePoint") == 0) {
45
- xt_string *out = xt_string_alloc((size_t)argc * 4 + 1);
46
- char *mutable = xt_string_mutable(out);
44
+ if (strcmp(fn, "fromCharCode") == 0) {
45
+ /* `fromCharCode` takes UTF-16 code units (modulo 65536) and joins adjacent
46
+ * high/low surrogates into one code point, like JavaScript. */
47
+ if (argc <= 0) return xt_string_from_cstr("");
48
+ uint16_t *units = (uint16_t *)malloc(sizeof(uint16_t) * (size_t)argc);
49
+ if (!units) abort();
50
+ for (int32_t i = 0; i < argc; i++) units[i] = (uint16_t)(xt_to_int32(argv[i]) & 0xFFFF);
51
+ xt_value result = xt_string_from_units(units, (size_t)argc);
52
+ free(units);
53
+ return result;
54
+ }
55
+ if (strcmp(fn, "fromCodePoint") == 0) {
56
+ char *out = (char *)malloc((size_t)argc * 4 + 1);
57
+ if (!out) abort();
47
58
  size_t length = 0;
48
59
  for (int32_t i = 0; i < argc; i++) {
49
- unsigned code = (unsigned)xt_to_int32(argv[i]);
50
- char buffer[4];
51
- int bytes = 0;
52
- if (code < 0x80) buffer[bytes++] = (char)code;
53
- else if (code < 0x800) { buffer[bytes++] = (char)(0xC0 | (code >> 6)); buffer[bytes++] = (char)(0x80 | (code & 0x3F)); }
54
- else if (code < 0x10000) { buffer[bytes++] = (char)(0xE0 | (code >> 12)); buffer[bytes++] = (char)(0x80 | ((code >> 6) & 0x3F)); buffer[bytes++] = (char)(0x80 | (code & 0x3F)); }
55
- else { buffer[bytes++] = (char)(0xF0 | (code >> 18)); buffer[bytes++] = (char)(0x80 | ((code >> 12) & 0x3F)); buffer[bytes++] = (char)(0x80 | ((code >> 6) & 0x3F)); buffer[bytes++] = (char)(0x80 | (code & 0x3F)); }
56
- memcpy(mutable + length, buffer, (size_t)bytes);
57
- length += (size_t)bytes;
60
+ int32_t code = xt_to_int32(argv[i]);
61
+ if (code < 0 || code > 0x10FFFF) {
62
+ free(out);
63
+ xt_throw(xt_error_from_message("RangeError: Invalid code point"));
64
+ return XT_UNDEFINED;
65
+ }
66
+ length += xt_utf8_encode((uint32_t)code, out + length);
58
67
  }
59
- mutable[length] = '\0';
60
- out->length = (uint32_t)length;
61
- return XT_FROM_PTR(XT_TAG_STRING, out);
68
+ xt_value result = xt_string_new(out, length);
69
+ free(out);
70
+ return result;
62
71
  }
63
72
  if (strcmp(fn, "raw") == 0) {
64
73
  xt_value strings = xt_arg_at(argc, argv, 0);