diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 103d548107..60890a2200 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -133,7 +133,7 @@ export class CRPage implements PageDelegate { return cb(frameSession); return cb(frameSession).catch(e => { // Broadcasting a message to the closed iframe shoule be a noop. - if (e.message && (e.message.includes('Target closed.') || e.message.includes('Session closed.'))) + if (e.message && e.message.includes('Target closed')) return; throw e; }); diff --git a/tests/library/chromium/oopif.spec.ts b/tests/library/chromium/oopif.spec.ts index 2d5671a219..cd61a75448 100644 --- a/tests/library/chromium/oopif.spec.ts +++ b/tests/library/chromium/oopif.spec.ts @@ -326,6 +326,16 @@ it('should emit filechooser event for iframe', async ({ page, server, browser }) expect(chooser).toBeTruthy(); }); +it('should not throw on exposeFunction when oopif detaches', async ({ page, browser, server }) => { + await page.goto(server.PREFIX + '/dynamic-oopif.html'); + expect(await countOOPIFs(browser)).toBe(1); + await Promise.all([ + page.exposeFunction('myFunc', () => 2022), + page.evaluate(() => document.querySelector('iframe').remove()), + ]); + expect(await page.evaluate(() => (window as any).myFunc())).toBe(2022); +}); + async function countOOPIFs(browser) { const browserSession = await browser.newBrowserCDPSession(); const oopifs = [];