Update dashboard, kb, memory +4 more (+28 ~18 -1)

This commit is contained in:
Echo
2026-02-06 14:25:10 +00:00
parent 7f64d5054a
commit 19d178268a
6767 changed files with 1346472 additions and 1282 deletions

View File

@@ -0,0 +1,103 @@
/**
* @license
* Copyright 2025 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @public
* Emulated bluetooth adapter state.
*/
export type AdapterState = 'absent' | 'powered-off' | 'powered-on';
/**
* @public
* Represents the simulated bluetooth peripheral's manufacturer data.
*/
export interface BluetoothManufacturerData {
/**
* The company identifier, as defined by the {@link https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers/|Bluetooth SIG}.
*/
key: number;
/**
* The manufacturer-specific data as a base64-encoded string.
*/
data: string;
}
/**
* @public
* A bluetooth peripheral to be simulated.
*/
export interface PreconnectedPeripheral {
address: string;
name: string;
manufacturerData: BluetoothManufacturerData[];
knownServiceUuids: string[];
}
/**
* Exposes the bluetooth emulation abilities.
*
* @remarks {@link https://webbluetoothcg.github.io/web-bluetooth/#simulated-bluetooth-adapter|Web Bluetooth specification}
* requires the emulated adapters should be isolated per top-level navigable. However,
* at the moment Chromium's bluetooth emulation implementation is tight to the browser
* context, not the page. This means the bluetooth emulation exposed from different pages
* of the same browser context would interfere their states.
*
* @example
*
* ```ts
* await page.bluetooth.emulateAdapter('powered-on');
* await page.bluetooth.simulatePreconnectedPeripheral({
* address: '09:09:09:09:09:09',
* name: 'SOME_NAME',
* manufacturerData: [
* {
* key: 17,
* data: 'AP8BAX8=',
* },
* ],
* knownServiceUuids: ['12345678-1234-5678-9abc-def123456789'],
* });
* await page.bluetooth.disableEmulation();
* ```
*
* @experimental
* @public
*/
export interface BluetoothEmulation {
/**
* Emulate Bluetooth adapter. Required for bluetooth simulations
* See {@link https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateAdapter-command|bluetooth.simulateAdapter}.
*
* @param state - The desired bluetooth adapter state.
* @param leSupported - Mark if the adapter supports low-energy bluetooth.
*
* @experimental
* @public
*/
emulateAdapter(state: AdapterState, leSupported?: boolean): Promise<void>;
/**
* Disable emulated bluetooth adapter.
* See {@link https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-disableSimulation-command|bluetooth.disableSimulation}.
*
* @experimental
* @public
*/
disableEmulation(): Promise<void>;
/**
* Simulated preconnected Bluetooth Peripheral.
* See {@link https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-simulateconnectedperipheral-command|bluetooth.simulatePreconnectedPeripheral}.
*
* @param preconnectedPeripheral - The peripheral to simulate.
*
* @experimental
* @public
*/
simulatePreconnectedPeripheral(
preconnectedPeripheral: PreconnectedPeripheral,
): Promise<void>;
}

730
node_modules/puppeteer-core/src/api/Browser.ts generated vendored Normal file
View File

