mirror of
https://github.com/morluto/rea.git
synced 2026-10-31 20:06:14 +00:00
fix(javascript): exclude overwritten Electron API identities (#1664)
* fix(javascript): exclude overwritten Electron API identities * test(javascript): bind Electron in file-base path fixture * test(electron): bind BrowserWindow in preload override fixtures * test(mcp): allow cold catalog validation in runtime probe * test(electron): bind APIs in option reconstruction fixtures
This commit is contained in:
1 parent
ad41afa2b5
commit
29cc1b8746
13 files changed
+434
-62
No files matched your search
@@ -0,0 +1,61 @@
|
||||
import * as t from "@babel/types";
|
||||
|
||||
import {
|
||||
semanticStaticPropertyKey,
|
||||
semanticMemberWriteTargets,
|
||||
unwrapJavaScriptExpression,
|
||||
} from "./javascriptAstValues.js";
|
||||
import { SemanticPropertyPathCoverage } from "./javascriptSemanticPropertyPaths.js";
|
||||
import { traverseJavaScriptAstSteps } from "./javascriptSemanticTraversal.js";
|
||||
|
||||
/** Match Electron's supported module entry points. */
|
||||
export const ELECTRON_MODULE =
|
||||
/^electron(?:\/(?:common|main|renderer|utility))?$/u;
|
||||
|
||||
/** Static identity recovery cannot establish the absence of Electron usage. */
|
||||
export const ELECTRON_IDENTITY_LIMITATION =
|
||||
"Electron API identity follows proven lexical module aliases. Reassigned bindings, dynamic selections, and visibly overwritten namespace members are unresolved; missing findings do not establish absence. Arbitrary call side effects and runtime registration are not evaluated.";
|
||||
|
||||
/** Preserve exact property segments instead of flattening literal dotted keys. */
|
||||
export const electronMemberPath = (
|
||||
node: t.Node,
|
||||
): {
|
||||
readonly root: t.Node;
|
||||
readonly members: readonly (string | null)[];
|
||||
} => {
|
||||
let root = unwrapJavaScriptExpression(node).node;
|
||||
const members: (string | null)[] = [];
|
||||
while (t.isMemberExpression(root) || t.isOptionalMemberExpression(root)) {
|
||||
members.push(semanticStaticPropertyKey(root.property, root.computed));
|
||||
root = unwrapJavaScriptExpression(root.object).node;
|
||||
}
|
||||
return { root, members: members.toReversed() };
|
||||
};
|
||||
|
||||
/** Index visible writes through proven Electron aliases, without executing them. */
|
||||
export function* collectElectronMemberWritesSteps(
|
||||
program: t.Program,
|
||||
origin: (root: t.Node) => readonly string[] | undefined,
|
||||
): Generator<void, SemanticPropertyPathCoverage> {
|
||||
const writes = new SemanticPropertyPathCoverage();
|
||||
yield* traverseJavaScriptAstSteps(program, {
|
||||
enter: (node) => {
|
||||
const target = t.isAssignmentExpression(node)
|
||||
? node.left
|
||||
: t.isUpdateExpression(node)
|
||||
? node.argument
|
||||
: t.isUnaryExpression(node, { operator: "delete" })
|
||||
? node.argument
|
||||
: t.isForOfStatement(node) || t.isForInStatement(node)
|
||||
? node.left
|
||||
: undefined;
|
||||
if (target === undefined) return;
|
||||
for (const member of semanticMemberWriteTargets(target)) {
|
||||
const { root, members } = electronMemberPath(member);
|
||||
const exported = origin(root);
|
||||
if (exported !== undefined) writes.retain([...exported, ...members]);
|
||||
}
|
||||
},
|
||||
});
|
||||
return writes;
|
||||
}
|
||||
Reference in new issue
Block a user