mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04:00
5d6eeb22fb
After #1542 the longest event-loop blocks on large bundles were single AST traversals inside one analyzer: member-mutation collection with its fixpoint, static source analysis, and function fingerprints, each about one second on Obsidian's 3.7 MB app.js. - traverseJavaScriptAstSteps yields every 1,024 visited nodes with the same visit order; traverseJavaScriptAst drains it, so every existing caller is unchanged. - Member mutations, static analysis and fingerprints run as steps. The member-mutation fixpoint yields every 64 references, and fingerprints yield between callables. - The now-unused synchronous member-mutation and fingerprint wrappers are removed. Graph IDs and complete result digests match main on three inputs, including obsidian.asar. Over two runs there, the longest block falls from about 920 ms to 740 ms, the second from 860 to 595 ms, and blocks over 250 ms from 27 to 18, with total time within 1.5%. Refs #1462 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
import type * as t from "@babel/types";
|
|
|
|
import { collectJavaScriptSemanticAsyncEffects } from "./javascriptSemanticAsyncEffects.js";
|
|
import { collectJavaScriptSemanticCalls } from "./javascriptSemanticCalls.js";
|
|
import { collectJavaScriptSemanticChildProcesses } from "./javascriptSemanticChildProcesses.js";
|
|
import { collectJavaScriptSemanticFingerprintsSteps } from "./javascriptSemanticFingerprints.js";
|
|
import { collectJavaScriptSemanticDataEffects } from "./javascriptSemanticDataEffects.js";
|
|
import type {
|
|
JavaScriptSemanticCallable,
|
|
JavaScriptSemanticIr,
|
|
} from "./javascriptSemanticIr.js";
|
|
import { collectJavaScriptSemanticPromises } from "./javascriptSemanticPromises.js";
|
|
import { collectJavaScriptSemanticObjects } from "./javascriptSemanticObjects.js";
|
|
import { collectJavaScriptSemanticResources } from "./javascriptSemanticResources.js";
|
|
import type { JavaScriptSemanticAnalysisState } from "./javascriptSemanticState.js";
|
|
|
|
type DerivedSemanticAnalysis = Pick<
|
|
JavaScriptSemanticIr,
|
|
| "argumentFlows"
|
|
| "callResultFlows"
|
|
| "callReturnFlows"
|
|
| "callSites"
|
|
| "boundaryOperations"
|
|
| "childProcessInteractions"
|
|
| "childProcessSpawns"
|
|
| "closureCaptures"
|
|
| "configurationOperations"
|
|
| "eventOperations"
|
|
| "frontiers"
|
|
| "functionFingerprints"
|
|
| "objectOperations"
|
|
| "promiseOperations"
|
|
| "requestOperations"
|
|
| "resourceOperations"
|
|
| "timerOperations"
|
|
>;
|
|
|
|
/** Compose bounded semantic passes after lexical definitions are available. */
|
|
/**
|
|
* Collect derived semantics with a yield between collectors. Each collector
|
|
* completes before the next starts, so results equal the synchronous form.
|
|
*/
|
|
export function* collectJavaScriptDerivedSemanticsSteps(
|
|
program: t.Program,
|
|
state: JavaScriptSemanticAnalysisState,
|
|
callables: readonly JavaScriptSemanticCallable[],
|
|
parserPartial: boolean,
|
|
): Generator<void, DerivedSemanticAnalysis> {
|
|
const calls = collectJavaScriptSemanticCalls(program, state, callables);
|
|
yield;
|
|
const promiseOperations = collectJavaScriptSemanticPromises(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const asyncEffects = collectJavaScriptSemanticAsyncEffects(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const childProcesses = collectJavaScriptSemanticChildProcesses(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const dataEffects = collectJavaScriptSemanticDataEffects(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const resourceOperations = collectJavaScriptSemanticResources(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const objectOperations = collectJavaScriptSemanticObjects(
|
|
program,
|
|
state,
|
|
callables,
|
|
);
|
|
yield;
|
|
const functionFingerprints =
|
|
yield* collectJavaScriptSemanticFingerprintsSteps({
|
|
state,
|
|
callables,
|
|
calls,
|
|
promises: promiseOperations,
|
|
events: asyncEffects.eventOperations,
|
|
timers: asyncEffects.timerOperations,
|
|
childProcessSpawns: childProcesses.childProcessSpawns,
|
|
childProcessInteractions: childProcesses.childProcessInteractions,
|
|
requestOperations: dataEffects.requestOperations,
|
|
resourceOperations,
|
|
parserPartial,
|
|
});
|
|
return {
|
|
...calls,
|
|
promiseOperations,
|
|
...asyncEffects,
|
|
...childProcesses,
|
|
...dataEffects,
|
|
resourceOperations,
|
|
objectOperations,
|
|
functionFingerprints,
|
|
};
|
|
}
|