xbintsc 0.3.18 → 0.3.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +33 -0
  2. package/dist/src/cli/main.js +124 -30
  3. package/dist/src/cli/main.js.map +1 -1
  4. package/dist/src/codegen/generator/calls/access.js +8 -1
  5. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  6. package/dist/src/codegen/generator/state.js +20 -0
  7. package/dist/src/codegen/generator/state.js.map +1 -1
  8. package/dist/src/codegen/generator/tables.d.ts +6 -0
  9. package/dist/src/codegen/generator/tables.js +38 -0
  10. package/dist/src/codegen/generator/tables.js.map +1 -1
  11. package/dist/src/driver/bundler/commonjs.d.ts +52 -0
  12. package/dist/src/driver/bundler/commonjs.js +493 -0
  13. package/dist/src/driver/bundler/commonjs.js.map +1 -0
  14. package/dist/src/driver/bundler/graph.d.ts +2 -1
  15. package/dist/src/driver/bundler/graph.js +32 -3
  16. package/dist/src/driver/bundler/graph.js.map +1 -1
  17. package/dist/src/driver/bundler/merge.d.ts +2 -1
  18. package/dist/src/driver/bundler/merge.js +16 -2
  19. package/dist/src/driver/bundler/merge.js.map +1 -1
  20. package/dist/src/driver/bundler/types.d.ts +8 -0
  21. package/dist/src/driver/compiler.d.ts +8 -1
  22. package/dist/src/driver/compiler.js +75 -7
  23. package/dist/src/driver/compiler.js.map +1 -1
  24. package/dist/src/driver/config.d.ts +53 -0
  25. package/dist/src/driver/config.js +141 -0
  26. package/dist/src/driver/config.js.map +1 -0
  27. package/dist/src/driver/icon.d.ts +62 -0
  28. package/dist/src/driver/icon.js +151 -0
  29. package/dist/src/driver/icon.js.map +1 -0
  30. package/dist/src/driver/index.d.ts +4 -0
  31. package/dist/src/driver/index.js +4 -0
  32. package/dist/src/driver/index.js.map +1 -1
  33. package/dist/src/driver/mac-bundle.d.ts +41 -0
  34. package/dist/src/driver/mac-bundle.js +123 -0
  35. package/dist/src/driver/mac-bundle.js.map +1 -0
  36. package/dist/src/driver/win-icon.d.ts +27 -0
  37. package/dist/src/driver/win-icon.js +80 -0
  38. package/dist/src/driver/win-icon.js.map +1 -0
  39. package/dist/src/extensions/gui/html.d.ts +25 -0
  40. package/dist/src/extensions/gui/html.js +203 -0
  41. package/dist/src/extensions/gui/html.js.map +1 -0
  42. package/dist/src/extensions/gui/index.js +11 -0
  43. package/dist/src/extensions/gui/index.js.map +1 -1
  44. package/dist/src/extensions/registry.d.ts +29 -0
  45. package/dist/src/extensions/registry.js +14 -0
  46. package/dist/src/extensions/registry.js.map +1 -1
  47. package/dist/src/index.d.ts +1 -1
  48. package/dist/src/index.js.map +1 -1
  49. package/dist/src/lexer/scanner/identifiers.js +4 -12
  50. package/dist/src/lexer/scanner/identifiers.js.map +1 -1
  51. package/dist/src/parser/statements.js +17 -4
  52. package/dist/src/parser/statements.js.map +1 -1
  53. package/dist/tests/cli/main.test.js +46 -1
  54. package/dist/tests/cli/main.test.js.map +1 -1
  55. package/dist/tests/driver/bundler-resolve.test.d.ts +1 -0
  56. package/dist/tests/driver/bundler-resolve.test.js +230 -0
  57. package/dist/tests/driver/bundler-resolve.test.js.map +1 -0
  58. package/dist/tests/driver/config.test.d.ts +1 -0
  59. package/dist/tests/driver/config.test.js +124 -0
  60. package/dist/tests/driver/config.test.js.map +1 -0
  61. package/dist/tests/driver/icon.test.d.ts +1 -0
  62. package/dist/tests/driver/icon.test.js +421 -0
  63. package/dist/tests/driver/icon.test.js.map +1 -0
  64. package/dist/tests/driver/modules.test.js +177 -0
  65. package/dist/tests/driver/modules.test.js.map +1 -1
  66. package/dist/tests/e2e/fetch.test.d.ts +12 -0
  67. package/dist/tests/e2e/fetch.test.js +272 -0
  68. package/dist/tests/e2e/fetch.test.js.map +1 -0
  69. package/dist/tests/e2e/gui-dom.test.d.ts +5 -0
  70. package/dist/tests/e2e/gui-dom.test.js +102 -0
  71. package/dist/tests/e2e/gui-dom.test.js.map +1 -0
  72. package/dist/tests/e2e/gui-events.test.d.ts +5 -0
  73. package/dist/tests/e2e/gui-events.test.js +60 -0
  74. package/dist/tests/e2e/gui-events.test.js.map +1 -0
  75. package/dist/tests/e2e/gui-helpers.d.ts +31 -0
  76. package/dist/tests/e2e/gui-helpers.js +74 -0
  77. package/dist/tests/e2e/gui-helpers.js.map +1 -0
  78. package/dist/tests/e2e/gui-layout.test.d.ts +4 -0
  79. package/dist/tests/e2e/gui-layout.test.js +88 -0
  80. package/dist/tests/e2e/gui-layout.test.js.map +1 -0
  81. package/dist/tests/e2e/gui-lifecycle.test.d.ts +5 -0
  82. package/dist/tests/e2e/gui-lifecycle.test.js +58 -0
  83. package/dist/tests/e2e/gui-lifecycle.test.js.map +1 -0
  84. package/dist/tests/e2e/gui-paint.test.d.ts +5 -0
  85. package/dist/tests/e2e/gui-paint.test.js +111 -0
  86. package/dist/tests/e2e/gui-paint.test.js.map +1 -0
  87. package/dist/tests/e2e/gui-script.test.d.ts +5 -0
  88. package/dist/tests/e2e/gui-script.test.js +78 -0
  89. package/dist/tests/e2e/gui-script.test.js.map +1 -0
  90. package/dist/tests/e2e/gui-style.test.d.ts +5 -0
  91. package/dist/tests/e2e/gui-style.test.js +175 -0
  92. package/dist/tests/e2e/gui-style.test.js.map +1 -0
  93. package/dist/tests/e2e/icon.test.d.ts +7 -0
  94. package/dist/tests/e2e/icon.test.js +80 -0
  95. package/dist/tests/e2e/icon.test.js.map +1 -0
  96. package/dist/tests/e2e/npm-modules.test.d.ts +4 -1
  97. package/dist/tests/e2e/npm-modules.test.js +47 -1
  98. package/dist/tests/e2e/npm-modules.test.js.map +1 -1
  99. package/dist/tests/e2e/runtime-coverage-typed-array.test.d.ts +9 -0
  100. package/dist/tests/e2e/runtime-coverage-typed-array.test.js +140 -0
  101. package/dist/tests/e2e/runtime-coverage-typed-array.test.js.map +1 -0
  102. package/dist/tests/extensions/gui-index.test.d.ts +1 -0
  103. package/dist/tests/extensions/gui-index.test.js +49 -0
  104. package/dist/tests/extensions/gui-index.test.js.map +1 -0
  105. package/dist/tests/extensions/gui.test.d.ts +1 -0
  106. package/dist/tests/extensions/gui.test.js +177 -0
  107. package/dist/tests/extensions/gui.test.js.map +1 -0
  108. package/dist/tests/extensions/registry.test.js +36 -0
  109. package/dist/tests/extensions/registry.test.js.map +1 -1
  110. package/dist/tests/parser/statements.test.js +11 -0
  111. package/dist/tests/parser/statements.test.js.map +1 -1
  112. package/dist/tests/public-api.test.d.ts +1 -0
  113. package/dist/tests/public-api.test.js +31 -0
  114. package/dist/tests/public-api.test.js.map +1 -0
  115. package/package.json +1 -1
  116. package/runtime/ext_gui/css.cpp +4 -517
  117. package/runtime/ext_gui/css_internal.h +27 -0
  118. package/runtime/ext_gui/css_match.cpp +195 -0
  119. package/runtime/ext_gui/css_selector.cpp +207 -0
  120. package/runtime/ext_gui/css_sheet.cpp +129 -0
  121. package/runtime/ext_gui/document.cpp +90 -0
  122. package/runtime/ext_gui/document.h +23 -0
  123. package/runtime/ext_gui/dom.cpp +43 -403
  124. package/runtime/ext_gui/dom.h +7 -0
  125. package/runtime/ext_gui/dom_api.cpp +164 -0
  126. package/runtime/ext_gui/dom_api.h +12 -0
  127. package/runtime/ext_gui/dom_api_document.cpp +96 -0
  128. package/runtime/ext_gui/dom_api_events.cpp +123 -0
  129. package/runtime/ext_gui/dom_api_internal.h +135 -0
  130. package/runtime/ext_gui/dom_api_node.cpp +329 -0
  131. package/runtime/ext_gui/dom_api_node_read.cpp +294 -0
  132. package/runtime/ext_gui/dom_api_proto.cpp +130 -0
  133. package/runtime/ext_gui/dom_api_style.cpp +192 -0
  134. package/runtime/ext_gui/dom_internal.h +39 -0
  135. package/runtime/ext_gui/dom_parse.cpp +348 -0
  136. package/runtime/ext_gui/dom_serialize.cpp +54 -0
  137. package/runtime/ext_gui/gui.cpp +61 -245
  138. package/runtime/ext_gui/gui_engine.h +54 -0
  139. package/runtime/ext_gui/gui_events.cpp +294 -0
  140. package/runtime/ext_gui/gui_internal.h +29 -0
  141. package/runtime/ext_gui/layout.cpp +6 -597
  142. package/runtime/ext_gui/layout_flex.cpp +200 -0
  143. package/runtime/ext_gui/layout_flow.cpp +191 -0
  144. package/runtime/ext_gui/layout_flow_internal.h +149 -0
  145. package/runtime/ext_gui/layout_inline.cpp +181 -0
  146. package/runtime/ext_gui/layout_internal.h +20 -0
  147. package/runtime/ext_gui/renderer.cpp +15 -679
  148. package/runtime/ext_gui/renderer_image.cpp +233 -0
  149. package/runtime/ext_gui/renderer_internal.h +112 -0
  150. package/runtime/ext_gui/renderer_shaders.h +108 -0
  151. package/runtime/ext_gui/renderer_text.cpp +342 -0
  152. package/runtime/ext_gui/script.cpp +63 -0
  153. package/runtime/ext_gui/style.cpp +12 -660
  154. package/runtime/ext_gui/style_internal.h +33 -0
  155. package/runtime/ext_gui/style_print.cpp +113 -0
  156. package/runtime/ext_gui/style_ua.cpp +98 -0
  157. package/runtime/ext_gui/style_values.cpp +468 -0
  158. package/runtime/ext_gui/window.cpp +60 -0
  159. package/runtime/rt.h +6 -0
  160. package/runtime/rt_internal.h +4 -0
  161. package/runtime/xt_builtins.c +1 -0
  162. package/runtime/xt_containers/access.inc +32 -1
  163. package/runtime/xt_fetch/buffer.inc +64 -0
  164. package/runtime/xt_fetch/headers.inc +312 -0
  165. package/runtime/xt_fetch/request.inc +386 -0
  166. package/runtime/xt_fetch/response.inc +107 -0
  167. package/runtime/xt_fetch/socket.inc +72 -0
  168. package/runtime/xt_fetch/url.inc +108 -0
  169. package/runtime/xt_fetch.c +39 -0
  170. package/runtime/xt_stdlib2/set.inc +1 -1
  171. package/runtime/xt_typed_array.c +614 -0
  172. package/src/cli/main.ts +137 -29
  173. package/src/codegen/generator/calls/access.ts +9 -1
  174. package/src/codegen/generator/state.ts +20 -0
  175. package/src/codegen/generator/tables.ts +40 -0
  176. package/src/driver/bundler/commonjs.ts +553 -0
  177. package/src/driver/bundler/graph.ts +35 -2
  178. package/src/driver/bundler/merge.ts +18 -1
  179. package/src/driver/bundler/types.ts +8 -0
  180. package/src/driver/compiler.ts +85 -7
  181. package/src/driver/config.ts +173 -0
  182. package/src/driver/icon.ts +184 -0
  183. package/src/driver/index.ts +30 -0
  184. package/src/driver/mac-bundle.ts +156 -0
  185. package/src/driver/win-icon.ts +96 -0
  186. package/src/extensions/gui/html.ts +236 -0
  187. package/src/extensions/gui/index.ts +11 -0
  188. package/src/extensions/registry.ts +39 -0
  189. package/src/index.ts +1 -1
  190. package/src/lexer/scanner/identifiers.ts +4 -11
  191. package/src/parser/statements.ts +17 -4
  192. package/dist/tests/e2e/gui.test.d.ts +0 -12
  193. package/dist/tests/e2e/gui.test.js +0 -493
  194. package/dist/tests/e2e/gui.test.js.map +0 -1
