Skip to content

Commit 6821aba

Browse files
committed
Persist navigation epochs in browser ref state
1 parent f187fc1 commit 6821aba

2 files changed

Lines changed: 17 additions & 0 deletions

File tree

packages/agent/src/translator/browser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export interface BrowserRefState {
7878
refCounter: number;
7979
activeTargetId?: string;
8080
generations: Array<[string, number]>;
81+
navigationEpochs?: Array<[string, number]>;
8182
refs: Array<[string, Omit<RefEntry, "sessionId">]>;
8283
frameParents?: Array<[string, string]>;
8384
frameOwners?: Array<[string, string]>;
@@ -226,6 +227,7 @@ export class BrowserExecutor {
226227
refCounter: this.refCounter,
227228
...(this.activeTargetId ? { activeTargetId: this.activeTargetId } : {}),
228229
generations: [...this.generations],
230+
navigationEpochs: [...this.navigationEpochs],
229231
refs: [...this.refs].map(([ref, { sessionId: _sessionId, ...entry }]) => [ref, entry]),
230232
frameParents: [...this.frameParents],
231233
frameOwners: [...this.frameOwners],
@@ -238,6 +240,7 @@ export class BrowserExecutor {
238240
this.refCounter = Math.max(this.refCounter, state.refCounter);
239241
this.activeTargetId = state.activeTargetId ?? this.activeTargetId;
240242
for (const [frameId, generation] of state.generations) this.generations.set(frameId, generation);
243+
for (const [targetId, epoch] of state.navigationEpochs ?? []) this.navigationEpochs.set(targetId, epoch);
241244
for (const [ref, entry] of state.refs) this.refs.set(ref, { ...entry, sessionId: "" });
242245
for (const [frame, parent] of state.frameParents ?? []) this.frameParents.set(frame, parent);
243246
for (const [frame, owner] of state.frameOwners ?? []) this.frameOwners.set(frame, owner);

packages/agent/test/translator-browser.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,20 @@ describe("BrowserExecutor ref state export/import", () => {
10741074
expect(pressed).toBeDefined();
10751075
});
10761076

1077+
it("persists navigation epochs across ref-state export/import", async () => {
1078+
const { cdp, emit } = createFakeCdp(BUTTON_TREE);
1079+
const first = new BrowserExecutor(cdp);
1080+
await snapshotText(first);
1081+
emit({ method: "Page.frameNavigated", params: { frame: { id: "TARGET-1" } }, sessionId: "session-1" });
1082+
const state = first.exportRefState();
1083+
expect(state.navigationEpochs).toEqual([["TARGET-1", 1]]);
1084+
1085+
const second = new BrowserExecutor(createFakeCdp(BUTTON_TREE).cdp);
1086+
second.importRefState(state);
1087+
const importedEpochs = (second as unknown as { navigationEpochs: Map<string, number> }).navigationEpochs;
1088+
expect(importedEpochs.get("TARGET-1")).toBe(1);
1089+
});
1090+
10771091
it("keeps minting unique refs after import and invalidates imported refs on navigation", async () => {
10781092
const first = new BrowserExecutor(createFakeCdp(BUTTON_TREE).cdp);
10791093
await snapshotText(first);

0 commit comments

Comments
 (0)