xbintsc 0.3.15 → 0.3.16

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 (156) hide show
  1. package/dist/src/cli/main.js +4 -4
  2. package/dist/src/cli/main.js.map +1 -1
  3. package/dist/src/codegen/generator/state.js +8 -0
  4. package/dist/src/codegen/generator/state.js.map +1 -1
  5. package/dist/src/codegen/generator/tables.js +8 -0
  6. package/dist/src/codegen/generator/tables.js.map +1 -1
  7. package/dist/src/driver/bundler/graph.d.ts +8 -0
  8. package/dist/src/driver/bundler/graph.js +85 -0
  9. package/dist/src/driver/bundler/graph.js.map +1 -0
  10. package/dist/src/driver/bundler/merge.d.ts +11 -0
  11. package/dist/src/driver/bundler/merge.js +288 -0
  12. package/dist/src/driver/bundler/merge.js.map +1 -0
  13. package/dist/src/driver/bundler/resolve.d.ts +12 -0
  14. package/dist/src/driver/bundler/resolve.js +246 -0
  15. package/dist/src/driver/bundler/resolve.js.map +1 -0
  16. package/dist/src/driver/bundler/symbols.d.ts +15 -0
  17. package/dist/src/driver/bundler/symbols.js +51 -0
  18. package/dist/src/driver/bundler/symbols.js.map +1 -0
  19. package/dist/src/driver/bundler/types.d.ts +36 -0
  20. package/dist/src/driver/bundler/types.js +5 -0
  21. package/dist/src/driver/bundler/types.js.map +1 -0
  22. package/dist/src/driver/modules.d.ts +9 -16
  23. package/dist/src/driver/modules.js +8 -644
  24. package/dist/src/driver/modules.js.map +1 -1
  25. package/dist/src/extensions/catalog.js +2 -1
  26. package/dist/src/extensions/catalog.js.map +1 -1
  27. package/dist/src/extensions/gui/index.d.ts +24 -0
  28. package/dist/src/extensions/gui/index.js +101 -0
  29. package/dist/src/extensions/gui/index.js.map +1 -0
  30. package/dist/tests/e2e/compile-basics.test.d.ts +4 -0
  31. package/dist/tests/e2e/compile-basics.test.js +134 -0
  32. package/dist/tests/e2e/compile-basics.test.js.map +1 -0
  33. package/dist/tests/e2e/compile-builtins.test.d.ts +4 -0
  34. package/dist/tests/e2e/compile-builtins.test.js +191 -0
  35. package/dist/tests/e2e/compile-builtins.test.js.map +1 -0
  36. package/dist/tests/e2e/compile-control-flow.test.d.ts +4 -0
  37. package/dist/tests/e2e/compile-control-flow.test.js +190 -0
  38. package/dist/tests/e2e/compile-control-flow.test.js.map +1 -0
  39. package/dist/tests/e2e/compile-modules.test.d.ts +4 -0
  40. package/dist/tests/e2e/compile-modules.test.js +48 -0
  41. package/dist/tests/e2e/compile-modules.test.js.map +1 -0
  42. package/dist/tests/e2e/compile-objects-classes.test.d.ts +4 -0
  43. package/dist/tests/e2e/compile-objects-classes.test.js +362 -0
  44. package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -0
  45. package/dist/tests/e2e/differential-helpers.d.ts +12 -0
  46. package/dist/tests/e2e/differential-helpers.js +16 -0
  47. package/dist/tests/e2e/differential-helpers.js.map +1 -0
  48. package/dist/tests/e2e/differential-language.test.d.ts +4 -0
  49. package/dist/tests/e2e/{differential.test.js → differential-language.test.js} +5 -287
  50. package/dist/tests/e2e/differential-language.test.js.map +1 -0
  51. package/dist/tests/e2e/differential-symbols.test.d.ts +4 -0
  52. package/dist/tests/e2e/differential-symbols.test.js +92 -0
  53. package/dist/tests/e2e/differential-symbols.test.js.map +1 -0
  54. package/dist/tests/e2e/differential-values.test.d.ts +4 -0
  55. package/dist/tests/e2e/differential-values.test.js +197 -0
  56. package/dist/tests/e2e/differential-values.test.js.map +1 -0
  57. package/dist/tests/e2e/gui.test.d.ts +12 -0
  58. package/dist/tests/e2e/gui.test.js +493 -0
  59. package/dist/tests/e2e/gui.test.js.map +1 -0
  60. package/dist/tests/e2e/runtime-coverage-buffer.test.d.ts +4 -0
  61. package/dist/tests/e2e/runtime-coverage-buffer.test.js +97 -0
  62. package/dist/tests/e2e/runtime-coverage-buffer.test.js.map +1 -0
  63. package/dist/tests/e2e/runtime-coverage-globals.test.d.ts +4 -0
  64. package/dist/tests/e2e/runtime-coverage-globals.test.js +149 -0
  65. package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -0
  66. package/dist/tests/e2e/runtime-coverage-node-modules.test.d.ts +4 -0
  67. package/dist/tests/e2e/runtime-coverage-node-modules.test.js +177 -0
  68. package/dist/tests/e2e/runtime-coverage-node-modules.test.js.map +1 -0
  69. package/dist/tests/e2e/runtime-coverage-streams.test.d.ts +4 -0
  70. package/dist/tests/e2e/runtime-coverage-streams.test.js +161 -0
  71. package/dist/tests/e2e/runtime-coverage-streams.test.js.map +1 -0
  72. package/dist/tests/e2e/runtime-coverage-system.test.d.ts +4 -0
  73. package/dist/tests/e2e/runtime-coverage-system.test.js +91 -0
  74. package/dist/tests/e2e/runtime-coverage-system.test.js.map +1 -0
  75. package/dist/tests/e2e/timers.test.d.ts +7 -0
  76. package/dist/tests/e2e/timers.test.js +63 -0
  77. package/dist/tests/e2e/timers.test.js.map +1 -0
  78. package/package.json +2 -1
  79. package/runtime/ext_gui/css.cpp +743 -0
  80. package/runtime/ext_gui/css.h +98 -0
  81. package/runtime/ext_gui/document.cpp +264 -0
  82. package/runtime/ext_gui/document.h +89 -0
  83. package/runtime/ext_gui/dom.cpp +472 -0
  84. package/runtime/ext_gui/dom.h +71 -0
  85. package/runtime/ext_gui/gui.cpp +457 -0
  86. package/runtime/ext_gui/gui_engine.h +81 -0
  87. package/runtime/ext_gui/image.cpp +125 -0
  88. package/runtime/ext_gui/image.h +42 -0
  89. package/runtime/ext_gui/layout.cpp +748 -0
  90. package/runtime/ext_gui/layout.h +93 -0
  91. package/runtime/ext_gui/paint.cpp +137 -0
  92. package/runtime/ext_gui/paint.h +75 -0
  93. package/runtime/ext_gui/renderer.cpp +959 -0
  94. package/runtime/ext_gui/renderer.h +68 -0
  95. package/runtime/ext_gui/stb_image.h +7988 -0
  96. package/runtime/ext_gui/style.cpp +771 -0
  97. package/runtime/ext_gui/style.h +117 -0
  98. package/runtime/ext_gui/text.cpp +378 -0
  99. package/runtime/ext_gui/text.h +78 -0
  100. package/runtime/ext_gui/window.cpp +405 -0
  101. package/runtime/ext_node/fs/fs_common.h +13 -527
  102. package/runtime/ext_node/fs/parts/buffer-bridge.inc +6 -0
  103. package/runtime/ext_node/fs/parts/builtins.inc +69 -0
  104. package/runtime/ext_node/fs/parts/dir.inc +47 -0
  105. package/runtime/ext_node/fs/parts/encoding.inc +186 -0
  106. package/runtime/ext_node/fs/parts/errors.inc +66 -0
  107. package/runtime/ext_node/fs/parts/flags.inc +39 -0
  108. package/runtime/ext_node/fs/parts/platform.inc +86 -0
  109. package/runtime/ext_node/fs/parts/promisify.inc +15 -0
  110. package/runtime/ext_node/fs/parts/time.inc +9 -0
  111. package/runtime/rt.h +33 -0
  112. package/runtime/xt_builtins.c +4 -0
  113. package/runtime/xt_containers/access.inc +168 -0
  114. package/runtime/xt_containers/arrays.inc +108 -0
  115. package/runtime/xt_containers/boxes.inc +11 -0
  116. package/runtime/xt_containers/objects.inc +326 -0
  117. package/runtime/xt_containers.c +8 -618
  118. package/runtime/xt_io/base64.inc +87 -0
  119. package/runtime/xt_io/console.inc +119 -0
  120. package/runtime/xt_io/exception.inc +142 -0
  121. package/runtime/xt_io/inspect.inc +212 -0
  122. package/runtime/xt_io.c +8 -553
  123. package/runtime/xt_loop.c +262 -24
  124. package/runtime/xt_regex/api.inc +58 -0
  125. package/runtime/xt_regex/helpers.inc +68 -0
  126. package/runtime/xt_regex/matcher.inc +248 -0
  127. package/runtime/xt_regex/parser.inc +236 -0
  128. package/runtime/xt_regex/types.inc +58 -0
  129. package/runtime/xt_regex.h +9 -672
  130. package/runtime/xt_values/arithmetic.inc +150 -0
  131. package/runtime/xt_values/comparison.inc +112 -0
  132. package/runtime/xt_values/constructors.inc +41 -0
  133. package/runtime/xt_values/conversions.inc +115 -0
  134. package/runtime/xt_values/number-format.inc +180 -0
  135. package/runtime/xt_values/strings.inc +22 -0
  136. package/runtime/xt_values.c +10 -626
  137. package/scripts/build-gui.ts +317 -0
  138. package/src/cli/main.ts +4 -3
  139. package/src/codegen/generator/state.ts +8 -0
  140. package/src/codegen/generator/tables.ts +8 -0
  141. package/src/driver/bundler/graph.ts +95 -0
  142. package/src/driver/bundler/merge.ts +312 -0
  143. package/src/driver/bundler/resolve.ts +240 -0
  144. package/src/driver/bundler/symbols.ts +55 -0
  145. package/src/driver/bundler/types.ts +37 -0
  146. package/src/driver/modules.ts +9 -693
  147. package/src/extensions/catalog.ts +2 -1
  148. package/src/extensions/gui/index.ts +107 -0
  149. package/dist/tests/e2e/compile.test.d.ts +0 -8
  150. package/dist/tests/e2e/compile.test.js +0 -893
  151. package/dist/tests/e2e/compile.test.js.map +0 -1
  152. package/dist/tests/e2e/differential.test.d.ts +0 -7
  153. package/dist/tests/e2e/differential.test.js.map +0 -1
  154. package/dist/tests/e2e/runtime-coverage.test.d.ts +0 -11
  155. package/dist/tests/e2e/runtime-coverage.test.js +0 -646
  156. package/dist/tests/e2e/runtime-coverage.test.js.map +0 -1