@@ -0,0 +1,730 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/// <reference types="node" preserve="true"/>
import type {ChildProcess} from 'node:child_process';
import type {Protocol} from 'devtools-protocol';
import {
firstValueFrom,
from,
merge,
raceWith,
} from '../../third_party/rxjs/rxjs.js';
import type {ProtocolType} from '../common/ConnectOptions.js';
import type {
Cookie,
CookieData,
DeleteCookiesRequest,
} from '../common/Cookie.js';
import type {DownloadBehavior} from '../common/DownloadBehavior.js';
import {EventEmitter, type EventType} from '../common/EventEmitter.js';
import {
debugError,
fromEmitterEvent,
filterAsync,
timeout,
fromAbortSignal,
} from '../common/util.js';
import {asyncDisposeSymbol, disposeSymbol} from '../util/disposable.js';
import type {BrowserContext} from './BrowserContext.js';
import type {Page} from './Page.js';
import type {Target} from './Target.js';
/**
* @public
*/
export interface BrowserContextOptions {
/**
* Proxy server with optional port to use for all requests.
* Username and password can be set in `Page.authenticate`.
*/
proxyServer?: string;
/**
* Bypass the proxy for the given list of hosts.
*/
proxyBypassList?: string[];
/**
* Behavior definition for when downloading a file.
*
* @remarks
* If not set, the default behavior will be used.
*/
downloadBehavior?: DownloadBehavior;
}
/**
* @internal
*/
export type BrowserCloseCallback = () => Promise<void> | void;
/**
* @public
*/
export type TargetFilterCallback = (target: Target) => boolean;
/**
* @internal
*/
export type IsPageTargetCallback = (target: Target) => boolean;
/**
* @internal
*/
export const WEB_PERMISSION_TO_PROTOCOL_PERMISSION = new Map<
Permission,
Protocol.Browser.PermissionType
>([
['accelerometer', 'sensors'],
['ambient-light-sensor', 'sensors'],
['background-sync', 'backgroundSync'],
['camera', 'videoCapture'],
['clipboard-read', 'clipboardReadWrite'],
['clipboard-sanitized-write', 'clipboardSanitizedWrite'],
['clipboard-write', 'clipboardReadWrite'],
['geolocation', 'geolocation'],
['gyroscope', 'sensors'],
['idle-detection', 'idleDetection'],
['keyboard-lock', 'keyboardLock'],
['magnetometer', 'sensors'],
['microphone', 'audioCapture'],
['midi', 'midi'],
['notifications', 'notifications'],
['payment-handler', 'paymentHandler'],
['persistent-storage', 'durableStorage'],
['pointer-lock', 'pointerLock'],
// chrome-specific permissions we have.
['midi-sysex', 'midiSysex'],
]);
/**
* @public
* @deprecated in favor of {@link PermissionDescriptor}.
*/
export type Permission =
| 'accelerometer'
| 'ambient-light-sensor'
| 'background-sync'
| 'camera'
| 'clipboard-read'
| 'clipboard-sanitized-write'
| 'clipboard-write'
| 'geolocation'
| 'gyroscope'
| 'idle-detection'
| 'keyboard-lock'
| 'magnetometer'
| 'microphone'
| 'midi-sysex'
| 'midi'
| 'notifications'
| 'payment-handler'
| 'persistent-storage'
| 'pointer-lock';
/**
* @public
*/
export interface PermissionDescriptor {
name: string;
userVisibleOnly?: boolean;
sysex?: boolean;
panTiltZoom?: boolean;
allowWithoutSanitization?: boolean;
}
/**
* @public
*/
export type PermissionState = 'granted' | 'denied' | 'prompt';
/**
* @public
*/
export interface WaitForTargetOptions {
/**
* Maximum wait time in milliseconds. Pass `0` to disable the timeout.
*
* @defaultValue `30_000`
*/
timeout?: number;
/**
* A signal object that allows you to cancel a waitFor call.
*/
signal?: AbortSignal;
}
/**
* All the events a {@link Browser | browser instance} may emit.
*
* @public
*/
export const enum BrowserEvent {
/**
* Emitted when Puppeteer gets disconnected from the browser instance. This
* might happen because either:
*
* - The browser closes/crashes or
* - {@link Browser.disconnect} was called.
*/
Disconnected = 'disconnected',
/**
* Emitted when the URL of a target changes. Contains a {@link Target}
* instance.
*
* @remarks Note that this includes target changes in all browser
* contexts.
*/
TargetChanged = 'targetchanged',
/**
* Emitted when a target is created, for example when a new page is opened by
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open | window.open}
* or by {@link Browser.newPage | browser.newPage}
*
* Contains a {@link Target} instance.
*
* @remarks Note that this includes target creations in all browser
* contexts.
*/
TargetCreated = 'targetcreated',
/**
* Emitted when a target is destroyed, for example when a page is closed.
* Contains a {@link Target} instance.
*
* @remarks Note that this includes target destructions in all browser
* contexts.
*/
TargetDestroyed = 'targetdestroyed',
/**
* @internal
*/
TargetDiscovered = 'targetdiscovered',
}
/**
* @public
*/
export interface BrowserEvents extends Record<EventType, unknown> {
[BrowserEvent.Disconnected]: undefined;
[BrowserEvent.TargetCreated]: Target;
[BrowserEvent.TargetDestroyed]: Target;
[BrowserEvent.TargetChanged]: Target;
/**
* @internal
*/
[BrowserEvent.TargetDiscovered]: Protocol.Target.TargetInfo;
}
/**
* @public
* @experimental
*/
export interface DebugInfo {
pendingProtocolErrors: Error[];
}
/**
* @public
*/
export type WindowState = 'normal' | 'minimized' | 'maximized' | 'fullscreen';
/**
* @public
*/
export interface WindowBounds {
left?: number;
top?: number;
width?: number;
height?: number;
windowState?: WindowState;
}
/**
* @public
*/
export type WindowId = string;
/**
* @public
*/
export type CreatePageOptions = (
| {
type?: 'tab';
}
| {
type: 'window';
windowBounds?: WindowBounds;
}
) & {
/**
* Whether to create the page in the background.
*
* @defaultValue `false`
*/
background?: boolean;
};
/**
* @public
*/
export interface ScreenOrientation {
angle: number;
type: string;
}
/**
* @public
*/
export interface ScreenInfo {
left: number;
top: number;
width: number;
height: number;
availLeft: number;
availTop: number;
availWidth: number;
availHeight: number;
devicePixelRatio: number;
colorDepth: number;
orientation: ScreenOrientation;
isExtended: boolean;
isInternal: boolean;
isPrimary: boolean;
label: string;
id: string;
}
/**
* @public
*/
export interface WorkAreaInsets {
top?: number;
left?: number;
bottom?: number;
right?: number;
}
/**
* @public
*/
export interface AddScreenParams {
left: number;
top: number;
width: number;
height: number;
workAreaInsets?: WorkAreaInsets;
devicePixelRatio?: number;
rotation?: number;
colorDepth?: number;
label?: string;
isInternal?: boolean;
}
/**
* {@link Browser} represents a browser instance that is either:
*
* - connected to via {@link Puppeteer.connect} or
* - launched by {@link PuppeteerNode.launch}.
*
* {@link Browser} {@link EventEmitter.emit | emits} various events which are
* documented in the {@link BrowserEvent} enum.
*
* @example Using a {@link Browser} to create a {@link Page}:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.goto('https://example.com');
* await browser.close();
* ```
*
* @example Disconnecting from and reconnecting to a {@link Browser}:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* const browser = await puppeteer.launch();
* // Store the endpoint to be able to reconnect to the browser.
* const browserWSEndpoint = browser.wsEndpoint();
* // Disconnect puppeteer from the browser.
* await browser.disconnect();
*
* // Use the endpoint to reestablish a connection
* const browser2 = await puppeteer.connect({browserWSEndpoint});
* // Close the browser.
* await browser2.close();
* ```
*
* @public
*/
export abstract class Browser extends EventEmitter<BrowserEvents> {
/**
* @internal
*/
constructor() {
super();
}
/**
* Gets the associated
* {@link https://nodejs.org/api/child_process.html#class-childprocess | ChildProcess}.
*
* @returns `null` if this instance was connected to via
* {@link Puppeteer.connect}.
*/
abstract process(): ChildProcess | null;
/**
* Creates a new {@link BrowserContext | browser context}.
*
* This won't share cookies/cache with other {@link BrowserContext | browser contexts}.
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* const browser = await puppeteer.launch();
* // Create a new browser context.
* const context = await browser.createBrowserContext();
* // Create a new page in a pristine context.
* const page = await context.newPage();
* // Do stuff
* await page.goto('https://example.com');
* ```
*/
abstract createBrowserContext(
options?: BrowserContextOptions,
): Promise<BrowserContext>;
/**
* Gets a list of open {@link BrowserContext | browser contexts}.
*
* In a newly-created {@link Browser | browser}, this will return a single
* instance of {@link BrowserContext}.
*/
abstract browserContexts(): BrowserContext[];
/**
* Gets the default {@link BrowserContext | browser context}.
*
* @remarks The default {@link BrowserContext | browser context} cannot be
* closed.
*/
abstract defaultBrowserContext(): BrowserContext;
/**
* Gets the WebSocket URL to connect to this {@link Browser | browser}.
*
* This is usually used with {@link Puppeteer.connect}.
*
* You can find the debugger URL (`webSocketDebuggerUrl`) from
* `http://HOST:PORT/json/version`.
*
* See {@link https://chromedevtools.github.io/devtools-protocol/#how-do-i-access-the-browser-target | browser endpoint}
* for more information.
*
* @remarks The format is always `ws://HOST:PORT/devtools/browser/<id>`.
*/
abstract wsEndpoint(): string;
/**
* Creates a new {@link Page | page} in the
* {@link Browser.defaultBrowserContext | default browser context}.
*/
abstract newPage(options?: CreatePageOptions): Promise<Page>;
/**
* Gets the specified window {@link WindowBounds | bounds}.
*/
abstract getWindowBounds(windowId: WindowId): Promise<WindowBounds>;
/**
* Sets the specified window {@link WindowBounds | bounds}.
*/
abstract setWindowBounds(
windowId: WindowId,
windowBounds: WindowBounds,
): Promise<void>;
/**
* Gets all active {@link Target | targets}.
*
* In case of multiple {@link BrowserContext | browser contexts}, this returns
* all {@link Target | targets} in all
* {@link BrowserContext | browser contexts}.
*/
abstract targets(): Target[];
/**
* Gets the {@link Target | target} associated with the
* {@link Browser.defaultBrowserContext | default browser context}).
*/
abstract target(): Target;
/**
* Waits until a {@link Target | target} matching the given `predicate`
* appears and returns it.
*
* This will look all open {@link BrowserContext | browser contexts}.
*
* @example Finding a target for a page opened via `window.open`:
*
* ```ts
* await page.evaluate(() => window.open('https://www.example.com/'));
* const newWindowTarget = await browser.waitForTarget(
* target => target.url() === 'https://www.example.com/',
* );
* ```
*/
async waitForTarget(
predicate: (x: Target) => boolean | Promise<boolean>,
options: WaitForTargetOptions = {},
): Promise<Target> {
const {timeout: ms = 30000, signal} = options;
return await firstValueFrom(
merge(
fromEmitterEvent(this, BrowserEvent.TargetCreated),
fromEmitterEvent(this, BrowserEvent.TargetChanged),
from(this.targets()),
).pipe(
filterAsync(predicate),
raceWith(fromAbortSignal(signal), timeout(ms)),
),
);
}
/**
* Gets a list of all open {@link Page | pages} inside this {@link Browser}.
*
* If there are multiple {@link BrowserContext | browser contexts}, this
* returns all {@link Page | pages} in all
* {@link BrowserContext | browser contexts}.
*
* @param includeAll - experimental, setting to true includes all kinds of pages.
*
* @remarks Non-visible {@link Page | pages}, such as `"background_page"`,
* will not be listed here. You can find them using {@link Target.page}.
*/
async pages(includeAll = false): Promise<Page[]> {
const contextPages = await Promise.all(
this.browserContexts().map(context => {
return context.pages(includeAll);
}),
);
// Flatten array.
return contextPages.reduce((acc, x) => {
return acc.concat(x);
}, []);
}
/**
* Gets a string representing this {@link Browser | browser's} name and
* version.
*
* For headless browser, this is similar to `"HeadlessChrome/61.0.3153.0"`. For
* non-headless or new-headless, this is similar to `"Chrome/61.0.3153.0"`. For
* Firefox, it is similar to `"Firefox/116.0a1"`.
*
* The format of {@link Browser.version} might change with future releases of
* browsers.
*/
abstract version(): Promise<string>;
/**
* Gets this {@link Browser | browser's} original user agent.
*
* {@link Page | Pages} can override the user agent with
* {@link Page.(setUserAgent:2) }.
*
*/
abstract userAgent(): Promise<string>;
/**
* Closes this {@link Browser | browser} and all associated
* {@link Page | pages}.
*/
abstract close(): Promise<void>;
/**
* Disconnects Puppeteer from this {@link Browser | browser}, but leaves the
* process running.
*/
abstract disconnect(): Promise<void>;
/**
* Returns all cookies in the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.cookies | browser.defaultBrowserContext().cookies()}.
*/
async cookies(): Promise<Cookie[]> {
return await this.defaultBrowserContext().cookies();
}
/**
* Sets cookies in the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.setCookie | browser.defaultBrowserContext().setCookie()}.
*/
async setCookie(...cookies: CookieData[]): Promise<void> {
return await this.defaultBrowserContext().setCookie(...cookies);
}
/**
* Removes cookies from the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.deleteCookie | browser.defaultBrowserContext().deleteCookie()}.
*/
async deleteCookie(...cookies: Cookie[]): Promise<void> {
return await this.defaultBrowserContext().deleteCookie(...cookies);
}
/**
* Deletes cookies matching the provided filters from the default
* {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.deleteMatchingCookies |
* browser.defaultBrowserContext().deleteMatchingCookies()}.
*/
async deleteMatchingCookies(
...filters: DeleteCookiesRequest[]
): Promise<void> {
return await this.defaultBrowserContext().deleteMatchingCookies(...filters);
}
/**
* Sets the permission for a specific origin in the default
* {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.setPermission |
* browser.defaultBrowserContext().setPermission()}.
*
* @param origin - The origin to set the permission for.
* @param permission - The permission descriptor.
* @param state - The state of the permission.
*
* @public
*/
async setPermission(
origin: string,
...permissions: Array<{
permission: PermissionDescriptor;
state: PermissionState;
}>
): Promise<void> {
return await this.defaultBrowserContext().setPermission(
origin,
...permissions,
);
}
/**
* Installs an extension and returns the ID. In Chrome, this is only
* available if the browser was created using `pipe: true` and the
* `--enable-unsafe-extension-debugging` flag is set.
*/
abstract installExtension(path: string): Promise<string>;
/**
* Uninstalls an extension. In Chrome, this is only available if the browser
* was created using `pipe: true` and the
* `--enable-unsafe-extension-debugging` flag is set.
*/
abstract uninstallExtension(id: string): Promise<void>;
/**
* Gets a list of {@link ScreenInfo | screen information objects}.
*/
abstract screens(): Promise<ScreenInfo[]>;
/**
* Adds a new screen, returns the added {@link ScreenInfo | screen information object}.
*
* @remarks
*
* Only supported in headless mode.
*/
abstract addScreen(params: AddScreenParams): Promise<ScreenInfo>;
/**
* Removes a screen.
*
* @remarks
*
* Only supported in headless mode. Fails if the primary screen id is specified.
*/
abstract removeScreen(screenId: string): Promise<void>;
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*
* @deprecated Use {@link Browser | Browser.connected}.
*/
isConnected(): boolean {
return this.connected;
}
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*/
abstract get connected(): boolean;
/** @internal */
override [disposeSymbol](): void {
if (this.process()) {
return void this.close().catch(debugError);
}
return void this.disconnect().catch(debugError);
}
/** @internal */
[asyncDisposeSymbol](): Promise<void> {
if (this.process()) {
return this.close();
}
return this.disconnect();
}
/**
* @internal
*/
abstract get protocol(): ProtocolType;
/**
* Get debug information from Puppeteer.
*
* @remarks
*
* Currently, includes pending protocol calls. In the future, we might add more info.
*
* @public
* @experimental
*/
abstract get debugInfo(): DebugInfo;
/**
* @internal
*/
abstract isNetworkEnabled(): boolean;
}

384
node_modules/puppeteer-core/src/api/BrowserContext.ts generated vendored Normal file
View File

