Skip to content

Commit 60e751d

Browse files
committed
chore(bidi): add support for context locators
1 parent e7bff52 commit 60e751d

File tree

4 files changed

+50
-28
lines changed

4 files changed

+50
-28
lines changed

packages/playwright-core/src/server/bidi/bidiBrowser.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,15 @@ export class BidiBrowser extends Browser {
135135
if (!parentFrame)
136136
continue;
137137
page._session.addFrameBrowsingContext(event.context);
138-
page._page.frameManager.frameAttached(event.context, parentFrameId);
139-
const frame = page._page.frameManager.frame(event.context);
140-
if (frame)
141-
frame._url = event.url;
138+
const frame = page._page.frameManager.frameAttached(event.context, parentFrameId);
139+
frame._url = event.url;
140+
page._frameNamePromises.set(
141+
event.context,
142+
page._getFrameNode(frame).then(node => {
143+
const attributes = node?.value?.attributes;
144+
return attributes?.name ?? attributes?.id ?? '';
145+
})
146+
);
142147
return;
143148
}
144149
return;

packages/playwright-core/src/server/bidi/bidiExecutionContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
141141
};
142142
}
143143

144-
async remoteObjectForNodeId(context: dom.FrameExecutionContext, nodeId: bidi.Script.SharedReference): Promise<js.JSHandle> {
144+
async remoteObjectForNodeId(context: dom.FrameExecutionContext, nodeId: bidi.Script.SharedReference): Promise<dom.ElementHandle> {
145145
const result = await this._remoteValueForReference(nodeId, true);
146146
if (!('handle' in result))
147147
throw new Error('Can\'t get remote object for nodeId');
148-
return createHandle(context, result);
148+
return createHandle(context, result) as dom.ElementHandle;
149149
}
150150

151151
async contentFrameIdForFrame(handle: dom.ElementHandle) {

packages/playwright-core/src/server/bidi/bidiPage.ts

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export class BidiPage implements PageDelegate {
5252
readonly _networkManager: BidiNetworkManager;
5353
private readonly _pdf: BidiPDF;
5454
private _initScriptIds = new Map<InitScript, string>();
55+
readonly _frameNamePromises = new Map<string, Promise<string>>();
5556

5657
constructor(browserContext: BidiBrowserContext, bidiSession: BidiSession, opener: BidiPage | null) {
5758
this._session = bidiSession;
@@ -195,16 +196,30 @@ export class BidiPage implements PageDelegate {
195196

196197
private _onNavigationCommitted(params: bidi.BrowsingContext.NavigationInfo) {
197198
const frameId = params.context;
198-
this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, '', params.navigation!, /* initial */ false);
199+
const namePromise = this._frameNamePromises.get(frameId) ?? '';
200+
this._frameNamePromises.delete(frameId);
201+
this._page.frameManager.frameCommittedNewDocumentNavigation(frameId, params.url, namePromise, params.navigation!, /* initial */ false);
199202
}
200203

201-
private _onDomContentLoaded(params: bidi.BrowsingContext.NavigationInfo) {
204+
private async _onDomContentLoaded(params: bidi.BrowsingContext.NavigationInfo) {
202205
const frameId = params.context;
206+
const frame = this._page.frameManager.frame(frameId)!;
207+
await this._waitForChildFrameNames(frame);
203208
this._page.frameManager.frameLifecycleEvent(frameId, 'domcontentloaded');
204209
}
205210

206-
private _onLoad(params: bidi.BrowsingContext.NavigationInfo) {
207-
this._page.frameManager.frameLifecycleEvent(params.context, 'load');
211+
private async _onLoad(params: bidi.BrowsingContext.NavigationInfo) {
212+
const frameId = params.context;
213+
const frame = this._page.frameManager.frame(frameId)!;
214+
await this._waitForChildFrameNames(frame);
215+
this._page.frameManager.frameLifecycleEvent(frameId, 'load');
216+
}
217+
218+
private async _waitForChildFrameNames(frame: frames.Frame) {
219+
for (const childFrame of frame.childFrames()) {
220+
await this._frameNamePromises.get(childFrame._id);
221+
await this._waitForChildFrameNames(childFrame);
222+
}
208223
}
209224

210225
private _onNavigationAborted(params: bidi.BrowsingContext.NavigationInfo) {
@@ -582,24 +597,24 @@ export class BidiPage implements PageDelegate {
582597
const parent = frame.parentFrame();
583598
if (!parent)
584599
throw new Error('Frame has been detached.');
585-
const parentContext = await parent._mainContext();
586-
const list = await parentContext.evaluateHandle(() => { return [...document.querySelectorAll('iframe,frame')]; });
587-
const length = await list.evaluate(list => list.length);
588-
let foundElement = null;
589-
for (let i = 0; i < length; i++) {
590-
const element = await list.evaluateHandle((list, i) => list[i], i);
591-
const candidate = await element.contentFrame();
592-
if (frame === candidate) {
593-
foundElement = element;
594-
break;
595-
} else {
596-
element.dispose();
597-
}
598-
}
599-
list.dispose();
600-
if (!foundElement)
600+
const node = await this._getFrameNode(frame);
601+
if (!node?.sharedId)
601602
throw new Error('Frame has been detached.');
602-
return foundElement;
603+
const parentFrameExecutionContext = await parent._mainContext();
604+
return await toBidiExecutionContext(parentFrameExecutionContext).remoteObjectForNodeId(parentFrameExecutionContext, { sharedId: node.sharedId });
605+
}
606+
607+
async _getFrameNode(frame: frames.Frame): Promise<bidi.Script.NodeRemoteValue | undefined> {
608+
const parent = frame.parentFrame();
609+
if (!parent)
610+
return undefined;
611+
612+
const result = await this._session.send('browsingContext.locateNodes', {
613+
context: parent._id,
614+
locator: { type: 'context', value: { context: frame._id } },
615+
});
616+
const node = result.nodes[0];
617+
return node;
603618
}
604619

605620
shouldToggleStyleSheetToSyncAnimations(): boolean {

packages/playwright-core/src/server/frames.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,13 @@ export class FrameManager {
208208
frame.setPendingDocument({ documentId, request });
209209
}
210210

211-
frameCommittedNewDocumentNavigation(frameId: string, url: string, name: string, documentId: string, initial: boolean) {
211+
async frameCommittedNewDocumentNavigation(frameId: string, url: string, name: string | Promise<string>, documentId: string, initial: boolean) {
212212
const frame = this._frames.get(frameId)!;
213213
this.removeChildFramesRecursively(frame);
214214
this.clearWebSockets(frame);
215215
frame._url = url;
216+
if (typeof name !== 'string')
217+
name = await name;
216218
frame._name = name;
217219

218220
let keepPending: DocumentInfo | undefined;

0 commit comments

Comments
 (0)