diff --git a/packages/playwright-core/src/server/firefox/ffPage.ts b/packages/playwright-core/src/server/firefox/ffPage.ts index ec85a1fdd5..2576884ef6 100644 --- a/packages/playwright-core/src/server/firefox/ffPage.ts +++ b/packages/playwright-core/src/server/firefox/ffPage.ts @@ -571,17 +571,14 @@ export class FFPage implements PageDelegate { const parent = frame.parentFrame(); if (!parent) throw new Error('Frame has been detached.'); - const info = this._page.parseSelector('frame,iframe'); - const handles = await this._page.selectors._queryAll(parent, info); - const items = await Promise.all(handles.map(async handle => { - const frame = await handle.contentFrame().catch(e => null); - return { handle, frame }; - })); - const result = items.find(item => item.frame === frame); - items.map(item => item === result ? Promise.resolve() : item.handle.dispose()); - if (!result) + const context = await parent._mainContext(); + const result = await this._session.send('Page.adoptNode', { + frameId: frame._id, + executionContextId: ((context as any)[contextDelegateSymbol] as FFExecutionContext)._executionContextId + }); + if (!result.remoteObject) throw new Error('Frame has been detached.'); - return result.handle; + return context.createHandle(result.remoteObject) as dom.ElementHandle; } } diff --git a/packages/playwright-core/src/server/webkit/wkPage.ts b/packages/playwright-core/src/server/webkit/wkPage.ts index 9af4813b1b..f3939b2993 100644 --- a/packages/playwright-core/src/server/webkit/wkPage.ts +++ b/packages/playwright-core/src/server/webkit/wkPage.ts @@ -988,17 +988,14 @@ export class WKPage implements PageDelegate { const parent = frame.parentFrame(); if (!parent) throw new Error('Frame has been detached.'); - const info = this._page.parseSelector('frame,iframe'); - const handles = await this._page.selectors._queryAll(parent, info); - const items = await Promise.all(handles.map(async handle => { - const frame = await handle.contentFrame().catch(e => null); - return { handle, frame }; - })); - const result = items.find(item => item.frame === frame); - items.map(item => item === result ? Promise.resolve() : item.handle.dispose()); - if (!result) + const context = await parent._mainContext(); + const result = await this._session.send('DOM.resolveNode', { + frameId: frame._id, + executionContextId: ((context as any)[contextDelegateSymbol] as WKExecutionContext)._contextId + }); + if (!result || result.object.subtype === 'null') throw new Error('Frame has been detached.'); - return result.handle; + return context.createHandle(result.object) as dom.ElementHandle; } _onRequestWillBeSent(session: WKSession, event: Protocol.Network.requestWillBeSentPayload) { diff --git a/tests/page/frame-frame-element.spec.ts b/tests/page/frame-frame-element.spec.ts index ba59188c0c..e3b25a8fe1 100644 --- a/tests/page/frame-frame-element.spec.ts +++ b/tests/page/frame-frame-element.spec.ts @@ -55,3 +55,23 @@ it('should throw when detached', async ({ page, server }) => { const error = await frame1.frameElement().catch(e => e); expect(error.message).toContain('Frame has been detached.'); }); + +it('should work inside closed shadow root', async ({ page, server, browserName }) => { + await page.goto(server.EMPTY_PAGE); + await page.setContent(` +
+
+ + `); + + const frame = page.frame({ name: 'myframe' }); + const element = await frame.frameElement(); + expect(await element.getAttribute('name')).toBe('myframe'); +});