@@ -0,0 +1,384 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import {
firstValueFrom,
from,
merge,
raceWith,
} from '../../third_party/rxjs/rxjs.js';
import type {
Cookie,
CookieData,
DeleteCookiesRequest,
} from '../common/Cookie.js';
import {EventEmitter, type EventType} from '../common/EventEmitter.js';
import {
debugError,
fromEmitterEvent,
filterAsync,
timeout,
} from '../common/util.js';
import {asyncDisposeSymbol, disposeSymbol} from '../util/disposable.js';
import {Mutex} from '../util/Mutex.js';
import type {
Browser,
CreatePageOptions,
Permission,
PermissionDescriptor,
PermissionState,
WaitForTargetOptions,
} from './Browser.js';
import type {Page} from './Page.js';
import type {Target} from './Target.js';
/**
* @public
*/
export const enum BrowserContextEvent {
/**
* Emitted when the url of a target inside the browser context changes.
* Contains a {@link Target} instance.
*/
TargetChanged = 'targetchanged',
/**
* Emitted when a target is created within the browser context, for example
* when a new page is opened by
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open | window.open}
* or by {@link BrowserContext.newPage | browserContext.newPage}
*
* Contains a {@link Target} instance.
*/
TargetCreated = 'targetcreated',
/**
* Emitted when a target is destroyed within the browser context, for example
* when a page is closed. Contains a {@link Target} instance.
*/
TargetDestroyed = 'targetdestroyed',
}
/**
* @public
*/
export interface BrowserContextEvents extends Record<EventType, unknown> {
[BrowserContextEvent.TargetChanged]: Target;
[BrowserContextEvent.TargetCreated]: Target;
[BrowserContextEvent.TargetDestroyed]: Target;
}
/**
* {@link BrowserContext} represents individual user contexts within a
* {@link Browser | browser}.
*
* When a {@link Browser | browser} is launched, it has at least one default
* {@link BrowserContext | browser context}. Others can be created
* using {@link Browser.createBrowserContext}. Each context has isolated storage
* (cookies/localStorage/etc.)
*
* {@link BrowserContext} {@link EventEmitter | emits} various events which are
* documented in the {@link BrowserContextEvent} enum.
*
* If a {@link Page | page} opens another {@link Page | page}, e.g. using
* `window.open`, the popup will belong to the parent {@link Page.browserContext
* | page's browser context}.
*
* @example Creating a new {@link BrowserContext | browser context}:
*
* ```ts
* // Create a new browser context
* const context = await browser.createBrowserContext();
* // Create a new page inside context.
* const page = await context.newPage();
* // ... do stuff with page ...
* await page.goto('https://example.com');
* // Dispose context once it's no longer needed.
* await context.close();
* ```
*
* @remarks
*
* In Chrome all non-default contexts are incognito,
* and {@link Browser.defaultBrowserContext | default browser context}
* might be incognito if you provide the `--incognito` argument when launching
* the browser.
*
* @public
*/
export abstract class BrowserContext extends EventEmitter<BrowserContextEvents> {
/**
* @internal
*/
constructor() {
super();
}
/**
* Gets all active {@link Target | targets} inside this
* {@link BrowserContext | browser context}.
*/
abstract targets(): Target[];
/**
* If defined, indicates an ongoing screenshot opereation.
*/
#pageScreenshotMutex?: Mutex;
#screenshotOperationsCount = 0;
/**
* @internal
*/
startScreenshot(): Promise<InstanceType<typeof Mutex.Guard>> {
const mutex = this.#pageScreenshotMutex || new Mutex();
this.#pageScreenshotMutex = mutex;
this.#screenshotOperationsCount++;
return mutex.acquire(() => {
this.#screenshotOperationsCount--;
if (this.#screenshotOperationsCount === 0) {
// Remove the mutex to indicate no ongoing screenshot operation.
this.#pageScreenshotMutex = undefined;
}
});
}
/**
* @internal
*/
waitForScreenshotOperations():
| Promise<InstanceType<typeof Mutex.Guard>>
| undefined {
return this.#pageScreenshotMutex?.acquire();
}
/**
* Waits until a {@link Target | target} matching the given `predicate`
* appears and returns it.
*
* This will look all open {@link BrowserContext | browser contexts}.
*
* @example Finding a target for a page opened via `window.open`:
*
* ```ts
* await page.evaluate(() => window.open('https://www.example.com/'));
* const newWindowTarget = await browserContext.waitForTarget(
* target => target.url() === 'https://www.example.com/',
* );
* ```
*/
async waitForTarget(
predicate: (x: Target) => boolean | Promise<boolean>,
options: WaitForTargetOptions = {},
): Promise<Target> {
const {timeout: ms = 30000} = options;
return await firstValueFrom(
merge(
fromEmitterEvent(this, BrowserContextEvent.TargetCreated),
fromEmitterEvent(this, BrowserContextEvent.TargetChanged),
from(this.targets()),
).pipe(filterAsync(predicate), raceWith(timeout(ms))),
);
}
/**
* Gets a list of all open {@link Page | pages} inside this
* {@link BrowserContext | browser context}.
*
* @param includeAll - experimental, setting to true includes all kinds of pages.
*
* @remarks Non-visible {@link Page | pages}, such as `"background_page"`,
* will not be listed here. You can find them using {@link Target.page}.
*/
abstract pages(includeAll?: boolean): Promise<Page[]>;
/**
* Grants this {@link BrowserContext | browser context} the given
* `permissions` within the given `origin`.
*
* @example Overriding permissions in the
* {@link Browser.defaultBrowserContext | default browser context}:
*
* ```ts
* const context = browser.defaultBrowserContext();
* await context.overridePermissions('https://html5demos.com', [
* 'geolocation',
* ]);
* ```
*
* @param origin - The origin to grant permissions to, e.g.
* "https://example.com".
* @param permissions - An array of permissions to grant. All permissions that
* are not listed here will be automatically denied.
*
* @deprecated in favor of {@link BrowserContext.setPermission}.
*/
abstract overridePermissions(
origin: string,
permissions: Permission[],
): Promise<void>;
/**
* Sets the permission for a specific origin.
*
* @param origin - The origin to set the permission for.
* @param permission - The permission descriptor.
* @param state - The state of the permission.
*
* @public
*/
abstract setPermission(
origin: string | '*',
...permissions: Array<{
permission: PermissionDescriptor;
state: PermissionState;
}>
): Promise<void>;
/**
* Clears all permission overrides for this
* {@link BrowserContext | browser context}.
*
* @example Clearing overridden permissions in the
* {@link Browser.defaultBrowserContext | default browser context}:
*
* ```ts
* const context = browser.defaultBrowserContext();
* context.overridePermissions('https://example.com', ['clipboard-read']);
* // do stuff ..
* context.clearPermissionOverrides();
* ```
*/
abstract clearPermissionOverrides(): Promise<void>;
/**
* Creates a new {@link Page | page} in this
* {@link BrowserContext | browser context}.
*/
abstract newPage(options?: CreatePageOptions): Promise<Page>;
/**
* Gets the {@link Browser | browser} associated with this
* {@link BrowserContext | browser context}.
*/
abstract browser(): Browser;
/**
* Closes this {@link BrowserContext | browser context} and all associated
* {@link Page | pages}.
*
* @remarks The
* {@link Browser.defaultBrowserContext | default browser context} cannot be
* closed.
*/
abstract close(): Promise<void>;
/**
* Gets all cookies in the browser context.
*/
abstract cookies(): Promise<Cookie[]>;
/**
* Sets a cookie in the browser context.
*/
abstract setCookie(...cookies: CookieData[]): Promise<void>;
/**
* Removes cookie in this browser context.
*
* @param cookies - Complete {@link Cookie | cookie} object to be removed.
*/
async deleteCookie(...cookies: Cookie[]): Promise<void> {
return await this.setCookie(
...cookies.map(cookie => {
return {
...cookie,
expires: 1,
};
}),
);
}
/**
* Deletes cookies matching the provided filters in this browser context.
*
* @param filters - {@link DeleteCookiesRequest}
*/
async deleteMatchingCookies(
...filters: DeleteCookiesRequest[]
): Promise<void> {
const cookies = await this.cookies();
const cookiesToDelete = cookies.filter(cookie => {
return filters.some(filter => {
if (filter.name === cookie.name) {
if (filter.domain !== undefined && filter.domain === cookie.domain) {
return true;
}
if (filter.path !== undefined && filter.path === cookie.path) {
return true;
}
if (
filter.partitionKey !== undefined &&
cookie.partitionKey !== undefined
) {
if (typeof cookie.partitionKey !== 'object') {
throw new Error('Unexpected string partition key');
}
if (typeof filter.partitionKey === 'string') {
if (filter.partitionKey === cookie.partitionKey?.sourceOrigin) {
return true;
}
} else {
if (
filter.partitionKey.sourceOrigin ===
cookie.partitionKey?.sourceOrigin
) {
return true;
}
}
}
if (filter.url !== undefined) {
const url = new URL(filter.url);
if (
url.hostname === cookie.domain &&
url.pathname === cookie.path
) {
return true;
}
}
return true;
}
return false;
});
});
await this.deleteCookie(...cookiesToDelete);
}
/**
* Whether this {@link BrowserContext | browser context} is closed.
*/
get closed(): boolean {
return !this.browser().browserContexts().includes(this);
}
/**
* Identifier for this {@link BrowserContext | browser context}.
*/
get id(): string | undefined {
return undefined;
}
/** @internal */
override [disposeSymbol](): void {
return void this.close().catch(debugError);
}
/** @internal */
[asyncDisposeSymbol](): Promise<void> {
return this.close();
}
}

137
node_modules/puppeteer-core/src/api/CDPSession.ts generated vendored Normal file
View File

@@ -0,0 +1,137 @@
/**
* @license
* Copyright 2024 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
import type {Connection} from '../cdp/Connection.js';
import {EventEmitter, type EventType} from '../common/EventEmitter.js';
/**
* @public
*/
export type CDPEvents = {
[Property in keyof ProtocolMapping.Events]: ProtocolMapping.Events[Property][0];
};
/**
* Events that the CDPSession class emits.
*
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace CDPSessionEvent {
/** @internal */
export const Disconnected = Symbol('CDPSession.Disconnected');
/** @internal */
export const Swapped = Symbol('CDPSession.Swapped');
/**
* Emitted when the session is ready to be configured during the auto-attach
* process. Right after the event is handled, the session will be resumed.
*
* @internal
*/
export const Ready = Symbol('CDPSession.Ready');
export const SessionAttached = 'sessionattached' as const;
export const SessionDetached = 'sessiondetached' as const;
}
/**
* @public
*/
export interface CDPSessionEvents
extends CDPEvents, Record<EventType, unknown> {
/** @internal */
[CDPSessionEvent.Disconnected]: undefined;
/** @internal */
[CDPSessionEvent.Swapped]: CDPSession;
/** @internal */
[CDPSessionEvent.Ready]: CDPSession;
[CDPSessionEvent.SessionAttached]: CDPSession;
[CDPSessionEvent.SessionDetached]: CDPSession;
}
/**
* @public
*/
export interface CommandOptions {
timeout: number;
}
/**
* The `CDPSession` instances are used to talk raw Chrome Devtools Protocol.
*
* @remarks
*
* Protocol methods can be called with {@link CDPSession.send} method and protocol
* events can be subscribed to with `CDPSession.on` method.
*
* Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer}
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}.
*
* @example
*
* ```ts
* const client = await page.createCDPSession();
* await client.send('Animation.enable');
* client.on('Animation.animationCreated', () =>
* console.log('Animation created!'),
* );
* const response = await client.send('Animation.getPlaybackRate');
* console.log('playback rate is ' + response.playbackRate);
* await client.send('Animation.setPlaybackRate', {
* playbackRate: response.playbackRate / 2,
* });
* ```
*
* @public
*/
export abstract class CDPSession extends EventEmitter<CDPSessionEvents> {
/**
* @internal
*/
constructor() {
super();
}
/**
* The underlying connection for this session, if any.
*
* @public
*/
abstract connection(): Connection | undefined;
/**
* True if the session has been detached, false otherwise.
*
* @public
*/
abstract get detached(): boolean;
/**
* Parent session in terms of CDP's auto-attach mechanism.
*
* @internal
*/
parentSession(): CDPSession | undefined {
return undefined;
}
abstract send<T extends keyof ProtocolMapping.Commands>(
method: T,
params?: ProtocolMapping.Commands[T]['paramsType'][0],
options?: CommandOptions,
): Promise<ProtocolMapping.Commands[T]['returnType']>;
/**
* Detaches the cdpSession from the target. Once detached, the cdpSession object
* won't emit any events and can't be used to send messages.
*/
abstract detach(): Promise<void>;
/**
* Returns the session's id.
*/
abstract id(): string;
}

