xbintsc 0.5.23 → 0.5.32

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 (481) hide show
  1. package/AGENTS.md +11 -2
  2. package/README.md +47 -16
  3. package/README.zh-CN.md +21 -2
  4. package/dist/scripts/support-matrix.d.ts +18 -0
  5. package/dist/scripts/support-matrix.js +141 -0
  6. package/dist/scripts/support-matrix.js.map +1 -0
  7. package/dist/src/ast/common.d.ts +2 -2
  8. package/dist/src/ast/declarations.d.ts +7 -1
  9. package/dist/src/ast/expressions.d.ts +5 -0
  10. package/dist/src/ast/kinds.d.ts +2 -0
  11. package/dist/src/ast/kinds.js +2 -0
  12. package/dist/src/ast/kinds.js.map +1 -1
  13. package/dist/src/binder/binder.d.ts +2 -1
  14. package/dist/src/binder/binder.js +2 -0
  15. package/dist/src/binder/binder.js.map +1 -1
  16. package/dist/src/binder/declarations.d.ts +9 -0
  17. package/dist/src/binder/declarations.js +64 -0
  18. package/dist/src/binder/declarations.js.map +1 -1
  19. package/dist/src/binder/references.js +99 -4
  20. package/dist/src/binder/references.js.map +1 -1
  21. package/dist/src/binder/types.d.ts +32 -0
  22. package/dist/src/binder/types.js.map +1 -1
  23. package/dist/src/canonical.d.ts +29 -0
  24. package/dist/src/canonical.js +35 -0
  25. package/dist/src/canonical.js.map +1 -0
  26. package/dist/src/checker/assignability.d.ts +13 -0
  27. package/dist/src/checker/assignability.js +146 -0
  28. package/dist/src/checker/assignability.js.map +1 -0
  29. package/dist/src/checker/calls.d.ts +13 -0
  30. package/dist/src/checker/calls.js +127 -0
  31. package/dist/src/checker/calls.js.map +1 -0
  32. package/dist/src/checker/checker.d.ts +26 -0
  33. package/dist/src/checker/checker.js +31 -0
  34. package/dist/src/checker/checker.js.map +1 -0
  35. package/dist/src/checker/declarations.d.ts +9 -0
  36. package/dist/src/checker/declarations.js +15 -0
  37. package/dist/src/checker/declarations.js.map +1 -0
  38. package/dist/src/checker/flow.d.ts +21 -0
  39. package/dist/src/checker/flow.js +241 -0
  40. package/dist/src/checker/flow.js.map +1 -0
  41. package/dist/src/checker/globals.d.ts +9 -0
  42. package/dist/src/checker/globals.js +29 -0
  43. package/dist/src/checker/globals.js.map +1 -0
  44. package/dist/src/checker/source.d.ts +38 -0
  45. package/dist/src/checker/source.js +48 -0
  46. package/dist/src/checker/source.js.map +1 -0
  47. package/dist/src/checker/type-infer.d.ts +18 -0
  48. package/dist/src/checker/type-infer.js +173 -0
  49. package/dist/src/checker/type-infer.js.map +1 -0
  50. package/dist/src/checker/type-model.d.ts +73 -0
  51. package/dist/src/checker/type-model.js +151 -0
  52. package/dist/src/checker/type-model.js.map +1 -0
  53. package/dist/src/checker/type-system.d.ts +58 -0
  54. package/dist/src/checker/type-system.js +569 -0
  55. package/dist/src/checker/type-system.js.map +1 -0
  56. package/dist/src/checker/typecheck-types.d.ts +22 -0
  57. package/dist/src/checker/typecheck-types.js +109 -0
  58. package/dist/src/checker/typecheck-types.js.map +1 -0
  59. package/dist/src/checker/typecheck.d.ts +62 -0
  60. package/dist/src/checker/typecheck.js +574 -0
  61. package/dist/src/checker/typecheck.js.map +1 -0
  62. package/dist/src/checker/undefined.d.ts +14 -0
  63. package/dist/src/checker/undefined.js +32 -0
  64. package/dist/src/checker/undefined.js.map +1 -0
  65. package/dist/src/checker/walk.d.ts +10 -0
  66. package/dist/src/checker/walk.js +15 -0
  67. package/dist/src/checker/walk.js.map +1 -0
  68. package/dist/src/cli/help.d.ts +7 -0
  69. package/dist/src/cli/help.js +64 -0
  70. package/dist/src/cli/help.js.map +1 -0
  71. package/dist/src/cli/hints.js +2 -1
  72. package/dist/src/cli/hints.js.map +1 -1
  73. package/dist/src/cli/main.js +12 -48
  74. package/dist/src/cli/main.js.map +1 -1
  75. package/dist/src/codegen/generator/calls/access.js +8 -8
  76. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  77. package/dist/src/codegen/generator/calls/invocation.js +9 -4
  78. package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
  79. package/dist/src/codegen/generator/calls/super.d.ts +9 -1
  80. package/dist/src/codegen/generator/calls/super.js +56 -5
  81. package/dist/src/codegen/generator/calls/super.js.map +1 -1
  82. package/dist/src/codegen/generator/context.d.ts +13 -2
  83. package/dist/src/codegen/generator/context.js +25 -19
  84. package/dist/src/codegen/generator/context.js.map +1 -1
  85. package/dist/src/codegen/generator/debug.js +2 -1
  86. package/dist/src/codegen/generator/debug.js.map +1 -1
  87. package/dist/src/codegen/generator/expressions/primary.d.ts +4 -1
  88. package/dist/src/codegen/generator/expressions/primary.js +68 -8
  89. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  90. package/dist/src/codegen/generator/generator.js +11 -1
  91. package/dist/src/codegen/generator/generator.js.map +1 -1
  92. package/dist/src/codegen/generator/module.d.ts +3 -0
  93. package/dist/src/codegen/generator/module.js +116 -26
  94. package/dist/src/codegen/generator/module.js.map +1 -1
  95. package/dist/src/codegen/generator/state.d.ts +11 -1
  96. package/dist/src/codegen/generator/state.js.map +1 -1
  97. package/dist/src/codegen/generator/statements/variables.js +26 -7
  98. package/dist/src/codegen/generator/statements/variables.js.map +1 -1
  99. package/dist/src/codegen/generator/tables.d.ts +2 -0
  100. package/dist/src/codegen/generator/tables.js +4 -0
  101. package/dist/src/codegen/generator/tables.js.map +1 -1
  102. package/dist/src/driver/build-key.d.ts +2 -0
  103. package/dist/src/driver/build-key.js +1 -0
  104. package/dist/src/driver/build-key.js.map +1 -1
  105. package/dist/src/driver/bundler/graph.js +5 -1
  106. package/dist/src/driver/bundler/graph.js.map +1 -1
  107. package/dist/src/driver/bundler/merge.js +16 -1
  108. package/dist/src/driver/bundler/merge.js.map +1 -1
  109. package/dist/src/driver/bundler/types.d.ts +12 -0
  110. package/dist/src/driver/compiler.d.ts +1 -1
  111. package/dist/src/driver/compiler.js +3 -0
  112. package/dist/src/driver/compiler.js.map +1 -1
  113. package/dist/src/driver/fingerprint.js +2 -1
  114. package/dist/src/driver/fingerprint.js.map +1 -1
  115. package/dist/src/driver/frontend.d.ts +8 -6
  116. package/dist/src/driver/frontend.js +4 -0
  117. package/dist/src/driver/frontend.js.map +1 -1
  118. package/dist/src/driver/options.d.ts +6 -0
  119. package/dist/src/driver/version.d.ts +1 -1
  120. package/dist/src/driver/version.js +1 -1
  121. package/dist/src/extensions/gui/css.d.ts +26 -0
  122. package/dist/src/extensions/gui/css.js +100 -0
  123. package/dist/src/extensions/gui/css.js.map +1 -0
  124. package/dist/src/extensions/gui/html.js +28 -7
  125. package/dist/src/extensions/gui/html.js.map +1 -1
  126. package/dist/src/extensions/gui/index.js +79 -2
  127. package/dist/src/extensions/gui/index.js.map +1 -1
  128. package/dist/src/extensions/gui/three.d.ts +16 -0
  129. package/dist/src/extensions/gui/three.js +22 -0
  130. package/dist/src/extensions/gui/three.js.map +1 -0
  131. package/dist/src/extensions/media/index.d.ts +6 -5
  132. package/dist/src/extensions/media/index.js +12 -14
  133. package/dist/src/extensions/media/index.js.map +1 -1
  134. package/dist/src/extensions/registry.d.ts +38 -0
  135. package/dist/src/extensions/registry.js +10 -0
  136. package/dist/src/extensions/registry.js.map +1 -1
  137. package/dist/src/index.d.ts +1 -0
  138. package/dist/src/index.js +1 -0
  139. package/dist/src/index.js.map +1 -1
  140. package/dist/src/parser/declarations/classes.js +7 -0
  141. package/dist/src/parser/declarations/classes.js.map +1 -1
  142. package/dist/src/parser/expressions.js +14 -1
  143. package/dist/src/parser/expressions.js.map +1 -1
  144. package/dist/src/parser/literals.js +6 -2
  145. package/dist/src/parser/literals.js.map +1 -1
  146. package/dist/tests/binder/binder.test.js +29 -0
  147. package/dist/tests/binder/binder.test.js.map +1 -1
  148. package/dist/tests/canonical.test.d.ts +1 -0
  149. package/dist/tests/canonical.test.js +19 -0
  150. package/dist/tests/canonical.test.js.map +1 -0
  151. package/dist/tests/checker/checker.test.d.ts +1 -0
  152. package/dist/tests/checker/checker.test.js +245 -0
  153. package/dist/tests/checker/checker.test.js.map +1 -0
  154. package/dist/tests/cli/check.test.js +20 -0
  155. package/dist/tests/cli/check.test.js.map +1 -1
  156. package/dist/tests/conformance/matrix.test.d.ts +6 -0
  157. package/dist/tests/conformance/matrix.test.js +23 -0
  158. package/dist/tests/conformance/matrix.test.js.map +1 -0
  159. package/dist/tests/conformance/test262/manifest.d.ts +115 -0
  160. package/dist/tests/conformance/test262/manifest.js +257 -0
  161. package/dist/tests/conformance/test262/manifest.js.map +1 -0
  162. package/dist/tests/conformance/test262.test.d.ts +11 -0
  163. package/dist/tests/conformance/test262.test.js +74 -0
  164. package/dist/tests/conformance/test262.test.js.map +1 -0
  165. package/dist/tests/docs/structure.test.js +9 -11
  166. package/dist/tests/docs/structure.test.js.map +1 -1
  167. package/dist/tests/e2e/child-process.test.js +3 -2
  168. package/dist/tests/e2e/child-process.test.js.map +1 -1
  169. package/dist/tests/e2e/compile-builtins.test.js +45 -0
  170. package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
  171. package/dist/tests/e2e/compile-objects-classes.test.js +77 -0
  172. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
  173. package/dist/tests/e2e/differential-syntax.test.d.ts +5 -0
  174. package/dist/tests/e2e/differential-syntax.test.js +95 -0
  175. package/dist/tests/e2e/differential-syntax.test.js.map +1 -0
  176. package/dist/tests/e2e/differential-values.test.js +15 -0
  177. package/dist/tests/e2e/differential-values.test.js.map +1 -1
  178. package/dist/tests/e2e/gui-browser.test.d.ts +13 -0
  179. package/dist/tests/e2e/gui-browser.test.js +163 -0
  180. package/dist/tests/e2e/gui-browser.test.js.map +1 -0
  181. package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
  182. package/dist/tests/e2e/gui-effects.test.js +262 -0
  183. package/dist/tests/e2e/gui-effects.test.js.map +1 -0
  184. package/dist/tests/e2e/gui-example-browser.test.js +2 -2
  185. package/dist/tests/e2e/gui-example-browser.test.js.map +1 -1
  186. package/dist/tests/e2e/gui-example-canvas.test.js +5 -4
  187. package/dist/tests/e2e/gui-example-canvas.test.js.map +1 -1
  188. package/dist/tests/e2e/gui-example-svg.test.js +4 -3
  189. package/dist/tests/e2e/gui-example-svg.test.js.map +1 -1
  190. package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
  191. package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
  192. package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
  193. package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
  194. package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
  195. package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
  196. package/dist/tests/e2e/gui-example.test.js +4 -3
  197. package/dist/tests/e2e/gui-example.test.js.map +1 -1
  198. package/dist/tests/e2e/gui-helpers.js +4 -3
  199. package/dist/tests/e2e/gui-helpers.js.map +1 -1
  200. package/dist/tests/e2e/gui-layout.test.js +48 -0
  201. package/dist/tests/e2e/gui-layout.test.js.map +1 -1
  202. package/dist/tests/e2e/gui-media.test.js +10 -8
  203. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  204. package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
  205. package/dist/tests/e2e/gui-webgl.test.js +179 -0
  206. package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
  207. package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
  208. package/dist/tests/e2e/gui-webgl2.test.js +238 -0
  209. package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
  210. package/dist/tests/e2e/harness.d.ts +9 -0
  211. package/dist/tests/e2e/harness.js +14 -2
  212. package/dist/tests/e2e/harness.js.map +1 -1
  213. package/dist/tests/e2e/native-extensions.test.js +2 -1
  214. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  215. package/dist/tests/e2e/property-descriptors.test.js +20 -0
  216. package/dist/tests/e2e/property-descriptors.test.js.map +1 -1
  217. package/dist/tests/e2e/unicode-output.test.js +5 -3
  218. package/dist/tests/e2e/unicode-output.test.js.map +1 -1
  219. package/dist/tests/e2e/weak-collections.test.js +16 -2
  220. package/dist/tests/e2e/weak-collections.test.js.map +1 -1
  221. package/dist/tests/extensions/gui.test.js +41 -0
  222. package/dist/tests/extensions/gui.test.js.map +1 -1
  223. package/dist/tests/extensions/media.test.js +7 -3
  224. package/dist/tests/extensions/media.test.js.map +1 -1
  225. package/dist/tests/helpers.d.ts +1 -0
  226. package/dist/tests/helpers.js +1 -0
  227. package/dist/tests/helpers.js.map +1 -1
  228. package/dist/tests/parser/declarations.test.js +20 -0
  229. package/dist/tests/parser/declarations.test.js.map +1 -1
  230. package/dist/tests/parser/expressions.test.js +36 -0
  231. package/dist/tests/parser/expressions.test.js.map +1 -1
  232. package/dist/tests/platform.d.ts +32 -0
  233. package/dist/tests/platform.js +40 -0
  234. package/dist/tests/platform.js.map +1 -0
  235. package/dist/tests/platform.test.d.ts +12 -0
  236. package/dist/tests/platform.test.js +51 -0
  237. package/dist/tests/platform.test.js.map +1 -0
  238. package/dist/tests/version.test.js +4 -4
  239. package/dist/tests/version.test.js.map +1 -1
  240. package/doc/ai/README.md +10 -4
  241. package/doc/ai/build-recipe.md +1 -0
  242. package/doc/ai/cli.md +17 -5
  243. package/doc/ai/contributing.md +59 -2
  244. package/doc/ai/extensions.md +38 -7
  245. package/doc/ai/language-support.md +25 -16
  246. package/doc/ai/troubleshooting.md +12 -8
  247. package/doc/ai/zh-CN/README.md +9 -4
  248. package/doc/ai/zh-CN/build-recipe.md +1 -0
  249. package/doc/ai/zh-CN/cli.md +13 -3
  250. package/doc/ai/zh-CN/contributing.md +49 -3
  251. package/doc/ai/zh-CN/extensions.md +33 -6
  252. package/doc/ai/zh-CN/language-support.md +23 -14
  253. package/doc/ai/zh-CN/troubleshooting.md +10 -6
  254. package/doc/gui/api.md +47 -1
  255. package/doc/gui/build.md +72 -16
  256. package/doc/gui/canvas.md +11 -3
  257. package/doc/gui/dom.md +33 -18
  258. package/doc/gui/known-issues.md +58 -15
  259. package/doc/gui/layout.md +18 -0
  260. package/doc/gui/media.md +17 -13
  261. package/doc/gui/rendering.md +50 -3
  262. package/doc/gui/runtime.md +18 -0
  263. package/doc/gui/webgl.md +256 -0
  264. package/doc/gui-scripts.md +7 -0
  265. package/doc/gui.md +108 -17
  266. package/doc/implemented/binder.md +2 -0
  267. package/doc/implemented/checker.md +117 -0
  268. package/doc/implemented/cli.md +13 -1
  269. package/doc/implemented/codegen.md +3 -2
  270. package/doc/implemented/driver.md +2 -2
  271. package/doc/implemented/operators.md +2 -1
  272. package/doc/implemented/parser.md +3 -2
  273. package/doc/implemented/pipeline.md +8 -1
  274. package/doc/implemented/stdlib.md +2 -1
  275. package/doc/implemented/tests.md +3 -1
  276. package/doc/implemented.md +2 -0
  277. package/doc/npm-package.md +419 -0
  278. package/doc/requirements.md +22 -10
  279. package/doc/support-matrix.md +83 -0
  280. package/doc/unimplemented/classes.md +3 -0
  281. package/doc/unimplemented/deviations.md +3 -2
  282. package/doc/unimplemented/toolchain.md +1 -1
  283. package/doc/unimplemented/types.md +24 -8
  284. package/doc/unimplemented.md +1 -1
  285. package/doc/zh-CN/gui/api.md +43 -1
  286. package/doc/zh-CN/gui/build.md +64 -15
  287. package/doc/zh-CN/gui/canvas.md +9 -2
  288. package/doc/zh-CN/gui/dom.md +20 -7
  289. package/doc/zh-CN/gui/known-issues.md +46 -13
  290. package/doc/zh-CN/gui/layout.md +14 -0
  291. package/doc/zh-CN/gui/media.md +15 -11
  292. package/doc/zh-CN/gui/rendering.md +41 -4
  293. package/doc/zh-CN/gui/runtime.md +16 -0
  294. package/doc/zh-CN/gui/webgl.md +115 -0
  295. package/doc/zh-CN/gui-scripts.md +5 -0
  296. package/doc/zh-CN/gui.md +89 -14
  297. package/doc/zh-CN/implemented/binder.md +2 -0
  298. package/doc/zh-CN/implemented/checker.md +99 -0
  299. package/doc/zh-CN/implemented/cli.md +12 -1
  300. package/doc/zh-CN/implemented/codegen.md +3 -2
  301. package/doc/zh-CN/implemented/driver.md +2 -2
  302. package/doc/zh-CN/implemented/operators.md +1 -1
  303. package/doc/zh-CN/implemented/parser.md +3 -2
  304. package/doc/zh-CN/implemented/pipeline.md +3 -1
  305. package/doc/zh-CN/implemented/stdlib.md +2 -1
  306. package/doc/zh-CN/implemented/tests.md +3 -1
  307. package/doc/zh-CN/implemented.md +2 -0
  308. package/doc/zh-CN/npm-package.md +394 -0
  309. package/doc/zh-CN/post/announce.md +47 -47
  310. package/doc/zh-CN/requirements.md +16 -7
  311. package/doc/zh-CN/support-matrix.md +82 -0
  312. package/doc/zh-CN/unimplemented/classes.md +3 -0
  313. package/doc/zh-CN/unimplemented/deviations.md +3 -2
  314. package/doc/zh-CN/unimplemented/toolchain.md +1 -1
  315. package/doc/zh-CN/unimplemented/types.md +16 -6
  316. package/doc/zh-CN/unimplemented.md +1 -1
  317. package/llms.txt +6 -1
  318. package/package.json +2 -1
  319. package/runtime/ext_gui/audio.cpp +316 -0
  320. package/runtime/ext_gui/browser.cpp +573 -0
  321. package/runtime/ext_gui/browser_escape.cpp +85 -0
  322. package/runtime/ext_gui/browser_loop.cpp +83 -0
  323. package/runtime/ext_gui/canvas.cpp +12 -21
  324. package/runtime/ext_gui/canvas_internal.h +10 -0
  325. package/runtime/ext_gui/canvas_raster.cpp +79 -1
  326. package/runtime/ext_gui/clip_values.cpp +246 -0
  327. package/runtime/ext_gui/css.cpp +94 -0
  328. package/runtime/ext_gui/css.h +22 -1
  329. package/runtime/ext_gui/css_match.cpp +3 -0
  330. package/runtime/ext_gui/css_selector.cpp +9 -0
  331. package/runtime/ext_gui/css_sheet.cpp +89 -45
  332. package/runtime/ext_gui/document.cpp +4 -1
  333. package/runtime/ext_gui/document.h +2 -0
  334. package/runtime/ext_gui/dom.h +16 -0
  335. package/runtime/ext_gui/dom_api.cpp +37 -0
  336. package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
  337. package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
  338. package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
  339. package/runtime/ext_gui/dom_api_document.cpp +96 -5
  340. package/runtime/ext_gui/dom_api_events.cpp +20 -0
  341. package/runtime/ext_gui/dom_api_internal.h +278 -0
  342. package/runtime/ext_gui/dom_api_proto.cpp +6 -0
  343. package/runtime/ext_gui/dom_api_webgl.cpp +376 -0
  344. package/runtime/ext_gui/dom_api_webgl2.cpp +434 -0
  345. package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
  346. package/runtime/ext_gui/dom_api_webgl_buffer.cpp +212 -0
  347. package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
  348. package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
  349. package/runtime/ext_gui/dom_api_webgl_state.cpp +444 -0
  350. package/runtime/ext_gui/dom_api_webgl_texture.cpp +445 -0
  351. package/runtime/ext_gui/effect_values.cpp +312 -0
  352. package/runtime/ext_gui/gradient_values.cpp +476 -0
  353. package/runtime/ext_gui/grid_values.cpp +230 -0
  354. package/runtime/ext_gui/gui.cpp +90 -23
  355. package/runtime/ext_gui/gui_canvas.cpp +50 -2
  356. package/runtime/ext_gui/gui_engine.h +71 -0
  357. package/runtime/ext_gui/gui_events.cpp +4 -1
  358. package/runtime/ext_gui/gui_media.cpp +1 -1
  359. package/runtime/ext_gui/gui_webgl.cpp +83 -0
  360. package/runtime/ext_gui/layout.cpp +21 -0
  361. package/runtime/ext_gui/layout_flow.cpp +81 -4
  362. package/runtime/ext_gui/layout_flow_internal.h +31 -0
  363. package/runtime/ext_gui/layout_grid.cpp +374 -0
  364. package/runtime/ext_gui/media.h +1 -1
  365. package/runtime/ext_gui/media_api.h +2 -2
  366. package/runtime/ext_gui/media_query.cpp +211 -0
  367. package/runtime/ext_gui/paint.cpp +111 -77
  368. package/runtime/ext_gui/paint.h +33 -3
  369. package/runtime/ext_gui/paint_background.cpp +229 -0
  370. package/runtime/ext_gui/paint_clip.cpp +268 -0
  371. package/runtime/ext_gui/paint_effects.cpp +324 -0
  372. package/runtime/ext_gui/paint_internal.h +85 -0
  373. package/runtime/ext_gui/renderer.cpp +8 -31
  374. package/runtime/ext_gui/renderer_clip.cpp +196 -0
  375. package/runtime/ext_gui/renderer_image.cpp +13 -8
  376. package/runtime/ext_gui/renderer_internal.h +15 -8
  377. package/runtime/ext_gui/renderer_text.cpp +6 -31
  378. package/runtime/ext_gui/style.cpp +343 -20
  379. package/runtime/ext_gui/style.h +144 -3
  380. package/runtime/ext_gui/style_print.cpp +134 -1
  381. package/runtime/ext_gui/style_values.cpp +152 -126
  382. package/runtime/ext_gui/style_values_internal.h +35 -0
  383. package/runtime/ext_gui/webgl.h +466 -0
  384. package/runtime/ext_gui/webgl2_constants.h +274 -0
  385. package/runtime/ext_gui/webgl_buffer.cpp +565 -0
  386. package/runtime/ext_gui/webgl_constants.h +317 -0
  387. package/runtime/ext_gui/webgl_context.cpp +466 -0
  388. package/runtime/ext_gui/webgl_draw.cpp +495 -0
  389. package/runtime/ext_gui/webgl_glsl.h +125 -0
  390. package/runtime/ext_gui/webgl_glsl_compile.cpp +431 -0
  391. package/runtime/ext_gui/webgl_glsl_rewrite.cpp +349 -0
  392. package/runtime/ext_gui/webgl_glsl_scan.cpp +581 -0
  393. package/runtime/ext_gui/webgl_msl.cpp +62 -0
  394. package/runtime/ext_gui/webgl_msl.h +33 -0
  395. package/runtime/ext_gui/webgl_pipeline.cpp +274 -0
  396. package/runtime/ext_gui/webgl_program_internal.h +18 -0
  397. package/runtime/ext_gui/webgl_shader.cpp +582 -0
  398. package/runtime/ext_gui/webgl_texture.cpp +293 -0
  399. package/runtime/ext_gui/webgl_uniform.cpp +167 -0
  400. package/runtime/ext_gui/webgl_webgl2.cpp +224 -0
  401. package/runtime/ext_gui/window.cpp +9 -0
  402. package/runtime/ext_media/media.cpp +1 -1
  403. package/runtime/ext_media/media_bridge.c +9 -3
  404. package/runtime/ext_node/path/path.c +7 -7
  405. package/runtime/ext_node/url/url.c +4 -2
  406. package/runtime/rt.h +15 -0
  407. package/runtime/rt_internal.h +1 -0
  408. package/runtime/xt_constructors.c +2 -1
  409. package/runtime/xt_containers/access.inc +8 -0
  410. package/runtime/xt_containers/objects.inc +22 -2
  411. package/runtime/xt_io/exception.inc +4 -2
  412. package/runtime/xt_regex/api.inc +2 -0
  413. package/runtime/xt_regex/matcher.inc +16 -3
  414. package/runtime/xt_regex/parser.inc +8 -2
  415. package/runtime/xt_regex/types.inc +3 -0
  416. package/runtime/xt_stdlib/math.inc +62 -0
  417. package/runtime/xt_stdlib2/date.inc +7 -1
  418. package/runtime/xt_stdlib2/objects.inc +14 -0
  419. package/runtime/xt_stdlib2/regexp-match.inc +60 -21
  420. package/runtime/xt_stdlib2/regexp.inc +1 -0
  421. package/runtime/xt_typed_array.c +1 -1
  422. package/scripts/build-gui.ts +90 -3
  423. package/scripts/build-media.ts +323 -58
  424. package/scripts/setup-vs-toolchain.ps1 +152 -0
  425. package/scripts/support-matrix.ts +167 -0
  426. package/src/ast/common.ts +2 -0
  427. package/src/ast/declarations.ts +12 -1
  428. package/src/ast/expressions.ts +6 -0
  429. package/src/ast/kinds.ts +2 -0
  430. package/src/binder/binder.ts +3 -0
  431. package/src/binder/declarations.ts +70 -0
  432. package/src/binder/references.ts +97 -4
  433. package/src/binder/types.ts +30 -0
  434. package/src/canonical.ts +37 -0
  435. package/src/checker/assignability.ts +134 -0
  436. package/src/checker/calls.ts +135 -0
  437. package/src/checker/checker.ts +47 -0
  438. package/src/checker/declarations.ts +26 -0
  439. package/src/checker/flow.ts +236 -0
  440. package/src/checker/globals.ts +40 -0
  441. package/src/checker/source.ts +53 -0
  442. package/src/checker/type-infer.ts +185 -0
  443. package/src/checker/type-model.ts +212 -0
  444. package/src/checker/type-system.ts +578 -0
  445. package/src/checker/typecheck-types.ts +112 -0
  446. package/src/checker/typecheck.ts +586 -0
  447. package/src/checker/undefined.ts +43 -0
  448. package/src/checker/walk.ts +16 -0
  449. package/src/cli/help.ts +65 -0
  450. package/src/cli/hints.ts +2 -1
  451. package/src/cli/main.ts +12 -49
  452. package/src/codegen/generator/calls/access.ts +8 -8
  453. package/src/codegen/generator/calls/invocation.ts +8 -5
  454. package/src/codegen/generator/calls/super.ts +67 -5
  455. package/src/codegen/generator/context.ts +31 -19
  456. package/src/codegen/generator/debug.ts +2 -1
  457. package/src/codegen/generator/expressions/primary.ts +84 -13
  458. package/src/codegen/generator/generator.ts +11 -1
  459. package/src/codegen/generator/module.ts +115 -24
  460. package/src/codegen/generator/state.ts +11 -1
  461. package/src/codegen/generator/statements/variables.ts +26 -6
  462. package/src/codegen/generator/tables.ts +5 -0
  463. package/src/driver/build-key.ts +3 -0
  464. package/src/driver/bundler/graph.ts +6 -2
  465. package/src/driver/bundler/merge.ts +14 -1
  466. package/src/driver/bundler/types.ts +13 -0
  467. package/src/driver/compiler.ts +4 -1
  468. package/src/driver/fingerprint.ts +2 -1
  469. package/src/driver/frontend.ts +13 -2
  470. package/src/driver/options.ts +6 -0
  471. package/src/driver/version.ts +1 -1
  472. package/src/extensions/gui/css.ts +113 -0
  473. package/src/extensions/gui/html.ts +31 -11
  474. package/src/extensions/gui/index.ts +81 -2
  475. package/src/extensions/gui/three.ts +25 -0
  476. package/src/extensions/media/index.ts +13 -16
  477. package/src/extensions/registry.ts +48 -0
  478. package/src/index.ts +1 -0
  479. package/src/parser/declarations/classes.ts +7 -0
  480. package/src/parser/expressions.ts +13 -1
  481. package/src/parser/literals.ts +6 -2
