mirror of
https://github.com/morluto/rea.git
synced 2026-11-13 10:12:50 +00:00
fix(browser): preserve uncertain main-frame navigation identity
Own CDP frame applicability and identity at the parsed event boundary. Preserve malformed or incomplete main-frame facts, recognize replacement roots, and carry the same document identity through captures, screenshots, timelines, and execution windows. Validation: full check:ci and docs:check; 763 browser and dispatch tests passed, 6 skipped. Independent source and fixture-lifecycle review passed. Local real-Chrome behavior was not exercised. Closes #5665
This commit is contained in:
1 parent
9dee989a79
commit
0bd14ca16c
16 files changed
+962
-179
No files matched your search
@@ -25,7 +25,7 @@ import {
|
||||
type UnknownRecord,
|
||||
} from "./CdpCaptureValues.js";
|
||||
import { mainFrameUrl } from "./CdpCaptureDocuments.js";
|
||||
import { isMainFrameNavigation } from "./CdpCaptureEventHelpers.js";
|
||||
import { cdpFrameIdentity } from "./CdpCaptureEventHelpers.js";
|
||||
import { cdpTargetEventMatches } from "./CdpTargetEvents.js";
|
||||
|
||||
interface ObservationContext {
|
||||
@@ -184,7 +184,7 @@ class TimelineCapture {
|
||||
|
||||
constructor(
|
||||
private readonly allowedOrigins: ReadonlySet<string>,
|
||||
private readonly mainFrameId: string,
|
||||
private mainFrameId: string,
|
||||
initialUrl: string,
|
||||
) {
|
||||
this.finalUrl =
|
||||
@@ -204,7 +204,15 @@ class TimelineCapture {
|
||||
#ingestArmed(event: CdpTransportEvent, bufferedBeforeArm = false): void {
|
||||
if (this.#endReason !== undefined || this.#scopeExcluded) return;
|
||||
const params = recordValue(event.params);
|
||||
if (params === undefined) return;
|
||||
if (params === undefined) {
|
||||
if (
|
||||
event.method === "Page.frameRequestedNavigation" ||
|
||||
event.method === "Page.frameNavigated" ||
|
||||
event.method === "Page.navigatedWithinDocument"
|
||||
)
|
||||
this.completeness.exclude("timeline", "invalid_protocol_value");
|
||||
return;
|
||||
}
|
||||
const contextOnly =
|
||||
bufferedBeforeArm && hasNoComparableProducerTimestamp(event.method);
|
||||
if (contextOnly) this.#hasUnknownEventTime = true;
|
||||
@@ -326,7 +334,10 @@ class TimelineCapture {
|
||||
params: UnknownRecord,
|
||||
contextOnly: boolean,
|
||||
): void {
|
||||
if (!isMainFrameNavigation(event, this.mainFrameId)) return;
|
||||
const identity = cdpFrameIdentity(event, this.mainFrameId);
|
||||
if (identity.identityIssue !== null || identity.parentIssue !== null)
|
||||
this.completeness.exclude("timeline", "invalid_protocol_value");
|
||||
if (identity.selection !== "main") return;
|
||||
const reason = safeDetail(params.reason);
|
||||
const rawUrl = cdpStringValue(params.url);
|
||||
const destination =
|
||||
@@ -349,12 +360,23 @@ class TimelineCapture {
|
||||
contextOnly: boolean,
|
||||
): void {
|
||||
const frame = recordValue(params.frame);
|
||||
if (!isMainFrameNavigation(event, this.mainFrameId)) return;
|
||||
const identity = cdpFrameIdentity(event, this.mainFrameId);
|
||||
if (identity.identityIssue !== null || identity.parentIssue !== null)
|
||||
this.completeness.exclude("timeline", "invalid_protocol_value");
|
||||
if (identity.selection !== "main" && !identity.isRootReplacement) return;
|
||||
const rawUrl = cdpStringValue(frame?.url);
|
||||
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
||||
if (identity.isRootReplacement) {
|
||||
this.mainFrameId = identity.frameId ?? this.mainFrameId;
|
||||
this.#pendingReload = false;
|
||||
if (contextOnly) {
|
||||
this.#stopIfOutOfScope(destination);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.#add({
|
||||
type:
|
||||
!contextOnly && this.#pendingReload
|
||||
!identity.isRootReplacement && !contextOnly && this.#pendingReload
|
||||
? "same_origin_reload"
|
||||
: "navigation_committed",
|
||||
params: { ...params, frameId: frame?.id, loaderId: frame?.loaderId },
|
||||
@@ -374,7 +396,10 @@ class TimelineCapture {
|
||||
params: UnknownRecord,
|
||||
contextOnly: boolean,
|
||||
): void {
|
||||
if (!isMainFrameNavigation(event, this.mainFrameId)) return;
|
||||
const identity = cdpFrameIdentity(event, this.mainFrameId);
|
||||
if (identity.identityIssue !== null || identity.parentIssue !== null)
|
||||
this.completeness.exclude("timeline", "invalid_protocol_value");
|
||||
if (identity.selection !== "main") return;
|
||||
const rawUrl = cdpStringValue(params.url);
|
||||
const destination = scopedUrl(rawUrl, this.allowedOrigins);
|
||||
this.#add({
|
||||
|
||||
Reference in new issue
Block a user