diff --git a/packages/puppeteer-core/src/bidi/Connection.ts b/packages/puppeteer-core/src/bidi/Connection.ts index 381ec65abae..dd688c309a5 100644 --- a/packages/puppeteer-core/src/bidi/Connection.ts +++ b/packages/puppeteer-core/src/bidi/Connection.ts @@ -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; + }; } /** diff --git a/packages/puppeteer-core/src/bidi/Frame.ts b/packages/puppeteer-core/src/bidi/Frame.ts index 0eb3e34df75..f08972f28d4 100644 --- a/packages/puppeteer-core/src/bidi/Frame.ts +++ b/packages/puppeteer-core/src/bidi/Frame.ts @@ -428,7 +428,7 @@ export class BidiFrame extends Frame { selector: Selector, options?: WaitForSelectorOptions ): Promise> | null> { - if (selector.startsWith('aria')) { + if (selector.startsWith('aria') && !this.page().browser().cdpSupported) { throw new UnsupportedOperation( 'ARIA selector is not supported for BiDi!' ); diff --git a/packages/puppeteer-core/src/bidi/Realm.ts b/packages/puppeteer-core/src/bidi/Realm.ts index dd073163a13..1027941e2fa 100644 --- a/packages/puppeteer-core/src/bidi/Realm.ts +++ b/packages/puppeteer-core/src/bidi/Realm.ts @@ -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> { + let promise = Promise.resolve() as Promise; + 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, + selector: string + ): Promise> => { + 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> { 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; + }); } } diff --git a/packages/puppeteer-core/src/bidi/core/Realm.ts b/packages/puppeteer-core/src/bidi/core/Realm.ts index c0aa37fb85c..392194cec8e 100644 --- a/packages/puppeteer-core/src/bidi/core/Realm.ts +++ b/packages/puppeteer-core/src/bidi/core/Realm.ts @@ -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 => { + // SAFETY: Disposal implies this exists. + return realm.#reason!; + }) + async resolveExecutionContextId(): Promise { + 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.'; diff --git a/test/TestExpectations.json b/test/TestExpectations.json index 33beaadf343..b5d171cd2c5 100644 --- a/test/TestExpectations.json +++ b/test/TestExpectations.json @@ -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"],