xbintsc 0.3.18 → 0.3.35

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 (194) hide show
  1. package/README.md +33 -0
  2. package/dist/src/cli/main.js +124 -30
  3. package/dist/src/cli/main.js.map +1 -1
  4. package/dist/src/codegen/generator/calls/access.js +8 -1
  5. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  6. package/dist/src/codegen/generator/state.js +20 -0
  7. package/dist/src/codegen/generator/state.js.map +1 -1
  8. package/dist/src/codegen/generator/tables.d.ts +6 -0
  9. package/dist/src/codegen/generator/tables.js +38 -0
  10. package/dist/src/codegen/generator/tables.js.map +1 -1
  11. package/dist/src/driver/bundler/commonjs.d.ts +52 -0
  12. package/dist/src/driver/bundler/commonjs.js +493 -0
  13. package/dist/src/driver/bundler/commonjs.js.map +1 -0
  14. package/dist/src/driver/bundler/graph.d.ts +2 -1
  15. package/dist/src/driver/bundler/graph.js +32 -3
  16. package/dist/src/driver/bundler/graph.js.map +1 -1
  17. package/dist/src/driver/bundler/merge.d.ts +2 -1
  18. package/dist/src/driver/bundler/merge.js +16 -2
  19. package/dist/src/driver/bundler/merge.js.map +1 -1
  20. package/dist/src/driver/bundler/types.d.ts +8 -0
  21. package/dist/src/driver/compiler.d.ts +8 -1
  22. package/dist/src/driver/compiler.js +75 -7
  23. package/dist/src/driver/compiler.js.map +1 -1
  24. package/dist/src/driver/config.d.ts +53 -0
  25. package/dist/src/driver/config.js +141 -0
  26. package/dist/src/driver/config.js.map +1 -0
  27. package/dist/src/driver/icon.d.ts +62 -0
  28. package/dist/src/driver/icon.js +151 -0
  29. package/dist/src/driver/icon.js.map +1 -0
  30. package/dist/src/driver/index.d.ts +4 -0
  31. package/dist/src/driver/index.js +4 -0
  32. package/dist/src/driver/index.js.map +1 -1
  33. package/dist/src/driver/mac-bundle.d.ts +41 -0
  34. package/dist/src/driver/mac-bundle.js +123 -0
  35. package/dist/src/driver/mac-bundle.js.map +1 -0
  36. package/dist/src/driver/win-icon.d.ts +27 -0
  37. package/dist/src/driver/win-icon.js +80 -0
  38. package/dist/src/driver/win-icon.js.map +1 -0
  39. package/dist/src/extensions/gui/html.d.ts +25 -0
  40. package/dist/src/extensions/gui/html.js +203 -0
  41. package/dist/src/extensions/gui/html.js.map +1 -0
  42. package/dist/src/extensions/gui/index.js +11 -0
  43. package/dist/src/extensions/gui/index.js.map +1 -1
  44. package/dist/src/extensions/registry.d.ts +29 -0
  45. package/dist/src/extensions/registry.js +14 -0
  46. package/dist/src/extensions/registry.js.map +1 -1
  47. package/dist/src/index.d.ts +1 -1
  48. package/dist/src/index.js.map +1 -1
  49. package/dist/src/lexer/scanner/identifiers.js +4 -12
  50. package/dist/src/lexer/scanner/identifiers.js.map +1 -1
  51. package/dist/src/parser/statements.js +17 -4
  52. package/dist/src/parser/statements.js.map +1 -1
  53. package/dist/tests/cli/main.test.js +46 -1
  54. package/dist/tests/cli/main.test.js.map +1 -1
  55. package/dist/tests/driver/bundler-resolve.test.d.ts +1 -0
  56. package/dist/tests/driver/bundler-resolve.test.js +230 -0
  57. package/dist/tests/driver/bundler-resolve.test.js.map +1 -0
  58. package/dist/tests/driver/config.test.d.ts +1 -0
  59. package/dist/tests/driver/config.test.js +124 -0
  60. package/dist/tests/driver/config.test.js.map +1 -0
  61. package/dist/tests/driver/icon.test.d.ts +1 -0
  62. package/dist/tests/driver/icon.test.js +421 -0
  63. package/dist/tests/driver/icon.test.js.map +1 -0
  64. package/dist/tests/driver/modules.test.js +177 -0
  65. package/dist/tests/driver/modules.test.js.map +1 -1
  66. package/dist/tests/e2e/fetch.test.d.ts +12 -0
  67. package/dist/tests/e2e/fetch.test.js +272 -0
  68. package/dist/tests/e2e/fetch.test.js.map +1 -0
  69. package/dist/tests/e2e/gui-dom.test.d.ts +5 -0
  70. package/dist/tests/e2e/gui-dom.test.js +102 -0
  71. package/dist/tests/e2e/gui-dom.test.js.map +1 -0
  72. package/dist/tests/e2e/gui-events.test.d.ts +5 -0
  73. package/dist/tests/e2e/gui-events.test.js +60 -0
  74. package/dist/tests/e2e/gui-events.test.js.map +1 -0
  75. package/dist/tests/e2e/gui-helpers.d.ts +31 -0
  76. package/dist/tests/e2e/gui-helpers.js +74 -0
  77. package/dist/tests/e2e/gui-helpers.js.map +1 -0
  78. package/dist/tests/e2e/gui-layout.test.d.ts +4 -0
  79. package/dist/tests/e2e/gui-layout.test.js +88 -0
  80. package/dist/tests/e2e/gui-layout.test.js.map +1 -0
  81. package/dist/tests/e2e/gui-lifecycle.test.d.ts +5 -0
  82. package/dist/tests/e2e/gui-lifecycle.test.js +58 -0
  83. package/dist/tests/e2e/gui-lifecycle.test.js.map +1 -0
  84. package/dist/tests/e2e/gui-paint.test.d.ts +5 -0
  85. package/dist/tests/e2e/gui-paint.test.js +111 -0
  86. package/dist/tests/e2e/gui-paint.test.js.map +1 -0
  87. package/dist/tests/e2e/gui-script.test.d.ts +5 -0
  88. package/dist/tests/e2e/gui-script.test.js +78 -0
  89. package/dist/tests/e2e/gui-script.test.js.map +1 -0
  90. package/dist/tests/e2e/gui-style.test.d.ts +5 -0
  91. package/dist/tests/e2e/gui-style.test.js +175 -0
  92. package/dist/tests/e2e/gui-style.test.js.map +1 -0
  93. package/dist/tests/e2e/icon.test.d.ts +7 -0
  94. package/dist/tests/e2e/icon.test.js +80 -0
  95. package/dist/tests/e2e/icon.test.js.map +1 -0
  96. package/dist/tests/e2e/npm-modules.test.d.ts +4 -1
  97. package/dist/tests/e2e/npm-modules.test.js +47 -1
  98. package/dist/tests/e2e/npm-modules.test.js.map +1 -1
  99. package/dist/tests/e2e/runtime-coverage-typed-array.test.d.ts +9 -0
  100. package/dist/tests/e2e/runtime-coverage-typed-array.test.js +140 -0
  101. package/dist/tests/e2e/runtime-coverage-typed-array.test.js.map +1 -0
  102. package/dist/tests/extensions/gui-index.test.d.ts +1 -0
  103. package/dist/tests/extensions/gui-index.test.js +49 -0
  104. package/dist/tests/extensions/gui-index.test.js.map +1 -0
  105. package/dist/tests/extensions/gui.test.d.ts +1 -0
  106. package/dist/tests/extensions/gui.test.js +177 -0
  107. package/dist/tests/extensions/gui.test.js.map +1 -0
  108. package/dist/tests/extensions/registry.test.js +36 -0
  109. package/dist/tests/extensions/registry.test.js.map +1 -1
  110. package/dist/tests/parser/statements.test.js +11 -0
  111. package/dist/tests/parser/statements.test.js.map +1 -1
  112. package/dist/tests/public-api.test.d.ts +1 -0
  113. package/dist/tests/public-api.test.js +31 -0
  114. package/dist/tests/public-api.test.js.map +1 -0
  115. package/package.json +1 -1
  116. package/runtime/ext_gui/css.cpp +4 -517
  117. package/runtime/ext_gui/css_internal.h +27 -0
  118. package/runtime/ext_gui/css_match.cpp +195 -0
  119. package/runtime/ext_gui/css_selector.cpp +207 -0
  120. package/runtime/ext_gui/css_sheet.cpp +129 -0
  121. package/runtime/ext_gui/document.cpp +90 -0
  122. package/runtime/ext_gui/document.h +23 -0
  123. package/runtime/ext_gui/dom.cpp +43 -403
  124. package/runtime/ext_gui/dom.h +7 -0
  125. package/runtime/ext_gui/dom_api.cpp +164 -0
  126. package/runtime/ext_gui/dom_api.h +12 -0
  127. package/runtime/ext_gui/dom_api_document.cpp +96 -0
  128. package/runtime/ext_gui/dom_api_events.cpp +123 -0
  129. package/runtime/ext_gui/dom_api_internal.h +135 -0
  130. package/runtime/ext_gui/dom_api_node.cpp +329 -0
  131. package/runtime/ext_gui/dom_api_node_read.cpp +294 -0
  132. package/runtime/ext_gui/dom_api_proto.cpp +130 -0
  133. package/runtime/ext_gui/dom_api_style.cpp +192 -0
  134. package/runtime/ext_gui/dom_internal.h +39 -0
  135. package/runtime/ext_gui/dom_parse.cpp +348 -0
  136. package/runtime/ext_gui/dom_serialize.cpp +54 -0
  137. package/runtime/ext_gui/gui.cpp +61 -245
  138. package/runtime/ext_gui/gui_engine.h +54 -0
  139. package/runtime/ext_gui/gui_events.cpp +294 -0
  140. package/runtime/ext_gui/gui_internal.h +29 -0
  141. package/runtime/ext_gui/layout.cpp +6 -597
  142. package/runtime/ext_gui/layout_flex.cpp +200 -0
  143. package/runtime/ext_gui/layout_flow.cpp +191 -0
  144. package/runtime/ext_gui/layout_flow_internal.h +149 -0
  145. package/runtime/ext_gui/layout_inline.cpp +181 -0
  146. package/runtime/ext_gui/layout_internal.h +20 -0
  147. package/runtime/ext_gui/renderer.cpp +15 -679
  148. package/runtime/ext_gui/renderer_image.cpp +233 -0
  149. package/runtime/ext_gui/renderer_internal.h +112 -0
  150. package/runtime/ext_gui/renderer_shaders.h +108 -0
  151. package/runtime/ext_gui/renderer_text.cpp +342 -0
  152. package/runtime/ext_gui/script.cpp +63 -0
  153. package/runtime/ext_gui/style.cpp +12 -660
  154. package/runtime/ext_gui/style_internal.h +33 -0
  155. package/runtime/ext_gui/style_print.cpp +113 -0
  156. package/runtime/ext_gui/style_ua.cpp +98 -0
  157. package/runtime/ext_gui/style_values.cpp +468 -0
  158. package/runtime/ext_gui/window.cpp +60 -0
  159. package/runtime/rt.h +6 -0
  160. package/runtime/rt_internal.h +4 -0
  161. package/runtime/xt_builtins.c +1 -0
  162. package/runtime/xt_containers/access.inc +32 -1
  163. package/runtime/xt_fetch/buffer.inc +64 -0
  164. package/runtime/xt_fetch/headers.inc +312 -0
  165. package/runtime/xt_fetch/request.inc +386 -0
  166. package/runtime/xt_fetch/response.inc +107 -0
  167. package/runtime/xt_fetch/socket.inc +72 -0
  168. package/runtime/xt_fetch/url.inc +108 -0
  169. package/runtime/xt_fetch.c +39 -0
  170. package/runtime/xt_stdlib2/set.inc +1 -1
  171. package/runtime/xt_typed_array.c +614 -0
  172. package/src/cli/main.ts +137 -29
  173. package/src/codegen/generator/calls/access.ts +9 -1
  174. package/src/codegen/generator/state.ts +20 -0
  175. package/src/codegen/generator/tables.ts +40 -0
  176. package/src/driver/bundler/commonjs.ts +553 -0
  177. package/src/driver/bundler/graph.ts +35 -2
  178. package/src/driver/bundler/merge.ts +18 -1
  179. package/src/driver/bundler/types.ts +8 -0
  180. package/src/driver/compiler.ts +85 -7
  181. package/src/driver/config.ts +173 -0
  182. package/src/driver/icon.ts +184 -0
  183. package/src/driver/index.ts +30 -0
  184. package/src/driver/mac-bundle.ts +156 -0
  185. package/src/driver/win-icon.ts +96 -0
  186. package/src/extensions/gui/html.ts +236 -0
  187. package/src/extensions/gui/index.ts +11 -0
  188. package/src/extensions/registry.ts +39 -0
  189. package/src/index.ts +1 -1
  190. package/src/lexer/scanner/identifiers.ts +4 -11
  191. package/src/parser/statements.ts +17 -4
  192. package/dist/tests/e2e/gui.test.d.ts +0 -12
  193. package/dist/tests/e2e/gui.test.js +0 -493
  194. package/dist/tests/e2e/gui.test.js.map +0 -1
