mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
fix(javascript): trace wrapped Electron IPC paths in large bundles (#1874)
Co-authored-by: David <17119984+fengdwx@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { expect, it } from "vitest";
|
||||
import { analyzeJavaScriptStaticSource } from "../../domain/javascript/javascriptStaticAnalysis.js";
|
||||
import { analyzeJavaScriptSemantics } from "../../domain/javascript/javascriptSemanticAnalysis.js";
|
||||
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
|
||||
import { projectJavaScriptSemanticFileSteps } from "./JavaScriptSemanticGraphBuilder.js";
|
||||
|
||||
const source = `${Array.from({ length: 40 }, (_, i) => `function library${String(i)}(){return ${String(i)}}`).join("\n")}
|
||||
const e=require("electron");
|
||||
function register(channel,callback){e.ipcMain.addListener(channel,event=>allowed(event)&&callback(event))}
|
||||
register("test:copy",event=>event.sender.copy());`;
|
||||
const file: JavaScriptArtifactFile = {
|
||||
path: "main.js",
|
||||
sha256: "a".repeat(64),
|
||||
container_sha256: "b".repeat(64),
|
||||
bytes: source.length,
|
||||
inventory_artifact_id: `art_${"a".repeat(64)}`,
|
||||
kind: "javascript",
|
||||
unpacked: false,
|
||||
text: { included: true, value: source },
|
||||
};
|
||||
const facts = analyzeJavaScriptStaticSource(source);
|
||||
const ir = analyzeJavaScriptSemantics(source);
|
||||
const project = (budget: number) => {
|
||||
const steps = projectJavaScriptSemanticFileSteps(
|
||||
file,
|
||||
ir,
|
||||
budget,
|
||||
facts.electron.call_paths,
|
||||
);
|
||||
let result = steps.next();
|
||||
while (!result.done) result = steps.next();
|
||||
return result.value;
|
||||
};
|
||||
|
||||
it("retains Electron calls before library definitions consume the node budget", () => {
|
||||
const result = project(20);
|
||||
expect(result.nodes).toHaveLength(20);
|
||||
expect(result.truncated).toBe(true);
|
||||
const terminal = result.nodes.find(
|
||||
(node) => node.label === "ipc-event.sender.copy",
|
||||
);
|
||||
expect(terminal).toBeDefined();
|
||||
expect(
|
||||
result.relations.some(
|
||||
(r) =>
|
||||
r.target_node_id === terminal?.node_id && r.resolution === "candidate",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
result.nodes.some(
|
||||
(node) =>
|
||||
node.properties.entry === "test:copy" &&
|
||||
Array.isArray(node.properties.conditions) &&
|
||||
node.properties.conditions.length === 1,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("reports truncation and keeps referential integrity even within a boundary path", () => {
|
||||
const result = project(3);
|
||||
expect(result.nodes).toHaveLength(3);
|
||||
expect(result.truncated).toBe(true);
|
||||
expect(
|
||||
result.nodes.some((node) => node.label === "ipc-event.sender.copy"),
|
||||
).toBe(false);
|
||||
const retained = new Set(result.nodes.map((node) => node.node_id));
|
||||
expect(
|
||||
result.relations.every(
|
||||
(r) => retained.has(r.source_node_id) && retained.has(r.target_node_id),
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
Reference in New Issue
Block a user