chore(bidi): move private handle conversion to execution context (#34765)
This commit is contained in:
parent
bab197b493
commit
6951e6ad9d
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
|
import { parseEvaluationResultValue } from '../isomorphic/utilityScriptSerializers';
|
||||||
import * as js from '../javascript';
|
import * as js from '../javascript';
|
||||||
|
import * as dom from '../dom';
|
||||||
import { BidiDeserializer } from './third_party/bidiDeserializer';
|
import { BidiDeserializer } from './third_party/bidiDeserializer';
|
||||||
import * as bidi from './third_party/bidiProtocol';
|
import * as bidi from './third_party/bidiProtocol';
|
||||||
import { BidiSerializer } from './third_party/bidiSerializer';
|
import { BidiSerializer } from './third_party/bidiSerializer';
|
||||||
|
|
@ -137,7 +138,45 @@ export class BidiExecutionContext implements js.ExecutionContextDelegate {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise<bidi.Script.RemoteValue> {
|
|
||||||
|
async nodeIdForElementHandle(handle: dom.ElementHandle): Promise<bidi.Script.SharedReference> {
|
||||||
|
const shared = await this._remoteValueForReference({ handle: handle._objectId });
|
||||||
|
// TODO: store sharedId in the handle.
|
||||||
|
if (!('sharedId' in shared))
|
||||||
|
throw new Error('Element is not a node');
|
||||||
|
return {
|
||||||
|
sharedId: shared.sharedId!,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async remoteObjectForNodeId(nodeId: bidi.Script.SharedReference): Promise<js.RemoteObject> {
|
||||||
|
const result = await this._remoteValueForReference(nodeId);
|
||||||
|
if ('handle' in result)
|
||||||
|
return { objectId: result.handle!, ...result };
|
||||||
|
throw new Error('Can\'t get remote object for nodeId');
|
||||||
|
}
|
||||||
|
|
||||||
|
async contentFrameIdForFrame(handle: dom.ElementHandle) {
|
||||||
|
const contentWindow = await this._rawCallFunction('e => e.contentWindow', { handle: handle._objectId });
|
||||||
|
if (contentWindow?.type === 'window')
|
||||||
|
return contentWindow.value.context;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async frameIdForWindowHandle(handle: js.JSHandle): Promise<string | null> {
|
||||||
|
if (!handle._objectId)
|
||||||
|
throw new Error('JSHandle is not a DOM node handle');
|
||||||
|
const contentWindow = await this._remoteValueForReference({ handle: handle._objectId });
|
||||||
|
if (contentWindow.type === 'window')
|
||||||
|
return contentWindow.value.context;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _remoteValueForReference(reference: bidi.Script.RemoteReference) {
|
||||||
|
return await this._rawCallFunction('e => e', reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _rawCallFunction(functionDeclaration: string, arg: bidi.Script.LocalValue): Promise<bidi.Script.RemoteValue> {
|
||||||
const response = await this._session.send('script.callFunction', {
|
const response = await this._session.send('script.callFunction', {
|
||||||
functionDeclaration,
|
functionDeclaration,
|
||||||
target: this._target,
|
target: this._target,
|
||||||
|
|
|
||||||
|
|
@ -413,13 +413,10 @@ export class BidiPage implements PageDelegate {
|
||||||
|
|
||||||
async getContentFrame(handle: dom.ElementHandle): Promise<frames.Frame | null> {
|
async getContentFrame(handle: dom.ElementHandle): Promise<frames.Frame | null> {
|
||||||
const executionContext = toBidiExecutionContext(handle._context);
|
const executionContext = toBidiExecutionContext(handle._context);
|
||||||
const contentWindow = await executionContext.rawCallFunction('e => e.contentWindow', { handle: handle._objectId });
|
const frameId = await executionContext.contentFrameIdForFrame(handle);
|
||||||
if (contentWindow.type === 'window') {
|
if (!frameId)
|
||||||
const frameId = contentWindow.value.context;
|
return null;
|
||||||
const result = this._page._frameManager.frame(frameId);
|
return this._page._frameManager.frame(frameId);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {
|
async getOwnerFrame(handle: dom.ElementHandle): Promise<string | null> {
|
||||||
|
|
@ -430,15 +427,8 @@ export class BidiPage implements PageDelegate {
|
||||||
});
|
});
|
||||||
if (!windowHandle)
|
if (!windowHandle)
|
||||||
return null;
|
return null;
|
||||||
if (!windowHandle._objectId)
|
const executionContext = toBidiExecutionContext(handle._context);
|
||||||
return null;
|
return executionContext.frameIdForWindowHandle(windowHandle);
|
||||||
const executionContext = toBidiExecutionContext(windowHandle._context as dom.FrameExecutionContext);
|
|
||||||
const contentWindow = await executionContext.rawCallFunction('e => e', { handle: windowHandle._objectId });
|
|
||||||
if (contentWindow.type === 'window') {
|
|
||||||
const frameId = contentWindow.value.context;
|
|
||||||
return frameId;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementHandle(remoteObject: bidi.Script.RemoteValue): boolean {
|
isElementHandle(remoteObject: bidi.Script.RemoteValue): boolean {
|
||||||
|
|
@ -535,29 +525,20 @@ export class BidiPage implements PageDelegate {
|
||||||
|
|
||||||
async setInputFilePaths(handle: dom.ElementHandle<HTMLInputElement>, paths: string[]): Promise<void> {
|
async setInputFilePaths(handle: dom.ElementHandle<HTMLInputElement>, paths: string[]): Promise<void> {
|
||||||
const fromContext = toBidiExecutionContext(handle._context);
|
const fromContext = toBidiExecutionContext(handle._context);
|
||||||
const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId });
|
|
||||||
// TODO: store sharedId in the handle.
|
|
||||||
if (!('sharedId' in shared))
|
|
||||||
throw new Error('Element is not a node');
|
|
||||||
const sharedId = shared.sharedId!;
|
|
||||||
await this._session.send('input.setFiles', {
|
await this._session.send('input.setFiles', {
|
||||||
context: this._session.sessionId,
|
context: this._session.sessionId,
|
||||||
element: { sharedId },
|
element: await fromContext.nodeIdForElementHandle(handle),
|
||||||
files: paths,
|
files: paths,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async adoptElementHandle<T extends Node>(handle: dom.ElementHandle<T>, to: dom.FrameExecutionContext): Promise<dom.ElementHandle<T>> {
|
async adoptElementHandle<T extends Node>(handle: dom.ElementHandle<T>, to: dom.FrameExecutionContext): Promise<dom.ElementHandle<T>> {
|
||||||
const fromContext = toBidiExecutionContext(handle._context);
|
const fromContext = toBidiExecutionContext(handle._context);
|
||||||
const shared = await fromContext.rawCallFunction('x => x', { handle: handle._objectId });
|
const nodeId = await fromContext.nodeIdForElementHandle(handle);
|
||||||
// TODO: store sharedId in the handle.
|
|
||||||
if (!('sharedId' in shared))
|
|
||||||
throw new Error('Element is not a node');
|
|
||||||
const sharedId = shared.sharedId!;
|
|
||||||
const executionContext = toBidiExecutionContext(to);
|
const executionContext = toBidiExecutionContext(to);
|
||||||
const result = await executionContext.rawCallFunction('x => x', { sharedId });
|
const objectId = await executionContext.remoteObjectForNodeId(nodeId);
|
||||||
if ('handle' in result)
|
if (objectId)
|
||||||
return to.createHandle({ objectId: result.handle!, ...result }) as dom.ElementHandle<T>;
|
return to.createHandle(objectId) as dom.ElementHandle<T>;
|
||||||
throw new Error('Failed to adopt element handle.');
|
throw new Error('Failed to adopt element handle.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue