xbintsc 0.5.21 → 0.5.23

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 (98) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +15 -5
  3. package/README.zh-CN.md +11 -4
  4. package/dist/src/cli/hints.js +11 -0
  5. package/dist/src/cli/hints.js.map +1 -1
  6. package/dist/src/cli/main.js +1 -1
  7. package/dist/src/driver/compiler.js +1 -0
  8. package/dist/src/driver/compiler.js.map +1 -1
  9. package/dist/src/driver/version.d.ts +1 -1
  10. package/dist/src/driver/version.js +1 -1
  11. package/dist/src/extensions/catalog.js +2 -1
  12. package/dist/src/extensions/catalog.js.map +1 -1
  13. package/dist/src/extensions/media/index.d.ts +27 -0
  14. package/dist/src/extensions/media/index.js +60 -0
  15. package/dist/src/extensions/media/index.js.map +1 -0
  16. package/dist/src/extensions/registry.d.ts +12 -0
  17. package/dist/src/extensions/registry.js +16 -0
  18. package/dist/src/extensions/registry.js.map +1 -1
  19. package/dist/src/index.d.ts +1 -0
  20. package/dist/src/index.js +1 -0
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/tests/cli/hints.test.js +15 -0
  23. package/dist/tests/cli/hints.test.js.map +1 -1
  24. package/dist/tests/cli/process.test.js +12 -0
  25. package/dist/tests/cli/process.test.js.map +1 -1
  26. package/dist/tests/e2e/gui-canvas.test.js +159 -0
  27. package/dist/tests/e2e/gui-canvas.test.js.map +1 -1
  28. package/dist/tests/e2e/gui-example-canvas.test.d.ts +11 -0
  29. package/dist/tests/e2e/gui-example-canvas.test.js +72 -0
  30. package/dist/tests/e2e/gui-example-canvas.test.js.map +1 -0
  31. package/dist/tests/e2e/gui-helpers.d.ts +3 -0
  32. package/dist/tests/e2e/gui-helpers.js +2 -0
  33. package/dist/tests/e2e/gui-helpers.js.map +1 -1
  34. package/dist/tests/e2e/gui-media-disabled.test.d.ts +9 -0
  35. package/dist/tests/e2e/gui-media-disabled.test.js +42 -0
  36. package/dist/tests/e2e/gui-media-disabled.test.js.map +1 -0
  37. package/dist/tests/e2e/gui-media.test.d.ts +6 -4
  38. package/dist/tests/e2e/gui-media.test.js +15 -12
  39. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  40. package/dist/tests/e2e/unicode-output.test.d.ts +16 -0
  41. package/dist/tests/e2e/unicode-output.test.js +65 -0
  42. package/dist/tests/e2e/unicode-output.test.js.map +1 -0
  43. package/dist/tests/extensions/media.test.d.ts +1 -0
  44. package/dist/tests/extensions/media.test.js +58 -0
  45. package/dist/tests/extensions/media.test.js.map +1 -0
  46. package/dist/tests/extensions/registry.test.js +8 -0
  47. package/dist/tests/extensions/registry.test.js.map +1 -1
  48. package/dist/tests/lexer/identifiers.test.js +12 -0
  49. package/dist/tests/lexer/identifiers.test.js.map +1 -1
  50. package/dist/tests/lexer/scanner.test.js +8 -0
  51. package/dist/tests/lexer/scanner.test.js.map +1 -1
  52. package/dist/tests/lexer/strings.test.js +30 -0
  53. package/dist/tests/lexer/strings.test.js.map +1 -1
  54. package/doc/ai/cli.md +1 -1
  55. package/doc/ai/extensions.md +35 -22
  56. package/doc/ai/troubleshooting.md +9 -0
  57. package/doc/ai/zh-CN/cli.md +1 -1
  58. package/doc/ai/zh-CN/extensions.md +22 -9
  59. package/doc/ai/zh-CN/troubleshooting.md +8 -0
  60. package/doc/gui/build.md +37 -21
  61. package/doc/gui/canvas.md +47 -21
  62. package/doc/gui/known-issues.md +7 -6
  63. package/doc/gui/media.md +26 -11
  64. package/doc/gui.md +50 -34
  65. package/doc/zh-CN/gui/build.md +28 -16
  66. package/doc/zh-CN/gui/canvas.md +36 -17
  67. package/doc/zh-CN/gui/known-issues.md +6 -5
  68. package/doc/zh-CN/gui/media.md +21 -10
  69. package/doc/zh-CN/gui.md +43 -34
  70. package/package.json +2 -1
  71. package/runtime/ext_gui/canvas.cpp +114 -199
  72. package/runtime/ext_gui/canvas.h +101 -2
  73. package/runtime/ext_gui/canvas_gradient.cpp +112 -0
  74. package/runtime/ext_gui/canvas_internal.h +6 -6
  75. package/runtime/ext_gui/canvas_raster.cpp +27 -5
  76. package/runtime/ext_gui/canvas_stroke.cpp +252 -0
  77. package/runtime/ext_gui/canvas_style.cpp +240 -0
  78. package/runtime/ext_gui/dom_api.cpp +1 -0
  79. package/runtime/ext_gui/dom_api_canvas.cpp +38 -4
  80. package/runtime/ext_gui/dom_api_canvas_extra.cpp +232 -0
  81. package/runtime/ext_gui/dom_api_internal.h +31 -0
  82. package/runtime/ext_gui/dom_api_proto.cpp +24 -0
  83. package/runtime/ext_gui/gui_media.cpp +69 -2
  84. package/runtime/ext_gui/media.cpp +34 -488
  85. package/runtime/ext_gui/media.h +54 -19
  86. package/runtime/ext_gui/media_api.h +65 -0
  87. package/runtime/ext_media/media.cpp +507 -0
  88. package/runtime/ext_media/media_bridge.c +35 -0
  89. package/scripts/build-gui.ts +6 -72
  90. package/scripts/build-media.ts +245 -0
  91. package/src/cli/hints.ts +11 -0
  92. package/src/cli/main.ts +1 -1
  93. package/src/driver/compiler.ts +1 -0
  94. package/src/driver/version.ts +1 -1
  95. package/src/extensions/catalog.ts +2 -1
  96. package/src/extensions/media/index.ts +67 -0
  97. package/src/extensions/registry.ts +24 -0
  98. package/src/index.ts +1 -0
