Skip to content

Commit 6951e6a

Browse files
authored
chore(bidi): move private handle conversion to execution context (#34765)
1 parent bab197b commit 6951e6a

File tree

2 files changed

+51
-31
lines changed

2 files changed

+51
-31
lines changed

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

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
1818
import * as js from '../javascript';
19+
import * as dom from '../dom';
1920
import { BidiDeserializer } from './third_party/bidiDeserializer';
2021
import * as bidi from './third_party/bidiProtocol';
2122
import { BidiSerializer } from './third_party/bidiSerializer';
@@ -137,7 +138,45 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
137138
});
138139
}
139140

140-
async rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise<bidi.Script.RemoteValue> {
141+
142+
async nodeIdForElementHandle(handle: dom.ElementHandle): Promise<bidi.Script.SharedReference> {
143+
const shared = await this._remoteValueForReference({ handle: handle._objectId });
144+
// TODO: store sharedId in the handle.
145+
if (!('sharedId' in shared))
146+
throw new Error('Element is not a node');
147+
return {
148+
sharedId: shared.sharedId!,
149+
};
150+
}
151+
152+
async remoteObjectForNodeId(nodeId: bidi.Script.SharedReference): Promise<js.RemoteObject> {
153+
const result = await this._remoteValueForReference(nodeId);
154+
if ('handle' in result)
155+
return { objectId: result.handle!, ...result };
156+
throw new Error('Can\'t get remote object for nodeId');
157+
}
158+
159+
async contentFrameIdForFrame(handle: dom.ElementHandle) {
160+
const contentWindow = await this._rawCallFunction('e => e.contentWindow', { handle: handle._objectId });
161+
if (contentWindow?.type === 'window')
162+
return contentWindow.value.context;
163+
return null;
164+
}
165+
166+
async frameIdForWindowHandle(handle: js.JSHandle): Promise<string | null> {
167+
if (!handle._objectId)
168+
throw new Error('JSHandle is not a DOM node handle');
169+
const contentWindow = await this._remoteValueForReference({ handle: handle._objectId });
170+
if (contentWindow.type === 'window')
171+
return contentWindow.value.context;
172+
return null;
173+
}
174+
175+
private async _remoteValueForReference(reference: bidi.Script.RemoteReference) {
176+
return await this._rawCallFunction('e => e', reference);
177+
}
178+
179+
private async _rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise<bidi.Script.RemoteValue> {
141180
const response = await this._session.send('script.callFunction', {
142181
functionDeclaration,
143182
target: this._target,

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

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -413,13 +413,10 @@ export class BidiPage implements PageDelegate {
413413

414414
async getContentFrame(handle: dom.ElementHandle): Promise<frames.Frame | null> {
415415
const executionContext = toBidiExecutionContext(handle._context);
416-
const contentWindow = await executionContext.rawCallFunction('e => e.contentWindow', { handle: handle._objectId });
417-
if (contentWindow.type === 'window') {
418-
const frameId = contentWindow.value.context;
419-
const result = this._page._frameManager.frame(frameId);
420-
return result;
421-
}
422-
return null;
416+
const frameId = await executionContext.contentFrameIdForFrame(handle);
417+
if (!frameId)
418+
return null;
419+
return this._page._frameManager.frame(frameId);
423420
}
424421

425422
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {
@@ -430,15 +427,8 @@ export class BidiPage implements PageDelegate {
430427
});
431428
if (!windowHandle)
432429
return null;
433-
if (!windowHandle._objectId)
434-
return null;
435-
const executionContext = toBidiExecutionContext(windowHandle._context as dom.FrameExecutionContext);
436-
const contentWindow = await executionContext.rawCallFunction('e => e', { handle: windowHandle._objectId });
437-
if (contentWindow.type === 'window') {
438-
const frameId = contentWindow.value.context;
439-
return frameId;
440-
}
441-
return null;
430+
const executionContext = toBidiExecutionContext(handle._context);
431+
return executionContext.frameIdForWindowHandle(windowHandle);
442432
}
443433

444434
isElementHandle(remoteObject: bidi.Script.RemoteValue): boolean {
@@ -535,29 +525,20 @@ export class BidiPage implements PageDelegate {
535525

536526
async setInputFilePaths(handle: dom.ElementHandle<HTMLInputElement>, paths: string[]): Promise<void> {
537527
const fromContext = toBidiExecutionContext(handle._context);
538-
const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId });
539-
// TODO: store sharedId in the handle.
540-
if (!('sharedId' in shared))
541-
throw new Error('Element is not a node');
542-
const sharedId = shared.sharedId!;
543528
await this._session.send('input.setFiles', {
544529
context: this._session.sessionId,
545-
element: { sharedId },
530+
element: await fromContext.nodeIdForElementHandle(handle),
546531
files: paths,
547532
});
548533
}
549534

550535
async adoptElementHandle<T extends Node>(handle: dom.ElementHandle<T>, to: dom.FrameExecutionContext): Promise<dom.ElementHandle<T>> {
551536
const fromContext = toBidiExecutionContext(handle._context);
552-
const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId });
553-
// TODO: store sharedId in the handle.
554-
if (!('sharedId' in shared))
555-
throw new Error('Element is not a node');
556-
const sharedId = shared.sharedId!;
537+
const nodeId = await fromContext.nodeIdForElementHandle(handle);
557538
const executionContext = toBidiExecutionContext(to);
558-
const result = await executionContext.rawCallFunction('x => x', { sharedId });
559-
if ('handle' in result)
560-
return to.createHandle({ objectId: result.handle!, ...result }) as dom.ElementHandle<T>;
539+
const objectId = await executionContext.remoteObjectForNodeId(nodeId);
540+
if (objectId)
541+
return to.createHandle(objectId) as dom.ElementHandle<T>;
561542
throw new Error('Failed to adopt element handle.');
562543
}
563544

0 commit comments

Comments
 (0)