diff --git a/src/common/DOMWorld.ts b/src/common/DOMWorld.ts index cfacc28734666..eb56d83325df0 100644 --- a/src/common/DOMWorld.ts +++ b/src/common/DOMWorld.ts @@ -111,9 +111,8 @@ export class DOMWorld { this._frame = frame; this._timeoutSettings = timeoutSettings; this._setContext(null); - this._client.on('Runtime.bindingCalled', (event) => - this._onBindingCalled(event) - ); + this._onBindingCalled = this._onBindingCalled.bind(this); + this._client.on('Runtime.bindingCalled', this._onBindingCalled); } frame(): Frame { @@ -144,6 +143,7 @@ export class DOMWorld { _detach(): void { this._detached = true; + this._client.off('Runtime.bindingCalled', this._onBindingCalled); for (const waitTask of this._waitTasks) waitTask.terminate( new Error('waitForFunction failed: frame got detached.') diff --git a/test/page.spec.ts b/test/page.spec.ts index 9fb6809b4d5d7..68fb6d87419f4 100644 --- a/test/page.spec.ts +++ b/test/page.spec.ts @@ -1035,6 +1035,22 @@ describe('Page', function () { }); expect(result).toBe(15); }); + it('should not throw when frames detach', async () => { + const { page, server } = getTestState(); + + await page.goto(server.EMPTY_PAGE); + await utils.attachFrame(page, 'frame1', server.EMPTY_PAGE); + await page.exposeFunction('compute', function (a, b) { + return Promise.resolve(a * b); + }); + await utils.detachFrame(page, 'frame1'); + + await expect( + page.evaluate(async function () { + return await globalThis.compute(3, 5); + }) + ).resolves.toEqual(15); + }); it('should work with complex objects', async () => { const { page } = getTestState();