fix(browser): ignore handled route navigation races · openclaw/openclaw@65b6072
steipete
·
2026-04-25
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
|
13 | 13 | |
14 | 14 | ### Fixes |
15 | 15 | |
| 16 | +- Browser/Playwright: ignore benign already-handled route races during guarded navigation so browser-page tasks no longer fail when Playwright tears down a route mid-flight. (#68708) Thanks @Steady-ai. |
16 | 17 | - Browser/Linux: detect Chromium-based installs under `/opt/google`, `/opt/brave.com`, `/usr/lib/chromium`, and `/usr/lib/chromium-browser` before asking users to set `browser.executablePath`. (#48563) Thanks @lupuletic. |
17 | 18 | - MCP/CLI: retire bundled MCP runtimes at the end of one-shot `openclaw agent` and `openclaw infer model run` gateway/local executions, so repeated scripted runs do not accumulate stdio MCP child processes. Fixes #71457. |
18 | 19 | - OpenAI/Codex image generation: canonicalize legacy `openai-codex.baseUrl` values such as `https://chatgpt.com/backend-api` to the Codex Responses backend before calling `gpt-image-2`, matching the chat transport. Fixes #71460. |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -345,6 +345,34 @@ describe("pw-session createPageViaPlaywright navigation guard", () => {
|
345 | 345 | expect(pageClose).not.toHaveBeenCalled(); |
346 | 346 | }); |
347 | 347 | |
| 348 | +it("ignores already-handled route races during guarded navigation", async () => { |
| 349 | +const { pageGoto, pageClose, getRouteHandler, mainFrame } = installBrowserMocks(); |
| 350 | +const route = createMockRoute({ |
| 351 | +continue: vi.fn(async () => { |
| 352 | +throw new Error("Route is already handled"); |
| 353 | +}), |
| 354 | +}); |
| 355 | +pageGoto.mockImplementationOnce(async () => { |
| 356 | +await dispatchMockNavigation({ |
| 357 | + getRouteHandler, |
| 358 | + mainFrame, |
| 359 | +url: "https://example.com", |
| 360 | + route, |
| 361 | +}); |
| 362 | +return null; |
| 363 | +}); |
| 364 | + |
| 365 | +const created = await createPageViaPlaywright({ |
| 366 | +cdpUrl: "http://127.0.0.1:18792", |
| 367 | +url: "https://example.com", |
| 368 | +}); |
| 369 | + |
| 370 | +expect(created.targetId).toBe("TARGET_1"); |
| 371 | +expect(route.continue).toHaveBeenCalledTimes(1); |
| 372 | +expect(pageGoto).toHaveBeenCalledTimes(1); |
| 373 | +expect(pageClose).not.toHaveBeenCalled(); |
| 374 | +}); |
| 375 | + |
348 | 376 | it("propagates unsupported redirect protocols as navigation errors", async () => { |
349 | 377 | const { pageGoto, pageClose, getRouteHandler, mainFrame } = installBrowserMocks(); |
350 | 378 | mockBlockedRedirectNavigation({ |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -818,6 +818,18 @@ export async function assertPageNavigationCompletedSafely(
|
818 | 818 | } |
819 | 819 | } |
820 | 820 | |
| 821 | +async function continueRouteSafely(route: Route): Promise<void> { |
| 822 | +try { |
| 823 | +await route.continue(); |
| 824 | +} catch (err) { |
| 825 | +const message = err instanceof Error ? err.message : ""; |
| 826 | +if (message.includes("Route is already handled")) { |
| 827 | +return; |
| 828 | +} |
| 829 | +throw err; |
| 830 | +} |
| 831 | +} |
| 832 | + |
821 | 833 | export async function gotoPageWithNavigationGuard( |
822 | 834 | opts: { |
823 | 835 | cdpUrl: string; |
@@ -841,7 +853,7 @@ export async function gotoPageWithNavigationGuard(
|
841 | 853 | const isSubframeDocument = |
842 | 854 | !isTopLevel && isSubframeDocumentNavigationRequest(opts.page, request); |
843 | 855 | if (!isTopLevel && !isSubframeDocument) { |
844 | | -await route.continue(); |
| 856 | +await continueRouteSafely(route); |
845 | 857 | return; |
846 | 858 | } |
847 | 859 | try { |
@@ -859,7 +871,7 @@ export async function gotoPageWithNavigationGuard(
|
859 | 871 | } |
860 | 872 | throw err; |
861 | 873 | } |
862 | | -await route.continue(); |
| 874 | +await continueRouteSafely(route); |
863 | 875 | }; |
864 | 876 | |
865 | 877 | await opts.page.route("**", handler); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。