View File

@@ -0,0 +1,71 @@
/**
* @license
* Copyright 2025 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {WaitTimeoutOptions} from './Page.js';
/**
* Device in a request prompt.
*
* @public
*/
export interface DeviceRequestPromptDevice {
/**
* Device id during a prompt.
*/
id: string;
/**
* Device name as it appears in a prompt.
*/
name: string;
}
/**
* Device request prompts let you respond to the page requesting for a device
* through an API like WebBluetooth.
*
* @remarks
* `DeviceRequestPrompt` instances are returned via the
* {@link Page.waitForDevicePrompt} method.
*
* @example
*
* ```ts
* const [devicePrompt] = Promise.all([
* page.waitForDevicePrompt(),
* page.click('#connect-bluetooth'),
* ]);
* await devicePrompt.select(
* await devicePrompt.waitForDevice(({name}) => name.includes('My Device')),
* );
* ```
*
* @public
*/
export abstract class DeviceRequestPrompt {
/**
* Current list of selectable devices.
*/
readonly devices: DeviceRequestPromptDevice[] = [];
/**
* Resolve to the first device in the prompt matching a filter.
*/
abstract waitForDevice(
filter: (device: DeviceRequestPromptDevice) => boolean,
options?: WaitTimeoutOptions,
): Promise<DeviceRequestPromptDevice>;
/**
* Select a device in the prompt's list.
*/
abstract select(device: DeviceRequestPromptDevice): Promise<void>;
/**
* Cancel the prompt.
*/
abstract cancel(): Promise<void>;
}

111
node_modules/puppeteer-core/src/api/Dialog.ts generated vendored Normal file
View File

@@ -0,0 +1,111 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {Protocol} from 'devtools-protocol';
import {assert} from '../util/assert.js';
/**
* Dialog instances are dispatched by the {@link Page} via the `dialog` event.
*
* @remarks
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* page.on('dialog', async dialog => {
* console.log(dialog.message());
* await dialog.dismiss();
* await browser.close();
* });
* await page.evaluate(() => alert('1'));
* ```
*
* @public
*/
export abstract class Dialog {
#type: Protocol.Page.DialogType;
#message: string;
#defaultValue: string;
/**
* @internal
*/
protected handled = false;
/**
* @internal
*/
constructor(
type: Protocol.Page.DialogType,
message: string,
defaultValue = '',
) {
this.#type = type;
this.#message = message;
this.#defaultValue = defaultValue;
}
/**
* The type of the dialog.
*/
type(): Protocol.Page.DialogType {
return this.#type;
}
/**
* The message displayed in the dialog.
*/
message(): string {
return this.#message;
}
/**
* The default value of the prompt, or an empty string if the dialog
* is not a `prompt`.
*/
defaultValue(): string {
return this.#defaultValue;
}
/**
* @internal
*/
protected abstract handle(options: {
accept: boolean;
text?: string;
}): Promise<void>;
/**
* A promise that resolves when the dialog has been accepted.
*
* @param promptText - optional text that will be entered in the dialog
* prompt. Has no effect if the dialog's type is not `prompt`.
*
*/
async accept(promptText?: string): Promise<void> {
assert(!this.handled, 'Cannot accept dialog which is already handled!');
this.handled = true;
await this.handle({
accept: true,
text: promptText,
});
}
/**
* A promise which will resolve once the dialog has been dismissed
*/
async dismiss(): Promise<void> {
assert(!this.handled, 'Cannot dismiss dialog which is already handled!');
this.handled = true;
await this.handle({
accept: false,
});
}
}

1666
node_modules/puppeteer-core/src/api/ElementHandle.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
*/
export const _isElementHandle = Symbol('_isElementHandle');

16
node_modules/puppeteer-core/src/api/Environment.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {CDPSession} from './CDPSession.js';
import type {Realm} from './Realm.js';
/**
* @internal
*/
export interface Environment {
get client(): CDPSession;
mainRealm(): Realm;
}

1203
node_modules/puppeteer-core/src/api/Frame.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

750
node_modules/puppeteer-core/src/api/HTTPRequest.ts generated vendored Normal file
View File

