chore: implement ARIA queries in BiDi (#11999)

This commit is contained in:
jrandolf 2024-02-26 14:09:37 +01:00 committed by GitHub
parent 53cf9ce5d7
commit 414f43388b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 75 additions and 73 deletions

View File

@ -36,6 +36,10 @@ export interface Commands extends BidiCommands {
params: Bidi.Cdp.GetSessionParameters;
returnType: Bidi.Cdp.GetSessionResult;
};
'cdp.resolveRealm': {
params: Bidi.Cdp.ResolveRealmParameters;
returnType: Bidi.Cdp.ResolveRealmResult;
};
}
/**

View File

@ -428,7 +428,7 @@ export class BidiFrame extends Frame {
selector: Selector,
options?: WaitForSelectorOptions
): Promise<ElementHandle<NodeFor<Selector>> | null> {
if (selector.startsWith('aria')) {
if (selector.startsWith('aria') && !this.page().browser().cdpSupported) {
throw new UnsupportedOperation(
'ARIA selector is not supported for BiDi!'
);

View File

@ -7,6 +7,7 @@ import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import type {JSHandle} from '../api/JSHandle.js';
import {Realm} from '../api/Realm.js';
import {ARIAQueryHandler} from '../cdp/AriaQueryHandler.js';
import {LazyArg} from '../common/LazyArg.js';
import {scriptInjector} from '../common/ScriptInjector.js';
import type {TimeoutSettings} from '../common/TimeoutSettings.js';
@ -20,6 +21,7 @@ import {
SOURCE_URL_REGEX,
} from '../common/util.js';
import type PuppeteerUtil from '../injected/injected.js';
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
import {stringifyFunction} from '../util/Function.js';
import type {
@ -30,6 +32,7 @@ import type {
import type {WindowRealm} from './core/Realm.js';
import {BidiDeserializer} from './Deserializer.js';
import {BidiElementHandle} from './ElementHandle.js';
import {ExposeableFunction} from './ExposedFunction.js';
import type {BidiFrame} from './Frame.js';
import {BidiJSHandle} from './JSHandle.js';
import {BidiSerializer} from './Serializer.js';
@ -277,12 +280,49 @@ export class BidiFrameRealm extends BidiRealm {
}
#initialize() {
super.initialize();
// This should run first.
this.realm.on('updated', () => {
this.environment.clearDocumentHandle();
this.#bindingsInstalled = false;
});
}
super.initialize();
#bindingsInstalled = false;
override get puppeteerUtil(): Promise<BidiJSHandle<PuppeteerUtil>> {
let promise = Promise.resolve() as Promise<unknown>;
if (!this.#bindingsInstalled) {
promise = Promise.all([
ExposeableFunction.from(
this.environment as BidiFrame,
'__ariaQuerySelector',
ARIAQueryHandler.queryOne,
!!this.sandbox
),
ExposeableFunction.from(
this.environment as BidiFrame,
'__ariaQuerySelectorAll',
async (
element: BidiElementHandle<Node>,
selector: string
): Promise<JSHandle<Node[]>> => {
const results = ARIAQueryHandler.queryAll(element, selector);
return await element.realm.evaluateHandle(
(...elements) => {
return elements;
},
...(await AsyncIterableUtil.collect(results))
);
},
!!this.sandbox
),
]);
this.#bindingsInstalled = true;
}
return promise.then(() => {
return super.puppeteerUtil;
});
}
get sandbox(): string | undefined {
@ -298,14 +338,19 @@ export class BidiFrameRealm extends BidiRealm {
): Promise<JSHandle<Node>> {
const {object} = await this.#frame.client.send('DOM.resolveNode', {
backendNodeId,
executionContextId: await this.realm.resolveExecutionContextId(),
});
return BidiElementHandle.from(
using handle = BidiElementHandle.from(
{
handle: object.objectId,
type: 'node',
},
this
);
// We need the sharedId, so we perform the following to obtain it.
return await handle.evaluateHandle(element => {
return element;
});
}
}

View File

@ -9,6 +9,7 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import {EventEmitter} from '../../common/EventEmitter.js';
import {inertIfDisposed, throwIfDisposed} from '../../util/decorators.js';
import {DisposableStack, disposeSymbol} from '../../util/disposable.js';
import type {BidiConnection} from '../Connection.js';
import type {Browser} from './Browser.js';
import type {BrowsingContext} from './BrowsingContext.js';
@ -121,6 +122,18 @@ export abstract class Realm extends EventEmitter<{
return result;
}
@throwIfDisposed<Realm>(realm => {
// SAFETY: Disposal implies this exists.
return realm.#reason!;
})
async resolveExecutionContextId(): Promise<number> {
const {result} = await (this.session.connection as BidiConnection).send(
'cdp.resolveRealm',
{realm: this.id}
);
return result.executionContextId;
}
[disposeSymbol](): void {
this.#reason ??=
'Realm already destroyed, probably because all associated browsing contexts closed.';

View File

@ -1,8 +1,8 @@
[
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) *",
"testIdPattern": "[ariaqueryhandler.spec] *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
@ -180,37 +180,13 @@
"expectations": ["SKIP"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should have an error message specifically for awaiting an element to be hidden",
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler queryOne (Chromium web test) should find by role \"button\"",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should have correct stack trace for timeout",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should respect timeout",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should throw when frame is detached",
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler queryOne (Chromium web test) should find by role \"heading\"",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
@ -725,25 +701,25 @@
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors with name and role",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"expectations": ["FAIL"]
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors with role",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work for ARIA selectors in multiple isolated worlds",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["webDriverBiDi"],
"parameters": ["firefox"],
"expectations": ["SKIP"]
},
{
@ -844,18 +820,6 @@
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler queryOne (Chromium web test) should find by role \"button\"",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler queryOne (Chromium web test) should find by role \"heading\"",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[bfcache.spec] BFCache can navigate to a BFCached page containing an OOPIF and a worker",
"platforms": ["darwin", "linux", "win32"],
@ -3003,30 +2967,6 @@
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors with name and role",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work ARIA selectors with role",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work for ARIA selectors in multiple isolated worlds",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["cdp", "firefox"],
"expectations": ["SKIP"]
},
{
"testIdPattern": "[queryObjects.spec] page.queryObjects should fail for disposed handles",
"platforms": ["darwin", "linux", "win32"],