puppeteer-core
Version:
A high-level API to control headless Chrome over the DevTools Protocol
208 lines (194 loc) • 5.88 kB
text/typescript
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {TimeoutSettings} from '../common/TimeoutSettings.js';
import type {EvaluateFunc, HandleFor} from '../common/types.js';
import {TaskManager, WaitTask} from '../common/WaitTask.js';
import {disposeSymbol} from '../util/disposable.js';
import type {ElementHandle} from './ElementHandle.js';
import type {Environment} from './Environment.js';
import type {Extension} from './Extension.js';
import type {JSHandle} from './JSHandle.js';
/**
* @public
*/
export abstract class Realm {
/** @internal */
protected readonly timeoutSettings: TimeoutSettings;
/** @internal */
readonly taskManager = new TaskManager();
/** @internal */
constructor(timeoutSettings: TimeoutSettings) {
this.timeoutSettings = timeoutSettings;
}
/** @internal */
abstract get environment(): Environment;
/**
* Returns the origin that created the Realm.
* For example, if the realm was created by an extension content script,
* this will return the origin of the extension
* (e.g., `chrome-extension://<extension-id>`).
*
* @experimental
* @example
* `chrome-extension://<chrome-extension-id>`
*/
abstract get origin(): string | undefined;
/**
* Returns the {@link Extension} that created this realm, if applicable.
* This is typically populated when the realm was created by an extension
* content script injected into a page.
*
* @returns A promise that resolves to the {@link Extension}
* or `null` if not created by an extension.
* @experimental
*/
abstract extension(): Promise<Extension | null>;
/** @internal */
abstract adoptHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
/** @internal */
abstract transferHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
/**
* Evaluates a function in the realm's context and returns a
* {@link JSHandle} to the result.
*
* If the function passed to `realm.evaluateHandle` returns a Promise,
* the method will wait for the promise to resolve and return its value.
*
* {@link JSHandle} instances can be passed as arguments to the function.
*
* @example
*
* ```ts
* const aHandle = await realm.evaluateHandle(() => document.body);
* const resultHandle = await realm.evaluateHandle(
* body => body.innerHTML,
* aHandle,
* );
* ```
*
* @param pageFunction - A function to be evaluated in the realm.
* @param args - Arguments to be passed to the `pageFunction`.
* @returns A promise that resolves to a {@link JSHandle} containing
* the result.
* @public
*/
abstract evaluateHandle<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
/**
* Evaluates a function in the realm's context and returns the
* resulting value.
*
* If the function passed to `realm.evaluate` returns a Promise,
* the method will wait for the promise to resolve and return its value.
*
* {@link JSHandle} instances can be passed as arguments to the function.
*
* @example
*
* ```ts
* const result = await realm.evaluate(() => {
* return Promise.resolve(8 * 7);
* });
* console.log(result); // prints "56"
* ```
*
* @param pageFunction - A function to be evaluated in the realm.
* @param args - Arguments to be passed to the `pageFunction`.
* @returns A promise that resolves to the return value of the function.
* @public
*/
abstract evaluate<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
/**
* Waits for a function to return a truthy value when evaluated in
* the realm's context.
*
* Arguments can be passed from Node.js to `pageFunction`.
*
* @example
*
* ```ts
* const selector = '.foo';
* await realm.waitForFunction(
* selector => !!document.querySelector(selector),
* {},
* selector,
* );
* ```
*
* @param pageFunction - A function to evaluate in the realm.
* @param options - Options for polling and timeouts.
* @param args - Arguments to pass to the function.
* @returns A promise that resolves when the function returns a truthy
* value.
* @public
*/
async waitForFunction<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<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 await waitTask.result;
}
/** @internal */
abstract adoptBackendNode(backendNodeId?: number): Promise<JSHandle<Node>>;
/** @internal */
get disposed(): boolean {
return this.#disposed;
}
#disposed = false;
/** @internal */
dispose(): void {
this.#disposed = true;
this.taskManager.terminateAll(
new Error('waitForFunction failed: frame got detached.'),
);
}
/** @internal */
[disposeSymbol](): void {
this.dispose();
}
}