@@ -0,0 +1,750 @@
/**
* @license
* Copyright 2020 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {Protocol} from 'devtools-protocol';
import type {ProtocolError} from '../common/Errors.js';
import {debugError, isString} from '../common/util.js';
import {assert} from '../util/assert.js';
import {typedArrayToBase64} from '../util/encoding.js';
import type {CDPSession} from './CDPSession.js';
import type {Frame} from './Frame.js';
import type {HTTPResponse} from './HTTPResponse.js';
/**
* @public
*/
export interface ContinueRequestOverrides {
/**
* If set, the request URL will change. This is not a redirect.
*/
url?: string;
method?: string;
postData?: string;
headers?: Record<string, string>;
}
/**
* @public
*/
export interface InterceptResolutionState {
action: InterceptResolutionAction;
priority?: number;
}
/**
* Required response data to fulfill a request with.
*
* @public
*/
export interface ResponseForRequest {
status: number;
/**
* Optional response headers.
*
* The record values will be converted to string following:
* Arrays' values will be mapped to String
* (Used when you need multiple headers with the same name).
* Non-arrays will be converted to String.
*/
headers: Record<string, string | string[] | unknown>;
contentType: string;
body: string | Uint8Array;
}
/**
* Resource types for HTTPRequests as perceived by the rendering engine.
*
* @public
*/
export type ResourceType = Lowercase<Protocol.Network.ResourceType>;
/**
* The default cooperative request interception resolution priority
*
* @public
*/
export const DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = 0;
/**
* Represents an HTTP request sent by a page.
* @remarks
*
* Whenever the page sends a request, such as for a network resource, the
* following events are emitted by Puppeteer's `page`:
*
* - `request`: emitted when the request is issued by the page.
*
* - `requestfinished` - emitted when the response body is downloaded and the
* request is complete.
*
* If request fails at some point, then instead of `requestfinished` event the
* `requestfailed` event is emitted.
*
* All of these events provide an instance of `HTTPRequest` representing the
* request that occurred:
*
* ```
* page.on('request', request => ...)
* ```
*
* NOTE: HTTP Error responses, such as 404 or 503, are still successful
* responses from HTTP standpoint, so request will complete with
* `requestfinished` event.
*
* If request gets a 'redirect' response, the request is successfully finished
* with the `requestfinished` event, and a new request is issued to a
* redirected url.
*
* @public
*/
export abstract class HTTPRequest {
/**
* @internal
*/
abstract get id(): string;
/**
* @internal
*/
_interceptionId: string | undefined;
/**
* @internal
*/
_failureText: string | null = null;
/**
* @internal
*/
_response: HTTPResponse | null = null;
/**
* @internal
*/
_fromMemoryCache = false;
/**
* @internal
*/
_redirectChain: HTTPRequest[] = [];
/**
* @internal
*/
protected interception: {
enabled: boolean;
handled: boolean;
handlers: Array<() => void | PromiseLike<any>>;
resolutionState: InterceptResolutionState;
requestOverrides: ContinueRequestOverrides;
response: Partial<ResponseForRequest> | null;
abortReason: Protocol.Network.ErrorReason | null;
} = {
enabled: false,
handled: false,
handlers: [],
resolutionState: {
action: InterceptResolutionAction.None,
},
requestOverrides: {},
response: null,
abortReason: null,
};
/**
* Warning! Using this client can break Puppeteer. Use with caution.
*
* @experimental
*/
abstract get client(): CDPSession;
/**
* @internal
*/
constructor() {}
/**
* The URL of the request
*/
abstract url(): string;
/**
* The `ContinueRequestOverrides` that will be used
* if the interception is allowed to continue (ie, `abort()` and
* `respond()` aren't called).
*/
continueRequestOverrides(): ContinueRequestOverrides {
return this.interception.requestOverrides;
}
/**
* The `ResponseForRequest` that gets used if the
* interception is allowed to respond (ie, `abort()` is not called).
*/
responseForRequest(): Partial<ResponseForRequest> | null {
return this.interception.response;
}
/**
* The most recent reason for aborting the request
*/
abortErrorReason(): Protocol.Network.ErrorReason | null {
return this.interception.abortReason;
}
/**
* An InterceptResolutionState object describing the current resolution
* action and priority.
*
* InterceptResolutionState contains:
* action: InterceptResolutionAction
* priority?: number
*
* InterceptResolutionAction is one of: `abort`, `respond`, `continue`,
* `disabled`, `none`, or `already-handled`.
*/
interceptResolutionState(): InterceptResolutionState {
if (!this.interception.enabled) {
return {action: InterceptResolutionAction.Disabled};
}
if (this.interception.handled) {
return {action: InterceptResolutionAction.AlreadyHandled};
}
return {...this.interception.resolutionState};
}
/**
* Is `true` if the intercept resolution has already been handled,
* `false` otherwise.
*/
isInterceptResolutionHandled(): boolean {
return this.interception.handled;
}
/**
* Adds an async request handler to the processing queue.
* Deferred handlers are not guaranteed to execute in any particular order,
* but they are guaranteed to resolve before the request interception
* is finalized.
*/
enqueueInterceptAction(
pendingHandler: () => void | PromiseLike<unknown>,
): void {
this.interception.handlers.push(pendingHandler);
}
/**
* @internal
*/
abstract _abort(
errorReason: Protocol.Network.ErrorReason | null,
): Promise<void>;
/**
* @internal
*/
abstract _respond(response: Partial<ResponseForRequest>): Promise<void>;
/**
* @internal
*/
abstract _continue(overrides: ContinueRequestOverrides): Promise<void>;
/**
* Awaits pending interception handlers and then decides how to fulfill
* the request interception.
*/
async finalizeInterceptions(): Promise<void> {
await this.interception.handlers.reduce((promiseChain, interceptAction) => {
return promiseChain.then(interceptAction);
}, Promise.resolve());
this.interception.handlers = [];
const {action} = this.interceptResolutionState();
switch (action) {
case 'abort':
return await this._abort(this.interception.abortReason);
case 'respond':
if (this.interception.response === null) {
throw new Error('Response is missing for the interception');
}
return await this._respond(this.interception.response);
case 'continue':
return await this._continue(this.interception.requestOverrides);
}
}
/**
* Contains the request's resource type as it was perceived by the rendering
* engine.
*/
abstract resourceType(): ResourceType;
/**
* The method used (`GET`, `POST`, etc.)
*/
abstract method(): string;
/**
* @deprecated Use {@link HTTPRequest.fetchPostData}.
*/
abstract postData(): string | undefined;
/**
* True when the request has POST data. Note that {@link HTTPRequest.postData}
* might still be undefined when this flag is true when the data is too long
* or not readily available in the decoded form. In that case, use
* {@link HTTPRequest.fetchPostData}.
*/
abstract hasPostData(): boolean;
/**
* Fetches the POST data for the request from the browser.
*/
abstract fetchPostData(): Promise<string | undefined>;
/**
* An object with HTTP headers associated with the request. All
* header names are lower-case.
*/
abstract headers(): Record<string, string>;
/**
* A matching `HTTPResponse` object, or null if the response has not
* been received yet.
*/
abstract response(): HTTPResponse | null;
/**
* The frame that initiated the request, or null if navigating to
* error pages.
*/
abstract frame(): Frame | null;
/**
* True if the request is the driver of the current frame's navigation.
*/
abstract isNavigationRequest(): boolean;
/**
* The initiator of the request.
*/
abstract initiator(): Protocol.Network.Initiator | undefined;
/**
* A `redirectChain` is a chain of requests initiated to fetch a resource.
* @remarks
*
* `redirectChain` is shared between all the requests of the same chain.
*
* For example, if the website `http://example.com` has a single redirect to
* `https://example.com`, then the chain will contain one request:
*
* ```ts
* const response = await page.goto('http://example.com');
* const chain = response.request().redirectChain();
* console.log(chain.length); // 1
* console.log(chain[0].url()); // 'http://example.com'
* ```
*
* If the website `https://google.com` has no redirects, then the chain will be empty:
*
* ```ts
* const response = await page.goto('https://google.com');
* const chain = response.request().redirectChain();
* console.log(chain.length); // 0
* ```
*
* @returns the chain of requests - if a server responds with at least a
* single redirect, this chain will contain all requests that were redirected.
*/
abstract redirectChain(): HTTPRequest[];
/**
* Access information about the request's failure.
*
* @remarks
*
* @example
*
* Example of logging all failed requests:
*
* ```ts
* page.on('requestfailed', request => {
* console.log(request.url() + ' ' + request.failure().errorText);
* });
* ```
*
* @returns `null` unless the request failed. If the request fails this can
* return an object with `errorText` containing a human-readable error
* message, e.g. `net::ERR_FAILED`. It is not guaranteed that there will be
* failure text if the request fails.
*/
abstract failure(): {errorText: string} | null;
/**
* @internal
*/
protected verifyInterception(): void {
assert(this.interception.enabled, 'Request Interception is not enabled!');
assert(!this.interception.handled, 'Request is already handled!');
}
/**
* @internal
*/
protected abstract canBeIntercepted(): boolean;
/**
* Continues request with optional request overrides.
*
* @example
*
* ```ts
* await page.setRequestInterception(true);
* page.on('request', request => {
* // Override headers
* const headers = Object.assign({}, request.headers(), {
* foo: 'bar', // set "foo" header
* origin: undefined, // remove "origin" header
* });
* request.continue({headers});
* });
* ```
*
* @param overrides - optional overrides to apply to the request.
* @param priority - If provided, intercept is resolved using cooperative
* handling rules. Otherwise, intercept is resolved immediately.
*
* @remarks
*
* To use this, request interception should be enabled with
* {@link Page.setRequestInterception}.
*
* Exception is immediately thrown if the request interception is not enabled.
*/
async continue(
overrides: ContinueRequestOverrides = {},
priority?: number,
): Promise<void> {
this.verifyInterception();
if (!this.canBeIntercepted()) {
return;
}
if (priority === undefined) {
return await this._continue(overrides);
}
this.interception.requestOverrides = overrides;
if (
this.interception.resolutionState.priority === undefined ||
priority > this.interception.resolutionState.priority
) {
this.interception.resolutionState = {
action: InterceptResolutionAction.Continue,
priority,
};
return;
}
if (priority === this.interception.resolutionState.priority) {
if (
this.interception.resolutionState.action === 'abort' ||
this.interception.resolutionState.action === 'respond'
) {
return;
}
this.interception.resolutionState.action =
InterceptResolutionAction.Continue;
}
return;
}
/**
* Fulfills a request with the given response.
*
* @example
* An example of fulfilling all requests with 404 responses:
*
* ```ts
* await page.setRequestInterception(true);
* page.on('request', request => {
* request.respond({
* status: 404,
* contentType: 'text/plain',
* body: 'Not Found!',
* });
* });
* ```
*
* NOTE: Mocking responses for dataURL requests is not supported.
* Calling `request.respond` for a dataURL request is a noop.
*
* @param response - the response to fulfill the request with.
* @param priority - If provided, intercept is resolved using
* cooperative handling rules. Otherwise, intercept is resolved
* immediately.
*
* @remarks
*
* To use this, request
* interception should be enabled with {@link Page.setRequestInterception}.
*
* Exception is immediately thrown if the request interception is not enabled.
*/
async respond(
response: Partial<ResponseForRequest>,
priority?: number,
): Promise<void> {
this.verifyInterception();
if (!this.canBeIntercepted()) {
return;
}
if (priority === undefined) {
return await this._respond(response);
}
this.interception.response = response;
if (
this.interception.resolutionState.priority === undefined ||
priority > this.interception.resolutionState.priority
) {
this.interception.resolutionState = {
action: InterceptResolutionAction.Respond,
priority,
};
return;
}
if (priority === this.interception.resolutionState.priority) {
if (this.interception.resolutionState.action === 'abort') {
return;
}
this.interception.resolutionState.action =
InterceptResolutionAction.Respond;
}
}
/**
* Aborts a request.
*
* @param errorCode - optional error code to provide.
* @param priority - If provided, intercept is resolved using
* cooperative handling rules. Otherwise, intercept is resolved
* immediately.
*
* @remarks
*
* To use this, request interception should be enabled with
* {@link Page.setRequestInterception}. If it is not enabled, this method will
* throw an exception immediately.
*/
async abort(
errorCode: ErrorCode = 'failed',
priority?: number,
): Promise<void> {
this.verifyInterception();
if (!this.canBeIntercepted()) {
return;
}
const errorReason = errorReasons[errorCode];
assert(errorReason, 'Unknown error code: ' + errorCode);
if (priority === undefined) {
return await this._abort(errorReason);
}
this.interception.abortReason = errorReason;
if (
this.interception.resolutionState.priority === undefined ||
priority >= this.interception.resolutionState.priority
) {
this.interception.resolutionState = {
action: InterceptResolutionAction.Abort,
priority,
};
return;
}
}
/**
* @internal
*/
static getResponse(body: string | Uint8Array): {
contentLength: number;
base64: string;
} {
// Needed to get the correct byteLength
const byteBody: Uint8Array = isString(body)
? new TextEncoder().encode(body)
: body;
return {
contentLength: byteBody.byteLength,
base64: typedArrayToBase64(byteBody),
};
}
}
/**
* @public
*/
export enum InterceptResolutionAction {
Abort = 'abort',
Respond = 'respond',
Continue = 'continue',
Disabled = 'disabled',
None = 'none',
AlreadyHandled = 'already-handled',
}
/**
* @public
*/
export type ErrorCode =
| 'aborted'
| 'accessdenied'
| 'addressunreachable'
| 'blockedbyclient'
| 'blockedbyresponse'
| 'connectionaborted'
| 'connectionclosed'
| 'connectionfailed'
| 'connectionrefused'
| 'connectionreset'
| 'internetdisconnected'
| 'namenotresolved'
| 'timedout'
| 'failed';
/**
* @public
*/
export type ActionResult = 'continue' | 'abort' | 'respond';
/**
* @internal
*/
export function headersArray(
headers: Record<string, string | string[]>,
): Array<{name: string; value: string}> {
const result = [];
for (const name in headers) {
const value = headers[name];
if (!Object.is(value, undefined)) {
const values = Array.isArray(value) ? value : [value];
result.push(
...values.map(value => {
return {name, value: value + ''};
}),
);
}
}
return result;
}
/**
* @internal
*
* @remarks
* List taken from {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml}
* with extra 306 and 418 codes.
*/
export const STATUS_TEXTS: Record<string, string> = {
'100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'103': 'Early Hints',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'205': 'Reset Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'208': 'Already Reported',
'226': 'IM Used',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Found',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'306': 'Switch Proxy',
'307': 'Temporary Redirect',
'308': 'Permanent Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Timeout',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Payload Too Large',
'414': 'URI Too Long',
'415': 'Unsupported Media Type',
'416': 'Range Not Satisfiable',
'417': 'Expectation Failed',
'418': "I'm a teapot",
'421': 'Misdirected Request',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'425': 'Too Early',
'426': 'Upgrade Required',
'428': 'Precondition Required',
'429': 'Too Many Requests',
'431': 'Request Header Fields Too Large',
'451': 'Unavailable For Legal Reasons',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Timeout',
'505': 'HTTP Version Not Supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'508': 'Loop Detected',
'510': 'Not Extended',
'511': 'Network Authentication Required',
} as const;
const errorReasons: Record<ErrorCode, Protocol.Network.ErrorReason> = {
aborted: 'Aborted',
accessdenied: 'AccessDenied',
addressunreachable: 'AddressUnreachable',
blockedbyclient: 'BlockedByClient',
blockedbyresponse: 'BlockedByResponse',
connectionaborted: 'ConnectionAborted',
connectionclosed: 'ConnectionClosed',
connectionfailed: 'ConnectionFailed',
connectionrefused: 'ConnectionRefused',
connectionreset: 'ConnectionReset',
internetdisconnected: 'InternetDisconnected',
namenotresolved: 'NameNotResolved',
timedout: 'TimedOut',
failed: 'Failed',
} as const;
/**
* @internal
*/
export function handleError(error: ProtocolError): void {
// Firefox throws an invalid argument error with a message starting with
// 'Expected "header" [...]'.
if (
error.originalMessage.includes('Invalid header') ||
error.originalMessage.includes('Unsafe header') ||
error.originalMessage.includes('Expected "header"') ||
// WebDriver BiDi error for invalid values, for example, headers.
error.originalMessage.includes('invalid argument')
) {
throw error;
}
// In certain cases, protocol will return error if the request was
// already canceled or the page was closed. We should tolerate these
// errors.
debugError(error);
}

