|
1 | 1 | import type {
|
2 | 2 | BrowserContext as PlaywrightContext,
|
| 3 | + CDPSession, |
3 | 4 | Page as PlaywrightPage,
|
4 | 5 | } from "playwright";
|
5 | 6 | import { Stagehand } from "./index";
|
6 | 7 | import { StagehandPage } from "./StagehandPage";
|
7 | 8 | import { Page } from "../types/page";
|
8 | 9 | import { EnhancedContext } from "../types/context";
|
| 10 | +import { Protocol } from "devtools-protocol"; |
9 | 11 |
|
10 | 12 | export class StagehandContext {
|
11 | 13 | private readonly stagehand: Stagehand;
|
@@ -84,20 +86,32 @@ export class StagehandContext {
|
84 | 86 | const existingPages = context.pages();
|
85 | 87 | for (const page of existingPages) {
|
86 | 88 | const stagehandPage = await instance.createStagehandPage(page);
|
| 89 | + await instance.attachFrameNavigatedListener(page); |
87 | 90 | // Set the first page as active
|
88 | 91 | if (!instance.activeStagehandPage) {
|
89 | 92 | instance.setActivePage(stagehandPage);
|
90 | 93 | }
|
91 | 94 | }
|
92 | 95 |
|
93 | 96 | context.on("page", (pwPage) => {
|
94 |
| - instance.handleNewPlaywrightPage(pwPage).catch((err) => |
95 |
| - stagehand.logger({ |
96 |
| - category: "context", |
97 |
| - message: `Failed to initialise new page: ${err}`, |
98 |
| - level: 0, |
99 |
| - }), |
100 |
| - ); |
| 97 | + instance |
| 98 | + .attachFrameNavigatedListener(pwPage) |
| 99 | + .catch((err) => |
| 100 | + stagehand.logger({ |
| 101 | + category: "cdp", |
| 102 | + message: `Failed to attach frameNavigated listener: ${err}`, |
| 103 | + level: 0, |
| 104 | + }), |
| 105 | + ) |
| 106 | + .finally(() => |
| 107 | + instance.handleNewPlaywrightPage(pwPage).catch((err) => |
| 108 | + stagehand.logger({ |
| 109 | + category: "context", |
| 110 | + message: `Failed to initialise new page: ${err}`, |
| 111 | + level: 0, |
| 112 | + }), |
| 113 | + ), |
| 114 | + ); |
101 | 115 | });
|
102 | 116 |
|
103 | 117 | return instance;
|
@@ -156,4 +170,33 @@ export class StagehandContext {
|
156 | 170 | }
|
157 | 171 | this.setActivePage(stagehandPage);
|
158 | 172 | }
|
| 173 | + |
| 174 | + private async attachFrameNavigatedListener( |
| 175 | + pwPage: PlaywrightPage, |
| 176 | + ): Promise<void> { |
| 177 | + const shPage = this.pageMap.get(pwPage); |
| 178 | + if (!shPage) return; |
| 179 | + const session: CDPSession = await this.intContext.newCDPSession(pwPage); |
| 180 | + await session.send("Page.enable"); |
| 181 | + |
| 182 | + pwPage.once("close", () => { |
| 183 | + this.unregisterFrameId(shPage.frameId); |
| 184 | + }); |
| 185 | + |
| 186 | + session.on( |
| 187 | + "Page.frameNavigated", |
| 188 | + (evt: Protocol.Page.FrameNavigatedEvent): void => { |
| 189 | + const { frame } = evt; |
| 190 | + |
| 191 | + if (!frame.parentId) { |
| 192 | + const oldId = shPage.frameId; |
| 193 | + if (frame.id !== oldId) { |
| 194 | + if (oldId) this.unregisterFrameId(oldId); |
| 195 | + this.registerFrameId(frame.id, shPage); |
| 196 | + shPage.updateRootFrameId(frame.id); |
| 197 | + } |
| 198 | + } |
| 199 | + }, |
| 200 | + ); |
| 201 | + } |
159 | 202 | }
|
0 commit comments