Skip to content

Commit 9365eb5

Browse files
authored
cherry-pick(#33834): fix: do not stall waiting for pending navigations after beforeunload dismiss (#33856)
1 parent f92b233 commit 9365eb5

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

packages/playwright-core/src/server/chromium/crPage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,9 @@ class FrameSession {
842842
event.type,
843843
event.message,
844844
async (accept: boolean, promptText?: string) => {
845+
// TODO: this should actually be a CDP event that notifies about a cancelled navigation attempt.
846+
if (this._isMainFrame() && event.type === 'beforeunload' && !accept)
847+
this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
845848
await this._client.send('Page.handleJavaScriptDialog', { accept, promptText });
846849
},
847850
event.defaultPrompt));

packages/playwright-core/src/server/webkit/wkPage.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ export class WKPage implements PageDelegate {
612612
event.type as dialog.DialogType,
613613
event.message,
614614
async (accept: boolean, promptText?: string) => {
615+
// TODO: this should actually be a RDP event that notifies about a cancelled navigation attempt.
616+
if (event.type === 'beforeunload' && !accept)
617+
this._page._frameManager.frameAbortedNavigation(this._page.mainFrame()._id, 'navigation cancelled by beforeunload dialog');
615618
await this._pageProxySession.send('Dialog.handleJavaScriptDialog', { accept, promptText });
616619
},
617620
event.defaultPrompt));

tests/library/beforeunload.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,25 @@ it('should not stall on evaluate when dismissing beforeunload', async ({ page, s
104104
]);
105105
});
106106

107+
it('should not stall on click when dismissing beforeunload', async ({ page, server }) => {
108+
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33806' });
109+
110+
await page.goto(server.EMPTY_PAGE);
111+
await page.setContent(`<a href="${server.PREFIX}/frames/one-frame.html">click me</a>`);
112+
113+
await page.evaluate(() => {
114+
window.onbeforeunload = () => false;
115+
});
116+
page.on('dialog', async dialog => {
117+
await dialog.dismiss();
118+
});
119+
120+
await page.getByRole('link').click({ noWaitAfter: true });
121+
await page.evaluate(() => {
122+
window.onbeforeunload = null;
123+
});
124+
125+
// This line should not timeout.
126+
await page.getByRole('link').click({ timeout: 5000 });
127+
await expect(page).toHaveURL(server.PREFIX + '/frames/one-frame.html');
128+
});

0 commit comments

Comments
 (0)