diff --git a/src/application/javascript/ElectronBoundaryGraphCallPaths.ts b/src/application/javascript/ElectronBoundaryGraphCallPaths.ts index b815e82bf..d1f1886db 100644 --- a/src/application/javascript/ElectronBoundaryGraphCallPaths.ts +++ b/src/application/javascript/ElectronBoundaryGraphCallPaths.ts @@ -165,7 +165,8 @@ export const addElectronCallPaths = ( pairing_basis: "unique-exact-literal-channel", resolution: "candidate", handler_path: to.file.path, - conditions: to.path.conditions, + bridge_conditions: from.path.conditions, + handler_conditions: to.path.conditions, }, limitations: [ "The unique static channel match does not establish runtime registration, sender acceptance, or dispatch.", diff --git a/tests/boundary/cli/electronWrappedCallPaths.test.ts b/tests/boundary/cli/electronWrappedCallPaths.test.ts index 4dd0d02a8..186abcbbe 100644 --- a/tests/boundary/cli/electronWrappedCallPaths.test.ts +++ b/tests/boundary/cli/electronWrappedCallPaths.test.ts @@ -55,7 +55,8 @@ cliTest( expect( byId.get(edge.target_node_id)?.observations[0]?.properties.channel, ).toBe(edge.properties.channel); - expect(edge.properties.conditions).toEqual([ + expect(edge.properties.bridge_conditions).toEqual([]); + expect(edge.properties.handler_conditions).toEqual([ expect.objectContaining({ expression: "allowed(event)" }), ]); } @@ -495,3 +496,44 @@ cliTest( ).toEqual(["empty:key"]); }, ); + +cliTest( + "retains bridge and handler conditions on Electron IPC join edges", + async ({ cli }) => { + const root = await createTestTempDirectory("rea-electron-join-conditions-"); + await writeFixtureFiles(root, { + "preload.js": `const e=require("electron"); + e.contextBridge.exposeInMainWorld("desktop", { + choose: flag + ? () => e.ipcRenderer.send("test:copy") + : () => e.ipcRenderer.send("test:cut") + });`, + "main.js": `const e=require("electron"); + if(!flag)e.ipcMain.on("test:copy",event=>allowed(event)&&event.sender.copy()); + if(flag)e.ipcMain.on("test:cut",event=>allowed(event)&&event.sender.cut());`, + }); + const { graph } = await analyzeJavaScriptDirectory("CLI", cli, root); + const joins = graph.edges.filter( + (edge) => + edge.evidence.extractor.operation === "join-electron-wrapper-paths", + ); + expect(joins).toHaveLength(2); + for (const [channel, bridgeCondition] of [ + ["test:copy", "flag"], + ["test:cut", "!(flag)"], + ]) { + const edge = joins.find( + (candidate) => candidate.properties.channel === channel, + ); + expect(edge?.properties.bridge_conditions).toEqual([ + expect.objectContaining({ expression: bridgeCondition }), + ]); + expect(edge?.properties.handler_conditions).toEqual([ + expect.objectContaining({ + expression: channel === "test:copy" ? "!flag" : "flag", + }), + expect.objectContaining({ expression: "allowed(event)" }), + ]); + } + }, +);