@@ -0,0 +1,294 @@
1
+ /*
2
+ * xbintsc GUI engine — element handle getters/setters (`tagName`, `id`,
3
+ * `className`, `textContent`, tree navigation, `classList`, `style`, ...).
4
+ */
5
+
6
+ #include "dom_api_internal.h"
7
+
8
+ #include <cctype>
9
+ #include <memory>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ namespace domapi {
14
+
15
+ static std::string to_upper(std::string text) {
16
+ for (char &c : text) c = (char)std::toupper((unsigned char)c);
17
+ return text;
18
+ }
19
+
20
+ static void collect_text(const xtgui::Node *node, std::string &out) {
21
+ if (node->isText()) {
22
+ out += node->text;
23
+ return;
24
+ }
25
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) collect_text(child.get(), out);
26
+ }
27
+
28
+ #define METHOD(name) xt_value name(xt_value self, xt_value env, int32_t argc, xt_value *argv)
29
+
30
+ METHOD(node_tag_name_get) {
31
+ (void)env;
32
+ (void)argc;
33
+ (void)argv;
34
+ XtGuiWindow *win = nullptr;
35
+ xtgui::Node *node = resolve_node(self, &win);
36
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
37
+ return xt_string_from_cstr(to_upper(node->tag).c_str());
38
+ }
39
+
40
+ METHOD(node_node_type_get) {
41
+ (void)env;
42
+ (void)argc;
43
+ (void)argv;
44
+ xtgui::Node *node = resolve_node(self, nullptr);
45
+ if (node == nullptr) return XT_UNDEFINED;
46
+ if (node->isElement()) return xt_number(1);
47
+ if (node->isText()) return xt_number(3);
48
+ return xt_number(9);
49
+ }
50
+
51
+ METHOD(node_id_get) {
52
+ (void)env;
53
+ (void)argc;
54
+ (void)argv;
55
+ xtgui::Node *node = resolve_node(self, nullptr);
56
+ if (node == nullptr || !node->isElement()) return xt_string_from_cstr("");
57
+ const std::string *value = node->attr("id");
58
+ return xt_string_from_cstr(value != nullptr ? value->c_str() : "");
59
+ }
60
+
61
+ METHOD(node_id_set) {
62
+ (void)env;
63
+ XtGuiWindow *win = nullptr;
64
+ xtgui::Node *node = resolve_node(self, &win);
65
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
66
+ set_attribute(win, node, "id", argc >= 1 ? to_string_value(xt_arg(argc, argv, 0)) : "");
67
+ return XT_UNDEFINED;
68
+ }
69
+
70
+ METHOD(node_class_name_get) {
71
+ (void)env;
72
+ (void)argc;
73
+ (void)argv;
74
+ xtgui::Node *node = resolve_node(self, nullptr);
75
+ if (node == nullptr || !node->isElement()) return xt_string_from_cstr("");
76
+ return xt_string_from_cstr(class_name_of(node).c_str());
77
+ }
78
+
79
+ METHOD(node_class_name_set) {
80
+ (void)env;
81
+ XtGuiWindow *win = nullptr;
82
+ xtgui::Node *node = resolve_node(self, &win);
83
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
84
+ set_class_name(win, node, argc >= 1 ? to_string_value(xt_arg(argc, argv, 0)) : "");
85
+ return XT_UNDEFINED;
86
+ }
87
+
88
+ METHOD(node_text_content_get) {
89
+ (void)env;
90
+ (void)argc;
91
+ (void)argv;
92
+ xtgui::Node *node = resolve_node(self, nullptr);
93
+ if (node == nullptr) return XT_UNDEFINED;
94
+ std::string out;
95
+ collect_text(node, out);
96
+ return xt_string_from_cstr(out.c_str());
97
+ }
98
+
99
+ METHOD(node_text_content_set) {
100
+ (void)env;
101
+ XtGuiWindow *win = nullptr;
102
+ xtgui::Node *node = resolve_node(self, &win);
103
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
104
+ std::string text = argc >= 1 ? to_string_value(xt_arg(argc, argv, 0)) : "";
105
+ std::vector<xtgui::Node *> existing;
106
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) existing.push_back(child.get());
107
+ for (xtgui::Node *child : existing) win->document->removeChild(node, child);
108
+ if (!text.empty()) node->addText(text);
109
+ mark_dirty(win);
110
+ return XT_UNDEFINED;
111
+ }
112
+
113
+ METHOD(node_inner_html_get) {
114
+ (void)env;
115
+ (void)argc;
116
+ (void)argv;
117
+ xtgui::Node *node = resolve_node(self, nullptr);
118
+ if (node == nullptr) return XT_UNDEFINED;
119
+ std::string out;
120
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) {
121
+ out += xtgui::xt_dom_to_string(child.get());
122
+ }
123
+ return xt_string_from_cstr(out.c_str());
124
+ }
125
+
126
+ METHOD(node_inner_html_set) {
127
+ (void)env;
128
+ XtGuiWindow *win = nullptr;
129
+ xtgui::Node *node = resolve_node(self, &win);
130
+ if (node == nullptr || !node->isElement()) return XT_UNDEFINED;
131
+ std::string html = argc >= 1 ? to_string_value(xt_arg(argc, argv, 0)) : "";
132
+ std::vector<xtgui::Node *> existing;
133
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) existing.push_back(child.get());
134
+ for (xtgui::Node *child : existing) win->document->removeChild(node, child);
135
+ std::unique_ptr<xtgui::Node> fragment = xtgui::xt_html_parse(html);
136
+ for (std::unique_ptr<xtgui::Node> &child : fragment->children) node->append(std::move(child));
137
+ mark_dirty(win);
138
+ return XT_UNDEFINED;
139
+ }
140
+
141
+ METHOD(node_parent_node_get) {
142
+ (void)env;
143
+ (void)argc;
144
+ (void)argv;
145
+ XtGuiWindow *win = nullptr;
146
+ xtgui::Node *node = resolve_node(self, &win);
147
+ if (node == nullptr || node->parent == nullptr || node->parent->isDocument()) return XT_UNDEFINED;
148
+ return xt_gui_node_handle(win, node->parent);
149
+ }
150
+
151
+ METHOD(node_parent_element_get) {
152
+ (void)env;
153
+ (void)argc;
154
+ (void)argv;
155
+ XtGuiWindow *win = nullptr;
156
+ xtgui::Node *node = resolve_node(self, &win);
157
+ if (node == nullptr || node->parent == nullptr || !node->parent->isElement()) return XT_UNDEFINED;
158
+ return xt_gui_node_handle(win, node->parent);
159
+ }
160
+
161
+ METHOD(node_children_get) {
162
+ (void)env;
163
+ (void)argc;
164
+ (void)argv;
165
+ XtGuiWindow *win = nullptr;
166
+ xtgui::Node *node = resolve_node(self, &win);
167
+ xt_value array = xt_array_new(0, NULL);
168
+ if (node == nullptr) return array;
169
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) {
170
+ if (child->isElement()) xt_array_push(array, xt_gui_node_handle(win, child.get()));
171
+ }
172
+ return array;
173
+ }
174
+
175
+ METHOD(node_child_nodes_get) {
176
+ (void)env;
177
+ (void)argc;
178
+ (void)argv;
179
+ XtGuiWindow *win = nullptr;
180
+ xtgui::Node *node = resolve_node(self, &win);
181
+ xt_value array = xt_array_new(0, NULL);
182
+ if (node == nullptr) return array;
183
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) {
184
+ xt_array_push(array, xt_gui_node_handle(win, child.get()));
185
+ }
186
+ return array;
187
+ }
188
+
189
+ METHOD(node_child_element_count_get) {
190
+ (void)env;
191
+ (void)argc;
192
+ (void)argv;
193
+ xtgui::Node *node = resolve_node(self, nullptr);
194
+ if (node == nullptr) return xt_number(0);
195
+ double count = 0;
196
+ for (const std::unique_ptr<xtgui::Node> &child : node->children) {
197
+ if (child->isElement()) count += 1;
198
+ }
199
+ return xt_number(count);
200
+ }
201
+
202
+ METHOD(node_first_element_child_get) {
203
+ (void)env;
204
+ (void)argc;
205
+ (void)argv;
206
+ XtGuiWindow *win = nullptr;
207
+ xtgui::Node *node = resolve_node(self, &win);
208
+ if (node == nullptr) return XT_UNDEFINED;
209
+ return xt_gui_node_handle(win, node->firstElementChild());
210
+ }
211
+
212
+ METHOD(node_last_element_child_get) {
213
+ (void)env;
214
+ (void)argc;
215
+ (void)argv;
216
+ XtGuiWindow *win = nullptr;
217
+ xtgui::Node *node = resolve_node(self, &win);
218
+ if (node == nullptr) return XT_UNDEFINED;
219
+ for (auto it = node->children.rbegin(); it != node->children.rend(); ++it) {
220
+ if ((*it)->isElement()) return xt_gui_node_handle(win, it->get());
221
+ }
222
+ return XT_UNDEFINED;
223
+ }
224
+
225
+ METHOD(node_next_element_sibling_get) {
226
+ (void)env;
227
+ (void)argc;
228
+ (void)argv;
229
+ XtGuiWindow *win = nullptr;
230
+ xtgui::Node *node = resolve_node(self, &win);
231
+ if (node == nullptr || node->parent == nullptr) return XT_UNDEFINED;
232
+ bool found = false;
233
+ for (const std::unique_ptr<xtgui::Node> &sibling : node->parent->children) {
234
+ if (sibling.get() == node) {
235
+ found = true;
236
+ continue;
237
+ }
238
+ if (found && sibling->isElement()) return xt_gui_node_handle(win, sibling.get());
239
+ }
240
+ return XT_UNDEFINED;
241
+ }
242
+
243
+ METHOD(node_previous_element_sibling_get) {
244
+ (void)env;
245
+ (void)argc;
246
+ (void)argv;
247
+ XtGuiWindow *win = nullptr;
248
+ xtgui::Node *node = resolve_node(self, &win);
249
+ if (node == nullptr || node->parent == nullptr) return XT_UNDEFINED;
250
+ xtgui::Node *previous = nullptr;
251
+ for (const std::unique_ptr<xtgui::Node> &sibling : node->parent->children) {
252
+ if (sibling.get() == node) break;
253
+ if (sibling->isElement()) previous = sibling.get();
254
+ }
255
+ return xt_gui_node_handle(win, previous);
256
+ }
257
+
258
+ METHOD(node_is_connected_get) {
259
+ (void)env;
260
+ (void)argc;
261
+ (void)argv;
262
+ XtGuiWindow *win = nullptr;
263
+ xtgui::Node *node = resolve_node(self, &win);
264
+ if (node == nullptr || win == nullptr || win->document == nullptr) return XT_FALSE;
265
+ return win->document->root()->contains(node) ? XT_TRUE : XT_FALSE;
266
+ }
267
+
268
+ METHOD(node_class_list_get) {
269
+ (void)env;
270
+ (void)argc;
271
+ (void)argv;
272
+ xt_value cached = xt_object_get_cstr(self, "__xt_gui_class_list");
273
+ if (XT_IS_OBJECT(cached)) return cached;
274
+ xt_value list = xt_object_new_with_proto(class_list_proto());
275
+ xt_object_set(list, xt_string_from_cstr("__xt_gui_node"), self);
276
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_class_list"), list);
277
+ return list;
278
+ }
279
+
280
+ METHOD(node_style_get) {
281
+ (void)env;
282
+ (void)argc;
283
+ (void)argv;
284
+ xt_value cached = xt_object_get_cstr(self, "__xt_gui_style");
285
+ if (XT_IS_OBJECT(cached)) return cached;
286
+ xt_value style = xt_object_new_with_proto(style_proto());
287
+ xt_object_set(style, xt_string_from_cstr("__xt_gui_node"), self);
288
+ xt_object_set(self, xt_string_from_cstr("__xt_gui_style"), style);
289
+ return style;
290
+ }
291
+
292
+ #undef METHOD
293
+
294
+ } // namespace domapi
@@ -0,0 +1,130 @@
1
+ /*
2
+ * xbintsc GUI engine — lazy construction of the DOM prototypes (node,
3
+ * document, event, classList, style).
4
+ */
5
+
6
+ #include "dom_api_internal.h"
7
+
8
+ namespace domapi {
9
+
10
+ static void define_method(xt_value proto, const char *name, void *fn) {
11
+ xt_object_set(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
12
+ }
13
+
14
+ static void define_getter(xt_value proto, const char *name, void *fn) {
15
+ xt_object_define_getter(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
16
+ }
17
+
18
+ static void define_setter(xt_value proto, const char *name, void *fn) {
19
+ xt_object_define_setter(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
20
+ }
21
+
22
+ xt_value node_proto() {
23
+ if (XT_IS_OBJECT(g_node_proto)) return g_node_proto;
24
+ xt_value proto = xt_object_new();
25
+ /* Getters. */
26
+ define_getter(proto, "tagName", (void *)node_tag_name_get);
27
+ define_getter(proto, "nodeName", (void *)node_tag_name_get);
28
+ define_getter(proto, "nodeType", (void *)node_node_type_get);
29
+ define_getter(proto, "id", (void *)node_id_get);
30
+ define_getter(proto, "className", (void *)node_class_name_get);
31
+ define_getter(proto, "textContent", (void *)node_text_content_get);
32
+ define_getter(proto, "innerText", (void *)node_text_content_get);
33
+ define_getter(proto, "innerHTML", (void *)node_inner_html_get);
34
+ define_getter(proto, "parentNode", (void *)node_parent_node_get);
35
+ define_getter(proto, "parentElement", (void *)node_parent_element_get);
36
+ define_getter(proto, "children", (void *)node_children_get);
37
+ define_getter(proto, "childNodes", (void *)node_child_nodes_get);
38
+ define_getter(proto, "childElementCount", (void *)node_child_element_count_get);
39
+ define_getter(proto, "firstElementChild", (void *)node_first_element_child_get);
40
+ define_getter(proto, "lastElementChild", (void *)node_last_element_child_get);
41
+ define_getter(proto, "nextElementSibling", (void *)node_next_element_sibling_get);
42
+ define_getter(proto, "previousElementSibling", (void *)node_previous_element_sibling_get);
43
+ define_getter(proto, "isConnected", (void *)node_is_connected_get);
44
+ define_getter(proto, "classList", (void *)node_class_list_get);
45
+ define_getter(proto, "style", (void *)node_style_get);
46
+ define_getter(proto, "offsetWidth", (void *)node_offset_width_get);
47
+ define_getter(proto, "offsetHeight", (void *)node_offset_height_get);
48
+ /* Setters. */
49
+ define_setter(proto, "id", (void *)node_id_set);
50
+ define_setter(proto, "className", (void *)node_class_name_set);
51
+ define_setter(proto, "textContent", (void *)node_text_content_set);
52
+ define_setter(proto, "innerText", (void *)node_text_content_set);
53
+ define_setter(proto, "innerHTML", (void *)node_inner_html_set);
54
+ /* Methods. */
55
+ define_method(proto, "getAttribute", (void *)node_get_attribute);
56
+ define_method(proto, "setAttribute", (void *)node_set_attribute);
57
+ define_method(proto, "removeAttribute", (void *)node_remove_attribute);
58
+ define_method(proto, "hasAttribute", (void *)node_has_attribute);
59
+ define_method(proto, "querySelector", (void *)node_query_selector);
60
+ define_method(proto, "querySelectorAll", (void *)node_query_selector_all);
61
+ define_method(proto, "matches", (void *)node_matches);
62
+ define_method(proto, "appendChild", (void *)node_append_child);
63
+ define_method(proto, "insertBefore", (void *)node_insert_before);
64
+ define_method(proto, "removeChild", (void *)node_remove_child);
65
+ define_method(proto, "replaceChild", (void *)node_replace_child);
66
+ define_method(proto, "remove", (void *)node_remove);
67
+ define_method(proto, "cloneNode", (void *)node_clone_node);
68
+ define_method(proto, "getBoundingClientRect", (void *)node_get_bounding_rect);
69
+ define_method(proto, "contains", (void *)node_contains);
70
+ define_method(proto, "focus", (void *)node_focus);
71
+ define_method(proto, "blur", (void *)node_blur);
72
+ define_method(proto, "click", (void *)node_click);
73
+ define_method(proto, "addEventListener", (void *)node_add_event_listener);
74
+ define_method(proto, "removeEventListener", (void *)node_remove_event_listener);
75
+ define_method(proto, "dispatchEvent", (void *)node_dispatch_event);
76
+ g_node_proto = proto;
77
+ return proto;
78
+ }
79
+
80
+ xt_value document_proto() {
81
+ if (XT_IS_OBJECT(g_document_proto)) return g_document_proto;
82
+ xt_value proto = xt_object_new_with_proto(node_proto());
83
+ define_getter(proto, "body", (void *)doc_body_get);
84
+ define_getter(proto, "documentElement", (void *)doc_document_element_get);
85
+ define_method(proto, "querySelector", (void *)doc_query_selector);
86
+ define_method(proto, "querySelectorAll", (void *)doc_query_selector_all);
87
+ define_method(proto, "getElementById", (void *)doc_get_element_by_id);
88
+ define_method(proto, "createElement", (void *)doc_create_element);
89
+ define_method(proto, "createTextNode", (void *)doc_create_text_node);
90
+ /* `document.addEventListener` / element listener plumbing come from the node
91
+ * prototype and operate on the document root node. */
92
+ define_method(proto, "addEventListener", (void *)node_add_event_listener);
93
+ define_method(proto, "removeEventListener", (void *)node_remove_event_listener);
94
+ define_method(proto, "dispatchEvent", (void *)node_dispatch_event);
95
+ g_document_proto = proto;
96
+ return proto;
97
+ }
98
+
99
+ xt_value event_proto() {
100
+ if (XT_IS_OBJECT(g_event_proto)) return g_event_proto;
101
+ xt_value proto = xt_object_new();
102
+ define_method(proto, "preventDefault", (void *)event_prevent_default);
103
+ define_method(proto, "stopPropagation", (void *)event_stop_propagation);
104
+ define_method(proto, "stopImmediatePropagation", (void *)event_stop_immediate_propagation);
105
+ g_event_proto = proto;
106
+ return proto;
107
+ }
108
+
109
+ xt_value class_list_proto() {
110
+ if (XT_IS_OBJECT(g_class_list_proto)) return g_class_list_proto;
111
+ xt_value proto = xt_object_new();
112
+ define_method(proto, "add", (void *)class_list_add);
113
+ define_method(proto, "remove", (void *)class_list_remove);
114
+ define_method(proto, "toggle", (void *)class_list_toggle);
115
+ define_method(proto, "contains", (void *)class_list_contains);
116
+ g_class_list_proto = proto;
117
+ return proto;
118
+ }
119
+
120
+ xt_value style_proto() {
121
+ if (XT_IS_OBJECT(g_style_proto)) return g_style_proto;
122
+ xt_value proto = xt_object_new();
123
+ define_method(proto, "setProperty", (void *)style_set_property);
124
+ define_method(proto, "getPropertyValue", (void *)style_get_property_value);
125
+ define_method(proto, "removeProperty", (void *)style_remove_property);
126
+ g_style_proto = proto;
127
+ return proto;
128
+ }
129
+
130
+ } // namespace domapi
@@ -0,0 +1,192 @@
1
+ /*
2
+ * xbintsc GUI engine — `classList` and inline `style` object methods.
3
+ */
4
+
5
+ #include "dom_api_internal.h"
6
+
7
+ #include <algorithm>
8
+ #include <cctype>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ namespace domapi {
13
+
14
+ static std::vector<std::string> split_classes(const std::string &text) {
15
+ std::vector<std::string> out;
16
+ size_t index = 0;
17
+ while (index < text.size()) {
18
+ while (index < text.size() && std::isspace((unsigned char)text[index])) index++;
19
+ size_t start = index;
20
+ while (index < text.size() && !std::isspace((unsigned char)text[index])) index++;
21
+ if (index > start) out.push_back(text.substr(start, index - start));
22
+ }
23
+ return out;
24
+ }
25
+
26
+ static std::string join_classes(const std::vector<std::string> &names) {
27
+ std::string out;
28
+ for (size_t i = 0; i < names.size(); i++) {
29
+ if (i > 0) out += " ";
30
+ out += names[i];
31
+ }
32
+ return out;
33
+ }
34
+
35
+ static std::string inline_style_of(const xtgui::Node *node) {
36
+ const std::string *value = node->attr("style");
37
+ return value != nullptr ? *value : std::string();
38
+ }
39
+
40
+ static void write_declarations(xtgui::Node *node, const std::vector<xtgui::Declaration> &decls) {
41
+ std::string out;
42
+ for (const xtgui::Declaration &decl : decls) {
43
+ if (!out.empty()) out += ";";
44
+ out += decl.property + ":" + decl.value + (decl.important ? " !important" : "");
45
+ }
46
+ if (out.empty()) {
47
+ remove_attribute_raw(node, "style");
48
+ } else {
49
+ set_attribute_raw(node, "style", out);
50
+ }
51
+ }
52
+
53
+ static void set_style_property(XtGuiWindow *win, xtgui::Node *node, const std::string &name,
54
+ const std::string &value) {
55
+ std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
56
+ bool found = false;
57
+ for (xtgui::Declaration &decl : decls) {
58
+ if (decl.property == name) {
59
+ decl.value = value;
60
+ decl.important = false;
61
+ found = true;
62
+ }
63
+ }
64
+ if (!found) decls.push_back({name, value, false});
65
+ write_declarations(node, decls);
66
+ mark_dirty(win);
67
+ }
68
+
69
+ static std::string get_style_property(const xtgui::Node *node, const std::string &name) {
70
+ std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
71
+ std::string value;
72
+ for (const xtgui::Declaration &decl : decls) {
73
+ if (decl.property == name) value = decl.value;
74
+ }
75
+ return value;
76
+ }
77
+
78
+ static void remove_style_property(XtGuiWindow *win, xtgui::Node *node, const std::string &name) {
79
+ std::vector<xtgui::Declaration> decls = xtgui::xt_css_parse_declarations(inline_style_of(node));
80
+ std::vector<xtgui::Declaration> kept;
81
+ for (const xtgui::Declaration &decl : decls) {
82
+ if (decl.property != name) kept.push_back(decl);
83
+ }
84
+ write_declarations(node, kept);
85
+ mark_dirty(win);
86
+ }
87
+
88
+ static xtgui::Node *class_list_node(xt_value self, XtGuiWindow **winOut) {
89
+ return resolve_node(xt_object_get_cstr(self, "__xt_gui_node"), winOut);
90
+ }
91
+
92
+ #define METHOD(name) xt_value name(xt_value self, xt_value env, int32_t argc, xt_value *argv)
93
+
94
+ METHOD(class_list_add) {
95
+ (void)env;
96
+ XtGuiWindow *win = nullptr;
97
+ xtgui::Node *node = class_list_node(self, &win);
98
+ if (node == nullptr) return self;
99
+ std::vector<std::string> names = split_classes(class_name_of(node));
100
+ bool changed = false;
101
+ for (int32_t i = 0; i < argc; i++) {
102
+ std::string name = to_string_value(xt_arg(argc, argv, i));
103
+ if (name.empty() || std::find(names.begin(), names.end(), name) != names.end()) continue;
104
+ names.push_back(name);
105
+ changed = true;
106
+ }
107
+ if (changed) set_class_name(win, node, join_classes(names));
108
+ return self;
109
+ }
110
+
111
+ METHOD(class_list_remove) {
112
+ (void)env;
113
+ XtGuiWindow *win = nullptr;
114
+ xtgui::Node *node = class_list_node(self, &win);
115
+ if (node == nullptr) return self;
116
+ std::vector<std::string> names = split_classes(class_name_of(node));
117
+ bool changed = false;
118
+ for (int32_t i = 0; i < argc; i++) {
119
+ std::string name = to_string_value(xt_arg(argc, argv, i));
120
+ auto it = std::find(names.begin(), names.end(), name);
121
+ if (it != names.end()) {
122
+ names.erase(it);
123
+ changed = true;
124
+ }
125
+ }
126
+ if (changed) set_class_name(win, node, join_classes(names));
127
+ return self;
128
+ }
129
+
130
+ METHOD(class_list_toggle) {
131
+ (void)env;
132
+ XtGuiWindow *win = nullptr;
133
+ xtgui::Node *node = class_list_node(self, &win);
134
+ if (node == nullptr || argc < 1) return XT_FALSE;
135
+ std::string name = to_string_value(xt_arg(argc, argv, 0));
136
+ std::vector<std::string> names = split_classes(class_name_of(node));
137
+ auto it = std::find(names.begin(), names.end(), name);
138
+ if (it != names.end()) {
139
+ names.erase(it);
140
+ set_class_name(win, node, join_classes(names));
141
+ return XT_FALSE;
142
+ }
143
+ if (!name.empty()) {
144
+ names.push_back(name);
145
+ set_class_name(win, node, join_classes(names));
146
+ }
147
+ return XT_TRUE;
148
+ }
149
+
150
+ METHOD(class_list_contains) {
151
+ (void)env;
152
+ xtgui::Node *node = class_list_node(self, nullptr);
153
+ if (node == nullptr || argc < 1) return XT_FALSE;
154
+ std::string name = to_string_value(xt_arg(argc, argv, 0));
155
+ std::vector<std::string> names = split_classes(class_name_of(node));
156
+ return std::find(names.begin(), names.end(), name) != names.end() ? XT_TRUE : XT_FALSE;
157
+ }
158
+
159
+ static xtgui::Node *style_node(xt_value self, XtGuiWindow **winOut) {
160
+ return resolve_node(xt_object_get_cstr(self, "__xt_gui_node"), winOut);
161
+ }
162
+
163
+ METHOD(style_set_property) {
164
+ (void)env;
165
+ XtGuiWindow *win = nullptr;
166
+ xtgui::Node *node = style_node(self, &win);
167
+ if (node == nullptr || argc < 2) return XT_UNDEFINED;
168
+ set_style_property(win, node, to_string_value(xt_arg(argc, argv, 0)),
169
+ to_string_value(xt_arg(argc, argv, 1)));
170
+ return XT_UNDEFINED;
171
+ }
172
+
173
+ METHOD(style_get_property_value) {
174
+ (void)env;
175
+ xtgui::Node *node = style_node(self, nullptr);
176
+ if (node == nullptr || argc < 1) return xt_string_from_cstr("");
177
+ return xt_string_from_cstr(
178
+ get_style_property(node, to_string_value(xt_arg(argc, argv, 0))).c_str());
179
+ }
180
+
181
+ METHOD(style_remove_property) {
182
+ (void)env;
183
+ XtGuiWindow *win = nullptr;
184
+ xtgui::Node *node = style_node(self, &win);
185
+ if (node == nullptr || argc < 1) return XT_UNDEFINED;
186
+ remove_style_property(win, node, to_string_value(xt_arg(argc, argv, 0)));
187
+ return XT_UNDEFINED;
188
+ }
189
+
190
+ #undef METHOD
191
+
192
+ } // namespace domapi
@@ -0,0 +1,39 @@
1
+ /*
2
+ * xbintsc GUI engine — shared helpers for the DOM translation units
3
+ * (`dom.cpp`, `dom_parse.cpp`, `dom_serialize.cpp`).
4
+ */
5
+ #ifndef XT_GUI_DOM_INTERNAL_H
6
+ #define XT_GUI_DOM_INTERNAL_H
7
+
8
+ #include <cctype>
9
+ #include <string>
10
+
11
+ #include "dom.h"
12
+
13
+ namespace xtgui {
14
+
15
+ inline bool xt_dom_is_alpha(char c) {
16
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
17
+ }
18
+
19
+ inline bool xt_dom_is_space(char c) {
20
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f';
21
+ }
22
+
23
+ inline std::string xt_dom_lower(const std::string &text) {
24
+ std::string out = text;
25
+ for (char &c : out) c = (char)std::tolower((unsigned char)c);
26
+ return out;
27
+ }
28
+
29
+ inline std::string xt_dom_trim(const std::string &text) {
30
+ size_t begin = 0;
31
+ size_t end = text.size();
32
+ while (begin < end && xt_dom_is_space(text[begin])) begin++;
33
+ while (end > begin && xt_dom_is_space(text[end - 1])) end--;
34
+ return text.substr(begin, end - begin);
35
+ }
36
+
37
+ } // namespace xtgui
38
+
39
+ #endif /* XT_GUI_DOM_INTERNAL_H */