148
node_modules/puppeteer-core/src/api/HTTPResponse.ts generated vendored Normal file
View File

@@ -0,0 +1,148 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type Protocol from 'devtools-protocol';
import type {SecurityDetails} from '../common/SecurityDetails.js';
import type {Frame} from './Frame.js';
import type {HTTPRequest} from './HTTPRequest.js';
/**
* @public
*/
export interface RemoteAddress {
ip?: string;
port?: number;
}
/**
* The HTTPResponse class represents responses which are received by the
* {@link Page} class.
*
* @public
*/
export abstract class HTTPResponse {
/**
* @internal
*/
constructor() {}
/**
* The IP address and port number used to connect to the remote
* server.
*/
abstract remoteAddress(): RemoteAddress;
/**
* The URL of the response.
*/
abstract url(): string;
/**
* True if the response was successful (status in the range 200-299).
*/
ok(): boolean {
// TODO: document === 0 case?
const status = this.status();
return status === 0 || (status >= 200 && status <= 299);
}
/**
* The status code of the response (e.g., 200 for a success).
*/
abstract status(): number;
/**
* The status text of the response (e.g. usually an "OK" for a
* success).
*/
abstract statusText(): string;
/**
* An object with HTTP headers associated with the response. All
* header names are lower-case.
*/
abstract headers(): Record<string, string>;
/**
* {@link SecurityDetails} if the response was received over the
* secure connection, or `null` otherwise.
*/
abstract securityDetails(): SecurityDetails | null;
/**
* Timing information related to the response.
*/
abstract timing(): Protocol.Network.ResourceTiming | null;
/**
* Promise which resolves to a buffer with response body.
*
* @remarks
*
* The buffer might be re-encoded by the browser
* based on HTTP-headers or other heuristics. If the browser
* failed to detect the correct encoding, the buffer might
* be encoded incorrectly. See
* https://github.com/puppeteer/puppeteer/issues/6478.
*/
abstract content(): Promise<Uint8Array>;
/**
* {@inheritDoc HTTPResponse.content}
*/
async buffer(): Promise<Buffer> {
const content = await this.content();
return Buffer.from(content);
}
/**
* Promise which resolves to a text (utf8) representation of response body.
*
* @remarks
*
* This method will throw if the content is not utf-8 string
*/
async text(): Promise<string> {
const content = await this.content();
return new TextDecoder('utf-8', {fatal: true}).decode(content);
}
/**
* Promise which resolves to a JSON representation of response body.
*
* @remarks
*
* This method will throw if the response body is not parsable via
* `JSON.parse`.
*/
async json(): Promise<any> {
const content = await this.text();
return JSON.parse(content);
}
/**
* A matching {@link HTTPRequest} object.
*/
abstract request(): HTTPRequest;
/**
* True if the response was served from either the browser's disk
* cache or memory cache.
*/
abstract fromCache(): boolean;
/**
* True if the response was served by a service worker.
*/
abstract fromServiceWorker(): boolean;
/**
* A {@link Frame} that initiated this response, or `null` if
* navigating to error pages.
*/
abstract frame(): Frame | null;
}

567
node_modules/puppeteer-core/src/api/Input.ts generated vendored Normal file
View File