@@ -72,6 +72,13 @@ class SelectorParser {
72
72
  }
73
73
  std::string name = xt_css_lower(readIdent(text, index));
74
74
  if (name.empty()) return false;
75
+ /* `::before`/`::after` are generated-content elements, not states. The
76
+ * single-colon spellings (`:before`) are the legacy equivalent. */
77
+ if (pseudoElement || name == "before" || name == "after") {
78
+ compound->pseudo_element = name;
79
+ any = true;
80
+ continue;
81
+ }
75
82
  if (!pseudoElement && *index < text.size() && text[*index] == '(') {
76
83
  int depth = 0;
77
84
  size_t start = *index;
@@ -192,6 +199,8 @@ class SelectorParser {
192
199
  if (!compound.id.empty()) ids++;
193
200
  classes += computeCompoundSpecificity(compound);
194
201
  if (!compound.tag.empty()) types++;
202
+ /* A pseudo-element counts like a type selector (CSS specificity). */
203
+ if (!compound.pseudo_element.empty()) types++;
195
204
  }
196
205
  return (ids << 20) | (classes << 10) | types;
197
206
  }
@@ -1,5 +1,9 @@
1
1
  /*
2
2
  * xbintsc GUI engine — CSS declaration and stylesheet parsing.
3
+ *
4
+ * At-rules are no longer all skipped: `@media` blocks are parsed recursively
5
+ * and each rule keeps its (possibly nested) query, which the cascade evaluates
6
+ * against the viewport. Every other at-rule is ignored with its block.
3
7
  */