@@ -0,0 +1,421 @@
1
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { build } from "../../src/driver/compiler.js";
6
+ import { EMPTY_ICON, ICON_SYMBOLS, IconError, ensureIconObject, iconSource, pngToIco, readIcon, toIcoBytes, } from "../../src/driver/icon.js";
7
+ import { ensureWindowsIconResource, resolveResourceCompiler } from "../../src/driver/win-icon.js";
8
+ import { bundlePathFor, infoPlist, packageMacApp } from "../../src/driver/mac-bundle.js";
9
+ import { DiagnosticCode } from "../../src/diagnostics/diagnostic.js";
10
+ import { guiExtension } from "../../src/extensions/gui/index.js";
11
+ import { createDefaultRegistry } from "../../src/extensions/registry.js";
12
+ import { findRuntimeDir, platformSlug } from "../../src/driver/paths.js";
13
+ /** The GUI suite only runs when the native archive has been built (see gui-helpers). */
14
+ const guiAvailable = existsSync(join(findRuntimeDir(), "lib", platformSlug(), "gui.a")) &&
15
+ process.platform !== "win32";
16
+ /** Resource compilers are discovered with the platform's executable suffix. */
17
+ const EXE_SUFFIX = process.platform === "win32" ? ".exe" : "";
18
+ const LLVM_RC = `llvm-rc${EXE_SUFFIX}`;
19
+ const LOGO_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAFElEQVR42mP4z8DwH4Sh1H8G0gUALFAf4eNWqTEAAAAASUVORK5CYII=";
20
+ const directories = [];
21
+ function temporaryDirectory() {
22
+ const directory = mkdtempSync(join(tmpdir(), "xbintsc-icon-"));
23
+ directories.push(directory);
24
+ return directory;
25
+ }
26
+ function writePng(directory, name = "icon.png") {
27
+ const path = join(directory, name);
28
+ writeFileSync(path, Buffer.from(LOGO_PNG_BASE64, "base64"));
29
+ return path;
30
+ }
31
+ function recordingRunner(handler) {
32
+ const calls = [];
33
+ const runner = {
34
+ run(command, args) {
35
+ calls.push({ command, args: [...args] });
36
+ return { status: 0, stdout: "", stderr: "", ...handler?.(command, args) };
37
+ },
38
+ };
39
+ return { runner, calls };
40
+ }
41
+ afterEach(() => {
42
+ while (directories.length > 0)
43
+ rmSync(directories.pop(), { recursive: true, force: true });
44
+ });
45
+ describe("readIcon", () => {
46
+ it("reads a PNG and sniffs its size", () => {
47
+ const path = writePng(temporaryDirectory());
48
+ const icon = readIcon(path);
49
+ expect(icon.format).toBe("png");
50
+ expect(icon.width).toBe(4);
51
+ expect(icon.height).toBe(4);
52
+ expect(icon.path).toBe(path);
53
+ });
54
+ it("reads an ICO directory entry", () => {
55
+ const directory = temporaryDirectory();
56
+ const path = join(directory, "icon.ico");
57
+ writeFileSync(path, Buffer.from([0, 0, 1, 0, 1, 0, 16, 16, 0, 0, 1, 0, 32, 0]));
58
+ const icon = readIcon(path);
59
+ expect(icon.format).toBe("ico");
60
+ expect(icon.width).toBe(16);
61
+ expect(icon.height).toBe(16);
62
+ });
63
+ it("treats a zero-sized ICO entry as 256 pixels", () => {
64
+ const directory = temporaryDirectory();
65
+ const path = join(directory, "big.ico");
66
+ writeFileSync(path, Buffer.from([0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0]));
67
+ const icon = readIcon(path);
68
+ expect(icon.width).toBe(256);
69
+ expect(icon.height).toBe(256);
70
+ });
71
+ it("reads an ICNS file", () => {
72
+ const directory = temporaryDirectory();
73
+ const path = join(directory, "icon.icns");
74
+ writeFileSync(path, Buffer.from("icns\0\0\0\x08test"));
75
+ const icon = readIcon(path);
76
+ expect(icon.format).toBe("icns");
77
+ expect(icon.width).toBe(0);
78
+ });
79
+ it("rejects missing, empty and unsupported files", () => {
80
+ const directory = temporaryDirectory();
81
+ expect(() => readIcon(join(directory, "nope.png"))).toThrow(IconError);
82
+ const empty = join(directory, "empty.png");
83
+ writeFileSync(empty, "");
84
+ expect(() => readIcon(empty)).toThrow(/empty/);
85
+ const bogus = join(directory, "icon.svg");
86
+ writeFileSync(bogus, "<svg/>");
87
+ expect(() => readIcon(bogus)).toThrow(/Unsupported icon format/);
88
+ });
89
+ });
90
+ describe("iconSource", () => {
91
+ it("embeds the bytes and metadata", () => {
92
+ const source = iconSource(readIcon(writePng(temporaryDirectory())));
93
+ expect(source).toContain(`const unsigned char ${ICON_SYMBOLS.data}[]`);
94
+ expect(source).toContain(`const unsigned long long ${ICON_SYMBOLS.size}`);
95
+ expect(source).toContain('const char xt_app_icon_format[] = "png";');
96
+ expect(source).toContain("const unsigned int xt_app_icon_width = 4u;");
97
+ });
98
+ it("emits a placeholder and size 0 for an empty icon", () => {
99
+ const source = iconSource(EMPTY_ICON);
100
+ expect(source).toContain(" 0x00,");
101
+ expect(source).toContain(`const unsigned long long ${ICON_SYMBOLS.size} = 0ull;`);
102
+ });
103
+ });
104
+ describe("ICO conversion", () => {
105
+ it("wraps a PNG in an ICO container", () => {
106
+ const png = Buffer.from(LOGO_PNG_BASE64, "base64");
107
+ const ico = Buffer.from(pngToIco(png, 4, 4));
108
+ expect(ico.readUInt16LE(0)).toBe(0);
109
+ expect(ico.readUInt16LE(2)).toBe(1);
110
+ expect(ico.readUInt16LE(4)).toBe(1);
111
+ expect(ico[6]).toBe(4);
112
+ expect(ico[7]).toBe(4);
113
+ expect(ico.readUInt32LE(14)).toBe(png.length);
114
+ expect(ico.readUInt32LE(18)).toBe(22);
115
+ });
116
+ it("marks large PNGs as 256", () => {
117
+ const ico = Buffer.from(pngToIco(Buffer.from([1, 2, 3]), 512, 512));
118
+ expect(ico[6]).toBe(0);
119
+ expect(ico[7]).toBe(0);
120
+ });
121
+ it("passes ICO through and rejects ICNS", () => {
122
+ const directory = temporaryDirectory();
123
+ const icoPath = join(directory, "a.ico");
124
+ const icoBytes = Buffer.from([0, 0, 1, 0, 1, 0, 16, 16, 0, 0, 1, 0, 32, 0]);
125
+ writeFileSync(icoPath, icoBytes);
126
+ expect(toIcoBytes(readIcon(icoPath))).toEqual(icoBytes);
127
+ const icnsPath = join(directory, "a.icns");
128
+ writeFileSync(icnsPath, Buffer.from("icns\0\0\0\x08test"));
129
+ expect(() => toIcoBytes(readIcon(icnsPath))).toThrow(/PE resource/);
130
+ });
131
+ });
132
+ describe("ensureIconObject", () => {
133
+ it("writes the generated C and compiles it once", () => {
134
+ const directory = temporaryDirectory();
135
+ const { runner, calls } = recordingRunner();
136
+ const icon = readIcon(writePng(directory));
137
+ const objectPath = ensureIconObject(runner, "clang", join(directory, "cache"), icon);
138
+ expect(existsSync(objectPath)).toBe(false);
139
+ const compile = calls.find((call) => call.args.includes("-c"));
140
+ expect(compile.command).toBe("clang");
141
+ expect(readFileSync(compile.args[compile.args.indexOf("-c") + 1], "utf8")).toContain(ICON_SYMBOLS.data);
142
+ });
143
+ it("reuses an existing object", () => {
144
+ const directory = temporaryDirectory();
145
+ const cacheDir = join(directory, "cache");
146
+ const { runner, calls } = recordingRunner();
147
+ const icon = readIcon(writePng(directory));
148
+ const first = ensureIconObject(runner, "clang", cacheDir, icon);
149
+ writeFileSync(first, "");
150
+ const before = calls.length;
151
+ const second = ensureIconObject(runner, "clang", cacheDir, icon);
152
+ expect(second).toBe(first);
153
+ expect(calls.length).toBe(before);
154
+ });
155
+ });
156
+ describe("resolveResourceCompiler", () => {
157
+ it("honours the xbintsc_RC override", () => {
158
+ const previous = process.env.xbintsc_RC;
159
+ process.env.xbintsc_RC = "my-rc";
160
+ try {
161
+ const { runner } = recordingRunner();
162
+ expect(resolveResourceCompiler(runner, "clang")).toEqual({ tool: "my-rc", kind: "llvm-rc" });
163
+ }
164
+ finally {
165
+ if (previous === undefined)
166
+ delete process.env.xbintsc_RC;
167
+ else
168
+ process.env.xbintsc_RC = previous;
169
+ }
170
+ });
171
+ it("detects windres overrides and skips missing sibling paths", () => {
172
+ const previous = process.env.xbintsc_RC;
173
+ process.env.xbintsc_RC = "/opt/mingw/bin/windres";
174
+ try {
175
+ const { runner } = recordingRunner();
176
+ expect(resolveResourceCompiler(runner, "clang")).toEqual({
177
+ tool: "/opt/mingw/bin/windres",
178
+ kind: "windres",
179
+ });
180
+ }
181
+ finally {
182
+ if (previous === undefined)
183
+ delete process.env.xbintsc_RC;
184
+ else
185
+ process.env.xbintsc_RC = previous;
186
+ }
187
+ const { runner, calls } = recordingRunner();
188
+ const clang = join(temporaryDirectory(), "bin", "clang");
189
+ expect(resolveResourceCompiler(runner, clang)).toEqual({ tool: LLVM_RC, kind: "llvm-rc" });
190
+ expect(calls.some((call) => call.command === clang)).toBe(false);
191
+ });
192
+ it("returns undefined when nothing responds", () => {
193
+ const { runner } = recordingRunner(() => ({ status: 127, stderr: "not found" }));
194
+ expect(resolveResourceCompiler(runner, "clang")).toBeUndefined();
195
+ });
196
+ it("falls back when a broken override cannot run", () => {
197
+ const previous = process.env.xbintsc_RC;
198
+ process.env.xbintsc_RC = "broken-rc";
199
+ try {
200
+ const { runner } = recordingRunner((command) => (command === "broken-rc" ? { status: 1 } : {}));
201
+ expect(resolveResourceCompiler(runner, "clang")).toEqual({ tool: LLVM_RC, kind: "llvm-rc" });
202
+ }
203
+ finally {
204
+ if (previous === undefined)
205
+ delete process.env.xbintsc_RC;
206
+ else
207
+ process.env.xbintsc_RC = previous;
208
+ }
209
+ });
210
+ });
211
+ describe("ensureWindowsIconResource", () => {
212
+ const compiler = { tool: "llvm-rc", kind: "llvm-rc" };
213
+ it("writes an .rc and compiles it", () => {
214
+ const directory = temporaryDirectory();
215
+ const cacheDir = join(directory, "cache");
216
+ const icon = readIcon(writePng(directory));
217
+ mkdirSync(cacheDir, { recursive: true });
218
+ const { runner, calls } = recordingRunner((_command, args) => {
219
+ const output = args[args.indexOf("/fo") + 1];
220
+ writeFileSync(output, "");
221
+ return {};
222
+ });
223
+ const objectPath = ensureWindowsIconResource(runner, cacheDir, icon, compiler);
224
+ expect(existsSync(objectPath)).toBe(true);
225
+ const rcPath = calls[0].args.at(-1);
226
+ const rcContents = readFileSync(rcPath, "utf8");
227
+ expect(rcContents).toMatch(/^1 ICON "icon-.*\.ico"\n$/);
228
+ // The generated .ico sits next to the .rc so the relative reference resolves.
229
+ const icoName = rcContents.match(/"([^"]+)"/)[1];
230
+ expect(existsSync(join(cacheDir, icoName))).toBe(true);
231
+ });
232
+ it("uses windres argument style", () => {
233
+ const directory = temporaryDirectory();
234
+ const cacheDir = join(directory, "cache");
235
+ const icon = readIcon(writePng(directory));
236
+ const { runner, calls } = recordingRunner((_command, args) => {
237
+ writeFileSync(args[args.indexOf("-o") + 1], "");
238
+ return {};
239
+ });
240
+ ensureWindowsIconResource(runner, cacheDir, icon, { tool: "windres", kind: "windres" });
241
+ expect(calls[0].args).toContain("-O");
242
+ expect(calls[0].args).toContain("coff");
243
+ });
244
+ it("throws when the resource compiler fails", () => {
245
+ const directory = temporaryDirectory();
246
+ const icon = readIcon(writePng(directory));
247
+ const { runner } = recordingRunner(() => ({ status: 1, stderr: "bad rc" }));
248
+ expect(() => ensureWindowsIconResource(runner, join(directory, "cache"), icon, compiler)).toThrow(IconError);
249
+ });
250
+ });
251
+ describe("mac bundle", () => {
252
+ it("lays out a bundle and falls back to shipping the PNG", () => {
253
+ const directory = temporaryDirectory();
254
+ const executable = join(directory, "Demo");
255
+ writeFileSync(executable, "#!/bin/sh\n");
256
+ const icon = readIcon(writePng(directory));
257
+ const { runner } = recordingRunner();
258
+ const bundle = packageMacApp({
259
+ executablePath: executable,
260
+ name: "Demo",
261
+ bundleId: "com.example.demo",
262
+ icon,
263
+ runner,
264
+ });
265
+ expect(bundle).toBe(bundlePathFor(executable, "Demo"));
266
+ expect(existsSync(join(bundle, "Contents", "MacOS", "Demo"))).toBe(true);
267
+ expect(existsSync(join(bundle, "Contents", "Resources", "AppIcon.png"))).toBe(true);
268
+ const plist = readFileSync(join(bundle, "Contents", "Info.plist"), "utf8");
269
+ expect(plist).toContain("<string>com.example.demo</string>");
270
+ expect(plist).toContain("<string>AppIcon.png</string>");
271
+ });
272
+ it("copies an ICNS icon and converts a PNG when iconutil works", () => {
273
+ const directory = temporaryDirectory();
274
+ const executable = join(directory, "Demo");
275
+ writeFileSync(executable, "#!/bin/sh\n");
276
+ const icns = join(directory, "icon.icns");
277
+ writeFileSync(icns, Buffer.from("icns\0\0\0\x08test"));
278
+ const first = packageMacApp({
279
+ executablePath: executable,
280
+ name: "Demo",
281
+ bundleId: "com.example.demo",
282
+ icon: readIcon(icns),
283
+ runner: recordingRunner().runner,
284
+ });
285
+ expect(existsSync(join(first, "Contents", "Resources", "AppIcon.icns"))).toBe(true);
286
+ const png = writePng(directory, "icon2.png");
287
+ const { runner } = recordingRunner((command, args) => {
288
+ if (command === "iconutil" && args[0] === "-c") {
289
+ writeFileSync(args[args.indexOf("-o") + 1], "icns");
290
+ }
291
+ return {};
292
+ });
293
+ const second = packageMacApp({
294
+ executablePath: executable,
295
+ name: "Demo",
296
+ bundleId: "com.example.demo",
297
+ icon: readIcon(png),
298
+ runner,
299
+ });
300
+ const plist = readFileSync(join(second, "Contents", "Info.plist"), "utf8");
301
+ expect(plist).toContain("<string>AppIcon</string>");
302
+ expect(plist).not.toContain("AppIcon.png");
303
+ });
304
+ it("omits the icon key without an icon and survives missing tools", () => {
305
+ const directory = temporaryDirectory();
306
+ const executable = join(directory, "Demo");
307
+ writeFileSync(executable, "#!/bin/sh\n");
308
+ const clean = packageMacApp({
309
+ executablePath: executable,
310
+ name: "Demo",
311
+ bundleId: "com.example.demo",
312
+ runner: recordingRunner().runner,
313
+ });
314
+ expect(readFileSync(join(clean, "Contents", "Info.plist"), "utf8")).not.toContain("CFBundleIconFile");
315
+ const icon = readIcon(writePng(directory));
316
+ const throwing = {
317
+ run() {
318
+ throw new Error("missing");
319
+ },
320
+ };
321
+ const fallback = packageMacApp({
322
+ executablePath: executable,
323
+ name: "Demo",
324
+ bundleId: "com.example.demo",
325
+ icon,
326
+ runner: throwing,
327
+ });
328
+ expect(existsSync(join(fallback, "Contents", "Resources", "AppIcon.png"))).toBe(true);
329
+ });
330
+ it("falls back to a PNG when the converters report failure", () => {
331
+ const directory = temporaryDirectory();
332
+ const executable = join(directory, "Demo");
333
+ writeFileSync(executable, "#!/bin/sh\n");
334
+ const icon = readIcon(writePng(directory));
335
+ const sipsFails = packageMacApp({
336
+ executablePath: executable,
337
+ name: "Demo",
338
+ bundleId: "com.example.demo",
339
+ icon,
340
+ runner: recordingRunner((command) => command === "sips" ? { status: 1, stderr: "bad image" } : {}).runner,
341
+ });
342
+ expect(existsSync(join(sipsFails, "Contents", "Resources", "AppIcon.png"))).toBe(true);
343
+ const iconutilFails = packageMacApp({
344
+ executablePath: executable,
345
+ name: "Demo",
346
+ bundleId: "com.example.demo",
347
+ icon,
348
+ runner: recordingRunner((command) => command === "iconutil" ? { status: 1, stderr: "no icns" } : {}).runner,
349
+ });
350
+ expect(existsSync(join(iconutilFails, "Contents", "Resources", "AppIcon.png"))).toBe(true);
351
+ });
352
+ it("renders and escapes the plist", () => {
353
+ const plist = infoPlist({ name: "A & B", bundleId: "com.<x>", executable: "A&B" });
354
+ expect(plist).toContain("<string>A &amp; B</string>");
355
+ expect(plist).toContain("<string>com.&lt;x&gt;</string>");
356
+ expect(plist).toContain("<string>A&amp;B</string>");
357
+ });
358
+ });
359
+ describe("build integration", () => {
360
+ it("links the embedded icon object", () => {
361
+ const directory = temporaryDirectory();
362
+ const entry = join(directory, "main.ts");
363
+ writeFileSync(entry, "console.log(1);");
364
+ const icon = writePng(directory, "logo.png");
365
+ // Simulate a real toolchain: create the files each stage is expected to
366
+ // produce (the icon object and, on Windows, the PE resource).
367
+ const { runner, calls } = recordingRunner((_command, args) => {
368
+ const dashO = args.indexOf("-o");
369
+ const slashFo = args.indexOf("/fo");
370
+ const output = dashO >= 0 ? args[dashO + 1] : slashFo >= 0 ? args[slashFo + 1] : undefined;
371
+ if (output)
372
+ writeFileSync(output, "");
373
+ return {};
374
+ });
375
+ const result = build(entry, {
376
+ emit: "exe",
377
+ outDir: join(directory, "out"),
378
+ cacheDir: join(directory, ".cache"),
379
+ runner,
380
+ clang: "clang",
381
+ preferPrebuilt: false,
382
+ icon,
383
+ });
384
+ expect(result.diagnostics).toHaveLength(0);
385
+ const linkCall = calls.at(-1);
386
+ expect(linkCall.args.some((arg) => arg.includes("icon-") && arg.endsWith(".o"))).toBe(true);
387
+ });
388
+ it.skipIf(!guiAvailable)("links an empty icon object for GUI programs without an icon", () => {
389
+ const directory = temporaryDirectory();
390
+ const entry = join(directory, "main.ts");
391
+ writeFileSync(entry, "console.log(1);");
392
+ const { runner, calls } = recordingRunner();
393
+ const registry = createDefaultRegistry().register(guiExtension);
394
+ const result = build(entry, {
395
+ emit: "exe",
396
+ outDir: join(directory, "out"),
397
+ cacheDir: join(directory, ".cache"),
398
+ runner,
399
+ clang: "clang",
400
+ preferPrebuilt: false,
401
+ extensions: registry,
402
+ });
403
+ expect(result.diagnostics).toHaveLength(0);
404
+ const linkCall = calls.at(-1);
405
+ expect(linkCall.args.some((arg) => arg.includes("icon-") && arg.endsWith(".o"))).toBe(true);
406
+ });
407
+ it("reports a missing icon as an IO diagnostic", () => {
408
+ const directory = temporaryDirectory();
409
+ const entry = join(directory, "main.ts");
410
+ writeFileSync(entry, "console.log(1);");
411
+ const result = build(entry, {
412
+ emit: "ir",
413
+ outDir: join(directory, "out"),
414
+ cacheDir: join(directory, ".cache"),
415
+ icon: join(directory, "missing.png"),
416
+ });
417
+ expect(result.diagnostics).toHaveLength(1);
418
+ expect(result.diagnostics[0].code).toBe(DiagnosticCode.IOError);
419
+ });
420
+ });
421
+ //# sourceMappingURL=icon.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.test.js","sourceRoot":"","sources":["../../../tests/driver/icon.test.ts"],"names":[],"mappings":"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"}
@@ -224,4 +224,181 @@ describe("bundleModules", () => {
224
224
  expect(bag.diagnostics.some((d) => d.message.includes("Cannot find module"))).toBe(true);
225
225
  });
