mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore: add waitForSelector for BiDi (#10383)
This commit is contained in:
parent
866addd132
commit
d560299aa8
16
package-lock.json
generated
16
package-lock.json
generated
@ -3085,9 +3085,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/chromium-bidi": {
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.11.tgz",
|
||||
"integrity": "sha512-p03ajLhlQ5gebw3cmbDBFmBc2wnJM5dnXS8Phu6mblGn/KQd76yOVL5VwE0VAisa7oazNfKGTaXlIZ8Q5Bb9OA==",
|
||||
"version": "0.4.12",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.12.tgz",
|
||||
"integrity": "sha512-yl0ngMHtYUGJa2G0lkcbPvbnUZ9WMQyMNSfYmlrGD1nHRNyI9KOGw3dOaofFugXHHToneUaSmF9iUdgCBamCjA==",
|
||||
"dependencies": {
|
||||
"mitt": "3.0.0"
|
||||
},
|
||||
@ -10164,7 +10164,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "1.4.1",
|
||||
"chromium-bidi": "0.4.11",
|
||||
"chromium-bidi": "0.4.12",
|
||||
"cross-fetch": "3.1.6",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1135028",
|
||||
@ -12317,9 +12317,9 @@
|
||||
"version": "1.1.4"
|
||||
},
|
||||
"chromium-bidi": {
|
||||
"version": "0.4.11",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.11.tgz",
|
||||
"integrity": "sha512-p03ajLhlQ5gebw3cmbDBFmBc2wnJM5dnXS8Phu6mblGn/KQd76yOVL5VwE0VAisa7oazNfKGTaXlIZ8Q5Bb9OA==",
|
||||
"version": "0.4.12",
|
||||
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.12.tgz",
|
||||
"integrity": "sha512-yl0ngMHtYUGJa2G0lkcbPvbnUZ9WMQyMNSfYmlrGD1nHRNyI9KOGw3dOaofFugXHHToneUaSmF9iUdgCBamCjA==",
|
||||
"requires": {
|
||||
"mitt": "3.0.0"
|
||||
}
|
||||
@ -15738,7 +15738,7 @@
|
||||
"version": "file:packages/puppeteer-core",
|
||||
"requires": {
|
||||
"@puppeteer/browsers": "1.4.1",
|
||||
"chromium-bidi": "0.4.11",
|
||||
"chromium-bidi": "0.4.12",
|
||||
"cross-fetch": "3.1.6",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1135028",
|
||||
|
@ -132,7 +132,7 @@
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"chromium-bidi": "0.4.11",
|
||||
"chromium-bidi": "0.4.12",
|
||||
"cross-fetch": "3.1.6",
|
||||
"debug": "4.3.4",
|
||||
"devtools-protocol": "0.0.1135028",
|
||||
|
@ -16,11 +16,13 @@
|
||||
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
|
||||
import {Frame} from '../api/Frame.js';
|
||||
import {CDPSession} from '../common/Connection.js';
|
||||
import {ExecutionContext} from '../common/ExecutionContext.js';
|
||||
import {getQueryHandlerAndSelector} from '../common/GetQueryHandler.js';
|
||||
import {MouseClickOptions} from '../common/Input.js';
|
||||
import {WaitForSelectorOptions} from '../common/IsolatedWorld.js';
|
||||
import {LazyArg} from '../common/LazyArg.js';
|
||||
import {
|
||||
ElementFor,
|
||||
EvaluateFuncWith,
|
||||
@ -33,7 +35,6 @@ import {isString, withSourcePuppeteerURLIfNone} from '../common/util.js';
|
||||
import {assert} from '../util/assert.js';
|
||||
import {AsyncIterableUtil} from '../util/AsyncIterableUtil.js';
|
||||
|
||||
import {Frame} from './Frame.js';
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {ScreenshotOptions} from './Page.js';
|
||||
|
||||
@ -485,12 +486,30 @@ export class ElementHandle<
|
||||
)) as ElementHandle<NodeFor<Selector>> | null;
|
||||
}
|
||||
|
||||
async #checkVisibility(visibility: boolean): Promise<boolean> {
|
||||
const element = await this.frame.isolatedRealm().adoptHandle(this);
|
||||
try {
|
||||
return await this.frame.isolatedRealm().evaluate(
|
||||
async (PuppeteerUtil, element, visibility) => {
|
||||
return Boolean(PuppeteerUtil.checkVisibility(element, visibility));
|
||||
},
|
||||
LazyArg.create(context => {
|
||||
return context.puppeteerUtil;
|
||||
}),
|
||||
element,
|
||||
visibility
|
||||
);
|
||||
} finally {
|
||||
await element.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an element is visible using the same mechanism as
|
||||
* {@link ElementHandle.waitForSelector}.
|
||||
*/
|
||||
async isVisible(): Promise<boolean> {
|
||||
throw new Error('Not implemented.');
|
||||
return this.#checkVisibility(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -498,7 +517,7 @@ export class ElementHandle<
|
||||
* {@link ElementHandle.waitForSelector}.
|
||||
*/
|
||||
async isHidden(): Promise<boolean> {
|
||||
throw new Error('Not implemented.');
|
||||
return this.#checkVisibility(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -565,14 +584,16 @@ export class ElementHandle<
|
||||
*/
|
||||
async waitForXPath(
|
||||
xpath: string,
|
||||
options?: {
|
||||
options: {
|
||||
visible?: boolean;
|
||||
hidden?: boolean;
|
||||
timeout?: number;
|
||||
} = {}
|
||||
): Promise<ElementHandle<Node> | null> {
|
||||
if (xpath.startsWith('//')) {
|
||||
xpath = `.${xpath}`;
|
||||
}
|
||||
): Promise<ElementHandle<Node> | null>;
|
||||
async waitForXPath(): Promise<ElementHandle<Node> | null> {
|
||||
throw new Error('Not implemented');
|
||||
return this.waitForSelector(`xpath/${xpath}`, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,6 +20,7 @@ import {Page, WaitTimeoutOptions} from '../api/Page.js';
|
||||
import {CDPSession} from '../common/Connection.js';
|
||||
import {DeviceRequestPrompt} from '../common/DeviceRequestPrompt.js';
|
||||
import {ExecutionContext} from '../common/ExecutionContext.js';
|
||||
import {getQueryHandlerAndSelector} from '../common/GetQueryHandler.js';
|
||||
import {
|
||||
IsolatedWorldChart,
|
||||
WaitForSelectorOptions,
|
||||
@ -29,11 +30,52 @@ import {
|
||||
EvaluateFunc,
|
||||
EvaluateFuncWith,
|
||||
HandleFor,
|
||||
InnerLazyParams,
|
||||
NodeFor,
|
||||
} from '../common/types.js';
|
||||
import {TaskManager} from '../common/WaitTask.js';
|
||||
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {Locator} from './Locator.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface Realm {
|
||||
taskManager: TaskManager;
|
||||
waitForFunction<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<InnerLazyParams<Params>> = EvaluateFunc<
|
||||
InnerLazyParams<Params>
|
||||
>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
options: {
|
||||
polling?: 'raf' | 'mutation' | number;
|
||||
timeout?: number;
|
||||
root?: ElementHandle<Node>;
|
||||
signal?: AbortSignal;
|
||||
},
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
adoptHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
|
||||
transferHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
|
||||
evaluateHandle<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -307,6 +349,20 @@ export class Frame {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
mainRealm(): Realm {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
isolatedRealm(): Realm {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves identically to {@link Page.evaluateHandle} except it's run within
|
||||
* the context of this frame.
|
||||
@ -529,12 +585,15 @@ export class Frame {
|
||||
*/
|
||||
async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options?: WaitForSelectorOptions
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null>;
|
||||
async waitForSelector<Selector extends string>(): Promise<ElementHandle<
|
||||
NodeFor<Selector>
|
||||
> | null> {
|
||||
throw new Error('Not implemented');
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
const {updatedSelector, QueryHandler} =
|
||||
getQueryHandlerAndSelector(selector);
|
||||
return (await QueryHandler.waitFor(
|
||||
this,
|
||||
updatedSelector,
|
||||
options
|
||||
)) as ElementHandle<NodeFor<Selector>> | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -561,10 +620,12 @@ export class Frame {
|
||||
*/
|
||||
async waitForXPath(
|
||||
xpath: string,
|
||||
options?: WaitForSelectorOptions
|
||||
): Promise<ElementHandle<Node> | null>;
|
||||
async waitForXPath(): Promise<ElementHandle<Node> | null> {
|
||||
throw new Error('Not implemented');
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<Node> | null> {
|
||||
if (xpath.startsWith('//')) {
|
||||
xpath = `.${xpath}`;
|
||||
}
|
||||
return this.waitForSelector(`xpath/${xpath}`, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -605,16 +666,15 @@ export class Frame {
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
options?: FrameWaitForFunctionOptions,
|
||||
options: FrameWaitForFunctionOptions = {},
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
waitForFunction<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
throw new Error('Not implemented');
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
return this.mainRealm().waitForFunction(
|
||||
pageFunction,
|
||||
options,
|
||||
...args
|
||||
) as Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The full HTML contents of the frame, including the DOCTYPE.
|
||||
*/
|
||||
|
@ -33,9 +33,7 @@ import {ExecutionContext} from './ExecutionContext.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {FrameManager} from './FrameManager.js';
|
||||
import {WaitForSelectorOptions} from './IsolatedWorld.js';
|
||||
import {PUPPETEER_WORLD} from './IsolatedWorlds.js';
|
||||
import {CDPJSHandle} from './JSHandle.js';
|
||||
import {LazyArg} from './LazyArg.js';
|
||||
import {CDPPage} from './Page.js';
|
||||
import {NodeFor} from './types.js';
|
||||
import {KeyInput} from './USKeyboardLayout.js';
|
||||
@ -128,46 +126,6 @@ export class CDPElementHandle<
|
||||
> | null;
|
||||
}
|
||||
|
||||
override async waitForXPath(
|
||||
xpath: string,
|
||||
options: {
|
||||
visible?: boolean;
|
||||
hidden?: boolean;
|
||||
timeout?: number;
|
||||
} = {}
|
||||
): Promise<CDPElementHandle<Node> | null> {
|
||||
if (xpath.startsWith('//')) {
|
||||
xpath = `.${xpath}`;
|
||||
}
|
||||
return this.waitForSelector(`xpath/${xpath}`, options);
|
||||
}
|
||||
|
||||
async #checkVisibility(visibility: boolean): Promise<boolean> {
|
||||
const element = await this.frame.worlds[PUPPETEER_WORLD].adoptHandle(this);
|
||||
try {
|
||||
return await this.frame.worlds[PUPPETEER_WORLD].evaluate(
|
||||
async (PuppeteerUtil, element, visibility) => {
|
||||
return Boolean(PuppeteerUtil.checkVisibility(element, visibility));
|
||||
},
|
||||
LazyArg.create(context => {
|
||||
return context.puppeteerUtil;
|
||||
}),
|
||||
element,
|
||||
visibility
|
||||
);
|
||||
} finally {
|
||||
await element.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
override async isVisible(): Promise<boolean> {
|
||||
return this.#checkVisibility(true);
|
||||
}
|
||||
|
||||
override async isHidden(): Promise<boolean> {
|
||||
return this.#checkVisibility(false);
|
||||
}
|
||||
|
||||
override async contentFrame(): Promise<Frame | null> {
|
||||
const nodeInfo = await this.client.send('DOM.describeNode', {
|
||||
objectId: this.id,
|
||||
|
@ -21,7 +21,6 @@ import {
|
||||
Frame as BaseFrame,
|
||||
FrameAddScriptTagOptions,
|
||||
FrameAddStyleTagOptions,
|
||||
FrameWaitForFunctionOptions,
|
||||
} from '../api/Frame.js';
|
||||
import {HTTPResponse} from '../api/HTTPResponse.js';
|
||||
import {Page, WaitTimeoutOptions} from '../api/Page.js';
|
||||
@ -36,12 +35,7 @@ import {
|
||||
} from './DeviceRequestPrompt.js';
|
||||
import {ExecutionContext} from './ExecutionContext.js';
|
||||
import {FrameManager} from './FrameManager.js';
|
||||
import {getQueryHandlerAndSelector} from './GetQueryHandler.js';
|
||||
import {
|
||||
IsolatedWorld,
|
||||
IsolatedWorldChart,
|
||||
WaitForSelectorOptions,
|
||||
} from './IsolatedWorld.js';
|
||||
import {IsolatedWorld, IsolatedWorldChart} from './IsolatedWorld.js';
|
||||
import {MAIN_WORLD, PUPPETEER_WORLD} from './IsolatedWorlds.js';
|
||||
import {LazyArg} from './LazyArg.js';
|
||||
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
|
||||
@ -221,6 +215,20 @@ export class Frame extends BaseFrame {
|
||||
return this.worlds[MAIN_WORLD].executionContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override mainRealm(): IsolatedWorld {
|
||||
return this.worlds[MAIN_WORLD];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
override isolatedRealm(): IsolatedWorld {
|
||||
return this.worlds[PUPPETEER_WORLD];
|
||||
}
|
||||
|
||||
override async evaluateHandle<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
@ -232,7 +240,7 @@ export class Frame extends BaseFrame {
|
||||
this.evaluateHandle.name,
|
||||
pageFunction
|
||||
);
|
||||
return this.worlds[MAIN_WORLD].evaluateHandle(pageFunction, ...args);
|
||||
return this.mainRealm().evaluateHandle(pageFunction, ...args);
|
||||
}
|
||||
|
||||
override async evaluate<
|
||||
@ -246,19 +254,19 @@ export class Frame extends BaseFrame {
|
||||
this.evaluate.name,
|
||||
pageFunction
|
||||
);
|
||||
return this.worlds[MAIN_WORLD].evaluate(pageFunction, ...args);
|
||||
return this.mainRealm().evaluate(pageFunction, ...args);
|
||||
}
|
||||
|
||||
override async $<Selector extends string>(
|
||||
selector: Selector
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
return this.worlds[MAIN_WORLD].$(selector);
|
||||
return this.mainRealm().$(selector);
|
||||
}
|
||||
|
||||
override async $$<Selector extends string>(
|
||||
selector: Selector
|
||||
): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
|
||||
return this.worlds[MAIN_WORLD].$$(selector);
|
||||
return this.mainRealm().$$(selector);
|
||||
}
|
||||
|
||||
override async $eval<
|
||||
@ -274,7 +282,7 @@ export class Frame extends BaseFrame {
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
pageFunction = withSourcePuppeteerURLIfNone(this.$eval.name, pageFunction);
|
||||
return this.worlds[MAIN_WORLD].$eval(selector, pageFunction, ...args);
|
||||
return this.mainRealm().$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
|
||||
override async $$eval<
|
||||
@ -290,53 +298,15 @@ export class Frame extends BaseFrame {
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
pageFunction = withSourcePuppeteerURLIfNone(this.$$eval.name, pageFunction);
|
||||
return this.worlds[MAIN_WORLD].$$eval(selector, pageFunction, ...args);
|
||||
return this.mainRealm().$$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
|
||||
override async $x(expression: string): Promise<Array<ElementHandle<Node>>> {
|
||||
return this.worlds[MAIN_WORLD].$x(expression);
|
||||
}
|
||||
|
||||
override async waitForSelector<Selector extends string>(
|
||||
selector: Selector,
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<NodeFor<Selector>> | null> {
|
||||
const {updatedSelector, QueryHandler} =
|
||||
getQueryHandlerAndSelector(selector);
|
||||
return (await QueryHandler.waitFor(
|
||||
this,
|
||||
updatedSelector,
|
||||
options
|
||||
)) as ElementHandle<NodeFor<Selector>> | null;
|
||||
}
|
||||
|
||||
override async waitForXPath(
|
||||
xpath: string,
|
||||
options: WaitForSelectorOptions = {}
|
||||
): Promise<ElementHandle<Node> | null> {
|
||||
if (xpath.startsWith('//')) {
|
||||
xpath = `.${xpath}`;
|
||||
}
|
||||
return this.waitForSelector(`xpath/${xpath}`, options);
|
||||
}
|
||||
|
||||
override waitForFunction<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
options: FrameWaitForFunctionOptions = {},
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
return this.worlds[MAIN_WORLD].waitForFunction(
|
||||
pageFunction,
|
||||
options,
|
||||
...args
|
||||
) as Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
return this.mainRealm().$x(expression);
|
||||
}
|
||||
|
||||
override async content(): Promise<string> {
|
||||
return this.worlds[PUPPETEER_WORLD].content();
|
||||
return this.isolatedRealm().content();
|
||||
}
|
||||
|
||||
override async setContent(
|
||||
@ -346,7 +316,7 @@ export class Frame extends BaseFrame {
|
||||
waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
|
||||
} = {}
|
||||
): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].setContent(html, options);
|
||||
return this.isolatedRealm().setContent(html, options);
|
||||
}
|
||||
|
||||
override name(): string {
|
||||
@ -388,8 +358,8 @@ export class Frame extends BaseFrame {
|
||||
|
||||
type = type ?? 'text/javascript';
|
||||
|
||||
return this.worlds[MAIN_WORLD].transferHandle(
|
||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||
return this.mainRealm().transferHandle(
|
||||
await this.isolatedRealm().evaluateHandle(
|
||||
async ({Deferred}, {url, id, type, content}) => {
|
||||
const deferred = Deferred.create<void>();
|
||||
const script = document.createElement('script');
|
||||
@ -456,8 +426,8 @@ export class Frame extends BaseFrame {
|
||||
options.content = content;
|
||||
}
|
||||
|
||||
return this.worlds[MAIN_WORLD].transferHandle(
|
||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||
return this.mainRealm().transferHandle(
|
||||
await this.isolatedRealm().evaluateHandle(
|
||||
async ({Deferred}, {url, content}) => {
|
||||
const deferred = Deferred.create<void>();
|
||||
let element: HTMLStyleElement | HTMLLinkElement;
|
||||
@ -504,23 +474,23 @@ export class Frame extends BaseFrame {
|
||||
selector: string,
|
||||
options: Readonly<ClickOptions> = {}
|
||||
): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].click(selector, options);
|
||||
return this.isolatedRealm().click(selector, options);
|
||||
}
|
||||
|
||||
override async focus(selector: string): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].focus(selector);
|
||||
return this.isolatedRealm().focus(selector);
|
||||
}
|
||||
|
||||
override async hover(selector: string): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].hover(selector);
|
||||
return this.isolatedRealm().hover(selector);
|
||||
}
|
||||
|
||||
override select(selector: string, ...values: string[]): Promise<string[]> {
|
||||
return this.worlds[PUPPETEER_WORLD].select(selector, ...values);
|
||||
return this.isolatedRealm().select(selector, ...values);
|
||||
}
|
||||
|
||||
override async tap(selector: string): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].tap(selector);
|
||||
return this.isolatedRealm().tap(selector);
|
||||
}
|
||||
|
||||
override async type(
|
||||
@ -528,11 +498,11 @@ export class Frame extends BaseFrame {
|
||||
text: string,
|
||||
options?: {delay: number}
|
||||
): Promise<void> {
|
||||
return this.worlds[PUPPETEER_WORLD].type(selector, text, options);
|
||||
return this.isolatedRealm().type(selector, text, options);
|
||||
}
|
||||
|
||||
override async title(): Promise<string> {
|
||||
return this.worlds[PUPPETEER_WORLD].title();
|
||||
return this.isolatedRealm().title();
|
||||
}
|
||||
|
||||
_deviceRequestPromptManager(): DeviceRequestPromptManager {
|
||||
|
@ -34,7 +34,10 @@ import {Target} from './Target.js';
|
||||
import {TimeoutSettings} from './TimeoutSettings.js';
|
||||
import {debugError, PuppeteerURL} from './util.js';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
|
||||
|
||||
/**
|
||||
* We use symbols to prevent external parties listening to these events.
|
||||
|
@ -17,6 +17,7 @@
|
||||
import {Protocol} from 'devtools-protocol';
|
||||
|
||||
import type {ClickOptions, ElementHandle} from '../api/ElementHandle.js';
|
||||
import {Realm} from '../api/Frame.js';
|
||||
import {JSHandle} from '../api/JSHandle.js';
|
||||
import {assert} from '../util/assert.js';
|
||||
import {Deferred} from '../util/Deferred.js';
|
||||
@ -99,7 +100,7 @@ export interface IsolatedWorldChart {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class IsolatedWorld {
|
||||
export class IsolatedWorld implements Realm {
|
||||
#frame: Frame;
|
||||
#document?: ElementHandle<Document>;
|
||||
#context = Deferred.create<ExecutionContext>();
|
||||
|
@ -22,7 +22,6 @@ import {interpolateFunction, stringifyFunction} from '../util/Function.js';
|
||||
|
||||
import {transposeIterableHandle} from './HandleIterator.js';
|
||||
import type {WaitForSelectorOptions} from './IsolatedWorld.js';
|
||||
import {MAIN_WORLD, PUPPETEER_WORLD} from './IsolatedWorlds.js';
|
||||
import {LazyArg} from './LazyArg.js';
|
||||
import type {Awaitable, AwaitableIterable} from './types.js';
|
||||
|
||||
@ -160,7 +159,7 @@ export class QueryHandler {
|
||||
frame = elementOrFrame;
|
||||
} else {
|
||||
frame = elementOrFrame.frame;
|
||||
element = await frame.worlds[PUPPETEER_WORLD].adoptHandle(elementOrFrame);
|
||||
element = await frame.isolatedRealm().adoptHandle(elementOrFrame);
|
||||
}
|
||||
|
||||
const {visible = false, hidden = false, timeout, signal} = options;
|
||||
@ -168,7 +167,7 @@ export class QueryHandler {
|
||||
try {
|
||||
signal?.throwIfAborted();
|
||||
|
||||
const handle = await frame.worlds[PUPPETEER_WORLD].waitForFunction(
|
||||
const handle = await frame.isolatedRealm().waitForFunction(
|
||||
async (PuppeteerUtil, query, selector, root, visible) => {
|
||||
const querySelector = PuppeteerUtil.createFunction(
|
||||
query
|
||||
@ -204,7 +203,7 @@ export class QueryHandler {
|
||||
await handle.dispose();
|
||||
return null;
|
||||
}
|
||||
return frame.worlds[MAIN_WORLD].transferHandle(handle);
|
||||
return frame.mainRealm().transferHandle(handle);
|
||||
} catch (error) {
|
||||
if (!isErrorLike(error)) {
|
||||
throw error;
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
import {ElementHandle} from '../api/ElementHandle.js';
|
||||
import {Realm} from '../api/Frame.js';
|
||||
import {JSHandle} from '../api/JSHandle.js';
|
||||
import type {Poller} from '../injected/Poller.js';
|
||||
import {Deferred} from '../util/Deferred.js';
|
||||
@ -22,7 +23,6 @@ import {isErrorLike} from '../util/ErrorLike.js';
|
||||
import {stringifyFunction} from '../util/Function.js';
|
||||
|
||||
import {TimeoutError} from './Errors.js';
|
||||
import {IsolatedWorld} from './IsolatedWorld.js';
|
||||
import {LazyArg} from './LazyArg.js';
|
||||
import {HandleFor} from './types.js';
|
||||
|
||||
@ -40,7 +40,7 @@ export interface WaitTaskOptions {
|
||||
* @internal
|
||||
*/
|
||||
export class WaitTask<T = unknown> {
|
||||
#world: IsolatedWorld;
|
||||
#world: Realm;
|
||||
#polling: 'raf' | 'mutation' | number;
|
||||
#root?: ElementHandle<Node>;
|
||||
|
||||
@ -55,7 +55,7 @@ export class WaitTask<T = unknown> {
|
||||
#signal?: AbortSignal;
|
||||
|
||||
constructor(
|
||||
world: IsolatedWorld,
|
||||
world: Realm,
|
||||
options: WaitTaskOptions,
|
||||
fn: ((...args: unknown[]) => Promise<T>) | string,
|
||||
...args: unknown[]
|
||||
|
@ -2,37 +2,17 @@ import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
import ProtocolMapping from 'devtools-protocol/types/protocol-mapping.js';
|
||||
|
||||
import {WaitForOptions} from '../../api/Page.js';
|
||||
import PuppeteerUtil from '../../injected/injected.js';
|
||||
import {assert} from '../../util/assert.js';
|
||||
import {Deferred} from '../../util/Deferred.js';
|
||||
import {stringifyFunction} from '../../util/Function.js';
|
||||
import type {CDPSession, Connection as CDPConnection} from '../Connection.js';
|
||||
import {ProtocolError, TimeoutError} from '../Errors.js';
|
||||
import {EventEmitter} from '../EventEmitter.js';
|
||||
import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js';
|
||||
import {scriptInjector} from '../ScriptInjector.js';
|
||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||
import {EvaluateFunc, HandleFor} from '../types.js';
|
||||
import {
|
||||
PuppeteerURL,
|
||||
getPageContent,
|
||||
getSourcePuppeteerURLIfAvailable,
|
||||
isString,
|
||||
setPageContent,
|
||||
waitWithTimeout,
|
||||
} from '../util.js';
|
||||
import {getPageContent, setPageContent, waitWithTimeout} from '../util.js';
|
||||
|
||||
import {Connection} from './Connection.js';
|
||||
import {ElementHandle} from './ElementHandle.js';
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
import {createEvaluationError} from './utils.js';
|
||||
|
||||
const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
|
||||
|
||||
const getSourceUrlComment = (url: string) => {
|
||||
return `//# sourceURL=${url}`;
|
||||
};
|
||||
import {Realm} from './Realm.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -104,8 +84,7 @@ export class CDPSessionWrapper extends EventEmitter implements CDPSession {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class BrowsingContext extends EventEmitter {
|
||||
connection: Connection;
|
||||
export class BrowsingContext extends Realm {
|
||||
#timeoutSettings: TimeoutSettings;
|
||||
#id: string;
|
||||
#url = 'about:blank';
|
||||
@ -116,27 +95,15 @@ export class BrowsingContext extends EventEmitter {
|
||||
timeoutSettings: TimeoutSettings,
|
||||
info: Bidi.BrowsingContext.Info
|
||||
) {
|
||||
super();
|
||||
super(connection, info.context);
|
||||
this.connection = connection;
|
||||
this.#timeoutSettings = timeoutSettings;
|
||||
this.#id = info.context;
|
||||
this.#cdpSession = new CDPSessionWrapper(this);
|
||||
}
|
||||
|
||||
#puppeteerUtil?: Promise<JSHandle<PuppeteerUtil>>;
|
||||
get puppeteerUtil(): Promise<JSHandle<PuppeteerUtil>> {
|
||||
const promise = Promise.resolve() as Promise<unknown>;
|
||||
scriptInjector.inject(script => {
|
||||
if (this.#puppeteerUtil) {
|
||||
void this.#puppeteerUtil.then(handle => {
|
||||
void handle.dispose();
|
||||
});
|
||||
}
|
||||
this.#puppeteerUtil = promise.then(() => {
|
||||
return this.evaluateHandle(script) as Promise<JSHandle<PuppeteerUtil>>;
|
||||
});
|
||||
}, !this.#puppeteerUtil);
|
||||
return this.#puppeteerUtil as Promise<JSHandle<PuppeteerUtil>>;
|
||||
createSandboxRealm(sandbox: string): Realm {
|
||||
return new Realm(this.connection, this.#id, sandbox);
|
||||
}
|
||||
|
||||
get url(): string {
|
||||
@ -212,97 +179,6 @@ export class BrowsingContext extends EventEmitter {
|
||||
);
|
||||
}
|
||||
|
||||
async evaluateHandle<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
return this.#evaluate(false, pageFunction, ...args);
|
||||
}
|
||||
|
||||
async evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
return this.#evaluate(true, pageFunction, ...args);
|
||||
}
|
||||
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: true,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>>;
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: false,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: boolean,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>> | Awaited<ReturnType<Func>>> {
|
||||
const sourceUrlComment = getSourceUrlComment(
|
||||
getSourcePuppeteerURLIfAvailable(pageFunction)?.toString() ??
|
||||
PuppeteerURL.INTERNAL_URL
|
||||
);
|
||||
|
||||
let responsePromise;
|
||||
const resultOwnership = returnByValue ? 'none' : 'root';
|
||||
if (isString(pageFunction)) {
|
||||
const expression = SOURCE_URL_REGEX.test(pageFunction)
|
||||
? pageFunction
|
||||
: `${pageFunction}\n${sourceUrlComment}\n`;
|
||||
|
||||
responsePromise = this.connection.send('script.evaluate', {
|
||||
expression,
|
||||
target: {context: this.#id},
|
||||
resultOwnership,
|
||||
awaitPromise: true,
|
||||
});
|
||||
} else {
|
||||
let functionDeclaration = stringifyFunction(pageFunction);
|
||||
functionDeclaration = SOURCE_URL_REGEX.test(functionDeclaration)
|
||||
? functionDeclaration
|
||||
: `${functionDeclaration}\n${sourceUrlComment}\n`;
|
||||
responsePromise = this.connection.send('script.callFunction', {
|
||||
functionDeclaration,
|
||||
arguments: await Promise.all(
|
||||
args.map(arg => {
|
||||
return BidiSerializer.serialize(arg, this);
|
||||
})
|
||||
),
|
||||
target: {context: this.#id},
|
||||
resultOwnership,
|
||||
awaitPromise: true,
|
||||
});
|
||||
}
|
||||
|
||||
const {result} = await responsePromise;
|
||||
|
||||
if ('type' in result && result.type === 'exception') {
|
||||
throw createEvaluationError(result.exceptionDetails);
|
||||
}
|
||||
|
||||
return returnByValue
|
||||
? BidiSerializer.deserialize(result.result)
|
||||
: getBidiHandle(this, result.result);
|
||||
}
|
||||
|
||||
async setContent(
|
||||
html: string,
|
||||
options: {
|
||||
@ -344,29 +220,16 @@ export class BrowsingContext extends EventEmitter {
|
||||
return this.#cdpSession.send(method, ...paramArgs);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.removeAllListeners();
|
||||
this.connection.unregisterBrowsingContexts(this.#id);
|
||||
}
|
||||
|
||||
title(): Promise<string> {
|
||||
return this.evaluate(() => {
|
||||
return document.title;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function getBidiHandle(
|
||||
context: BrowsingContext,
|
||||
result: Bidi.CommonDataTypes.RemoteValue
|
||||
): JSHandle | ElementHandle<Node> {
|
||||
if (result.type === 'node' || result.type === 'window') {
|
||||
return new ElementHandle(context, result);
|
||||
dispose(): void {
|
||||
this.removeAllListeners();
|
||||
this.connection.unregisterBrowsingContexts(this.#id);
|
||||
}
|
||||
return new JSHandle(context, result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,6 +65,10 @@ interface Commands {
|
||||
params: Bidi.Script.DisownParameters;
|
||||
returnType: Bidi.Script.DisownResult;
|
||||
};
|
||||
'script.addPreloadScript': {
|
||||
params: Bidi.Script.AddPreloadScriptParameters;
|
||||
returnType: Bidi.Script.AddPreloadScriptResult;
|
||||
};
|
||||
|
||||
'browsingContext.create': {
|
||||
params: Bidi.BrowsingContext.CreateParameters;
|
||||
@ -116,11 +120,11 @@ interface Commands {
|
||||
};
|
||||
'session.subscribe': {
|
||||
params: Bidi.Session.SubscriptionRequest;
|
||||
returnType: Bidi.Session.SubscribeResult;
|
||||
returnType: Bidi.Message.EmptyResult;
|
||||
};
|
||||
'session.unsubscribe': {
|
||||
params: Bidi.Session.SubscriptionRequest;
|
||||
returnType: Bidi.Session.UnsubscribeResult;
|
||||
returnType: Bidi.Message.EmptyResult;
|
||||
};
|
||||
'cdp.sendCommand': {
|
||||
params: Bidi.CDP.SendCommandParams;
|
||||
|
@ -18,8 +18,9 @@ import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
|
||||
import {ElementHandle as BaseElementHandle} from '../../api/ElementHandle.js';
|
||||
|
||||
import {BrowsingContext} from './BrowsingContext.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {Realm} from './Realm.js';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -28,15 +29,22 @@ export class ElementHandle<
|
||||
ElementType extends Node = Element
|
||||
> extends BaseElementHandle<ElementType> {
|
||||
declare handle: JSHandle<ElementType>;
|
||||
#frame: Frame;
|
||||
|
||||
constructor(
|
||||
context: BrowsingContext,
|
||||
remoteValue: Bidi.CommonDataTypes.RemoteValue
|
||||
realm: Realm,
|
||||
remoteValue: Bidi.CommonDataTypes.RemoteValue,
|
||||
frame: Frame
|
||||
) {
|
||||
super(new JSHandle(context, remoteValue));
|
||||
super(new JSHandle(realm, remoteValue));
|
||||
this.#frame = frame;
|
||||
}
|
||||
|
||||
context(): BrowsingContext {
|
||||
override get frame(): Frame {
|
||||
return this.#frame;
|
||||
}
|
||||
|
||||
context(): Realm {
|
||||
return this.handle.context();
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
import {ElementHandle} from '../../api/ElementHandle.js';
|
||||
import {Frame as BaseFrame} from '../../api/Frame.js';
|
||||
import {UTILITY_WORLD_NAME} from '../FrameManager.js';
|
||||
import {PuppeteerLifeCycleEvent} from '../LifecycleWatcher.js';
|
||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||
import {EvaluateFunc, EvaluateFuncWith, HandleFor, NodeFor} from '../types.js';
|
||||
import {withSourcePuppeteerURLIfNone} from '../util.js';
|
||||
|
||||
@ -40,7 +42,12 @@ export class Frame extends BaseFrame {
|
||||
sandboxes: SandboxChart;
|
||||
override _id: string;
|
||||
|
||||
constructor(page: Page, context: BrowsingContext, parentId?: string | null) {
|
||||
constructor(
|
||||
page: Page,
|
||||
context: BrowsingContext,
|
||||
timeoutSettings: TimeoutSettings,
|
||||
parentId?: string | null
|
||||
) {
|
||||
super();
|
||||
this.#page = page;
|
||||
this.#context = context;
|
||||
@ -48,11 +55,22 @@ export class Frame extends BaseFrame {
|
||||
this._parentId = parentId ?? undefined;
|
||||
|
||||
this.sandboxes = {
|
||||
[MAIN_SANDBOX]: new Sandbox(context),
|
||||
[PUPPETEER_SANDBOX]: new Sandbox(context),
|
||||
[MAIN_SANDBOX]: new Sandbox(context, timeoutSettings),
|
||||
[PUPPETEER_SANDBOX]: new Sandbox(
|
||||
context.createSandboxRealm(UTILITY_WORLD_NAME),
|
||||
timeoutSettings
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
override mainRealm(): Sandbox {
|
||||
return this.sandboxes[MAIN_SANDBOX];
|
||||
}
|
||||
|
||||
override isolatedRealm(): Sandbox {
|
||||
return this.sandboxes[PUPPETEER_SANDBOX];
|
||||
}
|
||||
|
||||
override page(): Page {
|
||||
return this.#page;
|
||||
}
|
||||
|
@ -21,26 +21,23 @@ import {JSHandle as BaseJSHandle} from '../../api/JSHandle.js';
|
||||
import {EvaluateFuncWith, HandleFor, HandleOr} from '../../common/types.js';
|
||||
import {withSourcePuppeteerURLIfNone} from '../util.js';
|
||||
|
||||
import {BrowsingContext} from './BrowsingContext.js';
|
||||
import {Realm} from './Realm.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
import {releaseReference} from './utils.js';
|
||||
|
||||
export class JSHandle<T = unknown> extends BaseJSHandle<T> {
|
||||
#disposed = false;
|
||||
#context;
|
||||
#realm: Realm;
|
||||
#remoteValue;
|
||||
|
||||
constructor(
|
||||
context: BrowsingContext,
|
||||
remoteValue: Bidi.CommonDataTypes.RemoteValue
|
||||
) {
|
||||
constructor(realm: Realm, remoteValue: Bidi.CommonDataTypes.RemoteValue) {
|
||||
super();
|
||||
this.#context = context;
|
||||
this.#realm = realm;
|
||||
this.#remoteValue = remoteValue;
|
||||
}
|
||||
|
||||
context(): BrowsingContext {
|
||||
return this.#context;
|
||||
context(): Realm {
|
||||
return this.#realm;
|
||||
}
|
||||
|
||||
override get disposed(): boolean {
|
||||
@ -136,7 +133,7 @@ export class JSHandle<T = unknown> extends BaseJSHandle<T> {
|
||||
}
|
||||
this.#disposed = true;
|
||||
if ('handle' in this.#remoteValue) {
|
||||
await releaseReference(this.#context, this.#remoteValue);
|
||||
await releaseReference(this.#realm, this.#remoteValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,12 +53,13 @@ import {
|
||||
|
||||
import {Browser} from './Browser.js';
|
||||
import {BrowserContext} from './BrowserContext.js';
|
||||
import {BrowsingContext, getBidiHandle} from './BrowsingContext.js';
|
||||
import {BrowsingContext} from './BrowsingContext.js';
|
||||
import {Connection} from './Connection.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {HTTPRequest} from './HTTPRequest.js';
|
||||
import {HTTPResponse} from './HTTPResponse.js';
|
||||
import {NetworkManager} from './NetworkManager.js';
|
||||
import {getBidiHandle} from './Realm.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
/**
|
||||
@ -208,7 +209,13 @@ export class Page extends PageBase {
|
||||
);
|
||||
this.#connection.registerBrowsingContexts(context);
|
||||
|
||||
const frame = new Frame(this, context, info.parent);
|
||||
const frame = new Frame(
|
||||
this,
|
||||
context,
|
||||
this.#timeoutSettings,
|
||||
info.parent
|
||||
);
|
||||
context.setFrame(frame);
|
||||
|
||||
this.#frameTree.addFrame(frame);
|
||||
this.emit(FrameManagerEmittedEvents.FrameAttached, frame);
|
||||
@ -250,12 +257,13 @@ export class Page extends PageBase {
|
||||
}
|
||||
|
||||
#onLogEntryAdded(event: Bidi.Log.LogEntry): void {
|
||||
if (!this.frame(event.source.context)) {
|
||||
const frame = this.frame(event.source.context);
|
||||
if (!frame) {
|
||||
return;
|
||||
}
|
||||
if (isConsoleLogEntry(event)) {
|
||||
const args = event.args.map(arg => {
|
||||
return getBidiHandle(this.mainFrame().context(), arg);
|
||||
return getBidiHandle(frame.context(), arg, frame);
|
||||
});
|
||||
|
||||
const text = args
|
||||
|
171
packages/puppeteer-core/src/common/bidi/Realm.ts
Normal file
171
packages/puppeteer-core/src/common/bidi/Realm.ts
Normal file
@ -0,0 +1,171 @@
|
||||
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
|
||||
import PuppeteerUtil from '../../injected/injected.js';
|
||||
import {stringifyFunction} from '../../util/Function.js';
|
||||
import {EventEmitter} from '../EventEmitter.js';
|
||||
import {scriptInjector} from '../ScriptInjector.js';
|
||||
import {EvaluateFunc, HandleFor} from '../types.js';
|
||||
import {
|
||||
PuppeteerURL,
|
||||
getSourcePuppeteerURLIfAvailable,
|
||||
isString,
|
||||
} from '../util.js';
|
||||
|
||||
import {Connection} from './Connection.js';
|
||||
import {ElementHandle} from './ElementHandle.js';
|
||||
import {Frame} from './Frame.js';
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
import {createEvaluationError} from './utils.js';
|
||||
|
||||
export const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
|
||||
|
||||
export const getSourceUrlComment = (url: string): string => {
|
||||
return `//# sourceURL=${url}`;
|
||||
};
|
||||
|
||||
export class Realm extends EventEmitter {
|
||||
connection: Connection;
|
||||
#frame!: Frame;
|
||||
#id: string;
|
||||
#sandbox?: string;
|
||||
|
||||
constructor(connection: Connection, id: string, sandbox?: string) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
this.#id = id;
|
||||
this.#sandbox = sandbox;
|
||||
}
|
||||
|
||||
get target(): Bidi.Script.Target {
|
||||
return {
|
||||
context: this.#id,
|
||||
sandbox: this.#sandbox,
|
||||
};
|
||||
}
|
||||
|
||||
setFrame(frame: Frame): void {
|
||||
this.#frame = frame;
|
||||
}
|
||||
|
||||
protected internalPuppeteerUtil?: Promise<JSHandle<PuppeteerUtil>>;
|
||||
get puppeteerUtil(): Promise<JSHandle<PuppeteerUtil>> {
|
||||
const promise = Promise.resolve() as Promise<unknown>;
|
||||
scriptInjector.inject(script => {
|
||||
if (this.internalPuppeteerUtil) {
|
||||
void this.internalPuppeteerUtil.then(handle => {
|
||||
void handle.dispose();
|
||||
});
|
||||
}
|
||||
this.internalPuppeteerUtil = promise.then(() => {
|
||||
return this.evaluateHandle(script) as Promise<JSHandle<PuppeteerUtil>>;
|
||||
});
|
||||
}, !this.internalPuppeteerUtil);
|
||||
return this.internalPuppeteerUtil as Promise<JSHandle<PuppeteerUtil>>;
|
||||
}
|
||||
|
||||
async evaluateHandle<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
return this.#evaluate(false, pageFunction, ...args);
|
||||
}
|
||||
|
||||
async evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
return this.#evaluate(true, pageFunction, ...args);
|
||||
}
|
||||
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: true,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>>;
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: false,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
|
||||
async #evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
returnByValue: boolean,
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>> | Awaited<ReturnType<Func>>> {
|
||||
const sourceUrlComment = getSourceUrlComment(
|
||||
getSourcePuppeteerURLIfAvailable(pageFunction)?.toString() ??
|
||||
PuppeteerURL.INTERNAL_URL
|
||||
);
|
||||
|
||||
let responsePromise;
|
||||
const resultOwnership = returnByValue ? 'none' : 'root';
|
||||
if (isString(pageFunction)) {
|
||||
const expression = SOURCE_URL_REGEX.test(pageFunction)
|
||||
? pageFunction
|
||||
: `${pageFunction}\n${sourceUrlComment}\n`;
|
||||
|
||||
responsePromise = this.connection.send('script.evaluate', {
|
||||
expression,
|
||||
target: this.target,
|
||||
resultOwnership,
|
||||
awaitPromise: true,
|
||||
});
|
||||
} else {
|
||||
let functionDeclaration = stringifyFunction(pageFunction);
|
||||
functionDeclaration = SOURCE_URL_REGEX.test(functionDeclaration)
|
||||
? functionDeclaration
|
||||
: `${functionDeclaration}\n${sourceUrlComment}\n`;
|
||||
responsePromise = this.connection.send('script.callFunction', {
|
||||
functionDeclaration,
|
||||
arguments: await Promise.all(
|
||||
args.map(arg => {
|
||||
return BidiSerializer.serialize(arg, this as any);
|
||||
})
|
||||
),
|
||||
target: this.target,
|
||||
resultOwnership,
|
||||
awaitPromise: true,
|
||||
});
|
||||
}
|
||||
|
||||
const {result} = await responsePromise;
|
||||
|
||||
if ('type' in result && result.type === 'exception') {
|
||||
throw createEvaluationError(result.exceptionDetails);
|
||||
}
|
||||
|
||||
return returnByValue
|
||||
? BidiSerializer.deserialize(result.result)
|
||||
: getBidiHandle(this as any, result.result, this.#frame);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function getBidiHandle(
|
||||
realmOrContext: Realm,
|
||||
result: Bidi.CommonDataTypes.RemoteValue,
|
||||
frame: Frame
|
||||
): JSHandle | ElementHandle<Node> {
|
||||
if (result.type === 'node' || result.type === 'window') {
|
||||
return new ElementHandle(realmOrContext, result, frame);
|
||||
}
|
||||
return new JSHandle(realmOrContext, result);
|
||||
}
|
@ -15,11 +15,21 @@
|
||||
*/
|
||||
|
||||
import {ElementHandle} from '../../api/ElementHandle.js';
|
||||
import {withSourcePuppeteerURLIfNone} from '../common.js';
|
||||
import {EvaluateFuncWith, NodeFor} from '../types.js';
|
||||
|
||||
import {BrowsingContext} from './BrowsingContext.js';
|
||||
import {Realm as RealmBase} from '../../api/Frame.js';
|
||||
import {JSHandle as BaseJSHandle} from '../../api/JSHandle.js';
|
||||
import {TimeoutSettings} from '../TimeoutSettings.js';
|
||||
import {
|
||||
EvaluateFunc,
|
||||
EvaluateFuncWith,
|
||||
HandleFor,
|
||||
InnerLazyParams,
|
||||
NodeFor,
|
||||
} from '../types.js';
|
||||
import {withSourcePuppeteerURLIfNone} from '../util.js';
|
||||
import {TaskManager, WaitTask} from '../WaitTask.js';
|
||||
|
||||
import {JSHandle} from './JSHandle.js';
|
||||
import {Realm} from './Realm.js';
|
||||
/**
|
||||
* A unique key for {@link SandboxChart} to denote the default world.
|
||||
* Realms are automatically created in the default sandbox.
|
||||
@ -47,19 +57,27 @@ export interface SandboxChart {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class Sandbox {
|
||||
export class Sandbox implements RealmBase {
|
||||
#document?: ElementHandle<Document>;
|
||||
#context: BrowsingContext;
|
||||
#realm: Realm;
|
||||
|
||||
constructor(context: BrowsingContext) {
|
||||
this.#context = context;
|
||||
#timeoutSettings: TimeoutSettings;
|
||||
#taskManager = new TaskManager();
|
||||
|
||||
constructor(context: Realm, timeoutSettings: TimeoutSettings) {
|
||||
this.#realm = context;
|
||||
this.#timeoutSettings = timeoutSettings;
|
||||
}
|
||||
|
||||
get taskManager(): TaskManager {
|
||||
return this.#taskManager;
|
||||
}
|
||||
|
||||
async document(): Promise<ElementHandle<Document>> {
|
||||
if (this.#document) {
|
||||
return this.#document;
|
||||
}
|
||||
this.#document = await this.#context.evaluateHandle(() => {
|
||||
this.#document = await this.#realm.evaluateHandle(() => {
|
||||
return document;
|
||||
});
|
||||
return this.#document;
|
||||
@ -117,4 +135,90 @@ export class Sandbox {
|
||||
const document = await this.document();
|
||||
return document.$x(expression);
|
||||
}
|
||||
|
||||
async evaluateHandle<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
pageFunction = withSourcePuppeteerURLIfNone(
|
||||
this.evaluateHandle.name,
|
||||
pageFunction
|
||||
);
|
||||
return this.#realm.evaluateHandle(pageFunction, ...args);
|
||||
}
|
||||
|
||||
async evaluate<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
...args: Params
|
||||
): Promise<Awaited<ReturnType<Func>>> {
|
||||
pageFunction = withSourcePuppeteerURLIfNone(
|
||||
this.evaluate.name,
|
||||
pageFunction
|
||||
);
|
||||
return this.#realm.evaluate(pageFunction, ...args);
|
||||
}
|
||||
|
||||
async adoptHandle<T extends BaseJSHandle<Node>>(handle: T): Promise<T> {
|
||||
return (await this.evaluateHandle(node => {
|
||||
return node;
|
||||
}, handle)) as unknown as T;
|
||||
}
|
||||
|
||||
async transferHandle<T extends BaseJSHandle<Node>>(handle: T): Promise<T> {
|
||||
if ((handle as unknown as JSHandle).context() === this.#realm) {
|
||||
return handle;
|
||||
}
|
||||
const transferredHandle = await this.evaluateHandle(node => {
|
||||
return node;
|
||||
}, handle);
|
||||
|
||||
await handle.dispose();
|
||||
return transferredHandle as unknown as T;
|
||||
}
|
||||
|
||||
waitForFunction<
|
||||
Params extends unknown[],
|
||||
Func extends EvaluateFunc<InnerLazyParams<Params>> = EvaluateFunc<
|
||||
InnerLazyParams<Params>
|
||||
>
|
||||
>(
|
||||
pageFunction: Func | string,
|
||||
options: {
|
||||
polling?: 'raf' | 'mutation' | number;
|
||||
timeout?: number;
|
||||
root?: ElementHandle<Node>;
|
||||
signal?: AbortSignal;
|
||||
} = {},
|
||||
...args: Params
|
||||
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
|
||||
const {
|
||||
polling = 'raf',
|
||||
timeout = this.#timeoutSettings.timeout(),
|
||||
root,
|
||||
signal,
|
||||
} = options;
|
||||
if (typeof polling === 'number' && polling < 0) {
|
||||
throw new Error('Cannot poll with non-positive interval');
|
||||
}
|
||||
const waitTask = new WaitTask(
|
||||
this,
|
||||
{
|
||||
polling,
|
||||
root,
|
||||
timeout,
|
||||
signal,
|
||||
},
|
||||
pageFunction as unknown as
|
||||
| ((...args: unknown[]) => Promise<Awaited<ReturnType<Func>>>)
|
||||
| string,
|
||||
...args
|
||||
);
|
||||
return waitTask.result;
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,10 @@ export class BidiSerializer {
|
||||
? arg
|
||||
: null;
|
||||
if (objectHandle) {
|
||||
if (objectHandle.context() !== context) {
|
||||
if (
|
||||
objectHandle.context() !== context &&
|
||||
!('sharedId' in objectHandle.remoteValue())
|
||||
) {
|
||||
throw new Error(
|
||||
'JSHandles can be evaluated only in the context they were created!'
|
||||
);
|
||||
|
@ -19,7 +19,7 @@ import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
||||
import {debug} from '../Debug.js';
|
||||
import {PuppeteerURL} from '../util.js';
|
||||
|
||||
import {BrowsingContext} from './BrowsingContext.js';
|
||||
import {Realm} from './Realm.js';
|
||||
import {BidiSerializer} from './Serializer.js';
|
||||
|
||||
/**
|
||||
@ -30,7 +30,7 @@ export const debugError = debug('puppeteer:error');
|
||||
* @internal
|
||||
*/
|
||||
export async function releaseReference(
|
||||
client: BrowsingContext,
|
||||
client: Realm,
|
||||
remoteReference: Bidi.CommonDataTypes.RemoteReference
|
||||
): Promise<void> {
|
||||
if (!remoteReference.handle) {
|
||||
@ -38,7 +38,7 @@ export async function releaseReference(
|
||||
}
|
||||
await client.connection
|
||||
.send('script.disown', {
|
||||
target: {context: client.id},
|
||||
target: client.target,
|
||||
handles: [remoteReference.handle],
|
||||
})
|
||||
.catch((error: any) => {
|
||||
|
@ -263,6 +263,24 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should have an error message specifically for awaiting an element to be hidden",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should have correct stack trace for timeout",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[ariaqueryhandler.spec] AriaQueryHandler waitForSelector (aria) should respect timeout",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[browser.spec] Browser specs Browser.process should return child_process instance",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -275,6 +293,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |pipe| option should fire \"disconnected\" when closing with pipe",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[Connection.spec] WebDriver BiDi Connection should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -311,35 +335,35 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitFor",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitForSelector",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Custom queries should wait correctly with waitForSelector on an element",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Element.toElement should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Element.waitForSelector should wait correctly with waitForSelector on an element",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs Element.waitForXPath should wait correctly with waitForXPath on an element",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[elementhandle.spec] ElementHandle specs ElementHandle.isVisible and ElementHandle.isHidden should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs Frame.evaluate should have different execution contexts",
|
||||
@ -773,6 +797,12 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.url should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.waitForNetworkIdle should work with aborted requests",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -807,7 +837,7 @@
|
||||
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work for ARIA selectors in multiple isolated worlds",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
"expectations": ["FAIL", "TIMEOUT"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[queryhandler.spec] Query handler tests P selectors should work with :hover",
|
||||
@ -875,6 +905,120 @@
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should be cancellable",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should have an error message specifically for awaiting an element to be hidden",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should have correct stack trace for timeout",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should immediately resolve promise if node exists",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should resolve promise when node is added",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should respect timeout",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should respond to node attribute mutation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should return null if waiting to hide non-existing element",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should return the element handle",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be hidden (bounding box)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be hidden (display)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be hidden (removal)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be hidden (visibility)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be visible (bounding box)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be visible (display)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be visible (visibility)",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should wait for element to be visible recursively",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should work when node is added through innerHTML",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForSelector should work with removed MutationObserver",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[waittask.spec] waittask specs Frame.waitForTimeout waits for the given timeout before resolving",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -971,12 +1115,30 @@
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |browserURL| option should be able to connect using browserUrl, with and without trailing slash",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |browserURL| option should throw when trying to connect to non-existing browser",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |browserURL| option should throw when trying to connect to non-existing browser",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[chromiumonly.spec] Chromium-Specific Launcher tests Puppeteer.launch |pipe| option should fire \"disconnected\" when closing with pipe",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[click.spec] Page.click should click on checkbox label and toggle",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1175,18 +1337,42 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulate should support clicking",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulate should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateCPUThrottling should change the CPU throttling rate successfully",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateMediaFeatures should throw in case of bad argument",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateMediaFeatures should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateMediaType should throw in case of bad argument",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateMediaType should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1199,6 +1385,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateNetworkConditions should change navigator.connection.effectiveType",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateTimezone should throw for invalid timezone IDs",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1211,12 +1403,24 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateVisionDeficiency should throw for invalid vision deficiencies",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateVisionDeficiency should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.viewport should detect touch when applying viewport with touches",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.viewport should get the proper viewport size",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1229,42 +1433,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] *",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.viewport should support touch emulation",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.viewport should detect touch when applying viewport with touches",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulate should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulate should support clicking",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[emulation.spec] Emulation Page.emulateNetworkConditions should change navigator.connection.effectiveType",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[evaluation.spec] Evaluation specs \"after each\" hook for \"should transfer 100Mb of data from page to node.js\"",
|
||||
"platforms": ["darwin"],
|
||||
@ -1367,6 +1541,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[ignorehttpserrors.spec] ignoreHTTPSErrors should work with mixed content",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[ignorehttpserrors.spec] ignoreHTTPSErrors should work with request interception",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -1553,12 +1733,36 @@
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[locator.spec] Locator Locator.click can be aborted",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[locator.spec] Locator Locator.click should retry clicks on errors",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[locator.spec] Locator Locator.click should time out",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[locator.spec] Locator Locator.race can be aborted",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[locator.spec] Locator Locator.scroll should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[mouse.spec] Mouse should reset properly",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -2177,6 +2381,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.addScriptTag should throw an error if loading from url fail",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.addScriptTag should throw when added with content to the CSP page",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -2189,6 +2399,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.addStyleTag should throw an error if loading from url fail",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.addStyleTag should throw when added with content to the CSP page",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -2459,12 +2675,6 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["FAIL"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.url should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["chrome", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[page.spec] Page Page.waitForNetworkIdle should work",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
@ -2783,6 +2993,12 @@
|
||||
"parameters": ["cdp", "firefox"],
|
||||
"expectations": ["SKIP"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[worker.spec] Workers should report errors",
|
||||
"platforms": ["darwin", "linux", "win32"],
|
||||
"parameters": ["firefox", "webDriverBiDi"],
|
||||
"expectations": ["PASS"]
|
||||
},
|
||||
{
|
||||
"testIdPattern": "[CDPSession.spec] Target.createCDPSession should send events",
|
||||
"platforms": ["win32"],
|
||||
|
@ -39,7 +39,7 @@ describe('headful tests', function () {
|
||||
/* These tests fire up an actual browser so let's
|
||||
* allow a higher timeout
|
||||
*/
|
||||
this.timeout(20 * 1000);
|
||||
this.timeout(20_000);
|
||||
|
||||
let headfulOptions: PuppeteerLaunchOptions | undefined;
|
||||
let headlessOptions: PuppeteerLaunchOptions & {headless: boolean};
|
||||
|
@ -35,7 +35,7 @@ import {
|
||||
import {dumpFrames, waitEvent} from './utils.js';
|
||||
|
||||
const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');
|
||||
const FIREFOX_TIMEOUT = 30 * 1000;
|
||||
const FIREFOX_TIMEOUT = 30_000;
|
||||
|
||||
describe('Launcher specs', function () {
|
||||
setupTestBrowserHooks();
|
||||
|
Loading…
Reference in New Issue
Block a user