4
8
 
5
9
  #include "css_internal.h"
@@ -41,6 +45,42 @@ size_t findTopLevel(const std::string &text, char needle, size_t from) {
41
45
  return std::string::npos;
42
46
  }
43
47
 
48
+ /** The `}` matching the `{` at `open`, respecting strings and nested blocks. */
49
+ size_t findBlockEnd(const std::string &text, size_t open) {
50
+ int depth = 0;
51
+ char quote = 0;
52
+ for (size_t i = open; i < text.size(); i++) {
53
+ char c = text[i];
54
+ if (quote != 0) {
55
+ if (c == quote) quote = 0;
56
+ continue;
57
+ }
58
+ if (c == '"' || c == '\'') quote = c;
59
+ else if (c == '{') depth++;
60
+ else if (c == '}') {
61
+ depth--;
62
+ if (depth == 0) return i;
63
+ }
64
+ }
65
+ return std::string::npos;
66
+ }
67
+
68
+ /** Join a nested `@media` prelude: distribute `inner` over an outer comma list. */
69
+ std::string combineMedia(const std::string &outer, const std::string &inner) {
70
+ if (outer.empty()) return inner;
71
+ if (inner.empty()) return outer;
72
+ std::vector<std::string> outerParts = xt_css_split_commas(outer);
73
+ std::vector<std::string> innerParts = xt_css_split_commas(inner);
74
+ std::string combined;
75
+ for (const std::string &o : outerParts) {
76
+ for (const std::string &i : innerParts) {
77
+ if (!combined.empty()) combined += ", ";
78
+ combined += o + " and " + i;
79
+ }
80
+ }
81
+ return combined;
82
+ }
83
+
44
84
  std::string stripImportant(std::string value, bool *important) {
45
85
  size_t pos = value.rfind('!');
46
86
  if (pos == std::string::npos) return value;
@@ -52,6 +92,54 @@ std::string stripImportant(std::string value, bool *important) {
52
92
  return value;
53
93
  }
54
94
 
95
+ /** Parse one rule list, carrying the enclosing `@media` prelude. */
96
+ void parseRules(const std::string &text, const std::string &media, int *order,
97
+ StyleSheet *sheet) {
98
+ size_t index = 0;
99
+ while (index < text.size()) {
100
+ while (index < text.size() && xt_is_css_space(text[index])) index++;
101
+ if (index >= text.size()) break;
102
+
103
+ if (text[index] == '@') {
104
+ size_t nameStart = index + 1;
105
+ size_t nameEnd = nameStart;
106
+ while (nameEnd < text.size() &&
107
+ (std::isalnum((unsigned char)text[nameEnd]) || text[nameEnd] == '-'))
108
+ nameEnd++;
109
+ std::string name = xt_css_lower(text.substr(nameStart, nameEnd - nameStart));
110
+ size_t brace = text.find('{', nameEnd);
111
+ size_t semi = text.find(';', nameEnd);
112
+ if (brace != std::string::npos && (semi == std::string::npos || brace < semi)) {
113
+ size_t close = findBlockEnd(text, brace);
114
+ if (close == std::string::npos) break;
115
+ if (name == "media") {
116
+ std::string query = xt_css_trim(text.substr(nameEnd, brace - nameEnd));
117
+ std::string nested = combineMedia(media, query);
118
+ parseRules(text.substr(brace + 1, close - brace - 1), nested, order, sheet);
119
+ }
120
+ /* Other block at-rules (`@supports`, `@keyframes`, `@font-face`, …) are
121
+ * not part of the engine's subset: ignore the whole block. */
122
+ index = close + 1;
123
+ } else {
124
+ index = (semi == std::string::npos) ? text.size() : semi + 1;
125
+ }
126
+ continue;
127
+ }
128
+
129
+ size_t brace = text.find('{', index);
130
+ if (brace == std::string::npos) break;
131
+ size_t close = findBlockEnd(text, brace);
132
+ if (close == std::string::npos) break;
133
+ Rule rule;
134
+ rule.selectors = xt_css_parse_selector_list(text.substr(index, brace - index));
135
+ rule.declarations = xt_css_parse_declarations(text.substr(brace + 1, close - brace - 1));
136
+ rule.order = (*order)++;
137
+ rule.media = media;
138
+ if (!rule.selectors.empty() && !rule.declarations.empty()) sheet->rules.push_back(std::move(rule));
139
+ index = close + 1;
140
+ }
141
+ }
142
+
55
143
  } // namespace
