xbintsc 0.3.18 → 0.3.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/src/cli/main.js +124 -30
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +8 -1
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/state.js +20 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +6 -0
- package/dist/src/codegen/generator/tables.js +38 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/commonjs.d.ts +52 -0
- package/dist/src/driver/bundler/commonjs.js +493 -0
- package/dist/src/driver/bundler/commonjs.js.map +1 -0
- package/dist/src/driver/bundler/graph.d.ts +2 -1
- package/dist/src/driver/bundler/graph.js +32 -3
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.d.ts +2 -1
- package/dist/src/driver/bundler/merge.js +16 -2
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/bundler/types.d.ts +8 -0
- package/dist/src/driver/compiler.d.ts +8 -1
- package/dist/src/driver/compiler.js +75 -7
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +53 -0
- package/dist/src/driver/config.js +141 -0
- package/dist/src/driver/config.js.map +1 -0
- package/dist/src/driver/icon.d.ts +62 -0
- package/dist/src/driver/icon.js +151 -0
- package/dist/src/driver/icon.js.map +1 -0
- package/dist/src/driver/index.d.ts +4 -0
- package/dist/src/driver/index.js +4 -0
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/mac-bundle.d.ts +41 -0
- package/dist/src/driver/mac-bundle.js +123 -0
- package/dist/src/driver/mac-bundle.js.map +1 -0
- package/dist/src/driver/win-icon.d.ts +27 -0
- package/dist/src/driver/win-icon.js +80 -0
- package/dist/src/driver/win-icon.js.map +1 -0
- package/dist/src/extensions/gui/html.d.ts +25 -0
- package/dist/src/extensions/gui/html.js +203 -0
- package/dist/src/extensions/gui/html.js.map +1 -0
- package/dist/src/extensions/gui/index.js +11 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/registry.d.ts +29 -0
- package/dist/src/extensions/registry.js +14 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.js +4 -12
- package/dist/src/lexer/scanner/identifiers.js.map +1 -1
- package/dist/src/parser/statements.js +17 -4
- package/dist/src/parser/statements.js.map +1 -1
- package/dist/tests/cli/main.test.js +46 -1
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/driver/bundler-resolve.test.d.ts +1 -0
- package/dist/tests/driver/bundler-resolve.test.js +230 -0
- package/dist/tests/driver/bundler-resolve.test.js.map +1 -0
- package/dist/tests/driver/config.test.d.ts +1 -0
- package/dist/tests/driver/config.test.js +124 -0
- package/dist/tests/driver/config.test.js.map +1 -0
- package/dist/tests/driver/icon.test.d.ts +1 -0
- package/dist/tests/driver/icon.test.js +421 -0
- package/dist/tests/driver/icon.test.js.map +1 -0
- package/dist/tests/driver/modules.test.js +177 -0
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/e2e/fetch.test.d.ts +12 -0
- package/dist/tests/e2e/fetch.test.js +272 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -0
- package/dist/tests/e2e/gui-dom.test.d.ts +5 -0
- package/dist/tests/e2e/gui-dom.test.js +102 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -0
- package/dist/tests/e2e/gui-events.test.d.ts +5 -0
- package/dist/tests/e2e/gui-events.test.js +60 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +31 -0
- package/dist/tests/e2e/gui-helpers.js +74 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -0
- package/dist/tests/e2e/gui-layout.test.d.ts +4 -0
- package/dist/tests/e2e/gui-layout.test.js +88 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -0
- package/dist/tests/e2e/gui-lifecycle.test.d.ts +5 -0
- package/dist/tests/e2e/gui-lifecycle.test.js +58 -0
- package/dist/tests/e2e/gui-lifecycle.test.js.map +1 -0
- package/dist/tests/e2e/gui-paint.test.d.ts +5 -0
- package/dist/tests/e2e/gui-paint.test.js +111 -0
- package/dist/tests/e2e/gui-paint.test.js.map +1 -0
- package/dist/tests/e2e/gui-script.test.d.ts +5 -0
- package/dist/tests/e2e/gui-script.test.js +78 -0
- package/dist/tests/e2e/gui-script.test.js.map +1 -0
- package/dist/tests/e2e/gui-style.test.d.ts +5 -0
- package/dist/tests/e2e/gui-style.test.js +175 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -0
- package/dist/tests/e2e/icon.test.d.ts +7 -0
- package/dist/tests/e2e/icon.test.js +80 -0
- package/dist/tests/e2e/icon.test.js.map +1 -0
- package/dist/tests/e2e/npm-modules.test.d.ts +4 -1
- package/dist/tests/e2e/npm-modules.test.js +47 -1
- package/dist/tests/e2e/npm-modules.test.js.map +1 -1
- package/dist/tests/e2e/runtime-coverage-typed-array.test.d.ts +9 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js +140 -0
- package/dist/tests/e2e/runtime-coverage-typed-array.test.js.map +1 -0
- package/dist/tests/extensions/gui-index.test.d.ts +1 -0
- package/dist/tests/extensions/gui-index.test.js +49 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.d.ts +1 -0
- package/dist/tests/extensions/gui.test.js +177 -0
- package/dist/tests/extensions/gui.test.js.map +1 -0
- package/dist/tests/extensions/registry.test.js +36 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/dist/tests/parser/statements.test.js +11 -0
- package/dist/tests/parser/statements.test.js.map +1 -1
- package/dist/tests/public-api.test.d.ts +1 -0
- package/dist/tests/public-api.test.js +31 -0
- package/dist/tests/public-api.test.js.map +1 -0
- package/package.json +1 -1
- package/runtime/ext_gui/css.cpp +4 -517
- package/runtime/ext_gui/css_internal.h +27 -0
- package/runtime/ext_gui/css_match.cpp +195 -0
- package/runtime/ext_gui/css_selector.cpp +207 -0
- package/runtime/ext_gui/css_sheet.cpp +129 -0
- package/runtime/ext_gui/document.cpp +90 -0
- package/runtime/ext_gui/document.h +23 -0
- package/runtime/ext_gui/dom.cpp +43 -403
- package/runtime/ext_gui/dom.h +7 -0
- package/runtime/ext_gui/dom_api.cpp +164 -0
- package/runtime/ext_gui/dom_api.h +12 -0
- package/runtime/ext_gui/dom_api_document.cpp +96 -0
- package/runtime/ext_gui/dom_api_events.cpp +123 -0
- package/runtime/ext_gui/dom_api_internal.h +135 -0
- package/runtime/ext_gui/dom_api_node.cpp +329 -0
- package/runtime/ext_gui/dom_api_node_read.cpp +294 -0
- package/runtime/ext_gui/dom_api_proto.cpp +130 -0
- package/runtime/ext_gui/dom_api_style.cpp +192 -0
- package/runtime/ext_gui/dom_internal.h +39 -0
- package/runtime/ext_gui/dom_parse.cpp +348 -0
- package/runtime/ext_gui/dom_serialize.cpp +54 -0
- package/runtime/ext_gui/gui.cpp +61 -245
- package/runtime/ext_gui/gui_engine.h +54 -0
- package/runtime/ext_gui/gui_events.cpp +294 -0
- package/runtime/ext_gui/gui_internal.h +29 -0
- package/runtime/ext_gui/layout.cpp +6 -597
- package/runtime/ext_gui/layout_flex.cpp +200 -0
- package/runtime/ext_gui/layout_flow.cpp +191 -0
- package/runtime/ext_gui/layout_flow_internal.h +149 -0
- package/runtime/ext_gui/layout_inline.cpp +181 -0
- package/runtime/ext_gui/layout_internal.h +20 -0
- package/runtime/ext_gui/renderer.cpp +15 -679
- package/runtime/ext_gui/renderer_image.cpp +233 -0
- package/runtime/ext_gui/renderer_internal.h +112 -0
- package/runtime/ext_gui/renderer_shaders.h +108 -0
- package/runtime/ext_gui/renderer_text.cpp +342 -0
- package/runtime/ext_gui/script.cpp +63 -0
- package/runtime/ext_gui/style.cpp +12 -660
- package/runtime/ext_gui/style_internal.h +33 -0
- package/runtime/ext_gui/style_print.cpp +113 -0
- package/runtime/ext_gui/style_ua.cpp +98 -0
- package/runtime/ext_gui/style_values.cpp +468 -0
- package/runtime/ext_gui/window.cpp +60 -0
- package/runtime/rt.h +6 -0
- package/runtime/rt_internal.h +4 -0
- package/runtime/xt_builtins.c +1 -0
- package/runtime/xt_containers/access.inc +32 -1
- package/runtime/xt_fetch/buffer.inc +64 -0
- package/runtime/xt_fetch/headers.inc +312 -0
- package/runtime/xt_fetch/request.inc +386 -0
- package/runtime/xt_fetch/response.inc +107 -0
- package/runtime/xt_fetch/socket.inc +72 -0
- package/runtime/xt_fetch/url.inc +108 -0
- package/runtime/xt_fetch.c +39 -0
- package/runtime/xt_stdlib2/set.inc +1 -1
- package/runtime/xt_typed_array.c +614 -0
- package/src/cli/main.ts +137 -29
- package/src/codegen/generator/calls/access.ts +9 -1
- package/src/codegen/generator/state.ts +20 -0
- package/src/codegen/generator/tables.ts +40 -0
- package/src/driver/bundler/commonjs.ts +553 -0
- package/src/driver/bundler/graph.ts +35 -2
- package/src/driver/bundler/merge.ts +18 -1
- package/src/driver/bundler/types.ts +8 -0
- package/src/driver/compiler.ts +85 -7
- package/src/driver/config.ts +173 -0
- package/src/driver/icon.ts +184 -0
- package/src/driver/index.ts +30 -0
- package/src/driver/mac-bundle.ts +156 -0
- package/src/driver/win-icon.ts +96 -0
- package/src/extensions/gui/html.ts +236 -0
- package/src/extensions/gui/index.ts +11 -0
- package/src/extensions/registry.ts +39 -0
- package/src/index.ts +1 -1
- package/src/lexer/scanner/identifiers.ts +4 -11
- package/src/parser/statements.ts +17 -4
- package/dist/tests/e2e/gui.test.d.ts +0 -12
- package/dist/tests/e2e/gui.test.js +0 -493
- package/dist/tests/e2e/gui.test.js.map +0 -1
|
@@ -0,0 +1,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 & B</string>");
|
|
355
|
+
expect(plist).toContain("<string>com.<x></string>");
|
|
356
|
+
expect(plist).toContain("<string>A&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
|