mirror of
https://github.com/morluto/rea.git
synced 2026-10-23 14:22:30 -05:00
Keep each parsed script's observed frame after context destruction or ID reuse. Remove the later context lookup so record identity and deduplication use the same historical fact. Unknown and unauthorized frame mappings remain null. Validated event-to-record behavior with real local files and simulated CDP events, plus existing provider tests; no real Electron engine was exercised. Refs #3823. Co-authored-by: Liu Jie <maxazure@gmail.com>
84 lines
2.8 KiB
TypeScript
84 lines
2.8 KiB
TypeScript
import type { CdpEvent } from "./CdpConnection.js";
|
|
import { CdpCaptureCompleteness } from "./CdpCaptureCompleteness.js";
|
|
import {
|
|
numberValue,
|
|
recordValue,
|
|
scriptMetadataValues,
|
|
cdpStringValue,
|
|
} from "./CdpCaptureValues.js";
|
|
|
|
export interface ElectronScriptDraft {
|
|
readonly scriptId: string;
|
|
readonly rawUrl: string;
|
|
readonly hash: string | null;
|
|
readonly length: number | null;
|
|
readonly isModule: boolean | null;
|
|
readonly language: string | null;
|
|
readonly frameId: string | null;
|
|
}
|
|
|
|
/** Retain script/frame metadata from passive Electron events. */
|
|
export const ingestElectronScriptEvent = (input: {
|
|
readonly event: CdpEvent;
|
|
readonly scripts: ElectronScriptDraft[];
|
|
readonly executionContextFrames: Map<string, string>;
|
|
readonly completeness: CdpCaptureCompleteness;
|
|
}): void => {
|
|
if (input.event.method === "Runtime.executionContextsCleared") {
|
|
input.executionContextFrames.clear();
|
|
return;
|
|
}
|
|
if (input.event.method === "Runtime.executionContextDestroyed") {
|
|
const parameters = recordValue(input.event.params);
|
|
const key = executionContextKey(parameters?.executionContextId);
|
|
if (key !== null) input.executionContextFrames.delete(key);
|
|
return;
|
|
}
|
|
if (input.event.method === "Runtime.executionContextCreated") {
|
|
retainExecutionContext(input.event, input.executionContextFrames);
|
|
return;
|
|
}
|
|
if (input.event.method !== "Debugger.scriptParsed") return;
|
|
const value = recordValue(input.event.params);
|
|
const scriptId = cdpStringValue(value?.scriptId);
|
|
const rawUrl = cdpStringValue(value?.url);
|
|
if (scriptId === undefined) {
|
|
input.completeness.exclude("scripts", "invalid_protocol_value");
|
|
return;
|
|
}
|
|
if (rawUrl === undefined || rawUrl === "") {
|
|
input.completeness.exclude("scripts", "unattributed_origin");
|
|
return;
|
|
}
|
|
const contextKey = executionContextKey(value?.executionContextId);
|
|
input.scripts.push({
|
|
scriptId,
|
|
rawUrl,
|
|
...scriptMetadataValues(value),
|
|
language: cdpStringValue(value?.scriptLanguage) ?? null,
|
|
frameId:
|
|
contextKey === null
|
|
? null
|
|
: (input.executionContextFrames.get(contextKey) ?? null),
|
|
});
|
|
};
|
|
|
|
const retainExecutionContext = (
|
|
event: CdpEvent,
|
|
frames: Map<string, string>,
|
|
): void => {
|
|
const parameters = recordValue(event.params);
|
|
const runtimeContext = recordValue(parameters?.context);
|
|
const contextKey = executionContextKey(runtimeContext?.id);
|
|
const frameId = cdpStringValue(recordValue(runtimeContext?.auxData)?.frameId);
|
|
if (contextKey === null || frameId === undefined) return;
|
|
frames.set(contextKey, frameId);
|
|
};
|
|
|
|
const executionContextKey = (value: unknown): string | null => {
|
|
const identifier = numberValue(value);
|
|
return identifier !== undefined && Number.isSafeInteger(identifier)
|
|
? String(identifier)
|
|
: null;
|
|
};
|