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