chore: move adoption to DOMWorld (#8760)
This commit is contained in:
parent
6934b94f23
commit
932a053d02
@ -95,7 +95,9 @@ const queryOne = async (
|
||||
if (!res[0] || !res[0].backendDOMNodeId) {
|
||||
return null;
|
||||
}
|
||||
return exeCtx._adoptBackendNodeId(res[0].backendDOMNodeId);
|
||||
return (await exeCtx._world!.adoptBackendNode(
|
||||
res[0].backendDOMNodeId
|
||||
)) as ElementHandle<Node>;
|
||||
};
|
||||
|
||||
const waitFor = async (
|
||||
@ -132,11 +134,12 @@ const queryAll = async (
|
||||
const exeCtx = element.executionContext();
|
||||
const {name, role} = parseAriaSelector(selector);
|
||||
const res = await queryAXTree(exeCtx._client, element, name, role);
|
||||
return Promise.all(
|
||||
const world = exeCtx._world!;
|
||||
return (await Promise.all(
|
||||
res.map(axNode => {
|
||||
return exeCtx._adoptBackendNodeId(axNode.backendDOMNodeId);
|
||||
return world.adoptBackendNode(axNode.backendDOMNodeId);
|
||||
})
|
||||
);
|
||||
)) as Array<ElementHandle<Node>>;
|
||||
};
|
||||
|
||||
const queryAllArray = async (
|
||||
|
@ -29,6 +29,7 @@ import {TimeoutSettings} from './TimeoutSettings.js';
|
||||
import {EvaluateFunc, HandleFor, NodeFor} from './types.js';
|
||||
import {
|
||||
createDeferredPromise,
|
||||
createJSHandle,
|
||||
debugError,
|
||||
DeferredPromise,
|
||||
importFS,
|
||||
@ -739,6 +740,29 @@ export class DOMWorld {
|
||||
return document.title;
|
||||
});
|
||||
}
|
||||
|
||||
async adoptBackendNode(
|
||||
backendNodeId?: Protocol.DOM.BackendNodeId
|
||||
): Promise<JSHandle<Node>> {
|
||||
const executionContext = await this.executionContext();
|
||||
const {object} = await this.#client.send('DOM.resolveNode', {
|
||||
backendNodeId: backendNodeId,
|
||||
executionContextId: executionContext._contextId,
|
||||
});
|
||||
return createJSHandle(executionContext, object) as JSHandle<Node>;
|
||||
}
|
||||
|
||||
async adoptHandle<T extends JSHandle<Node>>(handle: T): Promise<T> {
|
||||
const executionContext = await this.executionContext();
|
||||
assert(
|
||||
handle.executionContext() !== executionContext,
|
||||
'Cannot adopt handle that already belongs to this execution context'
|
||||
);
|
||||
const nodeInfo = await this.#client.send('DOM.describeNode', {
|
||||
objectId: handle._remoteObject.objectId,
|
||||
});
|
||||
return (await this.adoptBackendNode(nodeInfo.node.backendNodeId)) as T;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,8 +123,7 @@ export class ElementHandle<
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
const frame = this._context.frame();
|
||||
assert(frame);
|
||||
const secondaryContext = await frame._secondaryWorld.executionContext();
|
||||
const adoptedRoot = await secondaryContext._adoptElementHandle(this);
|
||||
const adoptedRoot = await frame._secondaryWorld.adoptHandle(this);
|
||||
const handle = await frame._secondaryWorld.waitForSelector(selector, {
|
||||
...options,
|
||||
root: adoptedRoot,
|
||||
@ -133,8 +132,9 @@ export class ElementHandle<
|
||||
if (!handle) {
|
||||
return null;
|
||||
}
|
||||
const mainExecutionContext = await frame._mainWorld.executionContext();
|
||||
const result = await mainExecutionContext._adoptElementHandle(handle);
|
||||
const result = (await frame._mainWorld.adoptHandle(
|
||||
handle
|
||||
)) as ElementHandle<NodeFor<Selector>>;
|
||||
await handle.dispose();
|
||||
return result;
|
||||
}
|
||||
|
@ -38,19 +38,16 @@ const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
|
||||
/**
|
||||
* This class represents a context for JavaScript execution. A [Page] might have
|
||||
* many execution contexts:
|
||||
* - each
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe |
|
||||
* frame } has "default" execution context that is always created after frame is
|
||||
* - each {@link
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe | frame}
|
||||
* has "default" execution context that is always created after frame is
|
||||
* attached to DOM. This context is returned by the
|
||||
* {@link Frame.executionContext} method.
|
||||
* - {@link https://developer.chrome.com/extensions | Extension}'s content scripts
|
||||
* create additional execution contexts.
|
||||
* - {@link https://developer.chrome.com/extensions | Extension}'s content
|
||||
* scripts create additional execution contexts.
|
||||
*
|
||||
* Besides pages, execution contexts can be found in
|
||||
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API |
|
||||
* workers }.
|
||||
*
|
||||
* @public
|
||||
* Besides pages, execution contexts can be found in {@link
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | workers}.
|
||||
*/
|
||||
export class ExecutionContext {
|
||||
/**
|
||||
@ -87,9 +84,9 @@ export class ExecutionContext {
|
||||
/**
|
||||
* @remarks
|
||||
*
|
||||
* Not every execution context is associated with a frame. For
|
||||
* example, workers and extensions have execution contexts that are not
|
||||
* associated with frames.
|
||||
* Not every execution context is associated with a frame. For example,
|
||||
* workers and extensions have execution contexts that are not associated with
|
||||
* frames.
|
||||
*
|
||||
* @returns The frame associated with this execution context.
|
||||
*/
|
||||
@ -422,21 +419,4 @@ export class ExecutionContext {
|
||||
});
|
||||
return createJSHandle(this, object) as ElementHandle<Node>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
async _adoptElementHandle<T extends ElementHandle<Node>>(
|
||||
elementHandle: T
|
||||
): Promise<T> {
|
||||
assert(
|
||||
elementHandle.executionContext() !== this,
|
||||
'Cannot adopt handle that already belongs to this execution context'
|
||||
);
|
||||
assert(this._world, 'Cannot adopt handle without DOMWorld');
|
||||
const nodeInfo = await this._client.send('DOM.describeNode', {
|
||||
objectId: elementHandle._remoteObject.objectId,
|
||||
});
|
||||
return (await this._adoptBackendNodeId(nodeInfo.node.backendNodeId)) as T;
|
||||
}
|
||||
}
|
||||
|
@ -1369,10 +1369,11 @@ export class Frame {
|
||||
if (!handle) {
|
||||
return null;
|
||||
}
|
||||
const mainExecutionContext = await this._mainWorld.executionContext();
|
||||
const result = await mainExecutionContext._adoptElementHandle(handle);
|
||||
const mainHandle = (await this._mainWorld.adoptHandle(
|
||||
handle
|
||||
)) as ElementHandle<NodeFor<Selector>>;
|
||||
await handle.dispose();
|
||||
return result;
|
||||
return mainHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -644,15 +644,13 @@ export class Page extends EventEmitter {
|
||||
}
|
||||
const frame = this.#frameManager.frame(event.frameId);
|
||||
assert(frame);
|
||||
const context = await frame.executionContext();
|
||||
const element = await context._adoptBackendNodeId(event.backendNodeId);
|
||||
// This is guaranteed to be an HTMLInputElement handle by the event.
|
||||
const handle = (await frame._mainWorld.adoptBackendNode(
|
||||
event.backendNodeId
|
||||
)) as ElementHandle<HTMLInputElement>;
|
||||
const interceptors = Array.from(this.#fileChooserInterceptors);
|
||||
this.#fileChooserInterceptors.clear();
|
||||
const fileChooser = new FileChooser(
|
||||
// This is guaranteed by the event.
|
||||
element as ElementHandle<HTMLInputElement>,
|
||||
event
|
||||
);
|
||||
const fileChooser = new FileChooser(handle, event);
|
||||
for (const interceptor of interceptors) {
|
||||
interceptor.call(undefined, fileChooser);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user