Files
rea/src/domain/javascript/electronStaticAnalysisOptions.test.ts
T
Ysopwnable d72d856f58 feat(electron): resolve stable local constant window options
Resolve stable local constant BrowserWindow options with retained provenance and shared early-exit mutation queries. Preserve source ordering and unknown results for relevant mutations or escapes.

Includes real Joplin correctness/cost receipts and regression coverage.

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-16 14:52:33 +08:00

399 lines
14 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
describe("Electron constant option evidence", () => {
it("keeps mixed constant, inline and unresolved windows in construction order", () => {
const analysis = analyzeJavaScriptStaticSource(
[
'const { BrowserWindow } = require("electron");',
"const options = { webPreferences: { sandbox: true } };",
"new BrowserWindow(options);",
"new BrowserWindow({ webPreferences: { sandbox: false } });",
"new BrowserWindow(dynamic);",
"new BrowserWindow(options);",
].join("\n"),
);
expect(
analysis.electron.browser_windows.map(
({ location }) => location.start.line,
),
).toEqual([3, 4, 5, 6]);
expect(
analysis.electron.browser_windows.map(
({ options_status }) => options_status,
),
).toEqual([
"object-literal",
"object-literal",
"dynamic",
// The first constructor already received this object; later contents
// remain unknown even though the declarations retain their source order.
"dynamic",
]);
});
it("resolves local constant options despite an unrelated option write", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron");
function open() {
const preferences = { nodeIntegration: true, contextIsolation: false };
const options = { webPreferences: preferences };
if (linux) options.icon = "icon.png";
new BrowserWindow(options);
}
`);
expect(analysis.electron.browser_windows).toMatchObject([
{
options_status: "object-literal",
web_preferences_status: "object-literal",
web_preferences: [
{
name: "contextIsolation",
value: { status: "literal", value: false },
},
{
name: "nodeIntegration",
value: { status: "literal", value: true },
},
],
resolution_sources: [expect.any(Object), expect.any(Object)],
},
]);
});
it.each([
"options.webPreferences.sandbox = false;",
"const alias = options.webPreferences; alias.sandbox = false;",
"mutate(options);",
"const { webPreferences: alias } = options; mutate(alias);",
"Object.assign(options, unknown);",
"const box = {}; box.options = options; box.options.webPreferences.sandbox = false;",
"options = replacement;",
])("keeps changed or escaped constant options unknown: %s", (mutation) => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron");
const options = { webPreferences: { sandbox: true } };
${mutation}
new BrowserWindow(options);
`);
expect(analysis.electron.browser_windows).toMatchObject([
{
options_status: "dynamic",
web_preferences_status: "dynamic",
web_preferences: [],
preload_path: null,
},
]);
});
it.each([
"new BrowserWindow(options); const options = { webPreferences: { sandbox: true } };",
"const options = alias; const alias = { webPreferences: { sandbox: true } }; new BrowserWindow(options);",
"const options = alias; const alias = options; new BrowserWindow(options);",
"const options = { webPreferences: { sandbox: true } }; { const options = unknown; new BrowserWindow(options); }",
"let options = { webPreferences: { sandbox: true } }; new BrowserWindow(options);",
])("does not invent a constant initializer: %s", (source) => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron"); ${source}
`);
expect(analysis.electron.browser_windows).toMatchObject([
{
options_status: "dynamic",
web_preferences_status: "dynamic",
web_preferences: [],
},
]);
});
it("preserves constants selected before later mutation and resolves preload context", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron");
const original = { webPreferences: { preload: require("path").join(__dirname, "preload.js"), sandbox: true } };
const options = original;
new BrowserWindow(options);
original.webPreferences.sandbox = false;
`);
expect(analysis.electron.browser_windows).toMatchObject([
{
options_status: "object-literal",
preload_path: "preload.js",
preload_resolution_context: "filesystem-expression",
},
]);
});
});
describe("Electron option evidence", () => {
it.each([
'({ webPreferences: { preload: "./preload.js", sandbox: true } } as const)',
'{ webPreferences: ({ preload: "./preload.js", sandbox: true } as const) }',
'{ webPreferences: { preload: "./preload.js" as const, sandbox: true } }',
])("unwraps type-only wrappers around inline options: %s", (options) => {
const analysis = analyzeJavaScriptStaticSource(`
import { BrowserWindow } from "electron";
new BrowserWindow(${options});
`);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.electron.browser_windows).toMatchObject([
{
options_status: "object-literal",
web_preferences_status: "object-literal",
preload_path: "./preload.js",
preload_resolution_context: "module-specifier",
web_preferences: [
{
name: "preload",
value: { status: "literal", value: "./preload.js" },
},
{ name: "sandbox", value: { status: "literal", value: true } },
],
},
]);
});
it("keeps the final explicit preload and service name with unrelated keys", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow, utilityProcess } = require("electron");
new BrowserWindow({ webPreferences: { preload: "./kept.js", sandbox: true }, title: "App" });
utilityProcess.fork("./worker.js", [], { serviceName: "kept", cwd: "/app" });
`);
expect(analysis.parse_status).toBe("complete");
expect(analysis.electron.browser_windows[0]).toMatchObject({
preload_path: "./kept.js",
preload_resolution_context: "module-specifier",
web_preferences: [
{ name: "preload", value: { status: "literal", value: "./kept.js" } },
{ name: "sandbox", value: { status: "literal", value: true } },
],
});
expect(analysis.electron.utility_processes[0]).toMatchObject({
module_path: "./worker.js",
service_name: "kept",
});
});
it.each([
["for initializer", 'for (var electron = require("electron"); false;) {}'],
["do body", 'do { var electron = require("electron"); } while (false);'],
])(
"recovers Electron bindings initialized unconditionally in a %s",
(_name, declaration) => {
const analysis = analyzeJavaScriptStaticSource(
`${declaration} new electron.BrowserWindow({webPreferences:{preload:"./preload.js"}});`,
);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.electron.browser_windows).toMatchObject([
{ preload_path: "./preload.js" },
]);
},
);
it.each([
'for (; false;) { var electron = require("electron"); }',
'while (false) { var electron = require("electron"); }',
'if (flag) { for (var electron = require("electron"); false;) {} }',
])(
"keeps conditionally skipped loop declarations unresolved: %s",
(declaration) => {
const analysis = analyzeJavaScriptStaticSource(
`${declaration} new electron.BrowserWindow({});`,
);
expect(analysis.electron.browser_windows).toEqual([]);
},
);
it("does not read an audio or video preload attribute as a preload script", () => {
const analysis = analyzeJavaScriptStaticSource(`
jsx("audio", { controls: true, preload: "metadata", src });
(0, React.createElement)(\`video\`, { preload: "auto" });
jsx("webview", { preload: "./guest.js" });
const options = { preload: "./preload.js" };
`);
expect(analysis.role_paths.map(({ path }) => path)).toEqual([
"./guest.js",
"./preload.js",
]);
});
it("keeps values unknown when a later computed key can override them", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow, utilityProcess } = require("electron");
new BrowserWindow({ webPreferences: { preload: "./maybe.js" }, [key]: null });
utilityProcess.fork("./worker.js", [], { serviceName: "maybe", [key]: null });
`);
expect(analysis.parse_status).toBe("partial");
expect(analysis.parse_error_count).toBe(0);
expect(analysis.limitations.join(" ")).toContain("remain unknown");
expect(analysis.electron.browser_windows[0]).toMatchObject({
preload_path: null,
preload_resolution_context: null,
web_preferences_status: "dynamic",
web_preferences: [],
});
expect(analysis.electron.utility_processes[0]).toMatchObject({
module_path: "./worker.js",
service_name: null,
});
});
it("keeps recovered templates with invalid escapes dynamic", () => {
const source = [
'const { BrowserWindow } = require("electron");',
"new BrowserWindow({ webPreferences: { sandbox: `",
String.raw`\unicode`,
"` } });",
].join("");
const analysis = analyzeJavaScriptStaticSource(source);
expect(analysis.parse_status).toBe("partial");
expect(analysis.parse_error_count).toBe(1);
expect(
analysis.electron.browser_windows[0]?.web_preferences,
).toContainEqual(
expect.objectContaining({
name: "sandbox",
value: expect.objectContaining({ status: "dynamic", value: null }),
}),
);
});
});
describe("Electron empty option keys", () => {
describe.each([
["plain empty string", '[""]'],
["empty template", "[``]"],
["wrapped empty string", '["" as const]'],
])("unrelated %s option keys", (_label, key) => {
it("retains an earlier explicit webPreferences object", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron");
new BrowserWindow({
webPreferences: { preload: "./kept.js", sandbox: true },
${key}: true
});
`);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.parse_status).toBe("complete");
expect(analysis.electron.browser_windows).toMatchObject([
{
web_preferences_status: "object-literal",
preload_path: "./kept.js",
preload_resolution_context: "module-specifier",
web_preferences: [
{
name: "preload",
value: { status: "literal", value: "./kept.js" },
},
{ name: "sandbox", value: { status: "literal", value: true } },
],
},
]);
});
it("retains an earlier explicit preload within webPreferences", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow } = require("electron");
new BrowserWindow({ webPreferences: {
preload: "./kept.js", sandbox: true, ${key}: false
} });
`);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.parse_status).toBe("complete");
expect(analysis.electron.browser_windows).toMatchObject([
{
web_preferences_status: "object-literal",
preload_path: "./kept.js",
preload_resolution_context: "module-specifier",
web_preferences: [
{ name: "", value: { status: "literal", value: false } },
{
name: "preload",
value: { status: "literal", value: "./kept.js" },
},
{ name: "sandbox", value: { status: "literal", value: true } },
],
},
]);
});
it("retains an earlier explicit utility-process service name", () => {
const analysis = analyzeJavaScriptStaticSource(`
const { utilityProcess } = require("electron");
utilityProcess.fork("./worker.js", [], {
serviceName: "kept", ${key}: true
});
`);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.parse_status).toBe("complete");
expect(analysis.electron.utility_processes).toMatchObject([
{ module_path: "./worker.js", service_name: "kept" },
]);
});
});
it.each([
["dynamic key", "[key]: null"],
["spread", "...options"],
])(
"keeps a preceding %s override unknown after an unrelated empty template key",
(_label, override) => {
const analysis = analyzeJavaScriptStaticSource(`
const { BrowserWindow, utilityProcess } = require("electron");
new BrowserWindow({
webPreferences: { preload: "./maybe.js" },
${override}, [\`\`]: true
});
new BrowserWindow({ webPreferences: {
preload: "./maybe.js", ${override}, [\`\`]: true
} });
utilityProcess.fork("./worker.js", [], {
serviceName: "maybe", ${override}, [\`\`]: true
});
`);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.parse_status).toBe("partial");
expect(analysis.electron.browser_windows).toMatchObject([
{
web_preferences_status: "dynamic",
web_preferences: [],
preload_path: null,
preload_resolution_context: null,
},
{
web_preferences_status: "object-literal",
preload_path: null,
preload_resolution_context: null,
},
]);
expect(analysis.electron.browser_windows[1]?.web_preferences).toEqual(
expect.arrayContaining([
{
name: "",
value: { status: "literal", value: true, expression: null },
},
{
name: "preload",
value: { status: "literal", value: "./maybe.js", expression: null },
},
expect.objectContaining({
name: expect.stringMatching(/^\[(?:dynamic|spread)@/u),
value: expect.objectContaining({ status: "dynamic", value: null }),
}),
]),
);
expect(analysis.electron.utility_processes).toMatchObject([
{ module_path: "./worker.js", service_name: null },
]);
},
);
});