@@ -0,0 +1,567 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {Protocol} from 'devtools-protocol';
import {TouchError} from '../common/Errors.js';
import type {KeyInput} from '../common/USKeyboardLayout.js';
import {createIncrementalIdGenerator} from '../util/incremental-id-generator.js';
import type {Point} from './ElementHandle.js';
/**
* @public
*/
export interface KeyDownOptions {
/**
* @deprecated Do not use. This is automatically handled.
*/
text?: string;
/**
* @deprecated Do not use. This is automatically handled.
*/
commands?: string[];
}
/**
* @public
*/
export interface KeyboardTypeOptions {
delay?: number;
}
/**
* @public
*/
export type KeyPressOptions = KeyDownOptions & KeyboardTypeOptions;
/**
* Keyboard provides an api for managing a virtual keyboard.
* The high level api is {@link Keyboard."type"},
* which takes raw characters and generates proper keydown, keypress/input,
* and keyup events on your page.
*
* @remarks
* For finer control, you can use {@link Keyboard.down},
* {@link Keyboard.up}, and {@link Keyboard.sendCharacter}
* to manually fire events as if they were generated from a real keyboard.
*
* On macOS, keyboard shortcuts like `⌘ A` -\> Select All do not work.
* See {@link https://github.com/puppeteer/puppeteer/issues/1313 | #1313}.
*
* @example
* An example of holding down `Shift` in order to select and delete some text:
*
* ```ts
* await page.keyboard.type('Hello World!');
* await page.keyboard.press('ArrowLeft');
*
* await page.keyboard.down('Shift');
* for (let i = 0; i < ' World'.length; i++)
* await page.keyboard.press('ArrowLeft');
* await page.keyboard.up('Shift');
*
* await page.keyboard.press('Backspace');
* // Result text will end up saying 'Hello!'
* ```
*
* @example
* An example of pressing `A`
*
* ```ts
* await page.keyboard.down('Shift');
* await page.keyboard.press('KeyA');
* await page.keyboard.up('Shift');
* ```
*
* @public
*/
export abstract class Keyboard {
/**
* @internal
*/
constructor() {}
/**
* Dispatches a `keydown` event.
*
* @remarks
* If `key` is a single character and no modifier keys besides `Shift`
* are being held down, a `keypress`/`input` event will also generated.
* The `text` option can be specified to force an input event to be generated.
* If `key` is a modifier key, `Shift`, `Meta`, `Control`, or `Alt`,
* subsequent key presses will be sent with that modifier active.
* To release the modifier key, use {@link Keyboard.up}.
*
* After the key is pressed once, subsequent calls to
* {@link Keyboard.down} will have
* {@link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat | repeat}
* set to true. To release the key, use {@link Keyboard.up}.
*
* Modifier keys DO influence {@link Keyboard.down}.
* Holding down `Shift` will type the text in upper case.
*
* @param key - Name of key to press, such as `ArrowLeft`.
* See {@link KeyInput} for a list of all key names.
*
* @param options - An object of options. Accepts text which, if specified,
* generates an input event with this text. Accepts commands which, if specified,
* is the commands of keyboard shortcuts,
* see {@link https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/editing/commands/editor_command_names.h | Chromium Source Code} for valid command names.
*/
abstract down(
key: KeyInput,
options?: Readonly<KeyDownOptions>,
): Promise<void>;
/**
* Dispatches a `keyup` event.
*
* @param key - Name of key to release, such as `ArrowLeft`.
* See {@link KeyInput | KeyInput}
* for a list of all key names.
*/
abstract up(key: KeyInput): Promise<void>;
/**
* Dispatches a `keypress` and `input` event.
* This does not send a `keydown` or `keyup` event.
*
* @remarks
* Modifier keys DO NOT effect {@link Keyboard.sendCharacter | Keyboard.sendCharacter}.
* Holding down `Shift` will not type the text in upper case.
*
* @example
*
* ```ts
* page.keyboard.sendCharacter('嗨');
* ```
*
* @param char - Character to send into the page.
*/
abstract sendCharacter(char: string): Promise<void>;
/**
* Sends a `keydown`, `keypress`/`input`,
* and `keyup` event for each character in the text.
*
* @remarks
* To press a special key, like `Control` or `ArrowDown`,
* use {@link Keyboard.press}.
*
* Modifier keys DO NOT effect `keyboard.type`.
* Holding down `Shift` will not type the text in upper case.
*
* @example
*
* ```ts
* await page.keyboard.type('Hello'); // Types instantly
* await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
* ```
*
* @param text - A text to type into a focused element.
* @param options - An object of options. Accepts delay which,
* if specified, is the time to wait between `keydown` and `keyup` in milliseconds.
* Defaults to 0.
*/
abstract type(
text: string,
options?: Readonly<KeyboardTypeOptions>,
): Promise<void>;
/**
* Shortcut for {@link Keyboard.down}
* and {@link Keyboard.up}.
*
* @remarks
* If `key` is a single character and no modifier keys besides `Shift`
* are being held down, a `keypress`/`input` event will also generated.
* The `text` option can be specified to force an input event to be generated.
*
* Modifier keys DO effect {@link Keyboard.press}.
* Holding down `Shift` will type the text in upper case.
*
* @param key - Name of key to press, such as `ArrowLeft`.
* See {@link KeyInput} for a list of all key names.
*
* @param options - An object of options. Accepts text which, if specified,
* generates an input event with this text. Accepts delay which,
* if specified, is the time to wait between `keydown` and `keyup` in milliseconds.
* Defaults to 0. Accepts commands which, if specified,
* is the commands of keyboard shortcuts,
* see {@link https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/editing/commands/editor_command_names.h | Chromium Source Code} for valid command names.
*/
abstract press(
key: KeyInput,
options?: Readonly<KeyPressOptions>,
): Promise<void>;
}
/**
* @public
*/
export interface MouseOptions {
/**
* Determines which button will be pressed.
*
* @defaultValue `'left'`
*/
button?: MouseButton;
/**
* Determines the click count for the mouse event. This does not perform
* multiple clicks.
*
* @deprecated Use {@link MouseClickOptions.count}.
* @defaultValue `1`
*/
clickCount?: number;
}
/**
* @public
*/
export interface MouseClickOptions extends MouseOptions {
/**
* Time (in ms) to delay the mouse release after the mouse press.
*/
delay?: number;
/**
* Number of clicks to perform.
*
* @defaultValue `1`
*/
count?: number;
}
/**
* @public
*/
export interface MouseWheelOptions {
deltaX?: number;
deltaY?: number;
}
/**
* @public
*/
export interface MouseMoveOptions {
/**
* Determines the number of movements to make from the current mouse position
* to the new one.
*
* @defaultValue `1`
*/
steps?: number;
}
/**
* Enum of valid mouse buttons.
*
* @public
*/
export const MouseButton = Object.freeze({
Left: 'left',
Right: 'right',
Middle: 'middle',
Back: 'back',
Forward: 'forward',
}) satisfies Record<string, Protocol.Input.MouseButton>;
/**
* @public
*/
export type MouseButton = (typeof MouseButton)[keyof typeof MouseButton];
/**
* The Mouse class operates in main-frame CSS pixels
* relative to the top-left corner of the viewport.
*
* @remarks
* Every `page` object has its own Mouse, accessible with {@link Page.mouse}.
*
* @example
*
* ```ts
* // Using page.mouse to trace a 100x100 square.
* await page.mouse.move(0, 0);
* await page.mouse.down();
* await page.mouse.move(0, 100);
* await page.mouse.move(100, 100);
* await page.mouse.move(100, 0);
* await page.mouse.move(0, 0);
* await page.mouse.up();
* ```
*
* **Note**: The mouse events trigger synthetic `MouseEvent`s.
* This means that it does not fully replicate the functionality of what a normal user
* would be able to do with their mouse.
*
* For example, dragging and selecting text is not possible using `page.mouse`.
* Instead, you can use the {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/getSelection | `DocumentOrShadowRoot.getSelection()`} functionality implemented in the platform.
*
* @example
* For example, if you want to select all content between nodes:
*
* ```ts
* await page.evaluate(
* (from, to) => {
* const selection = from.getRootNode().getSelection();
* const range = document.createRange();
* range.setStartBefore(from);
* range.setEndAfter(to);
* selection.removeAllRanges();
* selection.addRange(range);
* },
* fromJSHandle,
* toJSHandle,
* );
* ```
*
* If you then would want to copy-paste your selection, you can use the clipboard api:
*
* ```ts
* // The clipboard api does not allow you to copy, unless the tab is focused.
* await page.bringToFront();
* await page.evaluate(() => {
* // Copy the selected content to the clipboard
* document.execCommand('copy');
* // Obtain the content of the clipboard as a string
* return navigator.clipboard.readText();
* });
* ```
*
* **Note**: If you want access to the clipboard API,
* you have to give it permission to do so:
*
* ```ts
* await browser
* .defaultBrowserContext()
* .overridePermissions('<your origin>', [
* 'clipboard-read',
* 'clipboard-write',
* ]);
* ```
*
* @public
*/
export abstract class Mouse {
/**
* @internal
*/
constructor() {}
/**
* Resets the mouse to the default state: No buttons pressed; position at
* (0,0).
*/
abstract reset(): Promise<void>;
/**
* Moves the mouse to the given coordinate.
*
* @param x - Horizontal position of the mouse.
* @param y - Vertical position of the mouse.
* @param options - Options to configure behavior.
*/
abstract move(
x: number,
y: number,
options?: Readonly<MouseMoveOptions>,
): Promise<void>;
/**
* Presses the mouse.
*
* @param options - Options to configure behavior.
*/
abstract down(options?: Readonly<MouseOptions>): Promise<void>;
/**
* Releases the mouse.
*
* @param options - Options to configure behavior.
*/
abstract up(options?: Readonly<MouseOptions>): Promise<void>;
/**
* Shortcut for `mouse.move`, `mouse.down` and `mouse.up`.
*
* @param x - Horizontal position of the mouse.
* @param y - Vertical position of the mouse.
* @param options - Options to configure behavior.
*/
abstract click(
x: number,
y: number,
options?: Readonly<MouseClickOptions>,
): Promise<void>;
/**
* Dispatches a `mousewheel` event.
* @param options - Optional: `MouseWheelOptions`.
*
* @example
* An example of zooming into an element:
*
* ```ts
* await page.goto(
* 'https://mdn.mozillademos.org/en-US/docs/Web/API/Element/wheel_event$samples/Scaling_an_element_via_the_wheel?revision=1587366',
* );
*
* const elem = await page.$('div');
* const boundingBox = await elem.boundingBox();
* await page.mouse.move(
* boundingBox.x + boundingBox.width / 2,
* boundingBox.y + boundingBox.height / 2,
* );
*
* await page.mouse.wheel({deltaY: -100});
* ```
*/
abstract wheel(options?: Readonly<MouseWheelOptions>): Promise<void>;
/**
* Dispatches a `drag` event.
* @param start - starting point for drag
* @param target - point to drag to
*/
abstract drag(start: Point, target: Point): Promise<Protocol.Input.DragData>;
/**
* Dispatches a `dragenter` event.
* @param target - point for emitting `dragenter` event
* @param data - drag data containing items and operations mask
*/
abstract dragEnter(
target: Point,
data: Protocol.Input.DragData,
): Promise<void>;
/**
* Dispatches a `dragover` event.
* @param target - point for emitting `dragover` event
* @param data - drag data containing items and operations mask
*/
abstract dragOver(
target: Point,
data: Protocol.Input.DragData,
): Promise<void>;
/**
* Performs a dragenter, dragover, and drop in sequence.
* @param target - point to drop on
* @param data - drag data containing items and operations mask
*/
abstract drop(target: Point, data: Protocol.Input.DragData): Promise<void>;
/**
* Performs a drag, dragenter, dragover, and drop in sequence.
* @param start - point to drag from
* @param target - point to drop on
* @param options - An object of options. Accepts delay which,
* if specified, is the time to wait between `dragover` and `drop` in milliseconds.
* Defaults to 0.
*/
abstract dragAndDrop(
start: Point,
target: Point,
options?: {delay?: number},
): Promise<void>;
}
/**
* The TouchHandle interface exposes methods to manipulate touches that have been started
* @public
*/
export interface TouchHandle {
/**
* Dispatches a `touchMove` event for this touch.
* @param x - Horizontal position of the move.
* @param y - Vertical position of the move.
*/
move(x: number, y: number): Promise<void>;
/**
* Dispatches a `touchend` event for this touch.
*/
end(): Promise<void>;
}
/**
* The Touchscreen class exposes touchscreen events.
* @public
*/
export abstract class Touchscreen {
/**
* @internal
*/
idGenerator = createIncrementalIdGenerator();
/**
* @internal
*/
touches: TouchHandle[] = [];
/**
* @internal
*/
constructor() {}
/**
* @internal
*/
removeHandle(handle: TouchHandle): void {
const index = this.touches.indexOf(handle);
if (index === -1) {
return;
}
this.touches.splice(index, 1);
}
/**
* Dispatches a `touchstart` and `touchend` event.
* @param x - Horizontal position of the tap.
* @param y - Vertical position of the tap.
*/
async tap(x: number, y: number): Promise<void> {
const touch = await this.touchStart(x, y);
await touch.end();
}
/**
* Dispatches a `touchstart` event.
* @param x - Horizontal position of the tap.
* @param y - Vertical position of the tap.
* @returns A handle for the touch that was started.
*/
abstract touchStart(x: number, y: number): Promise<TouchHandle>;
/**
* Dispatches a `touchMove` event on the first touch that is active.
* @param x - Horizontal position of the move.
* @param y - Vertical position of the move.
*
* @remarks
*
* Not every `touchMove` call results in a `touchmove` event being emitted,
* depending on the browser's optimizations. For example, Chrome
* {@link https://developer.chrome.com/blog/a-more-compatible-smoother-touch/#chromes-new-model-the-throttled-async-touchmove-model | throttles}
* touch move events.
*/
async touchMove(x: number, y: number): Promise<void> {
const touch = this.touches[0];
if (!touch) {
throw new TouchError('Must start a new Touch first');
}
return await touch.move(x, y);
}
/**
* Dispatches a `touchend` event on the first touch that is active.
*/
async touchEnd(): Promise<void> {
const touch = this.touches.shift();
if (!touch) {
throw new TouchError('Must start a new Touch first');
}
await touch.end();
}
}

212
node_modules/puppeteer-core/src/api/JSHandle.ts generated vendored Normal file
View File

