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.
- package/README.md +33 -0
- package/dist/src/cli/main.js +124 -30
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +8 -1
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/state.js +20 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +6 -0
- package/dist/src/codegen/generator/tables.js +38 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/commonjs.d.ts +52 -0
- package/dist/src/driver/bundler/commonjs.js +493 -0
- package/dist/src/driver/bundler/commonjs.js.map +1 -0
- package/dist/src/driver/bundler/graph.d.ts +2 -1
- package/dist/src/driver/bundler/graph.js +32 -3
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.d.ts +2 -1
- package/dist/src/driver/bundler/merge.js +16 -2
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/bundler/types.d.ts +8 -0
- package/dist/src/driver/compiler.d.ts +8 -1
- package/dist/src/driver/compiler.js +75 -7
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +53 -0
- package/dist/src/driver/config.js +141 -0
- package/dist/src/driver/config.js.map +1 -0
- package/dist/src/driver/icon.d.ts +62 -0
- package/dist/src/driver/icon.js +151 -0
- package/dist/src/driver/icon.js.map +1 -0
- package/dist/src/driver/index.d.ts +4 -0
- package/dist/src/driver/index.js +4 -0
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/mac-bundle.d.ts +41 -0
- package/dist/src/driver/mac-bundle.js +123 -0
- package/dist/src/driver/mac-bundle.js.map +1 -0
- package/dist/src/driver/win-icon.d.ts +27 -0
- package/dist/src/driver/win-icon.js +80 -0
- package/dist/src/driver/win-icon.js.map +1 -0
- package/dist/src/extensions/gui/html.d.ts +25 -0
- package/dist/src/extensions/gui/html.js +203 -0
- package/dist/src/extensions/gui/html.js.map +1 -0
- package/dist/src/extensions/gui/index.js +11 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/registry.d.ts +29 -0
- package/dist/src/extensions/registry.js +14 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.js +4 -12
- package/dist/src/lexer/scanner/identifiers.js.map +1 -1
- package/dist/src/parser/statements.js +17 -4
- package/dist/src/parser/statements.js.map +1 -1
- package/dist/tests/cli/main.test.js +46 -1
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/driver/bundler-resolve.test.d.ts +1 -0
- package/dist/tests/driver/bundler-resolve.test.js +230 -0
- package/dist/tests/driver/bundler-resolve.test.js.map +1 -0
- package/dist/tests/driver/config.test.d.ts +1 -0
- package/dist/tests/driver/config.test.js +124 -0
- package/dist/tests/driver/config.test.js.map +1 -0
- package/dist/tests/driver/icon.test.d.ts +1 -0
- package/dist/tests/driver/icon.test.js +421 -0
- package/dist/tests/driver/icon.test.js.map +1 -0
- package/dist/tests/driver/modules.test.js +177 -0
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/e2e/fetch.test.d.ts +12 -0
- package/dist/tests/e2e/fetch.test.js +272 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -0
- package/dist/tests/e2e/gui-dom.test.d.ts +5 -0
- package/dist/tests/e2e/gui-dom.test.js +102 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -0
- package/dist/tests/e2e/gui-events.test.d.ts +5 -0
- package/dist/tests/e2e/gui-events.test.js +60 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +31 -0
- package/dist/tests/e2e/gui-helpers.js +74 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.d.ts +4 -0
- package/dist/tests/e2e/gui-layout.test.js +88 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -0
- package/dist/tests/e2e/gui-lifecycle.test.d.ts +5 -0
- package/dist/tests/e2e/gui-lifecycle.test.js +58 -0
- package/dist/tests/e2e/gui-lifecycle.test.js.map +1 -0
- package/dist/tests/e2e/gui-paint.test.d.ts +5 -0
- package/dist/tests/e2e/gui-paint.test.js +111 -0
- package/dist/tests/e2e/gui-paint.test.js.map +1 -0
- package/dist/tests/e2e/gui-script.test.d.ts +5 -0
- package/dist/tests/e2e/gui-script.test.js +78 -0
- package/dist/tests/e2e/gui-script.test.js.map +1 -0
- package/dist/tests/e2e/gui-style.test.d.ts +5 -0
- package/dist/tests/e2e/gui-style.test.js +175 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -0
- package/dist/tests/e2e/icon.test.d.ts +7 -0
- package/dist/tests/e2e/icon.test.js +80 -0
- package/dist/tests/e2e/icon.test.js.map +1 -0
- package/dist/tests/e2e/npm-modules.test.d.ts +4 -1
- package/dist/tests/e2e/npm-modules.test.js +47 -1
- package/dist/tests/e2e/npm-modules.test.js.map +1 -1
- package/dist/tests/e2e/runtime-coverage-typed-array.test.d.ts +9 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js +140 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js.map +1 -0
- package/dist/tests/extensions/gui-index.test.d.ts +1 -0
- package/dist/tests/extensions/gui-index.test.js +49 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.d.ts +1 -0
- package/dist/tests/extensions/gui.test.js +177 -0
- package/dist/tests/extensions/gui.test.js.map +1 -0
- package/dist/tests/extensions/registry.test.js +36 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/dist/tests/parser/statements.test.js +11 -0
- package/dist/tests/parser/statements.test.js.map +1 -1
- package/dist/tests/public-api.test.d.ts +1 -0
- package/dist/tests/public-api.test.js +31 -0
- package/dist/tests/public-api.test.js.map +1 -0
- package/package.json +1 -1
- package/runtime/ext_gui/css.cpp +4 -517
- package/runtime/ext_gui/css_internal.h +27 -0
- package/runtime/ext_gui/css_match.cpp +195 -0
- package/runtime/ext_gui/css_selector.cpp +207 -0
- package/runtime/ext_gui/css_sheet.cpp +129 -0
- package/runtime/ext_gui/document.cpp +90 -0
- package/runtime/ext_gui/document.h +23 -0
- package/runtime/ext_gui/dom.cpp +43 -403
- package/runtime/ext_gui/dom.h +7 -0
- package/runtime/ext_gui/dom_api.cpp +164 -0
- package/runtime/ext_gui/dom_api.h +12 -0
- package/runtime/ext_gui/dom_api_document.cpp +96 -0
- package/runtime/ext_gui/dom_api_events.cpp +123 -0
- package/runtime/ext_gui/dom_api_internal.h +135 -0
- package/runtime/ext_gui/dom_api_node.cpp +329 -0
- package/runtime/ext_gui/dom_api_node_read.cpp +294 -0
- package/runtime/ext_gui/dom_api_proto.cpp +130 -0
- package/runtime/ext_gui/dom_api_style.cpp +192 -0
- package/runtime/ext_gui/dom_internal.h +39 -0
- package/runtime/ext_gui/dom_parse.cpp +348 -0
- package/runtime/ext_gui/dom_serialize.cpp +54 -0
- package/runtime/ext_gui/gui.cpp +61 -245
- package/runtime/ext_gui/gui_engine.h +54 -0
- package/runtime/ext_gui/gui_events.cpp +294 -0
- package/runtime/ext_gui/gui_internal.h +29 -0
- package/runtime/ext_gui/layout.cpp +6 -597
- package/runtime/ext_gui/layout_flex.cpp +200 -0
- package/runtime/ext_gui/layout_flow.cpp +191 -0
- package/runtime/ext_gui/layout_flow_internal.h +149 -0
- package/runtime/ext_gui/layout_inline.cpp +181 -0
- package/runtime/ext_gui/layout_internal.h +20 -0
- package/runtime/ext_gui/renderer.cpp +15 -679
- package/runtime/ext_gui/renderer_image.cpp +233 -0
- package/runtime/ext_gui/renderer_internal.h +112 -0
- package/runtime/ext_gui/renderer_shaders.h +108 -0
- package/runtime/ext_gui/renderer_text.cpp +342 -0
- package/runtime/ext_gui/script.cpp +63 -0
- package/runtime/ext_gui/style.cpp +12 -660
- package/runtime/ext_gui/style_internal.h +33 -0
- package/runtime/ext_gui/style_print.cpp +113 -0
- package/runtime/ext_gui/style_ua.cpp +98 -0
- package/runtime/ext_gui/style_values.cpp +468 -0
- package/runtime/ext_gui/window.cpp +60 -0
- package/runtime/rt.h +6 -0
- package/runtime/rt_internal.h +4 -0
- package/runtime/xt_builtins.c +1 -0
- package/runtime/xt_containers/access.inc +32 -1
- package/runtime/xt_fetch/buffer.inc +64 -0
- package/runtime/xt_fetch/headers.inc +312 -0
- package/runtime/xt_fetch/request.inc +386 -0
- package/runtime/xt_fetch/response.inc +107 -0
- package/runtime/xt_fetch/socket.inc +72 -0
- package/runtime/xt_fetch/url.inc +108 -0
- package/runtime/xt_fetch.c +39 -0
- package/runtime/xt_stdlib2/set.inc +1 -1
- package/runtime/xt_typed_array.c +614 -0
- package/src/cli/main.ts +137 -29
- package/src/codegen/generator/calls/access.ts +9 -1
- package/src/codegen/generator/state.ts +20 -0
- package/src/codegen/generator/tables.ts +40 -0
- package/src/driver/bundler/commonjs.ts +553 -0
- package/src/driver/bundler/graph.ts +35 -2
- package/src/driver/bundler/merge.ts +18 -1
- package/src/driver/bundler/types.ts +8 -0
- package/src/driver/compiler.ts +85 -7
- package/src/driver/config.ts +173 -0
- package/src/driver/icon.ts +184 -0
- package/src/driver/index.ts +30 -0
- package/src/driver/mac-bundle.ts +156 -0
- package/src/driver/win-icon.ts +96 -0
- package/src/extensions/gui/html.ts +236 -0
- package/src/extensions/gui/index.ts +11 -0
- package/src/extensions/registry.ts +39 -0
- package/src/index.ts +1 -1
- package/src/lexer/scanner/identifiers.ts +4 -11
- package/src/parser/statements.ts +17 -4
- package/dist/tests/e2e/gui.test.d.ts +0 -12
- package/dist/tests/e2e/gui.test.js +0 -493
- package/dist/tests/e2e/gui.test.js.map +0 -1
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc GUI engine — CSS declaration application (value parsing and how each
|
|
3
|
+
* property maps onto `XtStyle`).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
#include "style_internal.h"
|
|
7
|
+
|
|
8
|
+
#include <cstdlib>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
namespace xtgui {
|
|
12
|
+
|
|
13
|
+
/* -- small helpers -------------------------------------------------------- */
|
|
14
|
+
|
|
15
|
+
static void setEdge(Edges *edges, const std::string &side, Length value) {
|
|
16
|
+
if (side == "top") edges->top = value;
|
|
17
|
+
else if (side == "right") edges->right = value;
|
|
18
|
+
else if (side == "bottom") edges->bottom = value;
|
|
19
|
+
else if (side == "left") edges->left = value;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static bool parseEdgeLengths(const std::string &value, Edges *edges) {
|
|
23
|
+
std::vector<std::string> parts = xt_css_split_whitespace(value);
|
|
24
|
+
if (parts.empty() || parts.size() > 4) return false;
|
|
25
|
+
Length values[4];
|
|
26
|
+
for (size_t i = 0; i < parts.size(); i++) {
|
|
27
|
+
Length length = xt_css_parse_length(parts[i]);
|
|
28
|
+
if (length.unit == Unit::Invalid) {
|
|
29
|
+
std::string keyword = xt_css_lower(parts[i]);
|
|
30
|
+
if (keyword == "thin") length = {1.0f, Unit::Px};
|
|
31
|
+
else if (keyword == "medium") length = {3.0f, Unit::Px};
|
|
32
|
+
else if (keyword == "thick") length = {5.0f, Unit::Px};
|
|
33
|
+
else return false;
|
|
34
|
+
}
|
|
35
|
+
values[i] = length;
|
|
36
|
+
}
|
|
37
|
+
switch (parts.size()) {
|
|
38
|
+
case 1:
|
|
39
|
+
edges->set(values[0]);
|
|
40
|
+
break;
|
|
41
|
+
case 2:
|
|
42
|
+
edges->top = edges->bottom = values[0];
|
|
43
|
+
edges->right = edges->left = values[1];
|
|
44
|
+
break;
|
|
45
|
+
case 3:
|
|
46
|
+
edges->top = values[0];
|
|
47
|
+
edges->right = edges->left = values[1];
|
|
48
|
+
edges->bottom = values[2];
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
edges->top = values[0];
|
|
52
|
+
edges->right = values[1];
|
|
53
|
+
edges->bottom = values[2];
|
|
54
|
+
edges->left = values[3];
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static bool assignLength(Length *target, const std::string &value) {
|
|
61
|
+
Length length = xt_css_parse_length(value);
|
|
62
|
+
if (length.unit == Unit::Invalid) return false;
|
|
63
|
+
*target = length;
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static bool assignColor(Color *target, bool *has, const std::string &value) {
|
|
68
|
+
Color color = xt_css_parse_color(value);
|
|
69
|
+
if (!color.valid) return false;
|
|
70
|
+
*target = color;
|
|
71
|
+
*has = true;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
float xt_style_resolve_absolute(const Length &length, float base, float em, float root, float vw,
|
|
76
|
+
float vh) {
|
|
77
|
+
switch (length.unit) {
|
|
78
|
+
case Unit::Px:
|
|
79
|
+
case Unit::Number:
|
|
80
|
+
return length.value;
|
|
81
|
+
case Unit::Percent:
|
|
82
|
+
return base * length.value / 100.0f;
|
|
83
|
+
case Unit::Em:
|
|
84
|
+
return em * length.value;
|
|
85
|
+
case Unit::Rem:
|
|
86
|
+
return root * length.value;
|
|
87
|
+
case Unit::Vw:
|
|
88
|
+
return vw * length.value / 100.0f;
|
|
89
|
+
case Unit::Vh:
|
|
90
|
+
return vh * length.value / 100.0f;
|
|
91
|
+
default:
|
|
92
|
+
return 0.0f;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static bool parseEnum(const std::string &value, const char *const *names, int count, int *out) {
|
|
97
|
+
std::string text = xt_css_lower(xt_css_trim(value));
|
|
98
|
+
for (int i = 0; i < count; i++) {
|
|
99
|
+
if (text == names[i]) {
|
|
100
|
+
*out = i;
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* -- transitions ---------------------------------------------------------- */
|
|
108
|
+
|
|
109
|
+
static bool parseTimeSeconds(const std::string &text, float *out) {
|
|
110
|
+
std::string token = xt_css_trim(text);
|
|
111
|
+
if (token.empty()) return false;
|
|
112
|
+
const char *begin = token.c_str();
|
|
113
|
+
char *end = nullptr;
|
|
114
|
+
double value = std::strtod(begin, &end);
|
|
115
|
+
if (end == begin) return false;
|
|
116
|
+
std::string unit = xt_css_lower(xt_css_trim(std::string(end)));
|
|
117
|
+
if (unit == "ms") {
|
|
118
|
+
*out = (float)(value / 1000.0);
|
|
119
|
+
} else if (unit.empty() || unit == "s") {
|
|
120
|
+
*out = (float)value;
|
|
121
|
+
} else {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static bool parseTimingFunction(const std::string &text, TimingFunction *out) {
|
|
128
|
+
std::string token = xt_css_lower(xt_css_trim(text));
|
|
129
|
+
if (token == "linear") {
|
|
130
|
+
*out = TimingFunction::Linear;
|
|
131
|
+
} else if (token == "ease") {
|
|
132
|
+
*out = TimingFunction::Ease;
|
|
133
|
+
} else if (token == "ease-in") {
|
|
134
|
+
*out = TimingFunction::EaseIn;
|
|
135
|
+
} else if (token == "ease-out") {
|
|
136
|
+
*out = TimingFunction::EaseOut;
|
|
137
|
+
} else if (token == "ease-in-out") {
|
|
138
|
+
*out = TimingFunction::EaseInOut;
|
|
139
|
+
} else {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static std::vector<std::string> splitCommas(const std::string &text) {
|
|
146
|
+
std::vector<std::string> parts;
|
|
147
|
+
size_t start = 0;
|
|
148
|
+
for (size_t i = 0; i <= text.size(); i++) {
|
|
149
|
+
if (i == text.size() || text[i] == ',') {
|
|
150
|
+
std::string part = xt_css_trim(text.substr(start, i - start));
|
|
151
|
+
if (!part.empty()) parts.push_back(part);
|
|
152
|
+
start = i + 1;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return parts;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static void parseTransitionShorthand(const std::string &value, std::vector<TransitionSpec> *out) {
|
|
159
|
+
out->clear();
|
|
160
|
+
for (const std::string &group : splitCommas(value)) {
|
|
161
|
+
std::vector<std::string> tokens = xt_css_split_whitespace(group);
|
|
162
|
+
if (tokens.empty()) continue;
|
|
163
|
+
TransitionSpec spec;
|
|
164
|
+
int time_seen = 0;
|
|
165
|
+
for (const std::string &token : tokens) {
|
|
166
|
+
float seconds = 0;
|
|
167
|
+
TimingFunction timing = TimingFunction::Ease;
|
|
168
|
+
if (parseTimeSeconds(token, &seconds)) {
|
|
169
|
+
if (time_seen == 0) {
|
|
170
|
+
spec.duration = seconds;
|
|
171
|
+
} else {
|
|
172
|
+
spec.delay = seconds;
|
|
173
|
+
}
|
|
174
|
+
time_seen++;
|
|
175
|
+
} else if (parseTimingFunction(token, &timing)) {
|
|
176
|
+
spec.timing = timing;
|
|
177
|
+
} else {
|
|
178
|
+
spec.property = xt_css_lower(token);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
out->push_back(spec);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* -- declaration application ---------------------------------------------- */
|
|
186
|
+
|
|
187
|
+
void xt_style_apply_declaration(XtStyle *style, const std::string &property,
|
|
188
|
+
const std::string &rawValue, const ApplyContext &context) {
|
|
189
|
+
std::string value = xt_css_trim(rawValue);
|
|
190
|
+
|
|
191
|
+
if (property == "display") {
|
|
192
|
+
static const char *const names[] = {"none", "block", "inline", "inline-block", "flex", "list-item"};
|
|
193
|
+
int index = 0;
|
|
194
|
+
if (parseEnum(value, names, 6, &index)) style->display = (Display)index;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (property == "position") {
|
|
198
|
+
static const char *const names[] = {"static", "relative", "absolute", "fixed"};
|
|
199
|
+
int index = 0;
|
|
200
|
+
if (parseEnum(value, names, 4, &index)) style->position = (Position)index;
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (property == "width") { assignLength(&style->width, value); return; }
|
|
204
|
+
if (property == "height") { assignLength(&style->height, value); return; }
|
|
205
|
+
if (property == "min-width") { assignLength(&style->min_width, value); return; }
|
|
206
|
+
if (property == "min-height") { assignLength(&style->min_height, value); return; }
|
|
207
|
+
if (property == "max-width") { assignLength(&style->max_width, value); return; }
|
|
208
|
+
if (property == "max-height") { assignLength(&style->max_height, value); return; }
|
|
209
|
+
if (property == "top") { assignLength(&style->top, value); return; }
|
|
210
|
+
if (property == "right") { assignLength(&style->right, value); return; }
|
|
211
|
+
if (property == "bottom") { assignLength(&style->bottom, value); return; }
|
|
212
|
+
if (property == "left") { assignLength(&style->left, value); return; }
|
|
213
|
+
|
|
214
|
+
if (property == "margin") { parseEdgeLengths(value, &style->margin); return; }
|
|
215
|
+
if (property == "padding") { parseEdgeLengths(value, &style->padding); return; }
|
|
216
|
+
if (property == "margin-top") { setEdge(&style->margin, "top", xt_css_parse_length(value)); return; }
|
|
217
|
+
if (property == "margin-right") { setEdge(&style->margin, "right", xt_css_parse_length(value)); return; }
|
|
218
|
+
if (property == "margin-bottom") { setEdge(&style->margin, "bottom", xt_css_parse_length(value)); return; }
|
|
219
|
+
if (property == "margin-left") { setEdge(&style->margin, "left", xt_css_parse_length(value)); return; }
|
|
220
|
+
if (property == "padding-top") { setEdge(&style->padding, "top", xt_css_parse_length(value)); return; }
|
|
221
|
+
if (property == "padding-right") { setEdge(&style->padding, "right", xt_css_parse_length(value)); return; }
|
|
222
|
+
if (property == "padding-bottom") { setEdge(&style->padding, "bottom", xt_css_parse_length(value)); return; }
|
|
223
|
+
if (property == "padding-left") { setEdge(&style->padding, "left", xt_css_parse_length(value)); return; }
|
|
224
|
+
|
|
225
|
+
if (property == "border-width") { parseEdgeLengths(value, &style->border_width); return; }
|
|
226
|
+
if (property == "border-top-width") { setEdge(&style->border_width, "top", xt_css_parse_length(value)); return; }
|
|
227
|
+
if (property == "border-right-width") { setEdge(&style->border_width, "right", xt_css_parse_length(value)); return; }
|
|
228
|
+
if (property == "border-bottom-width") { setEdge(&style->border_width, "bottom", xt_css_parse_length(value)); return; }
|
|
229
|
+
if (property == "border-left-width") { setEdge(&style->border_width, "left", xt_css_parse_length(value)); return; }
|
|
230
|
+
if (property == "border-radius") {
|
|
231
|
+
Length length = xt_css_parse_length(value);
|
|
232
|
+
if (length.unit == Unit::Px || length.unit == Unit::Number) style->border_radius = length.value;
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (property == "border-style" || property == "border-top-style" || property == "border-right-style" ||
|
|
236
|
+
property == "border-bottom-style" || property == "border-left-style") {
|
|
237
|
+
static const char *const names[] = {"none", "solid", "dashed", "dotted"};
|
|
238
|
+
int index = 0;
|
|
239
|
+
if (parseEnum(value, names, 4, &index)) style->border_style = (BorderStyle)index;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (property == "border-color" || property == "border-top-color" || property == "border-right-color" ||
|
|
243
|
+
property == "border-bottom-color" || property == "border-left-color") {
|
|
244
|
+
assignColor(&style->border_color, &style->has_border_color, value);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (property == "border" || property == "border-top" || property == "border-right" ||
|
|
248
|
+
property == "border-bottom" || property == "border-left") {
|
|
249
|
+
for (const std::string &token : xt_css_split_whitespace(value)) {
|
|
250
|
+
Length length = xt_css_parse_length(token);
|
|
251
|
+
if (length.unit == Unit::Px || length.unit == Unit::Number) {
|
|
252
|
+
if (property == "border") style->border_width.set(length);
|
|
253
|
+
else setEdge(&style->border_width, property.substr(7), length);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
static const char *const names[] = {"none", "solid", "dashed", "dotted"};
|
|
257
|
+
int index = 0;
|
|
258
|
+
if (parseEnum(token, names, 4, &index)) {
|
|
259
|
+
style->border_style = (BorderStyle)index;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
Color color = xt_css_parse_color(token);
|
|
263
|
+
if (color.valid) {
|
|
264
|
+
style->border_color = color;
|
|
265
|
+
style->has_border_color = true;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (property == "color") {
|
|
272
|
+
Color color = xt_css_parse_color(value);
|
|
273
|
+
if (color.valid) style->color = color;
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (property == "background-color") { assignColor(&style->background, &style->has_background, value); return; }
|
|
277
|
+
if (property == "background") {
|
|
278
|
+
Color color = xt_css_parse_color(value);
|
|
279
|
+
if (color.valid) {
|
|
280
|
+
style->background = color;
|
|
281
|
+
style->has_background = true;
|
|
282
|
+
}
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (property == "font-size") {
|
|
287
|
+
Length length = xt_css_parse_length(value);
|
|
288
|
+
if (length.unit == Unit::Invalid) return;
|
|
289
|
+
/* `em`/`%` resolve against the *parent* font size, never the element's own
|
|
290
|
+
* (possibly UA-set) size. */
|
|
291
|
+
style->font_size = xt_style_resolve_absolute(length, context.parentFontSize, context.parentFontSize,
|
|
292
|
+
context.rootFontSize, context.viewportWidth, context.viewportHeight);
|
|
293
|
+
if (style->font_size <= 0.0f) style->font_size = 16.0f;
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (property == "font-weight") {
|
|
297
|
+
std::string text = xt_css_lower(value);
|
|
298
|
+
if (text == "normal") style->font_weight = 400;
|
|
299
|
+
else if (text == "bold") style->font_weight = 700;
|
|
300
|
+
else if (text == "lighter") style->font_weight = 100;
|
|
301
|
+
else if (text == "bolder") style->font_weight = 700;
|
|
302
|
+
else {
|
|
303
|
+
float number = 0;
|
|
304
|
+
if (xt_css_parse_number(text, &number)) style->font_weight = (int)number;
|
|
305
|
+
}
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (property == "font-family") {
|
|
309
|
+
style->font_family = value;
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
if (property == "font-style") {
|
|
313
|
+
style->font_style = (xt_css_lower(value) == "italic") ? FontStyle::Italic : FontStyle::Normal;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (property == "line-height") {
|
|
317
|
+
std::string text = xt_css_lower(value);
|
|
318
|
+
if (text == "normal") {
|
|
319
|
+
style->line_height = {};
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
Length length = xt_css_parse_length(text);
|
|
323
|
+
if (length.unit == Unit::Invalid) return;
|
|
324
|
+
/* Relative units are resolved in `finalizeStyle`, once the element's own
|
|
325
|
+
* font size is settled. */
|
|
326
|
+
style->line_height = length;
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (property == "text-align") {
|
|
330
|
+
std::string text = xt_css_lower(value);
|
|
331
|
+
if (text == "left" || text == "start") style->text_align = TextAlign::Start;
|
|
332
|
+
else if (text == "right" || text == "end") style->text_align = TextAlign::End;
|
|
333
|
+
else if (text == "center") style->text_align = TextAlign::Center;
|
|
334
|
+
else if (text == "justify") style->text_align = TextAlign::Justify;
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (property == "white-space") {
|
|
338
|
+
static const char *const names[] = {"normal", "nowrap", "pre", "pre-wrap", "pre-line"};
|
|
339
|
+
int index = 0;
|
|
340
|
+
if (parseEnum(value, names, 5, &index)) style->white_space = (WhiteSpace)index;
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (property == "flex-direction") {
|
|
345
|
+
static const char *const names[] = {"row", "row-reverse", "column", "column-reverse"};
|
|
346
|
+
int index = 0;
|
|
347
|
+
if (parseEnum(value, names, 4, &index)) style->flex_direction = (FlexDirection)index;
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (property == "justify-content") {
|
|
351
|
+
static const char *const names[] = {"flex-start", "flex-end", "center", "space-between",
|
|
352
|
+
"space-around", "space-evenly"};
|
|
353
|
+
int index = 0;
|
|
354
|
+
if (parseEnum(value, names, 6, &index)) style->justify_content = (JustifyContent)index;
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (property == "align-items") {
|
|
358
|
+
static const char *const names[] = {"stretch", "flex-start", "flex-end", "center", "baseline"};
|
|
359
|
+
int index = 0;
|
|
360
|
+
if (parseEnum(value, names, 5, &index)) style->align_items = (AlignItems)index;
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (property == "gap" || property == "row-gap" || property == "column-gap") {
|
|
364
|
+
assignLength(&style->gap, value);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (property == "flex-grow") {
|
|
368
|
+
float number = 0;
|
|
369
|
+
if (xt_css_parse_number(value, &number)) style->flex_grow = number;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (property == "flex-shrink") {
|
|
373
|
+
float number = 0;
|
|
374
|
+
if (xt_css_parse_number(value, &number)) style->flex_shrink = number;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (property == "flex-basis") { assignLength(&style->flex_basis, value); return; }
|
|
378
|
+
if (property == "flex") {
|
|
379
|
+
std::string text = xt_css_lower(value);
|
|
380
|
+
if (text == "none") {
|
|
381
|
+
style->flex_grow = 0;
|
|
382
|
+
style->flex_shrink = 0;
|
|
383
|
+
style->flex_basis = {0.0f, Unit::Auto};
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (text == "auto") {
|
|
387
|
+
style->flex_grow = 1;
|
|
388
|
+
style->flex_shrink = 1;
|
|
389
|
+
style->flex_basis = {0.0f, Unit::Auto};
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (text == "initial") {
|
|
393
|
+
style->flex_grow = 0;
|
|
394
|
+
style->flex_shrink = 1;
|
|
395
|
+
style->flex_basis = {0.0f, Unit::Auto};
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
std::vector<std::string> parts = xt_css_split_whitespace(text);
|
|
399
|
+
style->flex_grow = 0;
|
|
400
|
+
style->flex_shrink = 1;
|
|
401
|
+
style->flex_basis = {0.0f, Unit::Auto};
|
|
402
|
+
size_t index = 0;
|
|
403
|
+
float number = 0;
|
|
404
|
+
if (index < parts.size() && xt_css_parse_number(parts[index], &number)) {
|
|
405
|
+
style->flex_grow = number;
|
|
406
|
+
index++;
|
|
407
|
+
if (index < parts.size() && xt_css_parse_number(parts[index], &number)) {
|
|
408
|
+
style->flex_shrink = number;
|
|
409
|
+
index++;
|
|
410
|
+
}
|
|
411
|
+
if (index >= parts.size()) style->flex_basis = {0.0f, Unit::Px};
|
|
412
|
+
}
|
|
413
|
+
if (index < parts.size()) assignLength(&style->flex_basis, parts[index]);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (property == "opacity") {
|
|
418
|
+
float number = 0;
|
|
419
|
+
if (xt_css_parse_number(value, &number)) style->opacity = number < 0 ? 0 : (number > 1 ? 1 : number);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (property == "overflow" || property == "overflow-x" || property == "overflow-y") {
|
|
423
|
+
static const char *const names[] = {"visible", "hidden", "scroll", "auto"};
|
|
424
|
+
int index = 0;
|
|
425
|
+
if (parseEnum(value, names, 4, &index)) style->overflow = (Overflow)index;
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (property == "z-index") {
|
|
429
|
+
float number = 0;
|
|
430
|
+
if (xt_css_parse_number(value, &number)) {
|
|
431
|
+
style->z_index = (int)number;
|
|
432
|
+
style->has_z_index = true;
|
|
433
|
+
}
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (property == "transition") {
|
|
437
|
+
parseTransitionShorthand(value, &style->transitions);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
if (property == "transition-property") {
|
|
441
|
+
std::vector<std::string> parts = splitCommas(value);
|
|
442
|
+
style->transitions.resize(parts.size());
|
|
443
|
+
for (size_t i = 0; i < parts.size(); i++) style->transitions[i].property = xt_css_lower(parts[i]);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (property == "transition-duration" || property == "transition-delay") {
|
|
447
|
+
std::vector<std::string> parts = splitCommas(value);
|
|
448
|
+
style->transitions.resize(parts.size());
|
|
449
|
+
for (size_t i = 0; i < parts.size(); i++) {
|
|
450
|
+
float seconds = 0;
|
|
451
|
+
if (!parseTimeSeconds(parts[i], &seconds)) continue;
|
|
452
|
+
if (property == "transition-duration") style->transitions[i].duration = seconds;
|
|
453
|
+
else style->transitions[i].delay = seconds;
|
|
454
|
+
}
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (property == "transition-timing-function") {
|
|
458
|
+
std::vector<std::string> parts = splitCommas(value);
|
|
459
|
+
style->transitions.resize(parts.size());
|
|
460
|
+
for (size_t i = 0; i < parts.size(); i++) {
|
|
461
|
+
TimingFunction timing = TimingFunction::Ease;
|
|
462
|
+
if (parseTimingFunction(parts[i], &timing)) style->transitions[i].timing = timing;
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
} // namespace xtgui
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
#include "gui_engine.h"
|
|
12
12
|
|
|
13
|
+
#include <algorithm>
|
|
14
|
+
|
|
13
15
|
#include "paint.h"
|
|
14
16
|
#include "text.h"
|
|
15
17
|
|
|
@@ -48,16 +50,23 @@ static xt_value win_load_html(xt_value self, xt_value env, int32_t argc, xt_valu
|
|
|
48
50
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
49
51
|
if (win != nullptr) {
|
|
50
52
|
win->html = html;
|
|
53
|
+
/* Fresh document: invalidate every previously handed-out handle. */
|
|
54
|
+
xt_gui_handles_reset(win);
|
|
51
55
|
win->document = std::make_unique<xtgui::XtDocument>();
|
|
52
56
|
float width = 0;
|
|
53
57
|
float height = 0;
|
|
54
58
|
xt_gui_window_viewport(win, &width, &height);
|
|
55
59
|
win->document->load(html, width, height);
|
|
56
60
|
win->geometry.dirty = 1;
|
|
61
|
+
/* Run the AOT-compiled `<script>` bodies now that the tree is parsed, so
|
|
62
|
+
* `document.getElementById(...)` resolves, then settle the first layout. */
|
|
63
|
+
xt_gui_run_scripts(win);
|
|
64
|
+
xt_gui_flush_dom(win);
|
|
57
65
|
}
|
|
58
66
|
xt_object_set(self, xt_string_from_cstr("__xt_gui_html"), xt_string_from_cstr(html.c_str()));
|
|
59
67
|
/* Painting the document is milestone M3b+; the parsed tree and computed
|
|
60
68
|
* styles are available now (see `computedStyle`). */
|
|
69
|
+
xt_gui_emit(win, "DOMContentLoaded");
|
|
61
70
|
xt_gui_emit(win, "load");
|
|
62
71
|
return XT_UNDEFINED;
|
|
63
72
|
}
|
|
@@ -69,12 +78,21 @@ static xt_value win_get_html(xt_value self, xt_value env, int32_t argc, xt_value
|
|
|
69
78
|
return xt_object_get_cstr(self, "__xt_gui_html");
|
|
70
79
|
}
|
|
71
80
|
|
|
81
|
+
/** The `document` handle for this window (created on first access). */
|
|
82
|
+
static xt_value win_document_get(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
83
|
+
(void)env;
|
|
84
|
+
(void)argc;
|
|
85
|
+
(void)argv;
|
|
86
|
+
return xt_gui_document_handle(xt_gui_window_from_this(self));
|
|
87
|
+
}
|
|
88
|
+
|
|
72
89
|
/** Diagnostic/test hook: computed value of `property` for the first match of
|
|
73
90
|
* `selector`, or an empty string. */
|
|
74
91
|
static xt_value win_computed_style(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
75
92
|
(void)env;
|
|
76
93
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
77
94
|
if (win == nullptr || win->document == nullptr || argc < 2) return xt_string_from_cstr("");
|
|
95
|
+
xt_gui_flush_dom(win);
|
|
78
96
|
xt_value selectorValue = xt_to_string(xt_arg(argc, argv, 0));
|
|
79
97
|
xt_value propertyValue = xt_to_string(xt_arg(argc, argv, 1));
|
|
80
98
|
const char *selector = xt_string_data(selectorValue);
|
|
@@ -95,6 +113,7 @@ static xt_value win_document_tree(xt_value self, xt_value env, int32_t argc, xt_
|
|
|
95
113
|
(void)argv;
|
|
96
114
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
97
115
|
if (win == nullptr || win->document == nullptr) return xt_string_from_cstr("");
|
|
116
|
+
xt_gui_flush_dom(win);
|
|
98
117
|
std::string text = win->document->toDebugString();
|
|
99
118
|
return xt_string_from_cstr(text.c_str());
|
|
100
119
|
}
|
|
@@ -104,6 +123,7 @@ static xt_value win_query_count(xt_value self, xt_value env, int32_t argc, xt_va
|
|
|
104
123
|
(void)env;
|
|
105
124
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
106
125
|
if (win == nullptr || win->document == nullptr || argc < 1) return xt_number(0);
|
|
126
|
+
xt_gui_flush_dom(win);
|
|
107
127
|
xt_value selectorValue = xt_to_string(xt_arg(argc, argv, 0));
|
|
108
128
|
const char *selector = xt_string_data(selectorValue);
|
|
109
129
|
if (selector == nullptr) return xt_number(0);
|
|
@@ -116,6 +136,7 @@ static xt_value win_get_bounding_rect(xt_value self, xt_value env, int32_t argc,
|
|
|
116
136
|
(void)env;
|
|
117
137
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
118
138
|
if (win == nullptr || win->document == nullptr || argc < 1) return XT_UNDEFINED;
|
|
139
|
+
xt_gui_flush_dom(win);
|
|
119
140
|
xt_value selectorValue = xt_to_string(xt_arg(argc, argv, 0));
|
|
120
141
|
const char *selector = xt_string_data(selectorValue);
|
|
121
142
|
if (selector == nullptr) return XT_UNDEFINED;
|
|
@@ -138,6 +159,7 @@ static xt_value win_layout_tree(xt_value self, xt_value env, int32_t argc, xt_va
|
|
|
138
159
|
(void)argv;
|
|
139
160
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
140
161
|
if (win == nullptr || win->document == nullptr) return xt_string_from_cstr("");
|
|
162
|
+
xt_gui_flush_dom(win);
|
|
141
163
|
std::string text = win->document->layout().dump();
|
|
142
164
|
return xt_string_from_cstr(text.c_str());
|
|
143
165
|
}
|
|
@@ -169,6 +191,7 @@ static xt_value win_paint_list(xt_value self, xt_value env, int32_t argc, xt_val
|
|
|
169
191
|
(void)argv;
|
|
170
192
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
171
193
|
if (win == nullptr || win->document == nullptr) return xt_string_from_cstr("");
|
|
194
|
+
xt_gui_flush_dom(win);
|
|
172
195
|
xtgui::DisplayList list;
|
|
173
196
|
xtgui::xt_paint_build(win->document->layout().root(), list);
|
|
174
197
|
std::string text = list.dump();
|
|
@@ -182,6 +205,7 @@ static xt_value win_paint_count(xt_value self, xt_value env, int32_t argc, xt_va
|
|
|
182
205
|
(void)argv;
|
|
183
206
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
184
207
|
if (win == nullptr || win->document == nullptr) return xt_number(0);
|
|
208
|
+
xt_gui_flush_dom(win);
|
|
185
209
|
xtgui::DisplayList list;
|
|
186
210
|
xtgui::xt_paint_build(win->document->layout().root(), list);
|
|
187
211
|
return xt_number((double)list.rects.size());
|
|
@@ -259,6 +283,34 @@ static xt_value win_is_open(xt_value self, xt_value env, int32_t argc, xt_value
|
|
|
259
283
|
return (win != NULL && win->open) ? XT_TRUE : XT_FALSE;
|
|
260
284
|
}
|
|
261
285
|
|
|
286
|
+
/** `requestAnimationFrame(fn)` -> id. The callback runs once on the next frame
|
|
287
|
+
* with the frame timestamp (ms) as its only argument. */
|
|
288
|
+
static xt_value win_request_animation_frame(xt_value self, xt_value env, int32_t argc,
|
|
289
|
+
xt_value *argv) {
|
|
290
|
+
(void)env;
|
|
291
|
+
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
292
|
+
if (win == NULL || !win->open) return xt_number(0);
|
|
293
|
+
xt_value fn = xt_arg(argc, argv, 0);
|
|
294
|
+
if (!XT_IS_FUNCTION(fn)) return xt_number(0);
|
|
295
|
+
int id = win->next_animation_frame_id++;
|
|
296
|
+
win->animation_frames.push_back(XtGuiAnimationFrame{id, fn});
|
|
297
|
+
return xt_number((double)id);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** `cancelAnimationFrame(id)` drops a callback queued for the next frame. */
|
|
301
|
+
static xt_value win_cancel_animation_frame(xt_value self, xt_value env, int32_t argc,
|
|
302
|
+
xt_value *argv) {
|
|
303
|
+
(void)env;
|
|
304
|
+
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
305
|
+
if (win == NULL || argc < 1) return XT_UNDEFINED;
|
|
306
|
+
int id = (int)xt_to_number(xt_arg(argc, argv, 0));
|
|
307
|
+
std::vector<XtGuiAnimationFrame> &frames = win->animation_frames;
|
|
308
|
+
frames.erase(std::remove_if(frames.begin(), frames.end(),
|
|
309
|
+
[id](const XtGuiAnimationFrame &frame) { return frame.id == id; }),
|
|
310
|
+
frames.end());
|
|
311
|
+
return XT_UNDEFINED;
|
|
312
|
+
}
|
|
313
|
+
|
|
262
314
|
static xt_value win_on(xt_value self, xt_value env, int32_t argc, xt_value *argv) {
|
|
263
315
|
(void)env;
|
|
264
316
|
if (argc >= 2) {
|
|
@@ -314,6 +366,7 @@ static xt_value win_hit_test(xt_value self, xt_value env, int32_t argc, xt_value
|
|
|
314
366
|
(void)env;
|
|
315
367
|
XtGuiWindow *win = xt_gui_window_from_this(self);
|
|
316
368
|
if (win == nullptr || win->document == nullptr || argc < 2) return xt_string_from_cstr("");
|
|
369
|
+
xt_gui_flush_dom(win);
|
|
317
370
|
float x = (float)xt_to_number(xt_arg(argc, argv, 0));
|
|
318
371
|
float y = (float)xt_to_number(xt_arg(argc, argv, 1));
|
|
319
372
|
std::string target = xt_gui_hit_test(win, x, y);
|
|
@@ -376,10 +429,15 @@ static void define_method(xt_value proto, const char *name, void *fn) {
|
|
|
376
429
|
xt_object_set(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
|
|
377
430
|
}
|
|
378
431
|
|
|
432
|
+
static void define_getter(xt_value proto, const char *name, void *fn) {
|
|
433
|
+
xt_object_define_getter(proto, xt_string_from_cstr(name), xt_closure_new(fn, 0, NULL));
|
|
434
|
+
}
|
|
435
|
+
|
|
379
436
|
xt_value xt_gui_window_proto(void) {
|
|
380
437
|
if (XT_IS_OBJECT(g_window_proto)) return g_window_proto;
|
|
381
438
|
xt_value proto = xt_object_new();
|
|
382
439
|
define_method(proto, "setTitle", (void *)win_set_title);
|
|
440
|
+
define_getter(proto, "document", (void *)win_document_get);
|
|
383
441
|
define_method(proto, "setSize", (void *)win_set_size);
|
|
384
442
|
define_method(proto, "loadHTML", (void *)win_load_html);
|
|
385
443
|
define_method(proto, "getHTML", (void *)win_get_html);
|
|
@@ -396,6 +454,8 @@ xt_value xt_gui_window_proto(void) {
|
|
|
396
454
|
define_method(proto, "fontMetrics", (void *)win_font_metrics);
|
|
397
455
|
define_method(proto, "close", (void *)win_close);
|
|
398
456
|
define_method(proto, "isOpen", (void *)win_is_open);
|
|
457
|
+
define_method(proto, "requestAnimationFrame", (void *)win_request_animation_frame);
|
|
458
|
+
define_method(proto, "cancelAnimationFrame", (void *)win_cancel_animation_frame);
|
|
399
459
|
define_method(proto, "on", (void *)win_on);
|
|
400
460
|
define_method(proto, "off", (void *)win_off);
|
|
401
461
|
define_method(proto, "hitTest", (void *)win_hit_test);
|
package/runtime/rt.h
CHANGED
|
@@ -218,6 +218,12 @@ xt_value xt_crypto_create_hash(int32_t argc, xt_value *argv);
|
|
|
218
218
|
/* -- node:child_process --------------------------------------------------- */
|
|
219
219
|
xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv);
|
|
220
220
|
|
|
221
|
+
/* -- fetch ---------------------------------------------------------------- */
|
|
222
|
+
/** Implements the global `fetch(input, init)`; returns a settled promise. */
|
|
223
|
+
xt_value xt_fetch(int32_t argc, xt_value *argv);
|
|
224
|
+
/** Construct a `TypeError` with one message argument (used by `fetch`). */
|
|
225
|
+
xt_value xt_type_error_ctor(int32_t argc, xt_value *argv);
|
|
226
|
+
|
|
221
227
|
/* -- promises / async ----------------------------------------------------- */
|
|
222
228
|
xt_value xt_promise_resolve(xt_value value);
|
|
223
229
|
xt_value xt_promise_reject(xt_value value);
|
package/runtime/rt_internal.h
CHANGED
|
@@ -286,4 +286,8 @@ int xt_value_equals(xt_value a, xt_value b);
|
|
|
286
286
|
xt_array *xt_as_array(xt_value value);
|
|
287
287
|
xt_value xt_arg_at(int32_t argc, xt_value *argv, int32_t index);
|
|
288
288
|
|
|
289
|
+
/* Typed arrays (xt_typed_array.c). */
|
|
290
|
+
int xt_typed_array_kind_of(xt_value value);
|
|
291
|
+
double xt_typed_array_coerce(int kind, double value);
|
|
292
|
+
|
|
289
293
|
#endif /* XT_RT_INTERNAL_H */
|
package/runtime/xt_builtins.c
CHANGED
|
@@ -305,6 +305,7 @@ XT_BUILTIN_TRAMPOLINE(xt_builtin_value_setTimeout, xt_set_timeout)
|
|
|
305
305
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_clearTimeout, xt_clear_timeout)
|
|
306
306
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_setInterval, xt_set_interval)
|
|
307
307
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_clearInterval, xt_clear_interval)
|
|
308
|
+
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_fetch, xt_fetch)
|
|
308
309
|
|
|
309
310
|
xt_value xt_in(xt_value key, xt_value value) {
|
|
310
311
|
if (XT_IS_OBJECT(value)) return xt_object_has(value, key);
|