perf(javascript): share one definitions pass and index wrapper IPC dedupe (#3779)

Static analysis rebuilt the full lexical definitions index three times per
file (open receivers, RPC client roots, binding lookup) and the Electron
wrapper pass checked each substituted IPC registration against every prior
finding with JSON.stringify, which is quadratic in registrations.

Classify open receivers and RPC client roots in one traversal over a single
definitions-only index, then extend that same state with ambient writes for
binding lookup. Index IPC findings by side, operation, channel and location
so duplicate checks only consult same-endpoint candidates.

Static facts are byte-identical on the measured corpora.

Refs #3670

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-14 17:59:44 -07:00
committed by GitHub
parent 084e540414
commit 59f528f0e5
8 changed files with 220 additions and 187 deletions
@@ -42,10 +42,7 @@ import type { JavaScriptStaticAnalysis } from "./javascriptStaticAnalysisTypes.j
import type { JavaScriptSemanticAnalysisState } from "./javascriptSemanticState.js";
import {
indexJavaScriptElectronIdentitySteps,
indexJavaScriptBindingsSteps,
classifyParsedJavaScriptRpcClientRootsSteps,
classifyParsedJavaScriptOpenReceivers,
type JavaScriptOpenReceiverFact,
indexJavaScriptBindingsWithReceiversSteps,
} from "./javascriptSemanticAnalysis.js";
import {
parseJavaScriptSource,
@@ -67,45 +64,38 @@ export const analyzeJavaScriptStaticSource = (
const file = parseJavaScriptSource(source);
return file === null
? failedJavaScriptStaticAnalysis()
: analyzeParsedJavaScriptStaticSource(
source,
file,
classifyParsedJavaScriptOpenReceivers(file),
);
: analyzeParsedJavaScriptStaticSource(source, file);
};
/** Recover static structure from an already parsed JavaScript artifact. */
export const analyzeParsedJavaScriptStaticSource = (
source: string,
file: ParsedJavaScriptSource,
openReceiverFacts?: ReadonlyMap<number, JavaScriptOpenReceiverFact>,
): JavaScriptStaticAnalysis =>
completeSemanticSteps(
analyzeParsedJavaScriptStaticSourceSteps(source, file, openReceiverFacts),
);
completeSemanticSteps(analyzeParsedJavaScriptStaticSourceSteps(source, file));
/** Static analysis that yields during its source traversal; results are unchanged. */
export function* analyzeParsedJavaScriptStaticSourceSteps(
source: string,
file: ParsedJavaScriptSource,
openReceiverFacts?: ReadonlyMap<number, JavaScriptOpenReceiverFact>,
): Generator<void, JavaScriptStaticAnalysis> {
const accumulator = createJavaScriptAnalysisAccumulator(source.length);
const bindings = yield* indexJavaScriptBindingsSteps(file.program);
// One definitions pass serves receiver classification and binding lookup.
const { bindings, receivers } =
yield* indexJavaScriptBindingsWithReceiversSteps(file.program);
const electronIdentity = yield* indexJavaScriptElectronIdentitySteps(
file.program,
bindings,
);
const clientRoots = yield* classifyParsedJavaScriptRpcClientRootsSteps(file);
yield* traverseStaticSourceSteps(
file,
{
source,
accumulator,
vitePreloadDependencyTable: indexVitePreloadDependencyTable(file.program),
...(openReceiverFacts === undefined ? {} : { openReceiverFacts }),
openReceiverFacts: receivers.openReceivers,
electronBindings: electronIdentity.bindings,
rpcScan: createJavaScriptRpcScan(source, clientRoots),
rpcScan: createJavaScriptRpcScan(source, receivers.rpcClientRoots),
},
bindings,
);