From 1d33e85ab68434d61a7cfdcb38d96475ad5ede3b Mon Sep 17 00:00:00 2001 From: Holger Benl Date: Fri, 19 Jun 2026 13:19:52 +0200 Subject: [PATCH] chore(bidi): fix redirected navigations from HAR routers --- .../src/server/bidi/bidiPage.ts | 28 +++++++++++++------ .../moz-firefox-nightly-library.txt | 5 +--- .../expectations/moz-firefox-nightly-page.txt | 4 +-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/packages/playwright-core/src/server/bidi/bidiPage.ts b/packages/playwright-core/src/server/bidi/bidiPage.ts index 2380c6da0a156..aec8cc1249ac8 100644 --- a/packages/playwright-core/src/server/bidi/bidiPage.ts +++ b/packages/playwright-core/src/server/bidi/bidiPage.ts @@ -28,9 +28,9 @@ import { BidiPDF } from './bidiPdf'; import * as bidi from './third_party/bidiProtocol'; import { nullProgress } from '../progress'; +import * as frames from '../frames'; import * as network from '../network'; import type { RegisteredListener } from '@utils/eventsHelper'; -import type * as frames from '../frames'; import type { InitScript, PageDelegate } from '../page'; import type { Progress } from '../progress'; import type * as types from '../types'; @@ -55,6 +55,7 @@ export class BidiPage implements PageDelegate { private readonly _pdf: BidiPDF; private _initScriptIds = new Map(); private readonly _fragmentNavigations = new Set(); + private readonly _failedNavigations = new Map(); constructor(browserContext: BidiBrowserContext, bidiSession: BidiSession, opener: BidiPage | null) { this._session = bidiSession; @@ -194,6 +195,7 @@ export class BidiPage implements PageDelegate { private _onNavigationStarted(params: bidi.BrowsingContext.NavigationInfo) { const frameId = params.context; + this._failedNavigations.delete(frameId); this._page.frameManager.frameRequestedNavigation(frameId, params.navigation!); } @@ -218,6 +220,8 @@ export class BidiPage implements PageDelegate { } private _onNavigationFailed(params: bidi.BrowsingContext.NavigationInfo) { + if (params.navigation) + this._failedNavigations.set(params.context, params.navigation); this._page.frameManager.frameAbortedNavigation(params.context, 'Navigation failed', params.navigation || undefined); } @@ -314,15 +318,21 @@ export class BidiPage implements PageDelegate { } async navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise { - const { navigation } = await this._session.send('browsingContext.navigate', { - context: frame._id, - url, - }); - if (navigation && this._fragmentNavigations.has(navigation)) { - this._fragmentNavigations.delete(navigation); - return {}; + try { + const { navigation } = await this._session.send('browsingContext.navigate', { + context: frame._id, + url, + }); + if (navigation && this._fragmentNavigations.has(navigation)) { + this._fragmentNavigations.delete(navigation); + return {}; + } + return { newDocumentId: navigation || undefined }; + } catch (error) { + const navigation = this._failedNavigations.get(frame._id); + this._failedNavigations.delete(frame._id); + throw new frames.NavigationAbortedError(navigation, `${error.message} at ${url}`); } - return { newDocumentId: navigation || undefined }; } async updateExtraHTTPHeaders(): Promise { diff --git a/tests/bidi/expectations/moz-firefox-nightly-library.txt b/tests/bidi/expectations/moz-firefox-nightly-library.txt index ccb2b75207955..768a2632f269c 100644 --- a/tests/bidi/expectations/moz-firefox-nightly-library.txt +++ b/tests/bidi/expectations/moz-firefox-nightly-library.txt @@ -19,12 +19,8 @@ library/browsercontext-devtools.spec.ts › should close tab via close button [f library/browsercontext-devtools.spec.ts › should display screencast image [fail] library/browsercontext-devtools.spec.ts › should show no-pages placeholder when all tabs are closed [fail] library/browsercontext-events.spec.ts › console event should work with element handles [fail] -library/browsercontext-har.spec.ts › should change document URL after redirected navigation [fail] -library/browsercontext-har.spec.ts › should change document URL after redirected navigation on click [timeout] -library/browsercontext-har.spec.ts › should goBack to redirected navigation [fail] library/browsercontext-har.spec.ts › should goForward to redirected navigation [fail] library/browsercontext-har.spec.ts › should record overridden requests to har [fail] -library/browsercontext-har.spec.ts › should reload redirected navigation [fail] library/browsercontext-har.spec.ts › should round-trip har with postData [fail] library/browsercontext-locale.spec.ts › should format number [fail] library/browsercontext-locale.spec.ts › should format number in popups [fail] @@ -129,6 +125,7 @@ library/har-websocket.spec.ts › should omit websocket messages [fail] library/har-websocket.spec.ts › should only have one websocket entry [fail] library/har-websocket.spec.ts › should record websocket connection failure [timeout] library/har-websocket.spec.ts › should record websocket handshake failure [fail] +library/har-websocket.spec.ts › should respect PLAYWRIGHT_HAR_NO_WEBSOCKET_FRAMES [fail] library/har-websocket.spec.ts › should still allow routeWebSocket to modify messages when capturing HAR [fail] library/har-websocket.spec.ts › should still capture websocket when route passes messages through [fail] library/har.spec.ts › should have connection details [fail] diff --git a/tests/bidi/expectations/moz-firefox-nightly-page.txt b/tests/bidi/expectations/moz-firefox-nightly-page.txt index 52ae8bc600876..69c58a9bbeebc 100644 --- a/tests/bidi/expectations/moz-firefox-nightly-page.txt +++ b/tests/bidi/expectations/moz-firefox-nightly-page.txt @@ -135,8 +135,8 @@ page/page-screenshot.spec.ts › page screenshot animations › should not captu page/page-screenshot.spec.ts › page screenshot animations › should not capture pseudo element css animation [fail] page/page-screenshot.spec.ts › page screenshot › should allow transparency [fail] page/page-set-input-files.spec.ts › should upload a folder [fail] -page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup [timeout] -page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup with noopener [timeout] +page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup [timeout] +page/page-wait-for-load-state.spec.ts › should wait for load state of about:blank popup with noopener [timeout] page/page-wait-for-load-state.spec.ts › should wait for load state of empty url popup [timeout] page/wheel.spec.ts › should dispatch wheel events after popup was opened @smoke [timeout] page/workers.spec.ts › Page.workers @smoke [timeout]