56
144
 
57
145
  std::vector<Declaration> xt_css_parse_declarations(const std::string &text) {
@@ -77,52 +165,8 @@ std::vector<Declaration> xt_css_parse_declarations(const std::string &text) {
77
165
  StyleSheet xt_css_parse_stylesheet(const std::string &text) {
78
166
  StyleSheet sheet;
79
167
  std::string clean = stripComments(text);
80
- size_t index = 0;
81
168
  int order = 0;
82
- while (index < clean.size()) {
83
- while (index < clean.size() && xt_is_css_space(clean[index])) index++;
84
- if (index >= clean.size()) break;
85
- if (clean[index] == '@') {
86
- size_t brace = clean.find('{', index);
87
- size_t semi = clean.find(';', index);
88
- if (brace != std::string::npos && (semi == std::string::npos || brace < semi)) {
89
- int depth = 0;
90
- size_t i = brace;
91
- for (; i < clean.size(); i++) {
92
- if (clean[i] == '{') depth++;
93
- else if (clean[i] == '}') {
94
- depth--;
95
- if (depth == 0) break;
96
- }
97
- }
98
- index = (i < clean.size()) ? i + 1 : clean.size();
99
- } else {
100
- index = (semi == std::string::npos) ? clean.size() : semi + 1;
101
- }
102
- continue;
103
- }
104
- size_t brace = clean.find('{', index);
105
- if (brace == std::string::npos) break;
106
- int depth = 0;
107
- size_t close = std::string::npos;
108
- for (size_t i = brace; i < clean.size(); i++) {
109
- if (clean[i] == '{') depth++;
110
- else if (clean[i] == '}') {
111
- depth--;
112
- if (depth == 0) {
113
- close = i;
114
- break;
115
- }
116
- }
117
- }
118
- if (close == std::string::npos) break;
119
- Rule rule;
120
- rule.selectors = xt_css_parse_selector_list(clean.substr(index, brace - index));
121
- rule.declarations = xt_css_parse_declarations(clean.substr(brace + 1, close - brace - 1));
122
- rule.order = order++;
123
- if (!rule.selectors.empty() && !rule.declarations.empty()) sheet.rules.push_back(std::move(rule));
124
- index = close + 1;
125
- }
169
+ parseRules(clean, "", &order, &sheet);
126
170
  return sheet;
127
171
  }
128
172
 
@@ -47,7 +47,7 @@ void XtDocument::restyle(float viewportWidth, float viewportHeight) {
47
47
  MatchState state;
48
48
  state.hover = hover_;
49
49
  state.focus = focus_;
50
- xt_style_compute(root_.get(), sheet_, styles_, viewportWidth, viewportHeight, state);
50
+ xt_style_compute(root_.get(), sheet_, styles_, viewportWidth, viewportHeight, state, &pseudos_);
51
51
  startTransitions();
52
52
  updateDisplay();
53
53
  }
@@ -124,6 +124,9 @@ void XtDocument::startTransitions() {
124
124
  for (auto &entry : styles_) {
125
125
  const Node *node = entry.first;
126
126
  const XtStyle &target = entry.second;
127
+ /* Generated boxes are rebuilt on every restyle; a transition keyed by one
128
+ * would address a node that no longer exists. */
129
+ if (node->is_pseudo) continue;
127
130
  if (target.transitions.empty()) continue;
128
131
  auto prev_it = display_.find(node);
129
132
  if (prev_it == display_.end()) continue;
@@ -118,6 +118,8 @@ class XtDocument {
118
118
  std::unique_ptr<Node> root_;
119
119
  /** Detached nodes (created or removed) stay alive here so handles remain valid. */
120
120
  std::unordered_map<const Node *, std::unique_ptr<Node>> detached_;
121
+ /** Synthetic `::before`/`::after` nodes for the current style generation. */
122
+ PseudoNodeSet pseudos_;
121
123
  bool dirty_ = false;
122
124
  StyleSheet sheet_;
123
125
  std::unordered_map<const Node *, XtStyle> styles_; // target (cascade)
@@ -18,6 +18,9 @@ namespace xtgui {
18
18
 
19
19
  enum class NodeType { Document, Element, Text };
20
20
 
21
+ /** Which generated-content box a synthetic pseudo-element node represents. */
22
+ enum class PseudoElement { None, Before, After };
23
+
21
24
  struct Attr {
22
25
  std::string name;
23
26
  std::string value;
@@ -32,6 +35,19 @@ struct Node {
32
35
  Node *parent = nullptr;
33
36
  std::vector<std::unique_ptr<Node>> children;
34
37
 
38
+ /* -- generated content (`::before` / `::after`) -------------------------
39
+ * A pseudo-element is a synthetic node owned by the document's per-restyle
40
+ * arena, not by the DOM tree: it is never in `children`, so traversal,
41
+ * queries, serialization and `elementIndex()` do not see it. `pseudo_origin`
42
+ * is the element the selector matched and whose computed style it inherits.
43
+ * `pseudo_before`/`pseudo_after` are transient pointers set by the cascade
44
+ * for the layout pass (the arena is rebuilt on every restyle). */
45
+ bool is_pseudo = false;
46
+ PseudoElement pseudo = PseudoElement::None;
47
+ const Node *pseudo_origin = nullptr;
48
+ Node *pseudo_before = nullptr;
49
+ Node *pseudo_after = nullptr;
50
+
35
51
  Node() = default;
36
52
  explicit Node(NodeType nodeType) : type(nodeType) {}
37
53
 
@@ -52,11 +52,39 @@ XtGuiWindow *resolve_window(xt_value self) {
52
52
  return xt_gui_window_from_this(xt_object_get_cstr(self, "__xt_gui_win"));
53
53
  }
54
54
 
55
+ /** Bind a pending handle to the node its key now finds: copy the slot
56
+ * bookkeeping of the canonical handle, then drop the pending marker so later
57
+ * resolutions take the normal path. */
58
+ static xtgui::Node *bind_pending(XtGuiWindow *win, xt_value self, xtgui::Node *node) {
59
+ xt_value canonical = xt_gui_node_handle(win, node);
60
+ if (!XT_IS_OBJECT(canonical)) return nullptr;
61
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_node"),
62
+ xt_object_get_cstr(canonical, "__xt_gui_node"));
63
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_slot_gen"),
64
+ xt_object_get_cstr(canonical, "__xt_gui_slot_gen"));
65
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_gen"),
66
+ xt_object_get_cstr(canonical, "__xt_gui_gen"));
67
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_pending"), XT_UNDEFINED);
68
+ xt_gui_canvas_bind_pending(win, node, self);
69
+ return node;
70
+ }
71
+
55
72
  /** Resolve a node handle to its node, or NULL when it is stale/foreign. */
56
73
  xtgui::Node *resolve_node(xt_value self, XtGuiWindow **winOut) {
57
74
  XtGuiWindow *win = resolve_window(self);
58
75
  if (winOut != nullptr) *winOut = win;
59
76
  if (win == nullptr || win->document == nullptr) return nullptr;
77
+ /* A pending handle names its node indirectly so that a module which queried
78
+ * `#id` before `loadHTML` ran still works: look the key up now and bind. */
79
+ xt_value pending = xt_object_get_cstr(self, "__xt_gui_pending");
80
+ if (XT_IS_NUMBER(pending)) {
81
+ std::string key = to_string_value(xt_object_get_cstr(self, "__xt_gui_pending_key"));
82
+ xtgui::Node *node = (int)xt_to_number(pending) == domapi::pending_by_id
83
+ ? domapi::document_find_by_id(win, key)
84
+ : domapi::document_query_selector(win, key);
85
+ if (node == nullptr) return nullptr;
86
+ return bind_pending(win, self, node);
87
+ }
60
88
  xt_value gen = xt_object_get_cstr(self, "__xt_gui_gen");
61
89
  if (!XT_IS_NUMBER(gen) || xt_to_number(gen) != win->doc_generation) return nullptr;
62
90
  if (value_truthy(xt_object_get_cstr(self, "__xt_gui_doc"))) {
@@ -121,6 +149,15 @@ void set_class_name(XtGuiWindow *win, xtgui::Node *node, const std::string &valu
121
149
  }
122
150
  }
123
151
 
152
+ xt_value pending_handle(XtGuiWindow *win, int kind, const std::string &key) {
153
+ xt_value handle = xt_object_new_with_proto(node_proto());
154
+ if (win != nullptr) xt_object_set(handle, xt_string_from_cstr("__xt_gui_win"), win->object);
155
+ xt_object_set(handle, xt_string_from_cstr("__xt_gui_pending"), xt_number((double)kind));
156
+ xt_object_set(handle, xt_string_from_cstr("__xt_gui_pending_key"),
157
+ xt_string_from_cstr(key.c_str()));
158
+ return handle;
159
+ }
160
+
124
161
  } // namespace domapi
125
162
 
126
163
  xt_value xt_gui_node_handle(XtGuiWindow *win, const xtgui::Node *node) {
@@ -58,8 +58,23 @@ METHOD(node_get_context) {
58
58
  std::string mode = string_arg(argc, argv, 0);
59
59
  XtGuiWindow *win = nullptr;
60
60
  xtgui::Node *node = resolve_node(self, &win);
61
- if (node == nullptr || !node->isElement() || !node->isTag("canvas")) return XT_NULL;
61
+ if (mode == "webgl" || mode == "experimental-webgl" || mode == "webgl2") {
62
+ const bool webgl2 = mode == "webgl2";
63
+ if (node == nullptr) return XT_NULL;
64
+ if (!node->isElement() || !node->isTag("canvas")) return XT_NULL;
65
+ if (xt_gui_canvas_find(win, node) != nullptr) return XT_NULL; // already a 2D canvas
66
+ xt_value cached = xt_object_get_cstr(self, "__xt_gui_gl");
67
+ if (XT_IS_OBJECT(cached)) {
68
+ const bool cached_webgl2 = value_truthy(xt_object_get_cstr(cached, "__xt_gl_webgl2"));
69
+ return cached_webgl2 == webgl2 ? cached : XT_NULL;
70
+ }
71
+ xtgui::WebGLContext *context = xt_gui_webgl_get(win, node, webgl2);
72
+ return webgl_context_handle(self, context);
73
+ }
62
74
  if (mode != "2d") return XT_NULL;
75
+ if (node == nullptr) return xt_canvas_pending_context(self, win);
76
+ if (!node->isElement() || !node->isTag("canvas")) return XT_NULL;
77
+ if (xt_gui_webgl_find(win, node) != nullptr) return XT_NULL; // already a WebGL canvas
63
78
  xtgui::Canvas2D *canvas = xt_gui_canvas_get(win, node);
64
79
  if (canvas == nullptr) return XT_NULL;
65
80
  xt_value cached = xt_object_get_cstr(self, "__xt_gui_ctx");
@@ -72,84 +87,6 @@ METHOD(node_get_context) {
72
87
  return ctx;
73
88
  }
74
89
 
75
- METHOD(node_width_get) {
76
- (void)env;
77
- (void)argc;
78
- (void)argv;
79
- XtGuiWindow *win = nullptr;
80
- xtgui::Node *node = resolve_node(self, &win);
81
- if (node == nullptr || !node->isElement()) return xt_number(0);
82
- if (node->isTag("canvas")) {
83
- xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
84
- if (canvas != nullptr) return xt_number(canvas->width());
85
- }
86
- const std::string *attr = node->attr("width");
87
- float value = 0.0f;
88
- if (attr != nullptr && xtgui::xt_css_parse_number(*attr, &value)) return xt_number(value);
89
- return xt_number(0);
90
- }
91
-
92
- METHOD(node_width_set) {
93
- (void)env;
94
- XtGuiWindow *win = nullptr;
95
- xtgui::Node *node = resolve_node(self, &win);
96
- if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
97
- double value = number_arg(argc, argv, 0, 0.0);
98
- if (node->isTag("canvas")) {
99
- xtgui::Canvas2D *canvas = xt_gui_canvas_get(win, node);
100
- if (canvas != nullptr) {
101
- canvas->resize((int)value, canvas->height());
102
- if (win != nullptr && win->document != nullptr) {
103
- win->document->setCanvasInfo(node, (float)canvas->width(), (float)canvas->height(),
104
- canvas->id());
105
- }
106
- }
107
- return XT_UNDEFINED;
108
- }
109
- set_attribute(win, node, "width", std::to_string((long long)value));
110
- return XT_UNDEFINED;
111
- }
112
-
113
- METHOD(node_height_get) {
114
- (void)env;
115
- (void)argc;
116
- (void)argv;
117
- XtGuiWindow *win = nullptr;
118
- xtgui::Node *node = resolve_node(self, &win);
119
- if (node == nullptr || !node->isElement()) return xt_number(0);
120
- if (node->isTag("canvas")) {
121
- xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
122
- if (canvas != nullptr) return xt_number(canvas->height());
123
- }
124
- const std::string *attr = node->attr("height");
125
- float value = 0.0f;
126
- if (attr != nullptr && xtgui::xt_css_parse_number(*attr, &value)) return xt_number(value);
127
- return xt_number(0);
128
- }
129
-
130
- METHOD(node_height_set) {
131
- (void)env;
132
- XtGuiWindow *win = nullptr;
133
- xtgui::Node *node = resolve_node(self, &win);
134
- if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
135
- double value = number_arg(argc, argv, 0, 0.0);
136
- if (node->isTag("canvas")) {
137
- xtgui::Canvas2D *canvas = xt_gui_canvas_get(win, node);
138
- if (canvas != nullptr) {
139
- canvas->resize(canvas->width(), (int)value);
140
- if (win != nullptr && win->document != nullptr) {
141
- win->document->setCanvasInfo(node, (float)canvas->width(), (float)canvas->height(),
142
- canvas->id());
143
- }
144
- }
145
- return XT_UNDEFINED;
146
- }
147
- set_attribute(win, node, "height", std::to_string((long long)value));
148
- return XT_UNDEFINED;
149
- }
150
-
151
- /* -- state / style getters and setters ------------------------------------ */
152
-
153
90
  METHOD(canvas_get_canvas) {
154
91
  (void)env;
155
92
  (void)argc;
@@ -579,4 +516,4 @@ METHOD(canvas_get_image_data) {
579
516
 
580
517
  } // namespace domapi
581
518
 
582
- #undef METHOD
519
+ #undef METHOD
@@ -227,6 +227,135 @@ METHOD(canvas_get_transform) {
227
227
  return result;
228
228
  }
229
229
 
230
+ METHOD(node_width_get) {
231
+ (void)env;
232
+ (void)argc;
233
+ (void)argv;
234
+ XtGuiWindow *win = nullptr;
235
+ xtgui::Node *node = resolve_node(self, &win);
236
+ if (node == nullptr || !node->isElement()) return xt_number(0);
237
+ if (node->isTag("canvas")) {
238
+ if (xtgui::WebGLContext *webgl = xt_gui_webgl_find(win, node)) {
239
+ return xt_number(webgl->width());
240
+ }
241
+ xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
242
+ if (canvas != nullptr) return xt_number(canvas->width());
243
+ }
244
+ const std::string *attr = node->attr("width");
245
+ float value = 0.0f;
246
+ if (attr != nullptr && xtgui::xt_css_parse_number(*attr, &value)) return xt_number(value);
247
+ /* A canvas with no context still reports the CSS default bitmap size. */
248
+ return xt_number(node->isTag("canvas") ? 300 : 0);
249
+ }
250
+
251
+ METHOD(node_width_set) {
252
+ (void)env;
253
+ XtGuiWindow *win = nullptr;
254
+ xtgui::Node *node = resolve_node(self, &win);
255
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
256
+ double value = canvas_number_arg(argc, argv, 0, 0.0);
257
+ if (node->isTag("canvas")) {
258
+ if (xtgui::WebGLContext *webgl = xt_gui_webgl_find(win, node)) {
259
+ webgl->resize((int)value, webgl->height());
260
+ /* A resize replaces the colour texture; the page has to re-upload the
261
+ * image op even when the box size did not change. */
262
+ mark_dirty(win);
263
+ if (win != nullptr && win->document != nullptr) {
264
+ win->document->setCanvasInfo(node, (float)webgl->width(), (float)webgl->height(),
265
+ webgl->id());
266
+ }
267
+ return XT_UNDEFINED;
268
+ }
269
+ xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
270
+ if (canvas != nullptr) {
271
+ canvas->resize((int)value, canvas->height());
272
+ if (win != nullptr && win->document != nullptr) {
273
+ win->document->setCanvasInfo(node, (float)canvas->width(), (float)canvas->height(),
274
+ canvas->id());
275
+ }
276
+ return XT_UNDEFINED;
277
+ }
278
+ /* No context yet: update the attribute so a later getContext uses it. */
279
+ int height = 150;
280
+ const std::string *height_attr = node->attr("height");
281
+ float parsed = 0.0f;
282
+ if (height_attr != nullptr && xtgui::xt_css_parse_number(*height_attr, &parsed)) {
283
+ height = (int)(parsed + 0.5f);
284
+ }
285
+ set_attribute(win, node, "width", std::to_string((long long)value));
286
+ if (win != nullptr && win->document != nullptr) {
287
+ win->document->setCanvasInfo(node, (float)value, (float)height, 0);
288
+ }
289
+ return XT_UNDEFINED;
290
+ }
291
+ set_attribute(win, node, "width", std::to_string((long long)value));
292
+ return XT_UNDEFINED;
293
+ }
294
+
295
+ METHOD(node_height_get) {
296
+ (void)env;
297
+ (void)argc;
298
+ (void)argv;
299
+ XtGuiWindow *win = nullptr;
300
+ xtgui::Node *node = resolve_node(self, &win);
301
+ if (node == nullptr || !node->isElement()) return xt_number(0);
302
+ if (node->isTag("canvas")) {
303
+ if (xtgui::WebGLContext *webgl = xt_gui_webgl_find(win, node)) {
304
+ return xt_number(webgl->height());
305
+ }
306
+ xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
307
+ if (canvas != nullptr) return xt_number(canvas->height());
308
+ }
309
+ const std::string *attr = node->attr("height");
310
+ float value = 0.0f;
311
+ if (attr != nullptr && xtgui::xt_css_parse_number(*attr, &value)) return xt_number(value);
312
+ return xt_number(node->isTag("canvas") ? 150 : 0);
313
+ }
314
+
315
+ METHOD(node_height_set) {
316
+ (void)env;
317
+ XtGuiWindow *win = nullptr;
318
+ xtgui::Node *node = resolve_node(self, &win);
319
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
320
+ double value = canvas_number_arg(argc, argv, 0, 0.0);
321
+ if (node->isTag("canvas")) {
322
+ if (xtgui::WebGLContext *webgl = xt_gui_webgl_find(win, node)) {
323
+ webgl->resize(webgl->width(), (int)value);
324
+ mark_dirty(win);
325
+ if (win != nullptr && win->document != nullptr) {
326
+ win->document->setCanvasInfo(node, (float)webgl->width(), (float)webgl->height(),
327
+ webgl->id());
328
+ }
329
+ return XT_UNDEFINED;
330
+ }
331
+ xtgui::Canvas2D *canvas = xt_gui_canvas_find(win, node);
332
+ if (canvas != nullptr) {
333
+ canvas->resize(canvas->width(), (int)value);
334
+ if (win != nullptr && win->document != nullptr) {
335
+ win->document->setCanvasInfo(node, (float)canvas->width(), (float)canvas->height(),
336
+ canvas->id());
337
+ }
338
+ return XT_UNDEFINED;
339
+ }
340
+ int width = 300;
341
+ const std::string *width_attr = node->attr("width");
342
+ float parsed = 0.0f;
343
+ if (width_attr != nullptr && xtgui::xt_css_parse_number(*width_attr, &parsed)) {
344
+ width = (int)(parsed + 0.5f);
345
+ }
346
+ set_attribute(win, node, "height", std::to_string((long long)value));
347
+ if (win != nullptr && win->document != nullptr) {
348
+ win->document->setCanvasInfo(node, (float)width, (float)value, 0);
349
+ }
350
+ return XT_UNDEFINED;
351
+ }
352
+ set_attribute(win, node, "height", std::to_string((long long)value));
353
+ return XT_UNDEFINED;
354
+ }
355
+
356
+ /* -- state / style getters and setters ------------------------------------ */
357
+
358
+
230
359
  } // namespace domapi
231
360
 
232
- #undef METHOD
361
+ #undef METHOD
@@ -0,0 +1,41 @@
1
+ /*
2
+ * xbintsc GUI engine — 2D contexts for pending canvas handles.
3
+ *
4
+ * The gui extension hands out element handles before `loadHTML`; a module may
5
+ * call `getContext("2d")` in that window. Keep the bridge here so
6
+ * `dom_api_canvas.cpp` stays focused (and under the per-file line budget).
7
+ */
8
+ #include <memory>
9
+ #include <string>
10
+
11
+ #include "canvas.h"
12
+ #include "dom_api_internal.h"
13
+ #include "gui_engine.h"
14
+
15
+ namespace {
16
+
17
+ bool is_pending_canvas(xt_value self) {
18
+ xt_value pending = xt_object_get_cstr(self, "__xt_gui_pending");
19
+ return XT_IS_NUMBER(pending);
20
+ }
21
+
22
+ } // namespace
23
+
24
+ namespace domapi {
25
+
26
+ xt_value xt_canvas_pending_context(xt_value self, XtGuiWindow *win) {
27
+ if (!is_pending_canvas(self) || win == nullptr) return XT_NULL;
28
+ xt_value cached = xt_object_get_cstr(self, "__xt_gui_ctx");
29
+ if (XT_IS_OBJECT(cached)) return cached;
30
+ auto created = std::make_unique<xtgui::Canvas2D>(300, 150);
31
+ xtgui::Canvas2D *raw = created.get();
32
+ win->pending_canvases[raw->id()] = std::move(created);
33
+ xt_value ctx = xt_object_new_with_proto(canvas_proto());
34
+ xt_object_set(ctx, xt_string_from_cstr("__xt_gui_canvas"), xt_number((double)raw->id()));
35
+ xt_object_set(ctx, xt_string_from_cstr("__xt_gui_node"), self);
36
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_ctx"), ctx);
37
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_pending_canvas"), xt_number((double)raw->id()));
38
+ return ctx;
39
+ }
40
+
41
+ } // namespace domapi