diff --git a/apps/desktop/src/preview/CdpRelay.test.ts b/apps/desktop/src/preview/CdpRelay.test.ts index 4ec88a7cc516..a87d8af85ea0 100644 --- a/apps/desktop/src/preview/CdpRelay.test.ts +++ b/apps/desktop/src/preview/CdpRelay.test.ts @@ -75,6 +75,28 @@ describe("CDP relay", () => { }); }); + it("resumes paused child frames, so cross-site iframes run", async () => { + const send = vi.fn(async () => ({})); + const relay = createCdpRelayConnection(makeTarget(send), () => {}); + // The page's own session is already running; only its children wait. + relay.receive( + JSON.stringify({ + id: 1, + method: "Runtime.runIfWaitingForDebugger", + sessionId: "t3-preview-page", + }), + ); + relay.receive( + JSON.stringify({ + id: 2, + method: "Runtime.runIfWaitingForDebugger", + sessionId: "iframe-session", + }), + ); + await settle(); + expect(send.mock.calls).toEqual([["Runtime.runIfWaitingForDebugger", {}, "iframe-session"]]); + }); + it("routes tab events to the page session once the page is announced", async () => { const written: Array> = []; const relay = createCdpRelayConnection(makeTarget(vi.fn()), (raw) => diff --git a/apps/desktop/src/preview/CdpRelay.ts b/apps/desktop/src/preview/CdpRelay.ts index 19000aa50c63..62c2410c19b8 100644 --- a/apps/desktop/src/preview/CdpRelay.ts +++ b/apps/desktop/src/preview/CdpRelay.ts @@ -158,9 +158,14 @@ export function createCdpRelayConnection( }; const pageCommand = (command: CdpCommand): Promise => { - // The page is already running; nothing waits for a debugger. - if (command.method === "Runtime.runIfWaitingForDebugger") return Promise.resolve({}); const child = sessions.get(command.sessionId!) === "page" ? undefined : command.sessionId; + // The page itself is already running, but its child frames are not: + // Playwright auto-attaches with waitForDebuggerOnStart, so Chromium pauses + // every new cross-site iframe and worker until this reaches it. Swallowing + // it left sign-in checks and captchas, which run in such frames, frozen. + if (command.method === "Runtime.runIfWaitingForDebugger" && child === undefined) { + return Promise.resolve({}); + } return target.send(command.method, command.params ?? {}, child); };