@@ -159,6 +159,165 @@ describe.skipIf(!guiAvailable)("gui extension — canvas", () => {
159
159
  expect(value("fill")).toBe("#ff0000");
160
160
  expect(value("text")).toBe("true");
161
161
  });
162
+ it("supports gradients, ellipses, rounded rects, dashes and line styles", () => {
163
+ const { value } = harness.compileAndRun("canvas-modern", `
164
+ import { createWindow, run } from "gui";
165
+
166
+ const HTML = \`
167
+ <html><head><style>body { margin: 0; }</style></head><body>
168
+ <canvas id="c" width="240" height="260"></canvas>
169
+ </body></html>
170
+ \`;
171
+
172
+ const win = createWindow({ title: "canvas-modern", width: 400, height: 300 });
173
+ win.on("ready", () => {
174
+ const canvas: any = win.document.getElementById("c");
175
+ const ctx: any = canvas.getContext("2d");
176
+ const px = (x: number, y: number): string => {
177
+ const d = ctx.getImageData(x, y, 1, 1).data;
178
+ return d[0] + "," + d[1] + "," + d[2] + "," + d[3];
179
+ };
180
+
181
+ ctx.fillStyle = "#ffffff";
182
+ ctx.fillRect(0, 0, 240, 260);
183
+
184
+ // A horizontal red -> blue gradient, sampled well inside both ends.
185
+ const linear = ctx.createLinearGradient(0, 0, 100, 0);
186
+ linear.addColorStop(0, "#ff0000");
187
+ linear.addColorStop(1, "#0000ff");
188
+ ctx.fillStyle = linear;
189
+ ctx.fillRect(0, 0, 100, 20);
190
+ console.log("grad-left=" + px(5, 10));
191
+ console.log("grad-right=" + px(95, 10));
192
+ // The getter returns the same handle, not a copy.
193
+ console.log("same-gradient=" + (ctx.fillStyle === linear));
194
+
195
+ // A stop added after assignment is live: the right side turns blue.
196
+ const live = ctx.createLinearGradient(0, 0, 100, 0);
197
+ live.addColorStop(0, "#ff0000");
198
+ ctx.fillStyle = live;
199
+ live.addColorStop(1, "#0000ff");
200
+ ctx.fillRect(0, 30, 100, 20);
201
+ console.log("live-right=" + px(95, 40));
202
+
203
+ const radial = ctx.createRadialGradient(50, 70, 0, 50, 70, 35);
204
+ radial.addColorStop(0, "#ffffff");
205
+ radial.addColorStop(1, "#000000");
206
+ ctx.fillStyle = radial;
207
+ ctx.fillRect(0, 60, 100, 40);
208
+ console.log("radial-centre=" + px(50, 70));
209
+ console.log("radial-edge=" + px(88, 70));
210
+
211
+ ctx.fillStyle = "#00ff00";
212
+ ctx.beginPath();
213
+ ctx.ellipse(170, 70, 40, 15, 0, 0, Math.PI * 2);
214
+ ctx.fill();
215
+ console.log("ellipse-centre=" + px(170, 70));
216
+ console.log("ellipse-outside=" + px(170, 40));
217
+
218
+ ctx.fillStyle = "#ff00ff";
219
+ ctx.beginPath();
220
+ ctx.roundRect(10, 100, 70, 50, 14);
221
+ ctx.fill();
222
+ console.log("roundrect-centre=" + px(45, 125));
223
+ console.log("roundrect-corner=" + px(11, 101));
224
+
225
+ ctx.strokeStyle = "#000000";
226
+ ctx.lineWidth = 4;
227
+ ctx.lineCap = "butt";
228
+ ctx.setLineDash([10, 10]);
229
+ ctx.lineDashOffset = 0;
230
+ console.log("cap=" + ctx.lineCap);
231
+ console.log("join=" + ctx.lineJoin);
232
+ console.log("miter=" + ctx.miterLimit);
233
+ console.log("dash=" + ctx.getLineDash().join(","));
234
+ ctx.beginPath();
235
+ ctx.moveTo(120, 150);
236
+ ctx.lineTo(230, 150);
237
+ ctx.stroke();
238
+ console.log("dash-on=" + px(124, 150));
239
+ console.log("dash-off=" + px(136, 150));
240
+
241
+ ctx.setLineDash([]);
242
+ ctx.strokeStyle = "#ff0000";
243
+ ctx.lineWidth = 10;
244
+ ctx.lineCap = "square";
245
+ ctx.beginPath();
246
+ ctx.moveTo(120, 190);
247
+ ctx.lineTo(180, 190);
248
+ ctx.stroke();
249
+ console.log("square-cap=" + px(115, 190));
250
+ console.log("square-cap-far=" + px(105, 190));
251
+
252
+ // A miter fills the outer corner right to the tip; a bevel cuts it off.
253
+ ctx.strokeStyle = "#000000";
254
+ ctx.lineWidth = 20;
255
+ ctx.lineCap = "butt";
256
+ ctx.lineJoin = "miter";
257
+ ctx.beginPath();
258
+ ctx.moveTo(120, 215);
259
+ ctx.lineTo(120, 245);
260
+ ctx.lineTo(160, 245);
261
+ ctx.stroke();
262
+ console.log("miter-join=" + px(111, 254));
263
+ ctx.lineJoin = "bevel";
264
+ ctx.beginPath();
265
+ ctx.moveTo(180, 215);
266
+ ctx.lineTo(180, 245);
267
+ ctx.lineTo(220, 245);
268
+ ctx.stroke();
269
+ console.log("bevel-join=" + px(171, 254));
270
+
271
+ ctx.save();
272
+ ctx.translate(100, 100);
273
+ ctx.rotate(Math.PI / 2);
274
+ const t = ctx.getTransform();
275
+ console.log("nested-transform=" + Math.round(t.e) + "," + Math.round(t.f));
276
+ // Post-multiplied: the square sits at (90,100)..(100,110), not at the
277
+ // rotated origin. A pre-multiplied transform would put it elsewhere.
278
+ ctx.fillStyle = "#ff8800";
279
+ ctx.fillRect(0, 0, 10, 10);
280
+ console.log("rotated-rect=" + px(95, 105));
281
+ ctx.restore();
282
+ const r = ctx.getTransform();
283
+ console.log("restored-transform=" + r.a + "," + r.e + "," + r.f);
284
+
285
+ win.close();
286
+ });
287
+ win.loadHTML(HTML);
288
+ run();
289
+ `);
290
+ const channels = (label) => value(label).split(",").map(Number);
291
+ const left = channels("grad-left");
292
+ expect(left[0]).toBeGreaterThan(200);
293
+ expect(left[2]).toBeLessThan(60);
294
+ const right = channels("grad-right");
295
+ expect(right[0]).toBeLessThan(60);
296
+ expect(right[2]).toBeGreaterThan(200);
297
+ expect(value("same-gradient")).toBe("true");
298
+ expect(channels("live-right")[2]).toBeGreaterThan(200);
299
+ // The radial gradient is white at its centre and black at its edge.
300
+ expect(channels("radial-centre")[0]).toBeGreaterThan(230);
301
+ expect(channels("radial-edge")[0]).toBeLessThan(40);
302
+ expect(channels("ellipse-centre")).toEqual([0, 255, 0, 255]);
303
+ expect(channels("ellipse-outside")).toEqual([255, 255, 255, 255]);
304
+ expect(channels("roundrect-centre")).toEqual([255, 0, 255, 255]);
305
+ expect(channels("roundrect-corner")).toEqual([255, 255, 255, 255]);
306
+ expect(value("cap")).toBe("butt");
307
+ expect(value("join")).toBe("miter");
308
+ expect(value("miter")).toBe("10");
309
+ expect(value("dash")).toBe("10,10");
310
+ expect(channels("dash-on")).toEqual([0, 0, 0, 255]);
311
+ expect(channels("dash-off")).toEqual([255, 255, 255, 255]);
312
+ // A square cap extends half a line width past the endpoint.
313
+ expect(channels("square-cap")).toEqual([255, 0, 0, 255]);
314
+ expect(channels("square-cap-far")).toEqual([255, 255, 255, 255]);
315
+ expect(channels("miter-join")).toEqual([0, 0, 0, 255]);
316
+ expect(channels("bevel-join")).toEqual([255, 255, 255, 255]);
317
+ expect(value("nested-transform")).toBe("100,100");
318
+ expect(channels("rotated-rect")).toEqual([255, 136, 0, 255]);
319
+ expect(value("restored-transform")).toBe("1,0,0");
320
+ });
162
321
  it("draws an image onto a canvas with drawImage", () => {
163
322
  const src = harness.imageSrc(harness.logoPath);
164
323
  const { value } = harness.compileAndRun("canvas-drawimage", `
@@ -1 +1 @@
1
- {"version":3,"file":"gui-canvas.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-canvas.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gui-canvas.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-canvas.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * End-to-end smoke test for `examples/gui/pelican-canvas` — the animated
3
+ * `<canvas>` drawing.
4
+ *
5
+ * The drawing lives in `scene.js`, loaded by `index.html` through a plain
6
+ * `<script src>`: a browser runs it as-is, while xbintsc AOT-compiles the same
7
+ * body via the gui `.html` loader. `main.ts` only hosts the native window and
8
+ * reports deterministic pixel probes, so this test can assert that the
9
+ * gradients, paths and text really rasterised.
10
+ */
11
+ export {};
@@ -0,0 +1,72 @@
1
+ /**
2
+ * End-to-end smoke test for `examples/gui/pelican-canvas` — the animated
3
+ * `<canvas>` drawing.
4
+ *
5
+ * The drawing lives in `scene.js`, loaded by `index.html` through a plain
6
+ * `<script src>`: a browser runs it as-is, while xbintsc AOT-compiles the same
7
+ * body via the gui `.html` loader. `main.ts` only hosts the native window and
8
+ * reports deterministic pixel probes, so this test can assert that the
9
+ * gradients, paths and text really rasterised.
10
+ */
11
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import { spawnSync } from "node:child_process";
15
+ import { Script } from "node:vm";
16
+ import { fileURLToPath } from "node:url";
17
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
18
+ import { build } from "../../src/driver/compiler.js";
19
+ import { createDefaultRegistry } from "../../src/extensions/registry.js";
20
+ import { guiExtension } from "../../src/extensions/gui/index.js";
21
+ import { guiAvailable } from "./gui-helpers.js";
22
+ /** The example lives at <repo>/examples/gui/pelican-canvas. */
23
+ const exampleDir = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "examples", "gui", "pelican-canvas");
24
+ let workdir = "";
25
+ describe("pelican canvas example — browser entry", () => {
26
+ it("loads the shared scene as a classic script", () => {
27
+ const html = readFileSync(join(exampleDir, "index.html"), "utf8");
28
+ expect(html).toContain('<script src="./scene.js"></script>');
29
+ const script = readFileSync(join(exampleDir, "scene.js"), "utf8");
30
+ // A browser compiles this as a classic script: no ESM, no TypeScript.
31
+ expect(() => new Script(script)).not.toThrow();
32
+ });
33
+ });
34
+ describe.skipIf(!guiAvailable)("gui example — pelican canvas", () => {
35
+ beforeAll(() => {
36
+ workdir = mkdtempSync(join(tmpdir(), "xbintsc-pelican-canvas-"));
37
+ for (const file of ["index.html", "main.ts", "scene.js"]) {
38
+ writeFileSync(join(workdir, file), readFileSync(join(exampleDir, file), "utf8"));
39
+ }
40
+ });
41
+ afterAll(() => {
42
+ rmSync(workdir, { recursive: true, force: true });
43
+ });
44
+ it("compiles the canvas drawing and reports pixels", () => {
45
+ const extensions = createDefaultRegistry().register(guiExtension);
46
+ const result = build(join(workdir, "main.ts"), {
47
+ emit: "exe",
48
+ outDir: join(workdir, "out"),
49
+ cacheDir: join(workdir, ".cache"),
50
+ extensions,
51
+ });
52
+ expect(result.diagnostics.filter((diagnostic) => diagnostic.category === "error")).toEqual([]);
53
+ const executed = spawnSync(result.outputPath, [], {
54
+ encoding: "utf8",
55
+ env: { ...process.env, XT_GUI_AUTOCLOSE_MS: "2000" },
56
+ });
57
+ expect(executed.status, executed.stderr).toBe(0);
58
+ const stdout = executed.stdout ?? "";
59
+ expect(stdout).toContain("window=1000x640 (gui extension, SDL_GPU)");
60
+ expect(stdout).toContain("canvas-box=x=0 y=0 1000x640");
61
+ expect(stdout).toContain("canvas-size=1000x640");
62
+ // The title is white text on the gradient sky. Probe its whole box: the
63
+ // ink offset depends on the platform font (YaHei vs STHeiti/PingFang), so a
64
+ // single point at the left edge is not stable across platforms.
65
+ expect(stdout).toContain("pixel-title=255,255,255,255");
66
+ // The road gradient, and the pelican body (not the sky colour).
67
+ expect(stdout).toMatch(/pixel-road=\d+,\d+,\d+,255/);
68
+ expect(stdout).toMatch(/pixel-pelican=\d+,\d+,\d+,255/);
69
+ expect(stdout).toContain("gui exited");
70
+ });
71
+ });
72
+ //# sourceMappingURL=gui-example-canvas.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gui-example-canvas.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-example-canvas.test.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@
18
18
  * test PNG; the suite calls `setup()` in `beforeAll` and `cleanup()` in
19
19
  * `afterAll`.
20
20
  */
21
+ import { type Extension } from "../../src/extensions/registry.js";
21
22
  /**
22
23
  * True when the GUI archive exists and the suite may run.
23
24
  *
@@ -37,6 +38,8 @@ export interface GuiRunResult {
37
38
  export interface GuiRunOptions {
38
39
  /** Extra files written into the work directory before the build. */
39
40
  files?: Record<string, string>;
41
+ /** Additional extensions to register next to `gui` (e.g. `media`). */
42
+ extensions?: readonly Extension[];
40
43
  /**
41
44
  * Milliseconds the frame loop may run before `XT_GUI_AUTOCLOSE_MS` closes
42
45
  * every window. A program whose handlers close the window does not need this
@@ -60,6 +60,8 @@ export function createGuiHarness() {
60
60
  const entry = join(workdir, `${name}.ts`);
61
61
  writeFileSync(entry, source);
62
62
  const extensions = createDefaultRegistry().register(guiExtension);
63
+ for (const extension of options.extensions ?? [])
64
+ extensions.register(extension);
63
65
  const result = build(entry, {
64
66
  emit: "exe",
65
67
  outDir: join(workdir, `out-${name}`),
@@ -1 +1 @@
1
- {"version":3,"file":"gui-helpers.js","sourceRoot":"","sources":["../../../tests/e2e/gui-helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gui-helpers.js","sourceRoot":"","sources":["../../../tests/e2e/gui-helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `<video>` / `<audio>` are part of the GUI DOM even when no decoder is linked.
3
+ *
4
+ * This suite compiles with `--ext gui` only (the harness never registers the
5
+ * `media` extension), which is the whole point of the split: a GUI program does
6
+ * not link FFmpeg unless it asks for it. The element still exists and its DOM
7
+ * API is callable, but opening a source fails and fires `error`.
8
+ */
9
+ export {};
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `<video>` / `<audio>` are part of the GUI DOM even when no decoder is linked.
3
+ *
4
+ * This suite compiles with `--ext gui` only (the harness never registers the
5
+ * `media` extension), which is the whole point of the split: a GUI program does
6
+ * not link FFmpeg unless it asks for it. The element still exists and its DOM
7
+ * API is callable, but opening a source fails and fires `error`.
8
+ */
9
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
10
+ import { createGuiHarness, guiAvailable } from "./gui-helpers.js";
11
+ describe.skipIf(!guiAvailable)("gui extension without media", () => {
12
+ const harness = createGuiHarness();
13
+ beforeAll(() => harness.setup());
14
+ afterAll(() => harness.cleanup());
15
+ it("reports error instead of decoding when the media extension is off", () => {
16
+ const { stdout } = harness.compileAndRun("media-off", `
17
+ import { createWindow, run } from "gui";
18
+
19
+ const win = createWindow({ title: "media off", width: 320, height: 200 });
20
+ win.on("ready", () => {
21
+ win.loadHTML('<video id="v" src="missing.mp4"></video>');
22
+ const v: any = win.document.getElementById("v");
23
+ v.addEventListener("loadedmetadata", () => {
24
+ console.log("unexpected-metadata");
25
+ win.close();
26
+ });
27
+ v.addEventListener("error", () => {
28
+ console.log("media-error");
29
+ win.close();
30
+ });
31
+ // The DOM surface is still there even without a decoder.
32
+ console.log("api=" + (v.paused === true) + ":" + (v.duration === 0));
33
+ });
34
+
35
+ run();
36
+ `, { autocloseMs: 1500 });
37
+ expect(stdout).toContain("media-error");
38
+ expect(stdout).not.toContain("unexpected-metadata");
39
+ expect(stdout).toContain("api=true:true");
40
+ });
41
+ });
42
+ //# sourceMappingURL=gui-media-disabled.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gui-media-disabled.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-media-disabled.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAElE,QAAQ,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACjE,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAElC,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CACtC,WAAW,EACX;;;;;;;;;;;;;;;;;;;;OAoBC,EACD,EAAE,WAAW,EAAE,IAAI,EAAE,CACtB,CAAC;QAEF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,8 +1,10 @@
1
1
  /**
2
- * End-to-end tests for `<video>` / `<audio>` support in the `gui` extension.
2
+ * End-to-end tests for `<video>` / `<audio>` support.
3
3
  *
4
- * These exercise the real decoding path (vendored FFmpeg + SDL audio) and the
5
- * DOM media API. The fixtures live in `examples/resources`; when they are
6
- * absent (a trim checkout) the suite is skipped rather than failing.
4
+ * These exercise the real decoding path (the `media` extension's vendored
5
+ * FFmpeg + the GUI's SDL audio sink) and the DOM media API. They are skipped
6
+ * unless both the `gui` and `media` archives exist: the `gui` extension alone
7
+ * is deliberately decoder-free. The fixtures live in `examples/resources`; when
8
+ * they are absent (a trim checkout) the suite is skipped rather than failing.
7
9
  */
8
10
  export {};
@@ -1,9 +1,11 @@
1
1
  /**
2
- * End-to-end tests for `<video>` / `<audio>` support in the `gui` extension.
2
+ * End-to-end tests for `<video>` / `<audio>` support.
3
3
  *
4
- * These exercise the real decoding path (vendored FFmpeg + SDL audio) and the
5
- * DOM media API. The fixtures live in `examples/resources`; when they are
6
- * absent (a trim checkout) the suite is skipped rather than failing.
4
+ * These exercise the real decoding path (the `media` extension's vendored
5
+ * FFmpeg + the GUI's SDL audio sink) and the DOM media API. They are skipped
6
+ * unless both the `gui` and `media` archives exist: the `gui` extension alone
7
+ * is deliberately decoder-free. The fixtures live in `examples/resources`; when
8
+ * they are absent (a trim checkout) the suite is skipped rather than failing.
7
9
  */
8
10
  import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
9
11
  import { tmpdir } from "node:os";
@@ -14,6 +16,8 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest";
14
16
  import { build } from "../../src/driver/compiler.js";
15
17
  import { createDefaultRegistry } from "../../src/extensions/registry.js";
16
18
  import { guiExtension } from "../../src/extensions/gui/index.js";
19
+ import { mediaExtension } from "../../src/extensions/media/index.js";
20
+ import { findRuntimeLibrary } from "../../src/driver/runtime-lib.js";
17
21
  import { createGuiHarness, guiAvailable } from "./gui-helpers.js";
18
22
  const root = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
19
23
  const resourceDir = join(root, "examples", "resources");
@@ -27,13 +31,12 @@ function mediaSrc(absolutePath) {
27
31
  }
28
32
  const resourcesAvailable = existsSync(moviePath) && existsSync(soundPath);
29
33
  /**
30
- * Windows builds the GUI archive without FFmpeg on purpose (see
31
- * `doc/gui/known-issues.md`), so media elements are inert there and the suite
32
- * would only report the expected `error` events as failures. It stays skipped
33
- * even with `xbintsc_GUI_TESTS=1`.
34
+ * The `media` archive is built separately (`npm run media`) and is POSIX-only
35
+ * for now. Without it the suite would compile GUI programs that report the
36
+ * expected `error` events, i.e. it would test the wrong thing.
34
37
  */
35
- const mediaAvailable = process.platform !== "win32";
36
- describe.skipIf(!guiAvailable || !resourcesAvailable || !mediaAvailable)("gui extension — media", () => {
38
+ const mediaAvailable = process.platform !== "win32" && findRuntimeLibrary("media") !== undefined;
39
+ describe.skipIf(!guiAvailable || !resourcesAvailable || !mediaAvailable)("gui + media extensions", () => {
37
40
  const harness = createGuiHarness();
38
41
  beforeAll(() => harness.setup());
39
42
  afterAll(() => harness.cleanup());
@@ -81,7 +84,7 @@ describe.skipIf(!guiAvailable || !resourcesAvailable || !mediaAvailable)("gui ex
81
84
  });
82
85
 
83
86
  run();
84
- `, { autocloseMs: 8000 });
87
+ `, { autocloseMs: 8000, extensions: [mediaExtension] });
85
88
  expect(stdout).not.toContain("video-error");
86
89
  expect(stdout).not.toContain("audio-error");
87
90
  expect(value("duration")).toBe("true:true");
@@ -98,7 +101,7 @@ describe.skipIf(!guiAvailable || !resourcesAvailable || !mediaAvailable)("gui ex
98
101
  try {
99
102
  writeFileSync(join(workdir, "media.html"), readFileSync(join(exampleDir, "media.html"), "utf8"));
100
103
  writeFileSync(join(workdir, "media.ts"), readFileSync(join(exampleDir, "media.ts"), "utf8"));
101
- const extensions = createDefaultRegistry().register(guiExtension);
104
+ const extensions = createDefaultRegistry().register(guiExtension).register(mediaExtension);
102
105
  const result = build(join(workdir, "media.ts"), {
103
106
  emit: "exe",
104
107
  outDir: join(workdir, "out"),
@@ -1 +1 @@
1
- {"version":3,"file":"gui-media.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-media.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gui-media.test.js","sourceRoot":"","sources":["../../../tests/e2e/gui-media.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Regression coverage for Chinese (and other non-ASCII) text reaching stdout.
3
+ *
4
+ * The driver reads a source file as UTF-8 bytes, the lexer stores a literal's
5
+ * bytes, and the runtime writes those bytes straight to `stdout`/`stderr`. A
6
+ * mis-encoded literal, a UTF-16 code-unit leak or a console writer that
7
+ * re-encodes the bytes changes the output sequence even when adjacent English
8
+ * text still looks fine — the issue reports exactly that:
9
+ *
10
+ * console.log('你好世界!');
11
+ * console.log('Hello World!');
12
+ *
13
+ * The program is run with its stdout/stderr captured as pipes, so these cases
14
+ * pin the bytes the terminal receives without depending on a local code page.
15
+ */
16
+ export {};
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Regression coverage for Chinese (and other non-ASCII) text reaching stdout.
3
+ *
4
+ * The driver reads a source file as UTF-8 bytes, the lexer stores a literal's
5
+ * bytes, and the runtime writes those bytes straight to `stdout`/`stderr`. A
6
+ * mis-encoded literal, a UTF-16 code-unit leak or a console writer that
7
+ * re-encodes the bytes changes the output sequence even when adjacent English
8
+ * text still looks fine — the issue reports exactly that:
9
+ *
10
+ * console.log('你好世界!');
11
+ * console.log('Hello World!');
12
+ *
13
+ * The program is run with its stdout/stderr captured as pipes, so these cases
14
+ * pin the bytes the terminal receives without depending on a local code page.
15
+ */
16
+ import { expect, it } from "vitest";
17
+ import { describeE2E } from "./harness.js";
18
+ /** The UTF-8 bytes of `text`, as hexadecimal, so a re-encoding cannot pass. */
19
+ function utf8Hex(text) {
20
+ return Buffer.from(text, "utf8").toString("hex");
21
+ }
22
+ const issueProgram = `console.log('你好世界!');
23
+ console.log('Hello World!');
24
+ `;
25
+ describeE2E("non-ASCII console output", (harness) => {
26
+ it("prints the issue's Chinese and English lines as exact UTF-8", () => {
27
+ const result = harness.runProgramFull(issueProgram, { name: "chinese_issue" });
28
+ expect(result.status).toBe(0);
29
+ expect(result.stderr).toBe("");
30
+ expect(result.stdout).toBe("你好世界!\nHello World!\n");
31
+ expect(utf8Hex(result.stdout)).toBe("e4bda0e5a5bde4b896e7958cefbc810a48656c6c6f20576f726c64210a");
32
+ });
33
+ it("prints Chinese literals, escapes, templates and identifiers byte-identically", () => {
34
+ const result = harness.runProgramFull(`
35
+ const 名字 = "世界";
36
+ console.log("你好," + 名字 + "!");
37
+ console.log("\\u4f60\\u597d\\uff0c\\u4e16\\u754c\\uff01");
38
+ console.log(\`你好,\${名字}!\`);
39
+ console.log(["中文", { 键: "值" }]);
40
+ console.log(JSON.stringify({ 你好: "世界" }));
41
+ `, { name: "chinese_values" });
42
+ expect(result.status).toBe(0);
43
+ expect(result.stderr).toBe("");
44
+ expect(result.stdout).toBe([
45
+ "你好,世界!",
46
+ "你好,世界!",
47
+ "你好,世界!",
48
+ "[ '中文', { '键': '值' } ]",
49
+ '{"你好":"世界"}',
50
+ "",
51
+ ].join("\n"));
52
+ });
53
+ it("routes Chinese console levels to the matching stream", () => {
54
+ const result = harness.runProgramFull(`
55
+ console.log("日志:中文");
56
+ console.info("信息:中文");
57
+ console.warn("警告:中文");
58
+ console.error("错误:中文");
59
+ `, { name: "chinese_console_levels" });
60
+ expect(result.status).toBe(0);
61
+ expect(result.stdout).toBe("日志:中文\n信息:中文\n");
62
+ expect(result.stderr).toBe("警告:中文\n错误:中文\n");
63
+ });
64
+ });
65
+ //# sourceMappingURL=unicode-output.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unicode-output.test.js","sourceRoot":"","sources":["../../../tests/e2e/unicode-output.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,+EAA+E;AAC/E,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,YAAY,GAAG;;CAEpB,CAAC;AAEF,WAAW,CAAC,0BAA0B,EAAE,CAAC,OAAO,EAAE,EAAE;IAClD,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,GAAG,EAAE;QACtF,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CACnC;;;;;;;OAOC,EACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAC3B,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CACxB;YACE,QAAQ;YACR,QAAQ;YACR,QAAQ;YACR,wBAAwB;YACxB,aAAa;YACb,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CACnC;;;;;OAKC,EACD,EAAE,IAAI,EAAE,wBAAwB,EAAE,CACnC,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};