226
226
  });
227
+ describe("CommonJS in node_modules", () => {
228
+ function requireCalls(node) {
229
+ let count = 0;
230
+ walk(node, (current) => {
231
+ if (current.kind !== SyntaxKind.CallExpression)
232
+ return;
233
+ const callee = current.expression;
234
+ if (callee.kind === SyntaxKind.Identifier && callee.text === "require")
235
+ count++;
236
+ });
237
+ return count;
238
+ }
239
+ it("lowers a require of another CommonJS package", () => {
240
+ const directory = writeFiles({
241
+ "node_modules/leftpad/package.json": '{ "name": "leftpad", "main": "index.js" }',
242
+ "node_modules/leftpad/index.js": 'exports.pad = function (s, n) { return s; };',
243
+ "node_modules/usecjs/package.json": '{ "name": "usecjs", "main": "index.js" }',
244
+ "node_modules/usecjs/index.js": 'var lp = require("leftpad");\nmodule.exports.run = function () { return lp.pad("x", 1); };',
245
+ "main.ts": 'import { run } from "usecjs";\nconsole.log(run());',
246
+ });
247
+ const { result, bag } = bundle(join(directory, "main.ts"));
248
+ expect(bag.hasErrors).toBe(false);
249
+ expect(result?.moduleCount).toBe(3);
250
+ // The `require` call is rewritten away.
251
+ expect(requireCalls(result.sourceFile)).toBe(0);
252
+ // Each `node_modules` module gets its own `exports` state.
253
+ const names = identifierTexts(result.sourceFile);
254
+ expect(new Set(names.filter((name) => name.endsWith("$cjs_module"))).size).toBe(2);
255
+ });
256
+ it("exposes CommonJS named exports to ESM imports", () => {
257
+ const directory = writeFiles({
258
+ "node_modules/n/package.json": '{ "name": "n", "main": "index.js" }',
259
+ "node_modules/n/index.js": "exports.foo = 1;\nexports.bar = function () { return 2; };",
260
+ "main.ts": 'import { foo, bar } from "n";\nconsole.log(foo, bar());',
261
+ });
262
+ const { result, bag } = bundle(join(directory, "main.ts"));
263
+ expect(bag.hasErrors).toBe(false);
264
+ const names = identifierTexts(result.sourceFile);
265
+ expect(names.some((name) => name.endsWith("$cjs_foo"))).toBe(true);
266
+ expect(names.some((name) => name.endsWith("$cjs_bar"))).toBe(true);
267
+ });
268
+ it("exposes the whole `module.exports` object as the default export", () => {
269
+ const directory = writeFiles({
270
+ "node_modules/obj/package.json": '{ "name": "obj", "main": "index.js" }',
271
+ "node_modules/obj/index.js": 'module.exports = { a: 1, b: 2 };',
272
+ "main.ts": 'import o from "obj";\nconsole.log(o.a);',
273
+ });
274
+ const { result, bag } = bundle(join(directory, "main.ts"));
275
+ expect(bag.hasErrors).toBe(false);
276
+ expect(identifierTexts(result.sourceFile).some((name) => name.endsWith("$cjs_default"))).toBe(true);
277
+ });
278
+ it("exposes a required ESM module as a synthetic namespace object", () => {
279
+ const directory = writeFiles({
280
+ "node_modules/c/package.json": '{ "name": "c", "main": "index.js" }',
281
+ "node_modules/c/index.js": 'var e = require("./dep.js");\nmodule.exports = function () { return e.hello(); };',
282
+ "node_modules/c/dep.js": 'export function hello() { return "hi"; }',
283
+ "main.ts": 'import f from "c";\nconsole.log(f());',
284
+ });
285
+ const { result, bag } = bundle(join(directory, "main.ts"));
286
+ expect(bag.hasErrors).toBe(false);
287
+ let hasObjectLiteral = false;
288
+ walk(result.sourceFile, (node) => {
289
+ if (node.kind === SyntaxKind.ObjectLiteralExpression)
290
+ hasObjectLiteral = true;
291
+ });
292
+ expect(hasObjectLiteral).toBe(true);
293
+ expect(requireCalls(result.sourceFile)).toBe(0);
294
+ });
295
+ it("hoists an external require into an ESM import", () => {
296
+ const directory = writeFiles({
297
+ "node_modules/useos/package.json": '{ "name": "useos", "main": "index.js" }',
298
+ "node_modules/useos/index.js": 'var os = require("node:os");\nmodule.exports = function () { return os.platform(); };',
299
+ "main.ts": 'import f from "useos";\nconsole.log(f());',
300
+ });
301
+ const bag = new DiagnosticBag();
302
+ const result = bundleModules(join(directory, "main.ts"), bag, new Set(["node:os"]));
303
+ expect(bag.hasErrors).toBe(false);
304
+ const imports = result.sourceFile.statements.filter((s) => s.kind === SyntaxKind.ImportDeclaration);
305
+ expect(imports.length).toBe(1);
306
+ expect(requireCalls(result.sourceFile)).toBe(0);
307
+ });
308
+ it("hoists a destructured external require into named imports", () => {
309
+ const directory = writeFiles({
310
+ "node_modules/usepath/package.json": '{ "name": "usepath", "main": "index.js" }',
311
+ "node_modules/usepath/index.js": 'const { basename } = require("node:path");\nmodule.exports = function () { return basename("/a/b"); };',
312
+ "main.ts": 'import f from "usepath";\nconsole.log(f());',
313
+ });
314
+ const bag = new DiagnosticBag();
315
+ const result = bundleModules(join(directory, "main.ts"), bag, new Set(["node:path"]));
316
+ expect(bag.hasErrors).toBe(false);
317
+ expect(result.sourceFile.statements.filter((s) => s.kind === SyntaxKind.ImportDeclaration).length).toBe(1);
318
+ });
319
+ it("leaves `require` in user code untouched", () => {
320
+ const directory = writeFiles({ "main.ts": 'var x = require("./missing");\nconsole.log(x);' });
321
+ const { result, bag } = bundle(join(directory, "main.ts"));
322
+ expect(result?.moduleCount).toBe(1);
323
+ expect(requireCalls(result.sourceFile)).toBe(1);
324
+ expect(bag.diagnostics.some((d) => d.code === DiagnosticCode.UnsupportedFeature)).toBe(false);
325
+ });
326
+ it("reports a require with a non-literal argument", () => {
327
+ const directory = writeFiles({
328
+ "node_modules/dyn/package.json": '{ "name": "dyn", "main": "index.js" }',
329
+ "node_modules/dyn/index.js": 'var name = "leftpad";\nmodule.exports = require(name);',
330
+ "main.ts": 'import x from "dyn";\nconsole.log(x);',
331
+ });
332
+ const { bag } = bundle(join(directory, "main.ts"));
333
+ expect(bag.diagnostics.some((d) => d.code === DiagnosticCode.UnsupportedFeature)).toBe(true);
334
+ });
335
+ });
336
+ describe("asset loaders", () => {
337
+ it("rewrites a matching asset extension into a TS module", () => {
338
+ const directory = writeFiles({
339
+ "data.foo": "hello",
340
+ "main.ts": 'import value from "./data.foo";\nconsole.log(value);',
341
+ });
342
+ const seen = [];
343
+ const loader = (path, source) => {
344
+ seen.push([path, source]);
345
+ return { moduleSource: `export default ${JSON.stringify(source)};` };
346
+ };
347
+ const bag = new DiagnosticBag();
348
+ const result = bundleModules(join(directory, "main.ts"), bag, new Set(), { ".foo": loader });
349
+ expect(bag.hasErrors).toBe(false);
350
+ expect(seen).toEqual([[join(directory, "data.foo"), "hello"]]);
351
+ expect(result?.text).toContain('export default "hello"');
352
+ });
353
+ it("follows imports from a loader-generated module", () => {
354
+ const directory = writeFiles({
355
+ "widget.html": "<div></div>",
356
+ "helper.ts": "export const n = 41;",
357
+ "main.ts": 'import html from "./widget.html";\nconsole.log(html);',
358
+ });
359
+ const loader = () => ({
360
+ moduleSource: 'import { n } from "./helper";\nexport default "loaded-" + n;',
361
+ });
362
+ const bag = new DiagnosticBag();
363
+ const result = bundleModules(join(directory, "main.ts"), bag, new Set(), { ".html": loader });
364
+ expect(bag.hasErrors).toBe(false);
365
+ expect(result?.moduleCount).toBe(3);
366
+ });
367
+ it("leaves files with other extensions untouched", () => {
368
+ const directory = writeFiles({ "main.ts": "console.log(1);" });
369
+ const loader = () => ({ moduleSource: 'throw new Error("should not run");' });
370
+ const bag = new DiagnosticBag();
371
+ bundleModules(join(directory, "main.ts"), bag, new Set(), { ".html": loader });
372
+ expect(bag.hasErrors).toBe(false);
373
+ });
374
+ it("reports a loader that throws as a build diagnostic", () => {
375
+ const directory = writeFiles({
376
+ "data.foo": "boom",
377
+ "main.ts": 'import value from "./data.foo";\nconsole.log(value);',
378
+ });
379
+ const loader = () => {
380
+ throw new Error("loader exploded");
381
+ };
382
+ const bag = new DiagnosticBag();
383
+ const result = bundleModules(join(directory, "main.ts"), bag, new Set(), { ".foo": loader });
384
+ expect(result).toBeUndefined();
385
+ expect(bag.hasErrors).toBe(true);
386
+ expect(bag.diagnostics.some((diagnostic) => diagnostic.message.includes("loader exploded"))).toBe(true);
387
+ });
388
+ it("reports an unresolvable relative import", () => {
389
+ const directory = writeFiles({ "main.ts": 'import value from "./missing";\nconsole.log(value);' });
390
+ const bag = new DiagnosticBag();
391
+ const result = bundleModules(join(directory, "main.ts"), bag);
392
+ expect(result).toBeUndefined();
393
+ expect(bag.hasErrors).toBe(true);
394
+ expect(bag.diagnostics.some((diagnostic) => diagnostic.message.includes("Cannot resolve module"))).toBe(true);
395
+ });
396
+ it("reports a missing entry file", () => {
397
+ const directory = writeFiles({ "main.ts": "console.log(1);" });
398
+ const bag = new DiagnosticBag();
399
+ const result = bundleModules(join(directory, "nope.ts"), bag);
400
+ expect(result).toBeUndefined();
401
+ expect(bag.diagnostics.some((diagnostic) => diagnostic.message.includes("Cannot find module"))).toBe(true);
402
+ });
403
+ });
227
404
  //# sourceMappingURL=modules.test.js.map