@@ -0,0 +1,493 @@
1
+ /**
2
+ * End-to-end tests for the `gui` extension.
3
+ *
4
+ * The suite compiles TypeScript programs that import `gui`, links them against
5
+ * the prebuilt `runtime/lib/<os>-<arch>/gui.a` and runs them. Programs close
6
+ * themselves through the `XT_GUI_AUTOCLOSE_MS` hook, so the tests never block on
7
+ * a real window.
8
+ *
9
+ * It is skipped when the GUI archive has not been built (run `npm run gui`
10
+ * first) and on Windows, where the archive is not produced yet.
11
+ */
12
+ import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { spawnSync } from "node:child_process";
16
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
17
+ import { build } from "../../src/driver/compiler.js";
18
+ import { createDefaultRegistry } from "../../src/extensions/registry.js";
19
+ import { guiExtension } from "../../src/extensions/gui/index.js";
20
+ import { findRuntimeDir, platformSlug } from "../../src/driver/paths.js";
21
+ const archivePath = join(findRuntimeDir(), "lib", platformSlug(), "gui.a");
22
+ const available = existsSync(archivePath) && process.platform !== "win32";
23
+ describe.skipIf(!available)("gui extension", () => {
24
+ let workdir;
25
+ let logoPath;
26
+ beforeAll(() => {
27
+ workdir = mkdtempSync(join(tmpdir(), "xbintsc-gui-"));
28
+ // A 4x4 PNG: left half red, right half blue (base64-encoded inline).
29
+ logoPath = join(workdir, "logo.png");
30
+ writeFileSync(logoPath, Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAFElEQVR42mP4z8DwH4Sh1H8G0gUALFAf4eNWqTEAAAAASUVORK5CYII=", "base64"));
31
+ });
32
+ afterAll(() => {
33
+ rmSync(workdir, { recursive: true, force: true });
34
+ });
35
+ /** Compile a program and run it with the auto-close hook, returning stdout. */
36
+ function compileAndRun(name, source) {
37
+ const entry = join(workdir, `${name}.ts`);
38
+ writeFileSync(entry, source);
39
+ const extensions = createDefaultRegistry().register(guiExtension);
40
+ const result = build(entry, {
41
+ emit: "exe",
42
+ outDir: join(workdir, `out-${name}`),
43
+ cacheDir: join(workdir, `.cache-${name}`),
44
+ extensions,
45
+ });
46
+ expect(result.diagnostics.filter((diagnostic) => diagnostic.category === "error")).toEqual([]);
47
+ const executed = spawnSync(result.outputPath, [], {
48
+ encoding: "utf8",
49
+ env: { ...process.env, XT_GUI_AUTOCLOSE_MS: "400" },
50
+ });
51
+ expect(executed.status, executed.stderr).toBe(0);
52
+ return { stdout: executed.stdout, status: executed.status };
53
+ }
54
+ it("opens a GPU-backed window and delivers lifecycle events", () => {
55
+ const { stdout } = compileAndRun("window", `
56
+ import { createWindow, run } from "gui";
57
+ const win = createWindow({ title: "test window", width: 320, height: 240 });
58
+ win.on("ready", () => console.log("gui ready"));
59
+ win.on("close", () => console.log("gui closed"));
60
+ win.setBackground("#101010");
61
+ win.loadHTML("<h1>hi</h1>");
62
+ run();
63
+ console.log("gui exited");
64
+ `);
65
+ const lines = stdout.trim().split("\n");
66
+ expect(lines).toContain("gui ready");
67
+ expect(lines).toContain("gui closed");
68
+ expect(lines).toContain("gui exited");
69
+ });
70
+ it("parses HTML/CSS and cascades computed styles", () => {
71
+ const { stdout } = compileAndRun("cascade", `
72
+ import { createWindow, run } from "gui";
73
+
74
+ const HTML = \`
75
+ <html>
76
+ <head>
77
+ <style>
78
+ body { font-size: 16px; color: #111111; }
79
+ div { width: 10%; }
80
+ .box { width: 25%; }
81
+ #main { width: 60%; color: #222222; }
82
+ .box > .inner { padding-top: 3px; }
83
+ .box .inner { padding-top: 5px; }
84
+ li:first-child { color: #555555; }
85
+ li:nth-child(2) { color: #666666; }
86
+ li:not(.skip) { font-weight: bold; }
87
+ [data-role="lead"] { text-align: center; }
88
+ .em { font-size: 2em; }
89
+ .rem { font-size: 2rem; }
90
+ .imp { color: #000000; }
91
+ .imp { color: #ff0000 !important; }
92
+ </style>
93
+ </head>
94
+ <body>
95
+ <div id="main" class="box">
96
+ <div class="inner" style="color: #00ff00">x</div>
97
+ <div class="inner">y</div>
98
+ </div>
99
+ <ul>
100
+ <li>one</li>
101
+ <li>two</li>
102
+ <li class="skip">three</li>
103
+ </ul>
104
+ <p data-role="lead">lead</p>
105
+ <div class="em">em</div>
106
+ <div class="rem">rem</div>
107
+ <div class="imp" style="color: #0000ff">important</div>
108
+ </body>
109
+ </html>
110
+ \`;
111
+
112
+ const win = createWindow({ title: "cascade", width: 800, height: 600 });
113
+ win.on("ready", () => {
114
+ const out = (label, value) => console.log(label + "=" + value);
115
+ out("main-width", win.computedStyle("#main", "width"));
116
+ out("inner-padding", win.computedStyle(".inner", "padding-top"));
117
+ out("inner-color", win.computedStyle(".inner", "color"));
118
+ out("body-color", win.computedStyle("body", "color"));
119
+ out("li1-color", win.computedStyle("li:first-child", "color"));
120
+ out("li2-color", win.computedStyle("li:nth-child(2)", "color"));
121
+ out("li2-weight", win.computedStyle("li:nth-child(2)", "font-weight"));
122
+ out("skip-weight", win.computedStyle("li.skip", "font-weight"));
123
+ out("lead-align", win.computedStyle("[data-role=\\"lead\\"]", "text-align"));
124
+ out("em-size", win.computedStyle(".em", "font-size"));
125
+ out("rem-size", win.computedStyle(".rem", "font-size"));
126
+ out("imp-color", win.computedStyle(".imp", "color"));
127
+ out("li-count", win.queryCount("li"));
128
+ out("lead-count", win.queryCount("[data-role=\\"lead\\"]"));
129
+ });
130
+ win.loadHTML(HTML);
131
+ run();
132
+ `);
133
+ const value = (label) => {
134
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
135
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
136
+ return line.slice(label.length + 1).trim();
137
+ };
138
+ expect(value("main-width")).toBe("60%"); // id beats class and tag
139
+ expect(value("inner-padding")).toBe("5px"); // equal specificity, later rule wins
140
+ expect(value("inner-color")).toBe("rgb(0, 255, 0)"); // inline beats the sheet
141
+ expect(value("body-color")).toBe("rgb(17, 17, 17)");
142
+ expect(value("li1-color")).toBe("rgb(85, 85, 85)"); // :first-child
143
+ expect(value("li2-color")).toBe("rgb(102, 102, 102)"); // :nth-child(2)
144
+ expect(value("li2-weight")).toBe("700"); // :not(.skip)
145
+ expect(value("skip-weight")).toBe("400"); // :not(.skip) excluded it
146
+ expect(value("lead-align")).toBe("center"); // [data-role="lead"]
147
+ expect(value("em-size")).toBe("32px"); // 2em of the 16px parent
148
+ expect(value("rem-size")).toBe("32px"); // 2rem of the 16px root
149
+ expect(value("imp-color")).toBe("rgb(255, 0, 0)"); // !important beats inline
150
+ expect(value("li-count")).toBe("3");
151
+ expect(value("lead-count")).toBe("1");
152
+ });
153
+ it("lays out block, inline and flex boxes", () => {
154
+ const { stdout } = compileAndRun("layout", `
155
+ import { createWindow, run } from "gui";
156
+
157
+ const HTML = \`
158
+ <html><head><style>
159
+ body { margin: 0; }
160
+ #box { width: 200px; height: 100px; padding: 10px; border: 2px solid #000; margin: 5px; }
161
+ #row { display: flex; width: 300px; gap: 10px; }
162
+ #row .a { width: 50px; height: 20px; }
163
+ #row .b { flex: 1; height: 20px; }
164
+ #wrap { width: 60px; font-size: 10px; }
165
+ </style></head><body>
166
+ <div id="box">hello</div>
167
+ <div id="row"><div class="a"></div><div class="b"></div></div>
168
+ <div id="wrap">aaaa bbbb cccc dddd</div>
169
+ </body></html>
170
+ \`;
171
+
172
+ const win = createWindow({ title: "layout", width: 800, height: 600 });
173
+ win.on("ready", () => {
174
+ const rect = (selector) => {
175
+ const r = win.getBoundingClientRect(selector);
176
+ return r.x + "," + r.y + "," + r.width + "," + r.height;
177
+ };
178
+ console.log("box=" + rect("#box"));
179
+ console.log("a=" + rect("#row .a"));
180
+ console.log("b=" + rect("#row .b"));
181
+ console.log("wrap=" + rect("#wrap"));
182
+ console.log("lh=" + win.fontMetrics(10).lineHeight);
183
+ });
184
+ win.loadHTML(HTML);
185
+ run();
186
+ `);
187
+ const value = (label) => {
188
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
189
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
190
+ return line.slice(label.length + 1).trim();
191
+ };
192
+ // Border box = content + padding (20) + border (4); margin offsets by 5.
193
+ expect(value("box")).toBe("5,5,224,124");
194
+ // Flex row: `.a` keeps 50px, `.b` grows into the remaining 240px after a 10px gap.
195
+ expect(value("a")).toBe("0,134,50,20");
196
+ expect(value("b")).toBe("60,134,240,20");
197
+ // 60px-wide box wraps "aaaa bbbb" / "cccc dddd" onto two lines. The line
198
+ // height comes from the real font metrics, so assert against them rather
199
+ // than hard-coding a pixel value (fonts differ per platform).
200
+ const wrap = value("wrap").split(",").map(Number);
201
+ expect(wrap.slice(0, 3)).toEqual([0, 154, 60]);
202
+ expect(wrap[3]).toBeCloseTo(2 * Number(value("lh")), 1);
203
+ });
204
+ it("sizes and paints images (intrinsic and explicit)", () => {
205
+ const { stdout } = compileAndRun("image", `
206
+ import { createWindow, run } from "gui";
207
+
208
+ const HTML = \`
209
+ <html><head><style>
210
+ body { margin: 0; }
211
+ #logo { width: 40px; height: 40px; }
212
+ </style></head><body>
213
+ <img id="logo" src="${logoPath}">
214
+ <img id="natural" src="${logoPath}">
215
+ </body></html>
216
+ \`;
217
+
218
+ const win = createWindow({ title: "image", width: 400, height: 300 });
219
+ win.on("ready", () => {
220
+ const logo = win.getBoundingClientRect("#logo");
221
+ console.log("logo=" + logo.width + "x" + logo.height);
222
+ const natural = win.getBoundingClientRect("#natural");
223
+ console.log("natural=" + natural.width + "x" + natural.height);
224
+ console.log(win.paintList().trim());
225
+ win.close();
226
+ });
227
+ win.loadHTML(HTML);
228
+ run();
229
+ `);
230
+ // Explicit CSS size wins; without one the intrinsic 4x4 size is used.
231
+ expect(stdout).toContain("logo=40x40");
232
+ expect(stdout).toContain("natural=4x4");
233
+ expect(stdout).toContain(`image x=0.0 y=0.0 w=40.0 h=40.0 src=${logoPath}`);
234
+ expect(stdout).toContain(`image x=0.0 y=40.0 w=4.0 h=4.0 src=${logoPath}`);
235
+ });
236
+ it("builds a display list of backgrounds and borders", () => {
237
+ const { stdout } = compileAndRun("paint", `
238
+ import { createWindow, run } from "gui";
239
+
240
+ const HTML = \`
241
+ <html><head><style>
242
+ body { margin: 0; background-color: #123456; }
243
+ #box { width: 100px; height: 40px; background: #ff0000; border: 4px solid #00ff00; border-radius: 8px; }
244
+ </style></head><body>
245
+ <div id="box">x</div>
246
+ </body></html>
247
+ \`;
248
+
249
+ const win = createWindow({ title: "paint", width: 800, height: 600 });
250
+ win.on("ready", () => {
251
+ const r = win.getBoundingClientRect("#box");
252
+ console.log("box-rect=" + r.x + "," + r.y + "," + r.width + "," + r.height);
253
+ console.log("paint-count=" + win.paintCount());
254
+ console.log("paint-list-start");
255
+ console.log(win.paintList());
256
+ console.log("paint-list-end");
257
+ });
258
+ win.loadHTML(HTML);
259
+ run();
260
+ `);
261
+ const value = (label) => {
262
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
263
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
264
+ return line.slice(label.length + 1).trim();
265
+ };
266
+ const list = stdout.slice(stdout.indexOf("paint-list-start"), stdout.indexOf("paint-list-end"));
267
+ const occurrences = (needle) => list.split(needle).length - 1;
268
+ // Border box = 100x40 content + 4px border on every side.
269
+ expect(value("box-rect")).toBe("0,0,108,48");
270
+ // body background + #box background + 4 border edges.
271
+ expect(value("paint-count")).toBe("6");
272
+ expect(occurrences("#123456ff")).toBe(1); // body background
273
+ expect(occurrences("#ff0000ff")).toBe(1); // #box background
274
+ expect(occurrences("#00ff00ff")).toBe(4); // four border edges
275
+ // The background rectangle carries the 8px corner radius.
276
+ expect(list).toContain("r=8.0 color=#ff0000ff");
277
+ });
278
+ it("emits shaped text runs into the display list", () => {
279
+ const { stdout } = compileAndRun("text-runs", `
280
+ import { createWindow, run } from "gui";
281
+
282
+ const HTML = \`
283
+ <html><head><style>
284
+ body { margin: 0; }
285
+ #t { font-size: 20px; color: #0000ff; }
286
+ </style></head><body>
287
+ <div id="t">Hi</div>
288
+ </body></html>
289
+ \`;
290
+
291
+ const win = createWindow({ title: "text-runs", width: 400, height: 300 });
292
+ win.on("ready", () => {
293
+ const r = win.getBoundingClientRect("#t");
294
+ console.log("rect=" + r.x + "," + r.y + "," + r.width + "," + r.height);
295
+ console.log("paint-list-start");
296
+ console.log(win.paintList());
297
+ console.log("paint-list-end");
298
+ });
299
+ win.loadHTML(HTML);
300
+ run();
301
+ `);
302
+ const list = stdout.slice(stdout.indexOf("paint-list-start"), stdout.indexOf("paint-list-end"));
303
+ // The text fragment carries the resolved font size and colour.
304
+ expect(list).toContain('text x=0.0');
305
+ expect(list).toContain('size=20.0');
306
+ expect(list).toContain('color=#0000ffff "Hi"');
307
+ });
308
+ it("hit-tests elements and delivers input events to handlers", () => {
309
+ const { stdout } = compileAndRun("input", `
310
+ import { createWindow, run } from "gui";
311
+
312
+ const HTML = \`
313
+ <html><head><style>
314
+ body { margin: 0; }
315
+ #box { width: 100px; height: 50px; }
316
+ #inner { width: 20px; height: 20px; }
317
+ </style></head><body>
318
+ <div id="box"><div id="inner">x</div></div>
319
+ </body></html>
320
+ \`;
321
+
322
+ const win = createWindow({ title: "input", width: 400, height: 300 });
323
+ const log = [];
324
+ win.on("mousemove", (e) => log.push("move:" + e.target));
325
+ win.on("mousedown", (e) => log.push("down:" + e.button + ":" + e.target));
326
+ win.on("click", (e) => log.push("click:" + e.x + "," + e.y + ":" + e.target));
327
+ win.on("wheel", (e) => log.push("wheel:" + e.deltaX + "," + e.deltaY));
328
+ win.on("keydown", (e) => log.push("key:" + e.key + ":" + e.shift));
329
+
330
+ win.on("ready", () => {
331
+ console.log("hit-inner=" + win.hitTest(5, 5));
332
+ console.log("hit-box=" + win.hitTest(50, 40));
333
+ console.log("hit-none=[" + win.hitTest(390, 290) + "]");
334
+ win.sendEvent("mousemove", { x: 5, y: 5 });
335
+ win.sendEvent("mousedown", { x: 5, y: 5, button: 0 });
336
+ win.sendEvent("click", { x: 5, y: 5, button: 0 });
337
+ win.sendEvent("wheel", { x: 5, y: 5, deltaX: 1, deltaY: 2 });
338
+ win.sendEvent("keydown", { key: "a", code: "KeyA" });
339
+ for (const line of log) console.log("event=" + line);
340
+ win.close();
341
+ });
342
+ win.loadHTML(HTML);
343
+ run();
344
+ `);
345
+ const value = (label) => {
346
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
347
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
348
+ return line.slice(label.length + 1).trim();
349
+ };
350
+ // Hit testing returns the deepest element under the point.
351
+ expect(value("hit-inner")).toBe("div#inner");
352
+ expect(value("hit-box")).toBe("div#box");
353
+ expect(value("hit-none")).toBe("[]");
354
+ // Handlers receive the payload (coordinates, button, target, deltas, key).
355
+ expect(stdout).toContain("event=move:div#inner");
356
+ expect(stdout).toContain("event=down:0:div#inner");
357
+ expect(stdout).toContain("event=click:5,5:div#inner");
358
+ expect(stdout).toContain("event=wheel:1,2");
359
+ expect(stdout).toContain("event=key:a:false");
360
+ });
361
+ it("applies :hover and :focus state to selector matching", () => {
362
+ const { stdout } = compileAndRun("state", `
363
+ import { createWindow, run } from "gui";
364
+
365
+ const HTML = \`
366
+ <html><head><style>
367
+ body { margin: 0; }
368
+ #box { width: 100px; height: 50px; background: #000000; }
369
+ #box:hover { background: #ff0000; }
370
+ #box:focus { background: #00ff00; }
371
+ #box:hover > #inner { color: #0000ff; }
372
+ #inner { width: 20px; height: 20px; color: #888888; }
373
+ </style></head><body>
374
+ <div id="box"><div id="inner">x</div></div>
375
+ </body></html>
376
+ \`;
377
+
378
+ const win = createWindow({ title: "state", width: 400, height: 300 });
379
+ win.on("ready", () => {
380
+ console.log("initial-bg=" + win.computedStyle("#box", "background-color"));
381
+ console.log("initial-color=" + win.computedStyle("#inner", "color"));
382
+ win.sendEvent("mousemove", { x: 50, y: 40 });
383
+ console.log("hover-bg=" + win.computedStyle("#box", "background-color"));
384
+ win.sendEvent("mousemove", { x: 5, y: 5 });
385
+ console.log("inner-hover-color=" + win.computedStyle("#inner", "color"));
386
+ win.sendEvent("mousedown", { x: 50, y: 40, button: 0 });
387
+ console.log("focus-bg=" + win.computedStyle("#box", "background-color"));
388
+ win.close();
389
+ });
390
+ win.loadHTML(HTML);
391
+ run();
392
+ `);
393
+ const value = (label) => {
394
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
395
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
396
+ return line.slice(label.length + 1).trim();
397
+ };
398
+ expect(value("initial-bg")).toBe("rgb(0, 0, 0)"); // no :hover rule match
399
+ expect(value("initial-color")).toBe("rgb(136, 136, 136)");
400
+ expect(value("hover-bg")).toBe("rgb(255, 0, 0)"); // hovering #box
401
+ // Hover also applies to ancestors of the hovered element.
402
+ expect(value("inner-hover-color")).toBe("rgb(0, 0, 255)");
403
+ expect(value("focus-bg")).toBe("rgb(0, 255, 0)"); // :focus wins over :hover
404
+ });
405
+ it("interpolates CSS transitions as the clock advances", () => {
406
+ const { stdout } = compileAndRun("transition", `
407
+ import { createWindow, run } from "gui";
408
+
409
+ const HTML = \`
410
+ <html><head><style>
411
+ body { margin: 0; }
412
+ #box {
413
+ width: 100px; height: 50px; background-color: #000000; color: #888888;
414
+ border-radius: 0px;
415
+ transition: background-color 1000ms linear, color 500ms linear, border-radius 1000ms linear;
416
+ }
417
+ #box:hover { background-color: #ffffff; color: #0000ff; border-radius: 10px; }
418
+ </style></head><body>
419
+ <div id="box">hi</div>
420
+ </body></html>
421
+ \`;
422
+
423
+ const win = createWindow({ title: "transition", width: 400, height: 300 });
424
+ win.on("ready", () => {
425
+ win.sendEvent("mousemove", { x: 50, y: 25 });
426
+ console.log("start=" + win.computedStyle("#box", "background-color"));
427
+ win.advance(250);
428
+ console.log("q1-bg=" + win.computedStyle("#box", "background-color"));
429
+ console.log("q1-color=" + win.computedStyle("#box", "color"));
430
+ win.advance(250);
431
+ console.log("q2-bg=" + win.computedStyle("#box", "background-color"));
432
+ console.log("q2-color=" + win.computedStyle("#box", "color"));
433
+ console.log("q2-radius=" + win.computedStyle("#box", "border-radius"));
434
+ win.advance(500);
435
+ console.log("end-bg=" + win.computedStyle("#box", "background-color"));
436
+ console.log("end-radius=" + win.computedStyle("#box", "border-radius"));
437
+ win.close();
438
+ });
439
+ win.loadHTML(HTML);
440
+ run();
441
+ `);
442
+ const value = (label) => {
443
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
444
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
445
+ return line.slice(label.length + 1).trim();
446
+ };
447
+ expect(value("start")).toBe("rgb(0, 0, 0)"); // 0% progress at t=0
448
+ expect(value("q1-bg")).toBe("rgb(64, 64, 64)"); // 25% of black->white
449
+ expect(value("q1-color")).toBe("rgb(68, 68, 196)"); // 50% of the 500ms color run
450
+ expect(value("q2-bg")).toBe("rgb(128, 128, 128)"); // halfway
451
+ expect(value("q2-color")).toBe("rgb(0, 0, 255)"); // finished
452
+ expect(value("q2-radius")).toBe("5px");
453
+ expect(value("end-bg")).toBe("rgb(255, 255, 255)"); // finished
454
+ expect(value("end-radius")).toBe("10px");
455
+ });
456
+ it("shapes and measures text with the font stack", () => {
457
+ const { stdout } = compileAndRun("text", `
458
+ import { createWindow, run } from "gui";
459
+
460
+ const win = createWindow({ title: "text", width: 400, height: 300 });
461
+ win.on("ready", () => {
462
+ const fm16 = win.fontMetrics(16);
463
+ console.log("ready=" + fm16.ready);
464
+ console.log("lh16=" + fm16.lineHeight);
465
+ console.log("ascent16=" + fm16.ascent);
466
+ console.log("m16=" + win.measureText("Hello", 16));
467
+ console.log("m32=" + win.measureText("Hello", 32));
468
+ console.log("empty=" + win.measureText("", 16));
469
+ console.log("wide=" + (win.measureText("WWWW", 16) > win.measureText("iiii", 16)));
470
+ win.close();
471
+ });
472
+ win.loadHTML("<html><body></body></html>");
473
+ run();
474
+ `);
475
+ const value = (label) => {
476
+ const line = stdout.split("\n").find((entry) => entry.startsWith(`${label}=`));
477
+ expect(line, `missing ${label} in:\n${stdout}`).toBeDefined();
478
+ return line.slice(label.length + 1).trim();
479
+ };
480
+ // Metrics are positive and scale ~linearly with the font size (this holds
481
+ // for both the real shaper and the no-font fallback).
482
+ const m16 = Number(value("m16"));
483
+ const m32 = Number(value("m32"));
484
+ expect(m16).toBeGreaterThan(0);
485
+ expect(m32).toBeGreaterThan(m16 * 1.8);
486
+ expect(m32).toBeLessThan(m16 * 2.2);
487
+ expect(Number(value("lh16"))).toBeGreaterThan(0);
488
+ expect(Number(value("ascent16"))).toBeGreaterThan(0);
489
+ expect(value("empty")).toBe("0");
490
+ expect(value("wide")).toBe("true");
491
+ });
492
+ });
493
+ //# sourceMappingURL=gui.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gui.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Runtime-coverage tests for the Buffer implementation.
3
+ */
4
+ export {};
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Runtime-coverage tests for the Buffer implementation.
3
+ */
4
+ import { expect, it } from "vitest";
5
+ import { describeE2E } from "./harness.js";
6
+ const TIMEOUT = 120000;
7
+ describeE2E("runtime coverage: buffer", (h) => {
8
+ it("exercises the Buffer implementation", () => {
9
+ const source = `
10
+ const b = Buffer.from("hello");
11
+ console.log(b.toString(), b.length, Buffer.isBuffer(b));
12
+ console.log(Buffer.from([1, 2, 3]).toString("hex"));
13
+ console.log(Buffer.from("68656c6c6f", "hex").toString());
14
+ console.log(Buffer.from("aGVsbG8=", "base64").toString());
15
+ console.log(Buffer.from(b).toString());
16
+ console.log(Buffer.alloc(3).toString("hex"), Buffer.alloc(4, 65).toString(), Buffer.alloc(3, "ab").toString());
17
+ console.log(Buffer.alloc(0).length, Buffer.alloc(3, "").toString("hex"), Buffer.alloc(3, "61", "hex").toString("hex"));
18
+ console.log(Buffer.allocUnsafe(2).length, Buffer.allocUnsafeSlow(2).length);
19
+ console.log(Buffer.byteLength("hello"), Buffer.byteLength("68656c6c6f", "hex"), Buffer.byteLength("aGVsbG8=", "base64"), Buffer.byteLength(b));
20
+ console.log(Buffer.concat([Buffer.from("foo"), Buffer.from("bar")]).toString());
21
+ console.log(Buffer.concat([Buffer.from("foo"), Buffer.from("bar")], 4).toString());
22
+ console.log(Buffer.compare(Buffer.from("a"), Buffer.from("b")), Buffer.compare(Buffer.from("b"), Buffer.from("a")), Buffer.compare(Buffer.from("a"), Buffer.from("a")));
23
+ const n = new Buffer("hey");
24
+ console.log(n.toString(), Buffer.of().length, new Buffer(2).length);
25
+ const j = Buffer.from("hi").toJSON();
26
+ console.log(j.type, j.data.join(","));
27
+ console.log(b.slice(1, 3).toString(), b.slice(-3).toString(), b.subarray(0, 2).toString(), "[" + b.slice(3, 1).toString() + "]");
28
+ console.log(Buffer.from("abc").equals(Buffer.from("abc")), Buffer.from("abc").equals(Buffer.from("abd")), true);
29
+ console.log(Buffer.from("abc").compare(Buffer.from("abd")), Buffer.from("abd").compare(Buffer.from("abc")), Buffer.from("abc").compare(Buffer.from("abc")));
30
+ const target = Buffer.alloc(6);
31
+ const copied = Buffer.from("hello").copy(target, 1, 0, 3);
32
+ console.log(copied, target.toString("hex"));
33
+ const w = Buffer.alloc(8);
34
+ console.log(w.write("abc"), w.write("def", 4), w.toString("hex"));
35
+ console.log(w.write("6161", 0, 4, "hex"), w.toString("hex"));
36
+ console.log(Buffer.alloc(5).fill("a").toString(), Buffer.alloc(5, 1).fill(66, 1, 3).toString("hex"), Buffer.alloc(2).fill(0).toString("hex"));
37
+ console.log(Buffer.from("abc").reverse().toString());
38
+ console.log(b.toString("hex"));
39
+ console.log(Buffer.from("hello world").indexOf("world"), Buffer.from("hello world").indexOf("o"), Buffer.from("hello").indexOf(101), Buffer.from("hello").indexOf(Buffer.from("ll")));
40
+ console.log(Buffer.from("hello world").lastIndexOf("o"), Buffer.from("hello").lastIndexOf("l", 2), Buffer.from("abc").includes("bc"), Buffer.from("abc").includes("z"));
41
+ console.log(Buffer.from("hello").indexOf("z"), Buffer.from("hello").indexOf("toolong"), Buffer.from("hello").indexOf(""), Buffer.from("hello").indexOf("l", -10), Buffer.from("hello").indexOf("l", 100));
42
+ console.log(Buffer.from("hello").lastIndexOf("l", 100), Buffer.from("hello").lastIndexOf("l", -1), Buffer.from("hello").lastIndexOf("lo", 3), Buffer.from("hello").lastIndexOf(111));
43
+ console.log(Buffer.from("hello").indexOf("6c6c", 0, "hex"));
44
+ const io = Buffer.alloc(16);
45
+ console.log(io.writeUInt8(200, 0), io.writeInt8(-56, 1), io.readUInt8(0), io.readInt8(1));
46
+ io.writeUInt16LE(0x1234, 2);
47
+ io.writeUInt16BE(0x1234, 4);
48
+ io.writeUInt16LE(0xfffe, 6);
49
+ io.writeUInt16BE(0xfffe, 8);
50
+ console.log(io.readUInt16LE(2), io.readUInt16BE(4), io.readInt16LE(6), io.readInt16BE(8));
51
+ io.writeUInt32LE(0xffffffff, 0);
52
+ console.log(io.readUInt32LE(0), io.readInt32LE(0));
53
+ io.writeUInt32BE(0x12345678, 4);
54
+ console.log(io.readUInt32BE(4), io.readInt32BE(4));
55
+ console.log(Array.from(Buffer.from("abc").keys()).join(","), Array.from(Buffer.from("abc").values()).join(","));
56
+ console.log(b.toString("base64"), b.toString("hex", 1, 3), "[" + b.toString("utf8", 3, 1) + "]");
57
+ `;
58
+ const stdout = h.runProgram(source, { extensions: true, timeout: TIMEOUT });
59
+ expect(stdout.split("\n")).toEqual([
60
+ "hello 5 true",
61
+ "010203",
62
+ "hello",
63
+ "hello",
64
+ "hello",
65
+ "000000 AAAA aba",
66
+ "0 000000 616161",
67
+ "2 2",
68
+ "5 5 6 5",
69
+ "foobar",
70
+ "foob",
71
+ "-1 1 0",
72
+ "hey 0 2",
73
+ "Buffer 104,105",
74
+ "el llo he []",
75
+ "true false true",
76
+ "-1 1 0",
77
+ "3 0068656c0000",
78
+ "3 3 6162630064656600",
79
+ "2 6161630064656600",
80
+ "aaaaa 0142420101 0000",
81
+ "cba",
82
+ "68656c6c6f",
83
+ "6 4 1 2",
84
+ "7 2 true false",
85
+ "-1 -1 -1 2 -1",
86
+ "3 3 3 4",
87
+ "2",
88
+ "1 2 200 -56",
89
+ "4660 4660 -2 -2",
90
+ "4294967295 -1",
91
+ "305419896 305419896",
92
+ "0,1,2 97,98,99",
93
+ "aGVsbG8= 656c []",
94
+ ]);
95
+ });
96
+ }, { tmpPrefix: "xbintsc-runtime-coverage-" });
97
+ //# sourceMappingURL=runtime-coverage-buffer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-coverage-buffer.test.js","sourceRoot":"","sources":["../../../tests/e2e/runtime-coverage-buffer.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,OAAO,GAAG,MAAM,CAAC;AAEvB,WAAW,CACT,0BAA0B,EAC1B,CAAC,CAAC,EAAE,EAAE;IACJ,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDd,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5E,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;YACjC,cAAc;YACd,QAAQ;YACR,OAAO;YACP,OAAO;YACP,OAAO;YACP,iBAAiB;YACjB,iBAAiB;YACjB,KAAK;YACL,SAAS;YACT,QAAQ;YACR,MAAM;YACN,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,cAAc;YACd,iBAAiB;YACjB,QAAQ;YACR,gBAAgB;YAChB,sBAAsB;YACtB,oBAAoB;YACpB,uBAAuB;YACvB,KAAK;YACL,YAAY;YACZ,SAAS;YACT,gBAAgB;YAChB,eAAe;YACf,SAAS;YACT,GAAG;YACH,aAAa;YACb,iBAAiB;YACjB,eAAe;YACf,qBAAqB;YACrB,gBAAgB;YAChB,kBAAkB;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,EACD,EAAE,SAAS,EAAE,2BAA2B,EAAE,CAC3C,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Runtime-coverage tests for the global objects, console helpers and BigInt.
3
+ */
4
+ export {};