@@ -0,0 +1,212 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type Protocol from 'devtools-protocol';
import type {EvaluateFuncWith, HandleFor, HandleOr} from '../common/types.js';
import {debugError, withSourcePuppeteerURLIfNone} from '../common/util.js';
import {moveable, throwIfDisposed} from '../util/decorators.js';
import {disposeSymbol, asyncDisposeSymbol} from '../util/disposable.js';
import type {ElementHandle} from './ElementHandle.js';
import type {Realm} from './Realm.js';
/**
* Represents a reference to a JavaScript object. Instances can be created using
* {@link Page.evaluateHandle}.
*
* Handles prevent the referenced JavaScript object from being garbage-collected
* unless the handle is purposely {@link JSHandle.dispose | disposed}. JSHandles
* are auto-disposed when their associated frame is navigated away or the parent
* context gets destroyed.
*
* Handles can be used as arguments for any evaluation function such as
* {@link Page.$eval}, {@link Page.evaluate}, and {@link Page.evaluateHandle}.
* They are resolved to their referenced object.
*
* @example
*
* ```ts
* const windowHandle = await page.evaluateHandle(() => window);
* ```
*
* @public
*/
@moveable
export abstract class JSHandle<T = unknown> {
declare move: () => this;
/**
* Used for nominally typing {@link JSHandle}.
*/
declare _?: T;
/**
* @internal
*/
constructor() {}
/**
* @internal
*/
abstract get realm(): Realm;
/**
* @internal
*/
abstract get disposed(): boolean;
/**
* Evaluates the given function with the current handle as its first argument.
*/
async evaluate<
Params extends unknown[],
Func extends EvaluateFuncWith<T, Params> = EvaluateFuncWith<T, Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>> {
pageFunction = withSourcePuppeteerURLIfNone(
this.evaluate.name,
pageFunction,
);
return await this.realm.evaluate(pageFunction, this, ...args);
}
/**
* Evaluates the given function with the current handle as its first argument.
*
*/
async evaluateHandle<
Params extends unknown[],
Func extends EvaluateFuncWith<T, Params> = EvaluateFuncWith<T, Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
pageFunction = withSourcePuppeteerURLIfNone(
this.evaluateHandle.name,
pageFunction,
);
return await this.realm.evaluateHandle(pageFunction, this, ...args);
}
/**
* Fetches a single property from the referenced object.
*/
getProperty<K extends keyof T>(
propertyName: HandleOr<K>,
): Promise<HandleFor<T[K]>>;
getProperty(propertyName: string): Promise<JSHandle<unknown>>;
/**
* @internal
*/
@throwIfDisposed()
async getProperty<K extends keyof T>(
propertyName: HandleOr<K>,
): Promise<HandleFor<T[K]>> {
return await this.evaluateHandle((object, propertyName) => {
return object[propertyName as K];
}, propertyName);
}
/**
* Gets a map of handles representing the properties of the current handle.
*
* @example
*
* ```ts
* const listHandle = await page.evaluateHandle(() => document.body.children);
* const properties = await listHandle.getProperties();
* const children = [];
* for (const property of properties.values()) {
* const element = property.asElement();
* if (element) {
* children.push(element);
* }
* }
* children; // holds elementHandles to all children of document.body
* ```
*/
@throwIfDisposed()
async getProperties(): Promise<Map<string, JSHandle>> {
const propertyNames = await this.evaluate(object => {
const enumerableProperties = [];
const descriptors = Object.getOwnPropertyDescriptors(object);
for (const propertyName in descriptors) {
if (descriptors[propertyName]?.enumerable) {
enumerableProperties.push(propertyName);
}
}
return enumerableProperties;
});
const map = new Map<string, JSHandle>();
const results = await Promise.all(
propertyNames.map(key => {
return this.getProperty(key);
}),
);
for (const [key, value] of Object.entries(propertyNames)) {
using handle = results[key as any];
if (handle) {
map.set(value, handle.move());
}
}
return map;
}
/**
* A vanilla object representing the serializable portions of the
* referenced object.
* @throws Throws if the object cannot be serialized due to circularity.
*
* @remarks
* If the object has a `toJSON` function, it **will not** be called.
*/
abstract jsonValue(): Promise<T>;
/**
* Either `null` or the handle itself if the handle is an
* instance of {@link ElementHandle}.
*/
abstract asElement(): ElementHandle<Node> | null;
/**
* Releases the object referenced by the handle for garbage collection.
*/
abstract dispose(): Promise<void>;
/**
* Returns a string representation of the JSHandle.
*
* @remarks
* Useful during debugging.
*/
abstract toString(): string;
/**
* @internal
*/
abstract get id(): string | undefined;
/**
* Provides access to the
* {@link https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-RemoteObject | Protocol.Runtime.RemoteObject}
* backing this handle.
*/
abstract remoteObject(): Protocol.Runtime.RemoteObject;
/** @internal */
[disposeSymbol](): void {
return void this.dispose().catch(debugError);
}
/** @internal */
[asyncDisposeSymbol](): Promise<void> {
return this.dispose();
}
}

3276
node_modules/puppeteer-core/src/api/Page.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff

108
node_modules/puppeteer-core/src/api/Realm.ts generated vendored Normal file
View File

@@ -0,0 +1,108 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {TimeoutSettings} from '../common/TimeoutSettings.js';
import type {
EvaluateFunc,
HandleFor,
InnerLazyParams,
} 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 {JSHandle} from './JSHandle.js';
/**
* @internal
*/
export abstract class Realm implements Disposable {
protected readonly timeoutSettings: TimeoutSettings;
readonly taskManager = new TaskManager();
constructor(timeoutSettings: TimeoutSettings) {
this.timeoutSettings = timeoutSettings;
}
abstract get environment(): Environment;
abstract adoptHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
abstract transferHandle<T extends JSHandle<Node>>(handle: T): Promise<T>;
abstract evaluateHandle<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
abstract evaluate<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(
pageFunction: Func | string,
...args: Params
): Promise<Awaited<ReturnType<Func>>>;
async 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 await waitTask.result;
}
abstract adoptBackendNode(backendNodeId?: number): Promise<JSHandle<Node>>;
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();
}
}

95
node_modules/puppeteer-core/src/api/Target.ts generated vendored Normal file
View File

@@ -0,0 +1,95 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type {Browser} from './Browser.js';
import type {BrowserContext} from './BrowserContext.js';
import type {CDPSession} from './CDPSession.js';
import type {Page} from './Page.js';
import type {WebWorker} from './WebWorker.js';
/**
* @public
*/
export enum TargetType {
PAGE = 'page',
BACKGROUND_PAGE = 'background_page',
SERVICE_WORKER = 'service_worker',
SHARED_WORKER = 'shared_worker',
BROWSER = 'browser',
WEBVIEW = 'webview',
OTHER = 'other',
/**
* @internal
*/
TAB = 'tab',
}
/**
* Target represents a
* {@link https://chromedevtools.github.io/devtools-protocol/tot/Target/ | CDP target}.
* In CDP a target is something that can be debugged such a frame, a page or a
* worker.
* @public
*/
export abstract class Target {
/**
* @internal
*/
protected constructor() {}
/**
* If the target is not of type `"service_worker"` or `"shared_worker"`, returns `null`.
*/
async worker(): Promise<WebWorker | null> {
return null;
}
/**
* If the target is not of type `"page"`, `"webview"` or `"background_page"`,
* returns `null`.
*/
async page(): Promise<Page | null> {
return null;
}
/**
* Forcefully creates a page for a target of any type. It is useful if you
* want to handle a CDP target of type `other` as a page. If you deal with a
* regular page target, use {@link Target.page}.
*/
abstract asPage(): Promise<Page>;
abstract url(): string;
/**
* Creates a Chrome Devtools Protocol session attached to the target.
*/
abstract createCDPSession(): Promise<CDPSession>;
/**
* Identifies what kind of target this is.
*
* @remarks
*
* See {@link https://developer.chrome.com/extensions/background_pages | docs} for more info about background pages.
*/
abstract type(): TargetType;
/**
* Get the browser the target belongs to.
*/
abstract browser(): Browser;
/**
* Get the browser context the target belongs to.
*/
abstract browserContext(): BrowserContext;
/**
* Get the target that opened this target. Top-level targets return `null`.
*/
abstract opener(): Target | undefined;
}

139
node_modules/puppeteer-core/src/api/WebWorker.ts generated vendored Normal file
View File

@@ -0,0 +1,139 @@
/**
* @license
* Copyright 2018 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import {UnsupportedOperation} from '../common/Errors.js';
import {EventEmitter, type EventType} from '../common/EventEmitter.js';
import {TimeoutSettings} from '../common/TimeoutSettings.js';
import type {EvaluateFunc, HandleFor} from '../common/types.js';
import {withSourcePuppeteerURLIfNone} from '../common/util.js';
import type {CDPSession} from './CDPSession.js';
import type {Realm} from './Realm.js';
/**
* This class represents a
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}.
*
* @remarks
* The events `workercreated` and `workerdestroyed` are emitted on the page
* object to signal the worker lifecycle.
*
* @example
*
* ```ts
* page.on('workercreated', worker =>
* console.log('Worker created: ' + worker.url()),
* );
* page.on('workerdestroyed', worker =>
* console.log('Worker destroyed: ' + worker.url()),
* );
*
* console.log('Current workers:');
* for (const worker of page.workers()) {
* console.log(' ' + worker.url());
* }
* ```
*
* @public
*/
export abstract class WebWorker extends EventEmitter<
Record<EventType, unknown>
> {
/**
* @internal
*/
readonly timeoutSettings = new TimeoutSettings();
readonly #url: string;
/**
* @internal
*/
constructor(url: string) {
super();
this.#url = url;
}
/**
* @internal
*/
abstract mainRealm(): Realm;
/**
* The URL of this web worker.
*/
url(): string {
return this.#url;
}
/**
* The CDP session client the WebWorker belongs to.
*/
abstract get client(): CDPSession;
/**
* Evaluates a given function in the {@link WebWorker | worker}.
*
* @remarks If the given function returns a promise,
* {@link WebWorker.evaluate | evaluate} will wait for the promise to resolve.
*
* As a rule of thumb, if the return value of the given function is more
* complicated than a JSON object (e.g. most classes), then
* {@link WebWorker.evaluate | evaluate} will _likely_ return some truncated
* value (or `{}`). This is because we are not returning the actual return
* value, but a deserialized version as a result of transferring the return
* value through a protocol to Puppeteer.
*
* In general, you should use
* {@link WebWorker.evaluateHandle | evaluateHandle} if
* {@link WebWorker.evaluate | evaluate} cannot serialize the return value
* properly or you need a mutable {@link JSHandle | handle} to the return
* object.
*
* @param func - Function to be evaluated.
* @param args - Arguments to pass into `func`.
* @returns The result of `func`.
*/
async evaluate<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(func: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>> {
func = withSourcePuppeteerURLIfNone(this.evaluate.name, func);
return await this.mainRealm().evaluate(func, ...args);
}
/**
* Evaluates a given function in the {@link WebWorker | worker}.
*
* @remarks If the given function returns a promise,
* {@link WebWorker.evaluate | evaluate} will wait for the promise to resolve.
*
* In general, you should use
* {@link WebWorker.evaluateHandle | evaluateHandle} if
* {@link WebWorker.evaluate | evaluate} cannot serialize the return value
* properly or you need a mutable {@link JSHandle | handle} to the return
* object.
*
* @param func - Function to be evaluated.
* @param args - Arguments to pass into `func`.
* @returns A {@link JSHandle | handle} to the return value of `func`.
*/
async evaluateHandle<
Params extends unknown[],
Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
>(
func: Func | string,
...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
func = withSourcePuppeteerURLIfNone(this.evaluateHandle.name, func);
return await this.mainRealm().evaluateHandle(func, ...args);
}
async close(): Promise<void> {
throw new UnsupportedOperation('WebWorker.close() is not supported');
}
}

24
node_modules/puppeteer-core/src/api/api.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
export type * from './BluetoothEmulation.js';
export * from './Browser.js';
export * from './BrowserContext.js';
export * from './CDPSession.js';
export * from './DeviceRequestPrompt.js';
export * from './Dialog.js';
export * from './ElementHandle.js';
export type * from './Environment.js';
export * from './Frame.js';
export * from './HTTPRequest.js';
export * from './HTTPResponse.js';
export * from './Input.js';
export * from './JSHandle.js';
export * from './Page.js';
export * from './Realm.js';
export * from './Target.js';
export * from './WebWorker.js';
export * from './locators/locators.js';

1149
node_modules/puppeteer-core/src/api/locators/locators.ts generated vendored Normal file

File diff suppressed because it is too large Load Diff