rea/src/domain/javascript/javascriptStaticAnalysisSta...

122 lines
4.4 KiB
TypeScript

import type * as t from "@babel/types";
import type { JavaScriptOpenReceiverFact } from "./javascriptSemanticAnalysis.js";
import type { JavaScriptRpcScan } from "./javascriptRpcEndpoints.js";
import type {
JavaScriptBundlerRegistration,
JavaScriptRolePath,
JavaScriptStaticAnalysis,
JavaScriptStaticEndpoint,
JavaScriptStaticReference,
JavaScriptStaticStorage,
} from "./javascriptStaticAnalysisTypes.js";
import type {
ElectronCallPath,
ElectronBrowserWindowFinding,
ElectronContextBridgeFinding,
ElectronIpcFinding,
ElectronNativeAddonBindingFinding,
ElectronSenderValidationFinding,
ElectronUtilityProcessFinding,
} from "./electronStaticAnalysisTypes.js";
import { JavaScriptModuleRangeIndex } from "./javascriptStaticAnalysisFindings.js";
/** Source offsets for one recovered bundle module factory. */
export interface JavaScriptModuleRange {
readonly start: number;
readonly end: number;
readonly key: string;
readonly runtime: string;
readonly requireName: string | null;
}
/** Static finding retained with its source offset until module attribution. */
export interface LocatedJavaScriptFinding<Value> {
readonly offset: number;
readonly value: Value;
}
/** Mutable collections used during one inert AST traversal. */
export interface JavaScriptAnalysisAccumulator {
electronCallPaths?: readonly ElectronCallPath[];
electronCallPathLimitReached?: boolean;
readonly references: LocatedJavaScriptFinding<JavaScriptStaticReference>[];
readonly endpoints: LocatedJavaScriptFinding<JavaScriptStaticEndpoint>[];
readonly storage: LocatedJavaScriptFinding<JavaScriptStaticStorage>[];
readonly roles: LocatedJavaScriptFinding<JavaScriptRolePath>[];
readonly sourceMaps: JavaScriptStaticAnalysis["source_map_urls"][number][];
readonly registrations: JavaScriptBundlerRegistration[];
readonly browserWindows: LocatedJavaScriptFinding<ElectronBrowserWindowFinding>[];
readonly contextBridgeApis: LocatedJavaScriptFinding<ElectronContextBridgeFinding>[];
readonly ipc: LocatedJavaScriptFinding<ElectronIpcFinding>[];
readonly senderValidations: LocatedJavaScriptFinding<ElectronSenderValidationFinding>[];
readonly utilityProcesses: LocatedJavaScriptFinding<ElectronUtilityProcessFinding>[];
readonly nativeAddonBindings: LocatedJavaScriptFinding<ElectronNativeAddonBindingFinding>[];
readonly moduleRangeIndex: JavaScriptModuleRangeIndex;
/** `preload` attributes of audio and video elements, which are not scripts. */
readonly mediaElementPreloads: WeakSet<t.Node>;
readonly seen: Set<string>;
visitedNodes: number;
unknownFindings: number;
}
/** Shared source and accumulator for helper inspections. */
export interface JavaScriptFindingContext {
readonly rpcScan: JavaScriptRpcScan;
readonly source: string;
readonly accumulator: JavaScriptAnalysisAccumulator;
readonly vitePreloadDependencyTable: readonly (string | undefined)[] | null;
readonly openReceiverFacts?: ReadonlyMap<number, JavaScriptOpenReceiverFact>;
/** Proven Electron export path segments by root offset. */
readonly electronBindings?: ReadonlyMap<number, readonly string[]>;
}
/** Candidate import, require, worker, or service-worker reference. */
export interface JavaScriptReferenceInput {
readonly node: t.Node;
readonly kind: JavaScriptStaticReference["kind"];
readonly specifier: string | undefined;
}
/** Candidate route or network endpoint literal. */
export interface JavaScriptEndpointInput {
readonly node: t.Node;
readonly kind: JavaScriptStaticEndpoint["kind"];
readonly value: string;
readonly mechanism: string;
readonly interpretation?: "candidate";
}
/** Values required to append one module-attributable static finding. */
export interface LocatedJavaScriptFindingInput<
Value extends { readonly module_key: string | null },
> {
readonly collection: LocatedJavaScriptFinding<Value>[];
readonly key: string;
readonly node: t.Node;
readonly value: Value;
}
/** Create isolated mutable state for one source analysis. */
export const createJavaScriptAnalysisAccumulator = (
sourceLength: number,
): JavaScriptAnalysisAccumulator => ({
references: [],
endpoints: [],
storage: [],
roles: [],
sourceMaps: [],
registrations: [],
browserWindows: [],
contextBridgeApis: [],
ipc: [],
senderValidations: [],
utilityProcesses: [],
nativeAddonBindings: [],
moduleRangeIndex: new JavaScriptModuleRangeIndex(sourceLength),
mediaElementPreloads: new WeakSet(),
seen: new Set(),
visitedNodes: 0,
unknownFindings: 0,
});