Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc --noEmit && vite build",
"build": "tsc --noEmit && vite build && node scripts/check-renderer-entry.mjs",
"preview": "vite preview",
"check": "tsc --noEmit",
"lint": "eslint . --max-warnings=0",
Expand Down
43 changes: 43 additions & 0 deletions scripts/check-renderer-entry.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { readFileSync, readdirSync } from "node:fs";
import { basename, join } from "node:path";
import { fileURLToPath } from "node:url";

const dist = new URL("../dist/", import.meta.url);
const html = readFileSync(new URL("index.html", dist), "utf8");
const entryMatch = html.match(/<script[^>]+type="module"[^>]+src="([^"]+)"/);
if (!entryMatch) throw new Error("renderer entry script was not found in dist/index.html");

const entryName = basename(entryMatch[1]);
const assetsDir = new URL("assets/", dist);
const assetsPath = fileURLToPath(assetsDir);
const entry = readFileSync(new URL(entryName, assetsDir), "utf8");

const forbiddenEntryMarkers = [
"react.transitional.element",
"__REACT_DEVTOOLS_GLOBAL_HOOK__",
"createRoot=function",
"The app shell could not start",
];
for (const marker of forbiddenEntryMarkers) {
if (entry.includes(marker)) {
throw new Error(`dependency-light renderer entry unexpectedly contains ${marker}`);
}
}
if (!entry.includes("管理器界面无法启动")) {
throw new Error("dependency-light renderer entry does not contain the static crash fallback");
}
if (!entry.includes("bootstrap-") || !entry.includes("import(")) {
throw new Error("renderer entry does not dynamically load a separate bootstrap chunk");
}
if (/rel="modulepreload"[^>]+bootstrap-/i.test(html)) {
throw new Error("bootstrap chunk is eagerly preloaded with the dependency-light entry");
}

const otherJavaScript = readdirSync(assetsPath)
.filter((name) => name.endsWith(".js") && name !== entryName)
.map((name) => readFileSync(join(assetsPath, name), "utf8"));
if (!otherJavaScript.some((source) => source.includes("react.transitional.element"))) {
throw new Error("React was not isolated into a non-entry renderer chunk");
}

console.log(`renderer entry isolation verified: ${entryName}`);
2 changes: 2 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ windows-sys = { version = "0.61.2", features = ["Win32_Foundation", "Win32_Stora

[target.'cfg(unix)'.dependencies]
libc = "0.2"

[target.'cfg(windows)'.dependencies]
# Keep these pinned to Tauri/Wry's WebView2 ABI: the platform handle returned
# by `WebviewWindow::with_webview` exposes these exact COM interfaces.
webview2-com = "=0.38.2"
windows-core = "0.61.2"
8 changes: 5 additions & 3 deletions src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
"description": "Default permissions for the main desktop window.",
"windows": ["main"],
"permissions": [
"core:default",
"core:event:allow-listen",
"core:event:allow-unlisten",
"core:webview:allow-internal-toggle-devtools",
"core:window:allow-internal-toggle-maximize",
"core:window:allow-start-dragging",
"core:window:allow-close",
"core:window:allow-minimize",
"dialog:allow-open",
"updater:default",
"process:default"
"process:allow-restart"
]
}
Loading
Loading