This commit is contained in:
nik
2025-10-03 22:27:28 +03:00
parent 829fad0e17
commit 871cf7e792
16520 changed files with 2967597 additions and 3 deletions

View File

@@ -0,0 +1,371 @@
/// <reference types="node" preserve="true" />
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { ChildProcess } from 'child_process';
import type { Protocol } from 'devtools-protocol';
import type { ProtocolType } from '../common/ConnectOptions.js';
import type { Cookie } from '../common/Cookie.js';
import type { DownloadBehavior } from '../common/DownloadBehavior.js';
import { EventEmitter, type EventType } from '../common/EventEmitter.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 declare const WEB_PERMISSION_TO_PROTOCOL_PERMISSION: Map<Permission, Protocol.Browser.PermissionType>;
/**
* @public
*/
export type Permission = 'geolocation' | 'midi' | 'notifications' | 'camera' | 'microphone' | 'background-sync' | 'ambient-light-sensor' | 'accelerometer' | 'gyroscope' | 'magnetometer' | 'accessibility-events' | 'clipboard-read' | 'clipboard-write' | 'clipboard-sanitized-write' | 'payment-handler' | 'persistent-storage' | 'idle-detection' | 'midi-sysex';
/**
* @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 declare 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[];
}
/**
* {@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 declare abstract class Browser extends EventEmitter<BrowserEvents> {
/**
* @internal
*/
constructor();
/**
* 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(): Promise<Page>;
/**
* 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/',
* );
* ```
*/
waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: WaitForTargetOptions): Promise<Target>;
/**
* 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}.
*
* @remarks Non-visible {@link Page | pages}, such as `"background_page"`,
* will not be listed here. You can find them using {@link Target.page}.
*/
pages(): Promise<Page[]>;
/**
* 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}.
*
*/
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()}.
*/
cookies(): Promise<Cookie[]>;
/**
* Sets cookies in the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.setCookie | browser.defaultBrowserContext().setCookie()}.
*/
setCookie(...cookies: Cookie[]): Promise<void>;
/**
* Removes cookies from the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.deleteCookie | browser.defaultBrowserContext().deleteCookie()}.
*/
deleteCookie(...cookies: Cookie[]): Promise<void>;
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*
* @deprecated Use {@link Browser | Browser.connected}.
*/
isConnected(): boolean;
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*/
abstract get connected(): boolean;
/** @internal */
[disposeSymbol](): void;
/** @internal */
[asyncDisposeSymbol](): Promise<void>;
/**
* @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;
}
//# sourceMappingURL=Browser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../../../../src/api/Browser.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,175 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Browser = exports.WEB_PERMISSION_TO_PROTOCOL_PERMISSION = void 0;
const rxjs_js_1 = require("../../third_party/rxjs/rxjs.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const disposable_js_1 = require("../util/disposable.js");
/**
* @internal
*/
exports.WEB_PERMISSION_TO_PROTOCOL_PERMISSION = new Map([
['geolocation', 'geolocation'],
['midi', 'midi'],
['notifications', 'notifications'],
// TODO: push isn't a valid type?
// ['push', 'push'],
['camera', 'videoCapture'],
['microphone', 'audioCapture'],
['background-sync', 'backgroundSync'],
['ambient-light-sensor', 'sensors'],
['accelerometer', 'sensors'],
['gyroscope', 'sensors'],
['magnetometer', 'sensors'],
['accessibility-events', 'accessibilityEvents'],
['clipboard-read', 'clipboardReadWrite'],
['clipboard-write', 'clipboardReadWrite'],
['clipboard-sanitized-write', 'clipboardSanitizedWrite'],
['payment-handler', 'paymentHandler'],
['persistent-storage', 'durableStorage'],
['idle-detection', 'idleDetection'],
// chrome-specific permissions we have.
['midi-sysex', 'midiSysex'],
]);
/**
* {@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
*/
class Browser extends EventEmitter_js_1.EventEmitter {
/**
* @internal
*/
constructor() {
super();
}
/**
* 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, options = {}) {
const { timeout: ms = 30000, signal } = options;
return await (0, rxjs_js_1.firstValueFrom)((0, rxjs_js_1.merge)((0, util_js_1.fromEmitterEvent)(this, "targetcreated" /* BrowserEvent.TargetCreated */), (0, util_js_1.fromEmitterEvent)(this, "targetchanged" /* BrowserEvent.TargetChanged */), (0, rxjs_js_1.from)(this.targets())).pipe((0, util_js_1.filterAsync)(predicate), (0, rxjs_js_1.raceWith)((0, util_js_1.fromAbortSignal)(signal), (0, util_js_1.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}.
*
* @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() {
const contextPages = await Promise.all(this.browserContexts().map(context => {
return context.pages();
}));
// Flatten array.
return contextPages.reduce((acc, x) => {
return acc.concat(x);
}, []);
}
/**
* Returns all cookies in the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.cookies | browser.defaultBrowserContext().cookies()}.
*/
async cookies() {
return await this.defaultBrowserContext().cookies();
}
/**
* Sets cookies in the default {@link BrowserContext}.
*
* @remarks
*
* Shortcut for
* {@link BrowserContext.setCookie | browser.defaultBrowserContext().setCookie()}.
*/
async setCookie(...cookies) {
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) {
return await this.defaultBrowserContext().deleteCookie(...cookies);
}
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*
* @deprecated Use {@link Browser | Browser.connected}.
*/
isConnected() {
return this.connected;
}
/** @internal */
[disposable_js_1.disposeSymbol]() {
if (this.process()) {
return void this.close().catch(util_js_1.debugError);
}
return void this.disconnect().catch(util_js_1.debugError);
}
/** @internal */
[disposable_js_1.asyncDisposeSymbol]() {
if (this.process()) {
return this.close();
}
return this.disconnect();
}
}
exports.Browser = Browser;
//# sourceMappingURL=Browser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Browser.js","sourceRoot":"","sources":["../../../../src/api/Browser.ts"],"names":[],"mappings":";;;AAUA,4DAKwC;AAIxC,+DAAuE;AACvE,+CAM2B;AAC3B,yDAAwE;AA0CxE;;GAEG;AACU,QAAA,qCAAqC,GAAG,IAAI,GAAG,CAG1D;IACA,CAAC,aAAa,EAAE,aAAa,CAAC;IAC9B,CAAC,MAAM,EAAE,MAAM,CAAC;IAChB,CAAC,eAAe,EAAE,eAAe,CAAC;IAClC,iCAAiC;IACjC,oBAAoB;IACpB,CAAC,QAAQ,EAAE,cAAc,CAAC;IAC1B,CAAC,YAAY,EAAE,cAAc,CAAC;IAC9B,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;IACrC,CAAC,sBAAsB,EAAE,SAAS,CAAC;IACnC,CAAC,eAAe,EAAE,SAAS,CAAC;IAC5B,CAAC,WAAW,EAAE,SAAS,CAAC;IACxB,CAAC,cAAc,EAAE,SAAS,CAAC;IAC3B,CAAC,sBAAsB,EAAE,qBAAqB,CAAC;IAC/C,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;IACxC,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACzC,CAAC,2BAA2B,EAAE,yBAAyB,CAAC;IACxD,CAAC,iBAAiB,EAAE,gBAAgB,CAAC;IACrC,CAAC,oBAAoB,EAAE,gBAAgB,CAAC;IACxC,CAAC,gBAAgB,EAAE,eAAe,CAAC;IACnC,uCAAuC;IACvC,CAAC,YAAY,EAAE,WAAW,CAAC;CAC5B,CAAC,CAAC;AA+GH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAsB,OAAQ,SAAQ,8BAA2B;IAC/D;;OAEG;IACH;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAsFD;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,aAAa,CACjB,SAAoD,EACpD,UAAgC,EAAE;QAElC,MAAM,EAAC,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,MAAM,EAAC,GAAG,OAAO,CAAC;QAC9C,OAAO,MAAM,IAAA,wBAAc,EACzB,IAAA,eAAK,EACH,IAAA,0BAAgB,EAAC,IAAI,mDAA6B,EAClD,IAAA,0BAAgB,EAAC,IAAI,mDAA6B,EAClD,IAAA,cAAI,EAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CACrB,CAAC,IAAI,CACJ,IAAA,qBAAW,EAAC,SAAS,CAAC,EACtB,IAAA,kBAAQ,EAAC,IAAA,yBAAe,EAAC,MAAM,CAAC,EAAE,IAAA,iBAAO,EAAC,EAAE,CAAC,CAAC,CAC/C,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,KAAK;QACT,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CACpC,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACnC,OAAO,OAAO,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC,CAAC,CACH,CAAC;QACF,iBAAiB;QACjB,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACpC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAoCD;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO;QACX,OAAO,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,OAAO,EAAE,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,SAAS,CAAC,GAAG,OAAiB;QAClC,OAAO,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC;IAClE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAAC,GAAG,OAAiB;QACrC,OAAO,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,CAAC;IACrE,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAOD,gBAAgB;IACP,CAAC,6BAAa,CAAC;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnB,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;IAClD,CAAC;IAED,gBAAgB;IAChB,CAAC,kCAAkB,CAAC;QAClB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;IAC3B,CAAC;CAkBF;AAtQD,0BAsQC"}

View File

@@ -0,0 +1,206 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Cookie, CookieData } from '../common/Cookie.js';
import { EventEmitter, type EventType } from '../common/EventEmitter.js';
import { asyncDisposeSymbol, disposeSymbol } from '../util/disposable.js';
import { Mutex } from '../util/Mutex.js';
import type { Browser, Permission, WaitForTargetOptions } from './Browser.js';
import type { Page } from './Page.js';
import type { Target } from './Target.js';
/**
* @public
*/
export declare 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 declare abstract class BrowserContext extends EventEmitter<BrowserContextEvents> {
#private;
/**
* @internal
*/
constructor();
/**
* Gets all active {@link Target | targets} inside this
* {@link BrowserContext | browser context}.
*/
abstract targets(): Target[];
/**
* @internal
*/
startScreenshot(): Promise<InstanceType<typeof Mutex.Guard>>;
/**
* @internal
*/
waitForScreenshotOperations(): Promise<InstanceType<typeof Mutex.Guard>> | undefined;
/**
* 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/',
* );
* ```
*/
waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: WaitForTargetOptions): Promise<Target>;
/**
* Gets a list of all open {@link Page | pages} inside this
* {@link BrowserContext | browser context}.
*
* @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(): 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.
*/
abstract overridePermissions(origin: string, permissions: Permission[]): 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(): 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 the browser context
* @param cookies - {@link Cookie | cookie} to remove
*/
deleteCookie(...cookies: Cookie[]): Promise<void>;
/**
* Whether this {@link BrowserContext | browser context} is closed.
*/
get closed(): boolean;
/**
* Identifier for this {@link BrowserContext | browser context}.
*/
get id(): string | undefined;
/** @internal */
[disposeSymbol](): void;
/** @internal */
[asyncDisposeSymbol](): Promise<void>;
}
//# sourceMappingURL=BrowserContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowserContext.d.ts","sourceRoot":"","sources":["../../../../src/api/BrowserContext.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,138 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserContext = void 0;
const rxjs_js_1 = require("../../third_party/rxjs/rxjs.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const disposable_js_1 = require("../util/disposable.js");
const Mutex_js_1 = require("../util/Mutex.js");
/**
* {@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
*/
class BrowserContext extends EventEmitter_js_1.EventEmitter {
/**
* @internal
*/
constructor() {
super();
}
/**
* If defined, indicates an ongoing screenshot opereation.
*/
#pageScreenshotMutex;
#screenshotOperationsCount = 0;
/**
* @internal
*/
startScreenshot() {
const mutex = this.#pageScreenshotMutex || new Mutex_js_1.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() {
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, options = {}) {
const { timeout: ms = 30000 } = options;
return await (0, rxjs_js_1.firstValueFrom)((0, rxjs_js_1.merge)((0, util_js_1.fromEmitterEvent)(this, "targetcreated" /* BrowserContextEvent.TargetCreated */), (0, util_js_1.fromEmitterEvent)(this, "targetchanged" /* BrowserContextEvent.TargetChanged */), (0, rxjs_js_1.from)(this.targets())).pipe((0, util_js_1.filterAsync)(predicate), (0, rxjs_js_1.raceWith)((0, util_js_1.timeout)(ms))));
}
/**
* Removes cookie in the browser context
* @param cookies - {@link Cookie | cookie} to remove
*/
async deleteCookie(...cookies) {
return await this.setCookie(...cookies.map(cookie => {
return {
...cookie,
expires: 1,
};
}));
}
/**
* Whether this {@link BrowserContext | browser context} is closed.
*/
get closed() {
return !this.browser().browserContexts().includes(this);
}
/**
* Identifier for this {@link BrowserContext | browser context}.
*/
get id() {
return undefined;
}
/** @internal */
[disposable_js_1.disposeSymbol]() {
return void this.close().catch(util_js_1.debugError);
}
/** @internal */
[disposable_js_1.asyncDisposeSymbol]() {
return this.close();
}
}
exports.BrowserContext = BrowserContext;
//# sourceMappingURL=BrowserContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowserContext.js","sourceRoot":"","sources":["../../../../src/api/BrowserContext.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,4DAKwC;AAExC,+DAAuE;AACvE,+CAK2B;AAC3B,yDAAwE;AACxE,+CAAuC;AAyCvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAsB,cAAe,SAAQ,8BAAkC;IAC7E;;OAEG;IACH;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAQD;;OAEG;IACH,oBAAoB,CAAS;IAC7B,0BAA0B,GAAG,CAAC,CAAC;IAE/B;;OAEG;IACH,eAAe;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,IAAI,IAAI,gBAAK,EAAE,CAAC;QACvD,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YACxB,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,0BAA0B,KAAK,CAAC,EAAE,CAAC;gBAC1C,gEAAgE;gBAChE,IAAI,CAAC,oBAAoB,GAAG,SAAS,CAAC;YACxC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,2BAA2B;QAGzB,OAAO,IAAI,CAAC,oBAAoB,EAAE,OAAO,EAAE,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,aAAa,CACjB,SAAoD,EACpD,UAAgC,EAAE;QAElC,MAAM,EAAC,OAAO,EAAE,EAAE,GAAG,KAAK,EAAC,GAAG,OAAO,CAAC;QACtC,OAAO,MAAM,IAAA,wBAAc,EACzB,IAAA,eAAK,EACH,IAAA,0BAAgB,EAAC,IAAI,0DAAoC,EACzD,IAAA,0BAAgB,EAAC,IAAI,0DAAoC,EACzD,IAAA,cAAI,EAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CACrB,CAAC,IAAI,CAAC,IAAA,qBAAW,EAAC,SAAS,CAAC,EAAE,IAAA,kBAAQ,EAAC,IAAA,iBAAO,EAAC,EAAE,CAAC,CAAC,CAAC,CACtD,CAAC;IACJ,CAAC;IAmFD;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,GAAG,OAAiB;QACrC,OAAO,MAAM,IAAI,CAAC,SAAS,CACzB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YACtB,OAAO;gBACL,GAAG,MAAM;gBACT,OAAO,EAAE,CAAC;aACX,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,IAAI,MAAM;QACR,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,IAAI,EAAE;QACJ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,gBAAgB;IACP,CAAC,6BAAa,CAAC;QACtB,OAAO,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;IAC7C,CAAC;IAED,gBAAgB;IAChB,CAAC,kCAAkB,CAAC;QAClB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF;AAjMD,wCAiMC"}

View File

@@ -0,0 +1,105 @@
/**
* @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
*/
export declare namespace CDPSessionEvent {
/** @internal */
const Disconnected: unique symbol;
/** @internal */
const Swapped: unique symbol;
/**
* 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
*/
const Ready: unique symbol;
const SessionAttached: "sessionattached";
const SessionDetached: "sessiondetached";
}
/**
* @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 declare abstract class CDPSession extends EventEmitter<CDPSessionEvents> {
/**
* @internal
*/
constructor();
abstract connection(): Connection | undefined;
/**
* Parent session in terms of CDP's auto-attach mechanism.
*
* @internal
*/
parentSession(): CDPSession | 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;
}
//# sourceMappingURL=CDPSession.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CDPSession.d.ts","sourceRoot":"","sources":["../../../../src/api/CDPSession.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,6CAA6C,CAAC;AAEjF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAC,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,2BAA2B,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;KACrB,QAAQ,IAAI,MAAM,eAAe,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CAChF,CAAC;AAEF;;;;GAIG;AAEH,yBAAiB,eAAe,CAAC;IAC/B,gBAAgB;IACT,MAAM,YAAY,eAAoC,CAAC;IAC9D,gBAAgB;IACT,MAAM,OAAO,eAA+B,CAAC;IACpD;;;;;OAKG;IACI,MAAM,KAAK,eAA6B,CAAC;IACzC,MAAM,eAAe,EAAG,iBAA0B,CAAC;IACnD,MAAM,eAAe,EAAG,iBAA0B,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,SAAS,EACf,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,gBAAgB;IAChB,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;IAC1C,gBAAgB;IAChB,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IACtC,gBAAgB;IAChB,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACpC,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;IAC9C,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,8BAAsB,UAAW,SAAQ,YAAY,CAAC,gBAAgB,CAAC;IACrE;;OAEG;;IAKH,QAAQ,CAAC,UAAU,IAAI,UAAU,GAAG,SAAS;IAE7C;;;;OAIG;IACH,aAAa,IAAI,UAAU,GAAG,SAAS;IAIvC,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EACpD,MAAM,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EACrD,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAErD;;;OAGG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC;;OAEG;IACH,QAAQ,CAAC,EAAE,IAAI,MAAM;CACtB"}

View File

@@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CDPSession = exports.CDPSessionEvent = void 0;
const EventEmitter_js_1 = require("../common/EventEmitter.js");
/**
* Events that the CDPSession class emits.
*
* @public
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var CDPSessionEvent;
(function (CDPSessionEvent) {
/** @internal */
CDPSessionEvent.Disconnected = Symbol('CDPSession.Disconnected');
/** @internal */
CDPSessionEvent.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
*/
CDPSessionEvent.Ready = Symbol('CDPSession.Ready');
CDPSessionEvent.SessionAttached = 'sessionattached';
CDPSessionEvent.SessionDetached = 'sessiondetached';
})(CDPSessionEvent || (exports.CDPSessionEvent = CDPSessionEvent = {}));
/**
* 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
*/
class CDPSession extends EventEmitter_js_1.EventEmitter {
/**
* @internal
*/
constructor() {
super();
}
/**
* Parent session in terms of CDP's auto-attach mechanism.
*
* @internal
*/
parentSession() {
return undefined;
}
}
exports.CDPSession = CDPSession;
//# sourceMappingURL=CDPSession.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CDPSession.js","sourceRoot":"","sources":["../../../../src/api/CDPSession.ts"],"names":[],"mappings":";;;AAQA,+DAAuE;AASvE;;;;GAIG;AACH,2DAA2D;AAC3D,IAAiB,eAAe,CAc/B;AAdD,WAAiB,eAAe;IAC9B,gBAAgB;IACH,4BAAY,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAC9D,gBAAgB;IACH,uBAAO,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpD;;;;;OAKG;IACU,qBAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;IACnC,+BAAe,GAAG,iBAA0B,CAAC;IAC7C,+BAAe,GAAG,iBAA0B,CAAC;AAC5D,CAAC,EAdgB,eAAe,+BAAf,eAAe,QAc/B;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAsB,UAAW,SAAQ,8BAA8B;IACrE;;OAEG;IACH;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAID;;;;OAIG;IACH,aAAa;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;CAkBF;AAnCD,gCAmCC"}

View File

@@ -0,0 +1,74 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Protocol } from 'devtools-protocol';
/**
* Dialog instances are dispatched by the {@link Page} via the `dialog` event.
*
* @remarks
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* 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();
* });
* page.evaluate(() => alert('1'));
* })();
* ```
*
* @public
*/
export declare abstract class Dialog {
#private;
/**
* @internal
*/
protected handled: boolean;
/**
* @internal
*/
constructor(type: Protocol.Page.DialogType, message: string, defaultValue?: string);
/**
* The type of the dialog.
*/
type(): Protocol.Page.DialogType;
/**
* The message displayed in the dialog.
*/
message(): string;
/**
* The default value of the prompt, or an empty string if the dialog
* is not a `prompt`.
*/
defaultValue(): string;
/**
* @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`.
*
*/
accept(promptText?: string): Promise<void>;
/**
* A promise which will resolve once the dialog has been dismissed
*/
dismiss(): Promise<void>;
}
//# sourceMappingURL=Dialog.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../../src/api/Dialog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAIhD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,MAAM;;IAI1B;;OAEG;IACH,SAAS,CAAC,OAAO,UAAS;IAE1B;;OAEG;gBAED,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,EAC9B,OAAO,EAAE,MAAM,EACf,YAAY,SAAK;IAOnB;;OAEG;IACH,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU;IAIhC;;OAEG;IACH,OAAO,IAAI,MAAM;IAIjB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE;QACjC,MAAM,EAAE,OAAO,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjB;;;;;;OAMG;IACG,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAO/B"}

View File

@@ -0,0 +1,96 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Dialog = void 0;
const assert_js_1 = require("../util/assert.js");
/**
* Dialog instances are dispatched by the {@link Page} via the `dialog` event.
*
* @remarks
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* 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();
* });
* page.evaluate(() => alert('1'));
* })();
* ```
*
* @public
*/
class Dialog {
#type;
#message;
#defaultValue;
/**
* @internal
*/
handled = false;
/**
* @internal
*/
constructor(type, message, defaultValue = '') {
this.#type = type;
this.#message = message;
this.#defaultValue = defaultValue;
}
/**
* The type of the dialog.
*/
type() {
return this.#type;
}
/**
* The message displayed in the dialog.
*/
message() {
return this.#message;
}
/**
* The default value of the prompt, or an empty string if the dialog
* is not a `prompt`.
*/
defaultValue() {
return this.#defaultValue;
}
/**
* 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) {
(0, assert_js_1.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() {
(0, assert_js_1.assert)(!this.handled, 'Cannot dismiss dialog which is already handled!');
this.handled = true;
await this.handle({
accept: false,
});
}
}
exports.Dialog = Dialog;
//# sourceMappingURL=Dialog.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Dialog.js","sourceRoot":"","sources":["../../../../src/api/Dialog.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAIH,iDAAyC;AAEzC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAsB,MAAM;IAC1B,KAAK,CAA2B;IAChC,QAAQ,CAAS;IACjB,aAAa,CAAS;IACtB;;OAEG;IACO,OAAO,GAAG,KAAK,CAAC;IAE1B;;OAEG;IACH,YACE,IAA8B,EAC9B,OAAe,EACf,YAAY,GAAG,EAAE;QAEjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAUD;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,UAAmB;QAC9B,IAAA,kBAAM,EAAC,CAAC,IAAI,CAAC,OAAO,EAAE,gDAAgD,CAAC,CAAC;QACxE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,IAAI,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,UAAU;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,IAAA,kBAAM,EAAC,CAAC,IAAI,CAAC,OAAO,EAAE,iDAAiD,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,MAAM,IAAI,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;CACF;AA9ED,wBA8EC"}

View File

@@ -0,0 +1,650 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Protocol } from 'devtools-protocol';
import type { Frame } from '../api/Frame.js';
import type { AwaitableIterable, ElementFor, EvaluateFuncWith, HandleFor, HandleOr, NodeFor } from '../common/types.js';
import type { KeyInput } from '../common/USKeyboardLayout.js';
import { _isElementHandle } from './ElementHandleSymbol.js';
import type { KeyboardTypeOptions, KeyPressOptions, MouseClickOptions, TouchHandle } from './Input.js';
import { JSHandle } from './JSHandle.js';
import type { QueryOptions, ScreenshotOptions, WaitForSelectorOptions } from './Page.js';
/**
* @public
*/
export type Quad = [Point, Point, Point, Point];
/**
* @public
*/
export interface BoxModel {
content: Quad;
padding: Quad;
border: Quad;
margin: Quad;
width: number;
height: number;
}
/**
* @public
*/
export interface BoundingBox extends Point {
/**
* the width of the element in pixels.
*/
width: number;
/**
* the height of the element in pixels.
*/
height: number;
}
/**
* @public
*/
export interface Offset {
/**
* x-offset for the clickable point relative to the top-left corner of the border box.
*/
x: number;
/**
* y-offset for the clickable point relative to the top-left corner of the border box.
*/
y: number;
}
/**
* @public
*/
export interface ClickOptions extends MouseClickOptions {
/**
* Offset for the clickable point relative to the top-left corner of the border box.
*/
offset?: Offset;
}
/**
* @public
*/
export interface Point {
x: number;
y: number;
}
/**
* @public
*/
export interface ElementScreenshotOptions extends ScreenshotOptions {
/**
* @defaultValue `true`
*/
scrollIntoView?: boolean;
}
/**
* A given method will have it's `this` replaced with an isolated version of
* `this` when decorated with this decorator.
*
* All changes of isolated `this` are reflected on the actual `this`.
*
* @internal
*/
export declare function bindIsolatedHandle<This extends ElementHandle<Node>>(target: (this: This, ...args: any[]) => Promise<any>, _: unknown): typeof target;
/**
* ElementHandle represents an in-page DOM element.
*
* @remarks
* ElementHandles can be created with the {@link Page.$} method.
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.goto('https://example.com');
* const hrefElement = await page.$('a');
* await hrefElement.click();
* // ...
* })();
* ```
*
* ElementHandle prevents the DOM element from being garbage-collected unless the
* handle is {@link JSHandle.dispose | disposed}. ElementHandles are auto-disposed
* when their origin frame gets navigated.
*
* ElementHandle instances can be used as arguments in {@link Page.$eval} and
* {@link Page.evaluate} methods.
*
* If you're using TypeScript, ElementHandle takes a generic argument that
* denotes the type of element the handle is holding within. For example, if you
* have a handle to a `<select>` element, you can type it as
* `ElementHandle<HTMLSelectElement>` and you get some nicer type checks.
*
* @public
*/
export declare abstract class ElementHandle<ElementType extends Node = Element> extends JSHandle<ElementType> {
#private;
/**
* @internal
*/
[_isElementHandle]: boolean;
/**
* @internal
* Cached isolatedHandle to prevent
* trying to adopt it multiple times
*/
isolatedHandle?: typeof this;
/**
* @internal
*/
protected readonly handle: JSHandle<ElementType>;
/**
* @internal
*/
constructor(handle: JSHandle<ElementType>);
/**
* @internal
*/
get id(): string | undefined;
/**
* @internal
*/
get disposed(): boolean;
/**
* @internal
*/
getProperty<K extends keyof ElementType>(propertyName: HandleOr<K>): Promise<HandleFor<ElementType[K]>>;
/**
* @internal
*/
getProperties(): Promise<Map<string, JSHandle>>;
/**
* @internal
*/
evaluate<Params extends unknown[], Func extends EvaluateFuncWith<ElementType, Params> = EvaluateFuncWith<ElementType, Params>>(pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* @internal
*/
evaluateHandle<Params extends unknown[], Func extends EvaluateFuncWith<ElementType, Params> = EvaluateFuncWith<ElementType, Params>>(pageFunction: Func | string, ...args: Params): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
/**
* @internal
*/
jsonValue(): Promise<ElementType>;
/**
* @internal
*/
toString(): string;
/**
* @internal
*/
remoteObject(): Protocol.Runtime.RemoteObject;
/**
* @internal
*/
dispose(): Promise<void>;
/**
* @internal
*/
asElement(): ElementHandle<ElementType>;
/**
* Frame corresponding to the current handle.
*/
abstract get frame(): Frame;
/**
* Queries the current element for an element matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @returns A {@link ElementHandle | element handle} to the first element
* matching the given selector. Otherwise, `null`.
*/
$<Selector extends string>(selector: Selector): Promise<ElementHandle<NodeFor<Selector>> | null>;
/**
* Queries the current element for all elements matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
$$<Selector extends string>(selector: Selector, options?: QueryOptions): Promise<Array<ElementHandle<NodeFor<Selector>>>>;
/**
* Runs the given function on the first element matching the given selector in
* the current element.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
*
* ```ts
* const tweetHandle = await page.$('.tweet');
* expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe(
* '100',
* );
* expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe(
* '10',
* );
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in this element's page's
* context. The first element matching the selector will be passed in as the
* first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
$eval<Selector extends string, Params extends unknown[], Func extends EvaluateFuncWith<NodeFor<Selector>, Params> = EvaluateFuncWith<NodeFor<Selector>, Params>>(selector: Selector, pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Runs the given function on an array of elements matching the given selector
* in the current element.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
* HTML:
*
* ```html
* <div class="feed">
* <div class="tweet">Hello!</div>
* <div class="tweet">Hi!</div>
* </div>
* ```
*
* JavaScript:
*
* ```ts
* const feedHandle = await page.$('.feed');
* expect(
* await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText)),
* ).toEqual(['Hello!', 'Hi!']);
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in the element's page's
* context. An array of elements matching the given selector will be passed to
* the function as its first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
$$eval<Selector extends string, Params extends unknown[], Func extends EvaluateFuncWith<Array<NodeFor<Selector>>, Params> = EvaluateFuncWith<Array<NodeFor<Selector>>, Params>>(selector: Selector, pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Wait for an element matching the given selector to appear in the current
* element.
*
* Unlike {@link Frame.waitForSelector}, this method does not work across
* navigations or if the element is detached from DOM.
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page
* .mainFrame()
* .waitForSelector('img')
* .then(() => console.log('First URL with image: ' + currentURL));
*
* for (currentURL of [
* 'https://example.com',
* 'https://google.com',
* 'https://bbc.com',
* ]) {
* await page.goto(currentURL);
* }
* await browser.close();
* })();
* ```
*
* @param selector - The selector to query and wait for.
* @param options - Options for customizing waiting behavior.
* @returns An element matching the given selector.
* @throws Throws if an element matching the given selector doesn't appear.
*/
waitForSelector<Selector extends string>(selector: Selector, options?: WaitForSelectorOptions): Promise<ElementHandle<NodeFor<Selector>> | null>;
/**
* An element is considered to be visible if all of the following is
* true:
*
* - the element has
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle | computed styles}.
*
* - the element has a non-empty
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect | bounding client rect}.
*
* - the element's {@link https://developer.mozilla.org/en-US/docs/Web/CSS/visibility | visibility}
* is not `hidden` or `collapse`.
*/
isVisible(): Promise<boolean>;
/**
* An element is considered to be hidden if at least one of the following is true:
*
* - the element has no
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle | computed styles}.
*
* - the element has an empty
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect | bounding client rect}.
*
* - the element's {@link https://developer.mozilla.org/en-US/docs/Web/CSS/visibility | visibility}
* is `hidden` or `collapse`.
*/
isHidden(): Promise<boolean>;
/**
* Converts the current handle to the given element type.
*
* @example
*
* ```ts
* const element: ElementHandle<Element> = await page.$(
* '.class-name-of-anchor',
* );
* // DO NOT DISPOSE `element`, this will be always be the same handle.
* const anchor: ElementHandle<HTMLAnchorElement> =
* await element.toElement('a');
* ```
*
* @param tagName - The tag name of the desired element type.
* @throws An error if the handle does not match. **The handle will not be
* automatically disposed.**
*/
toElement<K extends keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap>(tagName: K): Promise<HandleFor<ElementFor<K>>>;
/**
* Resolves the frame associated with the element, if any. Always exists for
* HTMLIFrameElements.
*/
abstract contentFrame(this: ElementHandle<HTMLIFrameElement>): Promise<Frame>;
abstract contentFrame(): Promise<Frame | null>;
/**
* Returns the middle point within an element unless a specific offset is provided.
*/
clickablePoint(offset?: Offset): Promise<Point>;
/**
* This method scrolls element into view if needed, and then
* uses {@link Page.mouse} to hover over the center of the element.
* If the element is detached from DOM, the method throws an error.
*/
hover(this: ElementHandle<Element>): Promise<void>;
/**
* This method scrolls element into view if needed, and then
* uses {@link Page.mouse} to click in the center of the element.
* If the element is detached from DOM, the method throws an error.
*/
click(this: ElementHandle<Element>, options?: Readonly<ClickOptions>): Promise<void>;
/**
* Drags an element over the given element or point.
*
* @returns DEPRECATED. When drag interception is enabled, the drag payload is
* returned.
*/
drag(this: ElementHandle<Element>, target: Point | ElementHandle<Element>): Promise<Protocol.Input.DragData | void>;
/**
* @deprecated Do not use. `dragenter` will automatically be performed during dragging.
*/
dragEnter(this: ElementHandle<Element>, data?: Protocol.Input.DragData): Promise<void>;
/**
* @deprecated Do not use. `dragover` will automatically be performed during dragging.
*/
dragOver(this: ElementHandle<Element>, data?: Protocol.Input.DragData): Promise<void>;
/**
* Drops the given element onto the current one.
*/
drop(this: ElementHandle<Element>, element: ElementHandle<Element>): Promise<void>;
/**
* @deprecated No longer supported.
*/
drop(this: ElementHandle<Element>, data?: Protocol.Input.DragData): Promise<void>;
/**
* @deprecated Use `ElementHandle.drop` instead.
*/
dragAndDrop(this: ElementHandle<Element>, target: ElementHandle<Node>, options?: {
delay: number;
}): Promise<void>;
/**
* Triggers a `change` and `input` event once all the provided options have been
* selected. If there's no `<select>` element matching `selector`, the method
* throws an error.
*
* @example
*
* ```ts
* handle.select('blue'); // single selection
* handle.select('red', 'green', 'blue'); // multiple selections
* ```
*
* @param values - Values of options to select. If the `<select>` has the
* `multiple` attribute, all values are considered, otherwise only the first
* one is taken into account.
*/
select(...values: string[]): Promise<string[]>;
/**
* Sets the value of an
* {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input | input element}
* to the given file paths.
*
* @remarks This will not validate whether the file paths exists. Also, if a
* path is relative, then it is resolved against the
* {@link https://nodejs.org/api/process.html#process_process_cwd | current working directory}.
* For locals script connecting to remote chrome environments, paths must be
* absolute.
*/
abstract uploadFile(this: ElementHandle<HTMLInputElement>, ...paths: string[]): Promise<void>;
/**
* @internal
*/
abstract queryAXTree(name?: string, role?: string): AwaitableIterable<ElementHandle<Node>>;
/**
* This method scrolls element into view if needed, and then uses
* {@link Touchscreen.tap} to tap in the center of the element.
* If the element is detached from DOM, the method throws an error.
*/
tap(this: ElementHandle<Element>): Promise<void>;
/**
* This method scrolls the element into view if needed, and then
* starts a touch in the center of the element.
* @returns A {@link TouchHandle} representing the touch that was started
*/
touchStart(this: ElementHandle<Element>): Promise<TouchHandle>;
/**
* This method scrolls the element into view if needed, and then
* moves the touch to the center of the element.
* @param touch - An optional {@link TouchHandle}. If provided, this touch
* will be moved. If not provided, the first active touch will be moved.
*/
touchMove(this: ElementHandle<Element>, touch?: TouchHandle): Promise<void>;
touchEnd(this: ElementHandle<Element>): Promise<void>;
/**
* Calls {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus | focus} on the element.
*/
focus(): Promise<void>;
/**
* Focuses the element, and then sends a `keydown`, `keypress`/`input`, and
* `keyup` event for each character in the text.
*
* To press a special key, like `Control` or `ArrowDown`,
* use {@link ElementHandle.press}.
*
* @example
*
* ```ts
* await elementHandle.type('Hello'); // Types instantly
* await elementHandle.type('World', {delay: 100}); // Types slower, like a user
* ```
*
* @example
* An example of typing into a text field and then submitting the form:
*
* ```ts
* const elementHandle = await page.$('input');
* await elementHandle.type('some text');
* await elementHandle.press('Enter');
* ```
*
* @param options - Delay in milliseconds. Defaults to 0.
*/
type(text: string, options?: Readonly<KeyboardTypeOptions>): Promise<void>;
/**
* Focuses the element, and then uses {@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 be generated.
* The `text` option can be specified to force an input event to be generated.
*
* **NOTE** Modifier keys DO affect `elementHandle.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.
*/
press(key: KeyInput, options?: Readonly<KeyPressOptions>): Promise<void>;
/**
* This method returns the bounding box of the element (relative to the main frame),
* or `null` if the element is {@link https://drafts.csswg.org/css-display-4/#box-generation | not part of the layout}
* (example: `display: none`).
*/
boundingBox(): Promise<BoundingBox | null>;
/**
* This method returns boxes of the element,
* or `null` if the element is {@link https://drafts.csswg.org/css-display-4/#box-generation | not part of the layout}
* (example: `display: none`).
*
* @remarks
*
* Boxes are represented as an array of points;
* Each Point is an object `{x, y}`. Box points are sorted clock-wise.
*/
boxModel(): Promise<BoxModel | null>;
/**
* This method scrolls element into view if needed, and then uses
* {@link Page.(screenshot:2) } to take a screenshot of the element.
* If the element is detached from DOM, the method throws an error.
*/
screenshot(options: Readonly<ScreenshotOptions> & {
encoding: 'base64';
}): Promise<string>;
screenshot(options?: Readonly<ScreenshotOptions>): Promise<Uint8Array>;
/**
* @internal
*/
protected assertConnectedElement(): Promise<void>;
/**
* @internal
*/
protected scrollIntoViewIfNeeded(this: ElementHandle<Element>): Promise<void>;
/**
* Resolves to true if the element is visible in the current viewport. If an
* element is an SVG, we check if the svg owner element is in the viewport
* instead. See https://crbug.com/963246.
*
* @param options - Threshold for the intersection between 0 (no intersection) and 1
* (full intersection). Defaults to 1.
*/
isIntersectingViewport(this: ElementHandle<Element>, options?: {
threshold?: number;
}): Promise<boolean>;
/**
* Scrolls the element into view using either the automation protocol client
* or by calling element.scrollIntoView.
*/
scrollIntoView(this: ElementHandle<Element>): Promise<void>;
/**
* If the element is a form input, you can use {@link ElementHandle.autofill}
* to test if the form is compatible with the browser's autofill
* implementation. Throws an error if the form cannot be autofilled.
*
* @remarks
*
* Currently, Puppeteer supports auto-filling credit card information only and
* in Chrome in the new headless and headful modes only.
*
* ```ts
* // Select an input on the credit card form.
* const name = await page.waitForSelector('form #name');
* // Trigger autofill with the desired data.
* await name.autofill({
* creditCard: {
* number: '4444444444444444',
* name: 'John Smith',
* expiryMonth: '01',
* expiryYear: '2030',
* cvc: '123',
* },
* });
* ```
*/
abstract autofill(data: AutofillData): Promise<void>;
/**
* When connected using Chrome DevTools Protocol, it returns a
* DOM.BackendNodeId for the element.
*/
abstract backendNodeId(): Promise<number>;
}
/**
* @public
*/
export interface AutofillData {
creditCard: {
number: string;
name: string;
expiryMonth: string;
expiryYear: string;
cvc: string;
};
}
//# sourceMappingURL=ElementHandle.d.ts.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
*/
export declare const _isElementHandle: unique symbol;
//# sourceMappingURL=ElementHandleSymbol.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ElementHandleSymbol.d.ts","sourceRoot":"","sources":["../../../../src/api/ElementHandleSymbol.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,eAA6B,CAAC"}

View File

@@ -0,0 +1,13 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports._isElementHandle = void 0;
/**
* @internal
*/
exports._isElementHandle = Symbol('_isElementHandle');
//# sourceMappingURL=ElementHandleSymbol.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ElementHandleSymbol.js","sourceRoot":"","sources":["../../../../src/api/ElementHandleSymbol.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH;;GAEG;AACU,QAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC"}

View File

@@ -0,0 +1,15 @@
/**
* @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;
}
//# sourceMappingURL=Environment.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Environment.d.ts","sourceRoot":"","sources":["../../../../src/api/Environment.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,MAAM,IAAI,UAAU,CAAC;IACzB,SAAS,IAAI,KAAK,CAAC;CACpB"}

View File

@@ -0,0 +1,8 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=Environment.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Environment.js","sourceRoot":"","sources":["../../../../src/api/Environment.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}

View File

@@ -0,0 +1,763 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type Protocol from 'devtools-protocol';
import type { ClickOptions, ElementHandle } from '../api/ElementHandle.js';
import type { HTTPResponse } from '../api/HTTPResponse.js';
import type { Page, QueryOptions, WaitForSelectorOptions, WaitTimeoutOptions } from '../api/Page.js';
import type { Accessibility } from '../cdp/Accessibility.js';
import type { DeviceRequestPrompt } from '../cdp/DeviceRequestPrompt.js';
import type { PuppeteerLifeCycleEvent } from '../cdp/LifecycleWatcher.js';
import { EventEmitter, type EventType } from '../common/EventEmitter.js';
import type { Awaitable, EvaluateFunc, EvaluateFuncWith, HandleFor, NodeFor } from '../common/types.js';
import type { CDPSession } from './CDPSession.js';
import type { KeyboardTypeOptions } from './Input.js';
import { type Locator } from './locators/locators.js';
import type { Realm } from './Realm.js';
/**
* @public
*/
export interface WaitForOptions {
/**
* Maximum wait time in milliseconds. Pass 0 to disable the timeout.
*
* The default value can be changed by using the
* {@link Page.setDefaultTimeout} or {@link Page.setDefaultNavigationTimeout}
* methods.
*
* @defaultValue `30000`
*/
timeout?: number;
/**
* When to consider waiting succeeds. Given an array of event strings, waiting
* is considered to be successful after all events have been fired.
*
* @defaultValue `'load'`
*/
waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
/**
* @internal
*/
ignoreSameDocumentNavigation?: boolean;
/**
* A signal object that allows you to cancel the call.
*/
signal?: AbortSignal;
}
/**
* @public
*/
export interface GoToOptions extends WaitForOptions {
/**
* If provided, it will take preference over the referer header value set by
* {@link Page.setExtraHTTPHeaders | page.setExtraHTTPHeaders()}.
*/
referer?: string;
/**
* If provided, it will take preference over the referer-policy header value
* set by {@link Page.setExtraHTTPHeaders | page.setExtraHTTPHeaders()}.
*/
referrerPolicy?: string;
}
/**
* @public
*/
export interface FrameWaitForFunctionOptions {
/**
* An interval at which the `pageFunction` is executed, defaults to `raf`. If
* `polling` is a number, then it is treated as an interval in milliseconds at
* which the function would be executed. If `polling` is a string, then it can
* be one of the following values:
*
* - `raf` - to constantly execute `pageFunction` in `requestAnimationFrame`
* callback. This is the tightest polling mode which is suitable to observe
* styling changes.
*
* - `mutation` - to execute `pageFunction` on every DOM mutation.
*/
polling?: 'raf' | 'mutation' | number;
/**
* Maximum time to wait in milliseconds. Defaults to `30000` (30 seconds).
* Pass `0` to disable the timeout. Puppeteer's default timeout can be changed
* using {@link Page.setDefaultTimeout}.
*/
timeout?: number;
/**
* A signal object that allows you to cancel a waitForFunction call.
*/
signal?: AbortSignal;
}
/**
* @public
*/
export interface FrameAddScriptTagOptions {
/**
* URL of the script to be added.
*/
url?: string;
/**
* Path to a JavaScript file to be injected into the frame.
*
* @remarks
* If `path` is a relative path, it is resolved relative to the current
* working directory (`process.cwd()` in Node.js).
*/
path?: string;
/**
* JavaScript to be injected into the frame.
*/
content?: string;
/**
* Sets the `type` of the script. Use `module` in order to load an ES2015 module.
*/
type?: string;
/**
* Sets the `id` of the script.
*/
id?: string;
}
/**
* @public
*/
export interface FrameAddStyleTagOptions {
/**
* the URL of the CSS file to be added.
*/
url?: string;
/**
* The path to a CSS file to be injected into the frame.
* @remarks
* If `path` is a relative path, it is resolved relative to the current
* working directory (`process.cwd()` in Node.js).
*/
path?: string;
/**
* Raw CSS content to be injected into the frame.
*/
content?: string;
}
/**
* @public
*/
export interface FrameEvents extends Record<EventType, unknown> {
/** @internal */
[FrameEvent.FrameNavigated]: Protocol.Page.NavigationType;
/** @internal */
[FrameEvent.FrameSwapped]: undefined;
/** @internal */
[FrameEvent.LifecycleEvent]: undefined;
/** @internal */
[FrameEvent.FrameNavigatedWithinDocument]: undefined;
/** @internal */
[FrameEvent.FrameDetached]: Frame;
/** @internal */
[FrameEvent.FrameSwappedByActivation]: undefined;
}
/**
* We use symbols to prevent external parties listening to these events.
* They are internal to Puppeteer.
*
* @internal
*/
export declare namespace FrameEvent {
const FrameNavigated: unique symbol;
const FrameSwapped: unique symbol;
const LifecycleEvent: unique symbol;
const FrameNavigatedWithinDocument: unique symbol;
const FrameDetached: unique symbol;
const FrameSwappedByActivation: unique symbol;
}
/**
* @internal
*/
export declare const throwIfDetached: (target: (this: Frame, ...args: any[]) => any, _: unknown) => (this: Frame, ...args: any[]) => any;
/**
* Represents a DOM frame.
*
* To understand frames, you can think of frames as `<iframe>` elements. Just
* like iframes, frames can be nested, and when JavaScript is executed in a
* frame, the JavaScript does not effect frames inside the ambient frame the
* JavaScript executes in.
*
* @example
* At any point in time, {@link Page | pages} expose their current frame
* tree via the {@link Page.mainFrame} and {@link Frame.childFrames} methods.
*
* @example
* An example of dumping frame tree:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.goto('https://www.google.com/chrome/browser/canary.html');
* dumpFrameTree(page.mainFrame(), '');
* await browser.close();
*
* function dumpFrameTree(frame, indent) {
* console.log(indent + frame.url());
* for (const child of frame.childFrames()) {
* dumpFrameTree(child, indent + ' ');
* }
* }
* })();
* ```
*
* @example
* An example of getting text from an iframe element:
*
* ```ts
* const frame = page.frames().find(frame => frame.name() === 'myframe');
* const text = await frame.$eval('.selector', element => element.textContent);
* console.log(text);
* ```
*
* @remarks
* Frame lifecycles are controlled by three events that are all dispatched on
* the parent {@link Frame.page | page}:
*
* - {@link PageEvent.FrameAttached}
* - {@link PageEvent.FrameNavigated}
* - {@link PageEvent.FrameDetached}
*
* @public
*/
export declare abstract class Frame extends EventEmitter<FrameEvents> {
#private;
/**
* @internal
*/
_id: string;
/**
* @internal
*/
_parentId?: string;
/**
* @internal
*/
_name?: string;
/**
* @internal
*/
_hasStartedLoading: boolean;
/**
* @internal
*/
constructor();
/**
* The page associated with the frame.
*/
abstract page(): Page;
/**
* Navigates the frame or page to the given `url`.
*
* @remarks
* Navigation to `about:blank` or navigation to the same URL with a different
* hash will succeed and return `null`.
*
* :::warning
*
* Headless shell mode doesn't support navigation to a PDF document. See the
* {@link https://crbug.com/761295 | upstream issue}.
*
* :::
*
* In headless shell, this method will not throw an error when any valid HTTP
* status code is returned by the remote server, including 404 "Not Found" and
* 500 "Internal Server Error". The status code for such responses can be
* retrieved by calling {@link HTTPResponse.status}.
*
* @param url - URL to navigate the frame to. The URL should include scheme,
* e.g. `https://`
* @param options - Options to configure waiting behavior.
* @returns A promise which resolves to the main resource response. In case of
* multiple redirects, the navigation will resolve with the response of the
* last redirect.
* @throws If:
*
* - there's an SSL error (e.g. in case of self-signed certificates).
*
* - target URL is invalid.
*
* - the timeout is exceeded during navigation.
*
* - the remote server does not respond or is unreachable.
*
* - the main resource failed to load.
*/
abstract goto(url: string, options?: GoToOptions): Promise<HTTPResponse | null>;
/**
* Waits for the frame to navigate. It is useful for when you run code which
* will indirectly cause the frame to navigate.
*
* Usage of the
* {@link https://developer.mozilla.org/en-US/docs/Web/API/History_API | History API}
* to change the URL is considered a navigation.
*
* @example
*
* ```ts
* const [response] = await Promise.all([
* // The navigation promise resolves after navigation has finished
* frame.waitForNavigation(),
* // Clicking the link will indirectly cause a navigation
* frame.click('a.my-link'),
* ]);
* ```
*
* @param options - Options to configure waiting behavior.
* @returns A promise which resolves to the main resource response.
*/
abstract waitForNavigation(options?: WaitForOptions): Promise<HTTPResponse | null>;
/**
* @internal
*/
abstract get client(): CDPSession;
/**
* @internal
*/
abstract get accessibility(): Accessibility;
/**
* @internal
*/
abstract mainRealm(): Realm;
/**
* @internal
*/
abstract isolatedRealm(): Realm;
/**
* Used to clear the document handle that has been destroyed.
*
* @internal
*/
clearDocumentHandle(): void;
/**
* @returns The frame element associated with this frame (if any).
*/
frameElement(): Promise<HandleFor<HTMLIFrameElement> | null>;
/**
* Behaves identically to {@link Page.evaluateHandle} except it's run within
* the context of this frame.
*
* See {@link Page.evaluateHandle} for details.
*/
evaluateHandle<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(pageFunction: Func | string, ...args: Params): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
/**
* Behaves identically to {@link Page.evaluate} except it's run within
* the context of this frame.
*
* See {@link Page.evaluate} for details.
*/
evaluate<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Creates a locator for the provided selector. See {@link Locator} for
* details and supported actions.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
*/
locator<Selector extends string>(selector: Selector): Locator<NodeFor<Selector>>;
/**
* Creates a locator for the provided function. See {@link Locator} for
* details and supported actions.
*/
locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>;
/**
* Queries the frame for an element matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
*
* @returns A {@link ElementHandle | element handle} to the first element
* matching the given selector. Otherwise, `null`.
*/
$<Selector extends string>(selector: Selector): Promise<ElementHandle<NodeFor<Selector>> | null>;
/**
* Queries the frame for all elements matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
*
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
$$<Selector extends string>(selector: Selector, options?: QueryOptions): Promise<Array<ElementHandle<NodeFor<Selector>>>>;
/**
* Runs the given function on the first element matching the given selector in
* the frame.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
*
* ```ts
* const searchValue = await frame.$eval('#search', el => el.value);
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in the frame's context.
* The first element matching the selector will be passed to the function as
* its first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
$eval<Selector extends string, Params extends unknown[], Func extends EvaluateFuncWith<NodeFor<Selector>, Params> = EvaluateFuncWith<NodeFor<Selector>, Params>>(selector: Selector, pageFunction: string | Func, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Runs the given function on an array of elements matching the given selector
* in the frame.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
*
* ```ts
* const divsCounts = await frame.$$eval('div', divs => divs.length);
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in the frame's context.
* An array of elements matching the given selector will be passed to the
* function as its first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
$$eval<Selector extends string, Params extends unknown[], Func extends EvaluateFuncWith<Array<NodeFor<Selector>>, Params> = EvaluateFuncWith<Array<NodeFor<Selector>>, Params>>(selector: Selector, pageFunction: string | Func, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Waits for an element matching the given selector to appear in the frame.
*
* This method works across navigations.
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page
* .mainFrame()
* .waitForSelector('img')
* .then(() => console.log('First URL with image: ' + currentURL));
*
* for (currentURL of [
* 'https://example.com',
* 'https://google.com',
* 'https://bbc.com',
* ]) {
* await page.goto(currentURL);
* }
* await browser.close();
* })();
* ```
*
* @param selector - The selector to query and wait for.
* @param options - Options for customizing waiting behavior.
* @returns An element matching the given selector.
* @throws Throws if an element matching the given selector doesn't appear.
*/
waitForSelector<Selector extends string>(selector: Selector, options?: WaitForSelectorOptions): Promise<ElementHandle<NodeFor<Selector>> | null>;
/**
* @example
* The `waitForFunction` can be used to observe viewport size change:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* . const browser = await puppeteer.launch();
* . const page = await browser.newPage();
* . const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
* . page.setViewport({width: 50, height: 50});
* . await watchDog;
* . await browser.close();
* })();
* ```
*
* To pass arguments from Node.js to the predicate of `page.waitForFunction` function:
*
* ```ts
* const selector = '.foo';
* await frame.waitForFunction(
* selector => !!document.querySelector(selector),
* {}, // empty options object
* selector,
* );
* ```
*
* @param pageFunction - the function to evaluate in the frame context.
* @param options - options to configure the polling method and timeout.
* @param args - arguments to pass to the `pageFunction`.
* @returns the promise which resolve when the `pageFunction` returns a truthy value.
*/
waitForFunction<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(pageFunction: Func | string, options?: FrameWaitForFunctionOptions, ...args: Params): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
/**
* The full HTML contents of the frame, including the DOCTYPE.
*/
content(): Promise<string>;
/**
* Set the content of the frame.
*
* @param html - HTML markup to assign to the page.
* @param options - Options to configure how long before timing out and at
* what point to consider the content setting successful.
*/
abstract setContent(html: string, options?: WaitForOptions): Promise<void>;
/**
* @internal
*/
setFrameContent(content: string): Promise<void>;
/**
* The frame's `name` attribute as specified in the tag.
*
* @remarks
* If the name is empty, it returns the `id` attribute instead.
*
* @remarks
* This value is calculated once when the frame is created, and will not
* update if the attribute is changed later.
*
* @deprecated Use
*
* ```ts
* const element = await frame.frameElement();
* const nameOrId = await element.evaluate(frame => frame.name ?? frame.id);
* ```
*/
name(): string;
/**
* The frame's URL.
*/
abstract url(): string;
/**
* The parent frame, if any. Detached and main frames return `null`.
*/
abstract parentFrame(): Frame | null;
/**
* An array of child frames.
*/
abstract childFrames(): Frame[];
/**
* @returns `true` if the frame has detached. `false` otherwise.
*/
abstract get detached(): boolean;
/**
* Is`true` if the frame has been detached. Otherwise, `false`.
*
* @deprecated Use the `detached` getter.
*/
isDetached(): boolean;
/**
* @internal
*/
get disposed(): boolean;
/**
* Adds a `<script>` tag into the page with the desired url or content.
*
* @param options - Options for the script.
* @returns An {@link ElementHandle | element handle} to the injected
* `<script>` element.
*/
addScriptTag(options: FrameAddScriptTagOptions): Promise<ElementHandle<HTMLScriptElement>>;
/**
* Adds a `HTMLStyleElement` into the frame with the desired URL
*
* @returns An {@link ElementHandle | element handle} to the loaded `<style>`
* element.
*/
addStyleTag(options: Omit<FrameAddStyleTagOptions, 'url'>): Promise<ElementHandle<HTMLStyleElement>>;
/**
* Adds a `HTMLLinkElement` into the frame with the desired URL
*
* @returns An {@link ElementHandle | element handle} to the loaded `<link>`
* element.
*/
addStyleTag(options: FrameAddStyleTagOptions): Promise<ElementHandle<HTMLLinkElement>>;
/**
* Clicks the first element found that matches `selector`.
*
* @remarks
* If `click()` triggers a navigation event and there's a separate
* `page.waitForNavigation()` promise to be resolved, you may end up with a
* race condition that yields unexpected results. The correct pattern for
* click and wait for navigation is the following:
*
* ```ts
* const [response] = await Promise.all([
* page.waitForNavigation(waitOptions),
* frame.click(selector, clickOptions),
* ]);
* ```
*
* @param selector - The selector to query for.
*/
click(selector: string, options?: Readonly<ClickOptions>): Promise<void>;
/**
* Focuses the first element that matches the `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
focus(selector: string): Promise<void>;
/**
* Hovers the pointer over the center of the first element that matches the
* `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
hover(selector: string): Promise<void>;
/**
* Selects a set of value on the first `<select>` element that matches the
* `selector`.
*
* @example
*
* ```ts
* frame.select('select#colors', 'blue'); // single selection
* frame.select('select#colors', 'red', 'green', 'blue'); // multiple selections
* ```
*
* @param selector - The selector to query for.
* @param values - The array of values to select. If the `<select>` has the
* `multiple` attribute, all values are considered, otherwise only the first
* one is taken into account.
* @returns the list of values that were successfully selected.
* @throws Throws if there's no `<select>` matching `selector`.
*/
select(selector: string, ...values: string[]): Promise<string[]>;
/**
* Taps the first element that matches the `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
tap(selector: 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}.
*
* @example
*
* ```ts
* await frame.type('#mytextarea', 'Hello'); // Types instantly
* await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
* ```
*
* @param selector - the selector for the element to type into. If there are
* multiple the first will be used.
* @param text - text to type into the element
* @param options - takes one option, `delay`, which sets the time to wait
* between key presses in milliseconds. Defaults to `0`.
*/
type(selector: string, text: string, options?: Readonly<KeyboardTypeOptions>): Promise<void>;
/**
* The frame's title.
*/
title(): Promise<string>;
/**
* This method is typically coupled with an action that triggers a device
* request from an api such as WebBluetooth.
*
* :::caution
*
* This must be called before the device request is made. It will not return a
* currently active device prompt.
*
* :::
*
* @example
*
* ```ts
* const [devicePrompt] = Promise.all([
* frame.waitForDevicePrompt(),
* frame.click('#connect-bluetooth'),
* ]);
* await devicePrompt.select(
* await devicePrompt.waitForDevice(({name}) => name.includes('My Device')),
* );
* ```
*
* @internal
*/
abstract waitForDevicePrompt(options?: WaitTimeoutOptions): Promise<DeviceRequestPrompt>;
}
//# sourceMappingURL=Frame.d.ts.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,895 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.Frame = exports.throwIfDetached = exports.FrameEvent = void 0;
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const GetQueryHandler_js_1 = require("../common/GetQueryHandler.js");
const HandleIterator_js_1 = require("../common/HandleIterator.js");
const util_js_1 = require("../common/util.js");
const environment_js_1 = require("../environment.js");
const assert_js_1 = require("../util/assert.js");
const decorators_js_1 = require("../util/decorators.js");
const locators_js_1 = require("./locators/locators.js");
/**
* We use symbols to prevent external parties listening to these events.
* They are internal to Puppeteer.
*
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var FrameEvent;
(function (FrameEvent) {
FrameEvent.FrameNavigated = Symbol('Frame.FrameNavigated');
FrameEvent.FrameSwapped = Symbol('Frame.FrameSwapped');
FrameEvent.LifecycleEvent = Symbol('Frame.LifecycleEvent');
FrameEvent.FrameNavigatedWithinDocument = Symbol('Frame.FrameNavigatedWithinDocument');
FrameEvent.FrameDetached = Symbol('Frame.FrameDetached');
FrameEvent.FrameSwappedByActivation = Symbol('Frame.FrameSwappedByActivation');
})(FrameEvent || (exports.FrameEvent = FrameEvent = {}));
/**
* @internal
*/
exports.throwIfDetached = (0, decorators_js_1.throwIfDisposed)(frame => {
return `Attempted to use detached Frame '${frame._id}'.`;
});
/**
* Represents a DOM frame.
*
* To understand frames, you can think of frames as `<iframe>` elements. Just
* like iframes, frames can be nested, and when JavaScript is executed in a
* frame, the JavaScript does not effect frames inside the ambient frame the
* JavaScript executes in.
*
* @example
* At any point in time, {@link Page | pages} expose their current frame
* tree via the {@link Page.mainFrame} and {@link Frame.childFrames} methods.
*
* @example
* An example of dumping frame tree:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* await page.goto('https://www.google.com/chrome/browser/canary.html');
* dumpFrameTree(page.mainFrame(), '');
* await browser.close();
*
* function dumpFrameTree(frame, indent) {
* console.log(indent + frame.url());
* for (const child of frame.childFrames()) {
* dumpFrameTree(child, indent + ' ');
* }
* }
* })();
* ```
*
* @example
* An example of getting text from an iframe element:
*
* ```ts
* const frame = page.frames().find(frame => frame.name() === 'myframe');
* const text = await frame.$eval('.selector', element => element.textContent);
* console.log(text);
* ```
*
* @remarks
* Frame lifecycles are controlled by three events that are all dispatched on
* the parent {@link Frame.page | page}:
*
* - {@link PageEvent.FrameAttached}
* - {@link PageEvent.FrameNavigated}
* - {@link PageEvent.FrameDetached}
*
* @public
*/
let Frame = (() => {
let _classSuper = EventEmitter_js_1.EventEmitter;
let _instanceExtraInitializers = [];
let _frameElement_decorators;
let _evaluateHandle_decorators;
let _evaluate_decorators;
let _locator_decorators;
let _$_decorators;
let _$$_decorators;
let _$eval_decorators;
let _$$eval_decorators;
let _waitForSelector_decorators;
let _waitForFunction_decorators;
let _content_decorators;
let _addScriptTag_decorators;
let _addStyleTag_decorators;
let _click_decorators;
let _focus_decorators;
let _hover_decorators;
let _select_decorators;
let _tap_decorators;
let _type_decorators;
let _title_decorators;
return class Frame extends _classSuper {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_frameElement_decorators = [exports.throwIfDetached];
_evaluateHandle_decorators = [exports.throwIfDetached];
_evaluate_decorators = [exports.throwIfDetached];
_locator_decorators = [exports.throwIfDetached];
_$_decorators = [exports.throwIfDetached];
_$$_decorators = [exports.throwIfDetached];
_$eval_decorators = [exports.throwIfDetached];
_$$eval_decorators = [exports.throwIfDetached];
_waitForSelector_decorators = [exports.throwIfDetached];
_waitForFunction_decorators = [exports.throwIfDetached];
_content_decorators = [exports.throwIfDetached];
_addScriptTag_decorators = [exports.throwIfDetached];
_addStyleTag_decorators = [exports.throwIfDetached];
_click_decorators = [exports.throwIfDetached];
_focus_decorators = [exports.throwIfDetached];
_hover_decorators = [exports.throwIfDetached];
_select_decorators = [exports.throwIfDetached];
_tap_decorators = [exports.throwIfDetached];
_type_decorators = [exports.throwIfDetached];
_title_decorators = [exports.throwIfDetached];
__esDecorate(this, null, _frameElement_decorators, { kind: "method", name: "frameElement", static: false, private: false, access: { has: obj => "frameElement" in obj, get: obj => obj.frameElement }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _evaluateHandle_decorators, { kind: "method", name: "evaluateHandle", static: false, private: false, access: { has: obj => "evaluateHandle" in obj, get: obj => obj.evaluateHandle }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _evaluate_decorators, { kind: "method", name: "evaluate", static: false, private: false, access: { has: obj => "evaluate" in obj, get: obj => obj.evaluate }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _locator_decorators, { kind: "method", name: "locator", static: false, private: false, access: { has: obj => "locator" in obj, get: obj => obj.locator }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _$_decorators, { kind: "method", name: "$", static: false, private: false, access: { has: obj => "$" in obj, get: obj => obj.$ }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _$$_decorators, { kind: "method", name: "$$", static: false, private: false, access: { has: obj => "$$" in obj, get: obj => obj.$$ }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _$eval_decorators, { kind: "method", name: "$eval", static: false, private: false, access: { has: obj => "$eval" in obj, get: obj => obj.$eval }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _$$eval_decorators, { kind: "method", name: "$$eval", static: false, private: false, access: { has: obj => "$$eval" in obj, get: obj => obj.$$eval }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _waitForSelector_decorators, { kind: "method", name: "waitForSelector", static: false, private: false, access: { has: obj => "waitForSelector" in obj, get: obj => obj.waitForSelector }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _waitForFunction_decorators, { kind: "method", name: "waitForFunction", static: false, private: false, access: { has: obj => "waitForFunction" in obj, get: obj => obj.waitForFunction }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _content_decorators, { kind: "method", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _addScriptTag_decorators, { kind: "method", name: "addScriptTag", static: false, private: false, access: { has: obj => "addScriptTag" in obj, get: obj => obj.addScriptTag }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _addStyleTag_decorators, { kind: "method", name: "addStyleTag", static: false, private: false, access: { has: obj => "addStyleTag" in obj, get: obj => obj.addStyleTag }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _click_decorators, { kind: "method", name: "click", static: false, private: false, access: { has: obj => "click" in obj, get: obj => obj.click }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _focus_decorators, { kind: "method", name: "focus", static: false, private: false, access: { has: obj => "focus" in obj, get: obj => obj.focus }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _hover_decorators, { kind: "method", name: "hover", static: false, private: false, access: { has: obj => "hover" in obj, get: obj => obj.hover }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _select_decorators, { kind: "method", name: "select", static: false, private: false, access: { has: obj => "select" in obj, get: obj => obj.select }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _tap_decorators, { kind: "method", name: "tap", static: false, private: false, access: { has: obj => "tap" in obj, get: obj => obj.tap }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _type_decorators, { kind: "method", name: "type", static: false, private: false, access: { has: obj => "type" in obj, get: obj => obj.type }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _title_decorators, { kind: "method", name: "title", static: false, private: false, access: { has: obj => "title" in obj, get: obj => obj.title }, metadata: _metadata }, null, _instanceExtraInitializers);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
/**
* @internal
*/
_id = __runInitializers(this, _instanceExtraInitializers);
/**
* @internal
*/
_parentId;
/**
* @internal
*/
_name;
/**
* @internal
*/
_hasStartedLoading = false;
/**
* @internal
*/
constructor() {
super();
}
#_document;
/**
* @internal
*/
#document() {
if (!this.#_document) {
this.#_document = this.mainRealm().evaluateHandle(() => {
return document;
});
}
return this.#_document;
}
/**
* Used to clear the document handle that has been destroyed.
*
* @internal
*/
clearDocumentHandle() {
this.#_document = undefined;
}
/**
* @returns The frame element associated with this frame (if any).
*/
async frameElement() {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const parentFrame = this.parentFrame();
if (!parentFrame) {
return null;
}
const list = __addDisposableResource(env_1, await parentFrame.isolatedRealm().evaluateHandle(() => {
return document.querySelectorAll('iframe,frame');
}), false);
for await (const iframe_1 of (0, HandleIterator_js_1.transposeIterableHandle)(list)) {
const env_2 = { stack: [], error: void 0, hasError: false };
try {
const iframe = __addDisposableResource(env_2, iframe_1, false);
const frame = await iframe.contentFrame();
if (frame?._id === this._id) {
return (await parentFrame
.mainRealm()
.adoptHandle(iframe));
}
}
catch (e_1) {
env_2.error = e_1;
env_2.hasError = true;
}
finally {
__disposeResources(env_2);
}
}
return null;
}
catch (e_2) {
env_1.error = e_2;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
/**
* Behaves identically to {@link Page.evaluateHandle} except it's run within
* the context of this frame.
*
* See {@link Page.evaluateHandle} for details.
*/
async evaluateHandle(pageFunction, ...args) {
pageFunction = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.evaluateHandle.name, pageFunction);
return await this.mainRealm().evaluateHandle(pageFunction, ...args);
}
/**
* Behaves identically to {@link Page.evaluate} except it's run within
* the context of this frame.
*
* See {@link Page.evaluate} for details.
*/
async evaluate(pageFunction, ...args) {
pageFunction = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.evaluate.name, pageFunction);
return await this.mainRealm().evaluate(pageFunction, ...args);
}
/**
* @internal
*/
locator(selectorOrFunc) {
if (typeof selectorOrFunc === 'string') {
return locators_js_1.NodeLocator.create(this, selectorOrFunc);
}
else {
return locators_js_1.FunctionLocator.create(this, selectorOrFunc);
}
}
/**
* Queries the frame for an element matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
*
* @returns A {@link ElementHandle | element handle} to the first element
* matching the given selector. Otherwise, `null`.
*/
async $(selector) {
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$(selector);
}
/**
* Queries the frame for all elements matching the given selector.
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
*
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
async $$(selector, options) {
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$$(selector, options);
}
/**
* Runs the given function on the first element matching the given selector in
* the frame.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
*
* ```ts
* const searchValue = await frame.$eval('#search', el => el.value);
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in the frame's context.
* The first element matching the selector will be passed to the function as
* its first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
async $eval(selector, pageFunction, ...args) {
pageFunction = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.$eval.name, pageFunction);
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$eval(selector, pageFunction, ...args);
}
/**
* Runs the given function on an array of elements matching the given selector
* in the frame.
*
* If the given function returns a promise, then this method will wait till
* the promise resolves.
*
* @example
*
* ```ts
* const divsCounts = await frame.$$eval('div', divs => divs.length);
* ```
*
* @param selector -
* {@link https://pptr.dev/guides/page-interactions#selectors | selector}
* to query the page for.
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
* can be passed as-is and a
* {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
* allows quering by
* {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
* {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
* and
* {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
* and
* {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
* Alternatively, you can specify the selector type using a
* {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
* @param pageFunction - The function to be evaluated in the frame's context.
* An array of elements matching the given selector will be passed to the
* function as its first argument.
* @param args - Additional arguments to pass to `pageFunction`.
* @returns A promise to the result of the function.
*/
async $$eval(selector, pageFunction, ...args) {
pageFunction = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.$$eval.name, pageFunction);
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$$eval(selector, pageFunction, ...args);
}
/**
* Waits for an element matching the given selector to appear in the frame.
*
* This method works across navigations.
*
* @example
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page
* .mainFrame()
* .waitForSelector('img')
* .then(() => console.log('First URL with image: ' + currentURL));
*
* for (currentURL of [
* 'https://example.com',
* 'https://google.com',
* 'https://bbc.com',
* ]) {
* await page.goto(currentURL);
* }
* await browser.close();
* })();
* ```
*
* @param selector - The selector to query and wait for.
* @param options - Options for customizing waiting behavior.
* @returns An element matching the given selector.
* @throws Throws if an element matching the given selector doesn't appear.
*/
async waitForSelector(selector, options = {}) {
const { updatedSelector, QueryHandler, polling } = (0, GetQueryHandler_js_1.getQueryHandlerAndSelector)(selector);
return (await QueryHandler.waitFor(this, updatedSelector, {
polling,
...options,
}));
}
/**
* @example
* The `waitForFunction` can be used to observe viewport size change:
*
* ```ts
* import puppeteer from 'puppeteer';
*
* (async () => {
* . const browser = await puppeteer.launch();
* . const page = await browser.newPage();
* . const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
* . page.setViewport({width: 50, height: 50});
* . await watchDog;
* . await browser.close();
* })();
* ```
*
* To pass arguments from Node.js to the predicate of `page.waitForFunction` function:
*
* ```ts
* const selector = '.foo';
* await frame.waitForFunction(
* selector => !!document.querySelector(selector),
* {}, // empty options object
* selector,
* );
* ```
*
* @param pageFunction - the function to evaluate in the frame context.
* @param options - options to configure the polling method and timeout.
* @param args - arguments to pass to the `pageFunction`.
* @returns the promise which resolve when the `pageFunction` returns a truthy value.
*/
async waitForFunction(pageFunction, options = {}, ...args) {
return await this.mainRealm().waitForFunction(pageFunction, options, ...args);
}
/**
* The full HTML contents of the frame, including the DOCTYPE.
*/
async content() {
return await this.evaluate(() => {
let content = '';
for (const node of document.childNodes) {
switch (node) {
case document.documentElement:
content += document.documentElement.outerHTML;
break;
default:
content += new XMLSerializer().serializeToString(node);
break;
}
}
return content;
});
}
/**
* @internal
*/
async setFrameContent(content) {
return await this.evaluate(html => {
document.open();
document.write(html);
document.close();
}, content);
}
/**
* The frame's `name` attribute as specified in the tag.
*
* @remarks
* If the name is empty, it returns the `id` attribute instead.
*
* @remarks
* This value is calculated once when the frame is created, and will not
* update if the attribute is changed later.
*
* @deprecated Use
*
* ```ts
* const element = await frame.frameElement();
* const nameOrId = await element.evaluate(frame => frame.name ?? frame.id);
* ```
*/
name() {
return this._name || '';
}
/**
* Is`true` if the frame has been detached. Otherwise, `false`.
*
* @deprecated Use the `detached` getter.
*/
isDetached() {
return this.detached;
}
/**
* @internal
*/
get disposed() {
return this.detached;
}
/**
* Adds a `<script>` tag into the page with the desired url or content.
*
* @param options - Options for the script.
* @returns An {@link ElementHandle | element handle} to the injected
* `<script>` element.
*/
async addScriptTag(options) {
let { content = '', type } = options;
const { path } = options;
if (+!!options.url + +!!path + +!!content !== 1) {
throw new Error('Exactly one of `url`, `path`, or `content` must be specified.');
}
if (path) {
content = await environment_js_1.environment.value.fs.promises.readFile(path, 'utf8');
content += `//# sourceURL=${path.replace(/\n/g, '')}`;
}
type = type ?? 'text/javascript';
return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, id, type, content }) => {
return await new Promise((resolve, reject) => {
const script = document.createElement('script');
script.type = type;
script.text = content;
script.addEventListener('error', event => {
reject(new Error(event.message ?? 'Could not load script'));
}, { once: true });
if (id) {
script.id = id;
}
if (url) {
script.src = url;
script.addEventListener('load', () => {
resolve(script);
}, { once: true });
document.head.appendChild(script);
}
else {
document.head.appendChild(script);
resolve(script);
}
});
}, { ...options, type, content }));
}
/**
* @internal
*/
async addStyleTag(options) {
let { content = '' } = options;
const { path } = options;
if (+!!options.url + +!!path + +!!content !== 1) {
throw new Error('Exactly one of `url`, `path`, or `content` must be specified.');
}
if (path) {
content = await environment_js_1.environment.value.fs.promises.readFile(path, 'utf8');
content += '/*# sourceURL=' + path.replace(/\n/g, '') + '*/';
options.content = content;
}
return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ url, content }) => {
return await new Promise((resolve, reject) => {
let element;
if (!url) {
element = document.createElement('style');
element.appendChild(document.createTextNode(content));
}
else {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
element = link;
}
element.addEventListener('load', () => {
resolve(element);
}, { once: true });
element.addEventListener('error', event => {
reject(new Error(event.message ?? 'Could not load style'));
}, { once: true });
document.head.appendChild(element);
return element;
});
}, options));
}
/**
* Clicks the first element found that matches `selector`.
*
* @remarks
* If `click()` triggers a navigation event and there's a separate
* `page.waitForNavigation()` promise to be resolved, you may end up with a
* race condition that yields unexpected results. The correct pattern for
* click and wait for navigation is the following:
*
* ```ts
* const [response] = await Promise.all([
* page.waitForNavigation(waitOptions),
* frame.click(selector, clickOptions),
* ]);
* ```
*
* @param selector - The selector to query for.
*/
async click(selector, options = {}) {
const env_3 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_3, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
await handle.click(options);
await handle.dispose();
}
catch (e_3) {
env_3.error = e_3;
env_3.hasError = true;
}
finally {
__disposeResources(env_3);
}
}
/**
* Focuses the first element that matches the `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
async focus(selector) {
const env_4 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_4, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
await handle.focus();
}
catch (e_4) {
env_4.error = e_4;
env_4.hasError = true;
}
finally {
__disposeResources(env_4);
}
}
/**
* Hovers the pointer over the center of the first element that matches the
* `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
async hover(selector) {
const env_5 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_5, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
await handle.hover();
}
catch (e_5) {
env_5.error = e_5;
env_5.hasError = true;
}
finally {
__disposeResources(env_5);
}
}
/**
* Selects a set of value on the first `<select>` element that matches the
* `selector`.
*
* @example
*
* ```ts
* frame.select('select#colors', 'blue'); // single selection
* frame.select('select#colors', 'red', 'green', 'blue'); // multiple selections
* ```
*
* @param selector - The selector to query for.
* @param values - The array of values to select. If the `<select>` has the
* `multiple` attribute, all values are considered, otherwise only the first
* one is taken into account.
* @returns the list of values that were successfully selected.
* @throws Throws if there's no `<select>` matching `selector`.
*/
async select(selector, ...values) {
const env_6 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_6, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
return await handle.select(...values);
}
catch (e_6) {
env_6.error = e_6;
env_6.hasError = true;
}
finally {
__disposeResources(env_6);
}
}
/**
* Taps the first element that matches the `selector`.
*
* @param selector - The selector to query for.
* @throws Throws if there's no element matching `selector`.
*/
async tap(selector) {
const env_7 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_7, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
await handle.tap();
}
catch (e_7) {
env_7.error = e_7;
env_7.hasError = true;
}
finally {
__disposeResources(env_7);
}
}
/**
* 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}.
*
* @example
*
* ```ts
* await frame.type('#mytextarea', 'Hello'); // Types instantly
* await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
* ```
*
* @param selector - the selector for the element to type into. If there are
* multiple the first will be used.
* @param text - text to type into the element
* @param options - takes one option, `delay`, which sets the time to wait
* between key presses in milliseconds. Defaults to `0`.
*/
async type(selector, text, options) {
const env_8 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_8, await this.$(selector), false);
(0, assert_js_1.assert)(handle, `No element found for selector: ${selector}`);
await handle.type(text, options);
}
catch (e_8) {
env_8.error = e_8;
env_8.hasError = true;
}
finally {
__disposeResources(env_8);
}
}
/**
* The frame's title.
*/
async title() {
return await this.isolatedRealm().evaluate(() => {
return document.title;
});
}
};
})();
exports.Frame = Frame;
//# sourceMappingURL=Frame.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,422 @@
/**
* @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 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 declare 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 declare abstract class HTTPRequest {
#private;
/**
* @internal
*/
abstract get id(): string;
/**
* @internal
*/
_interceptionId: string | undefined;
/**
* @internal
*/
_failureText: string | null;
/**
* @internal
*/
_response: HTTPResponse | null;
/**
* @internal
*/
_fromMemoryCache: boolean;
/**
* @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;
};
/**
* 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;
/**
* The `ResponseForRequest` that gets used if the
* interception is allowed to respond (ie, `abort()` is not called).
*/
responseForRequest(): Partial<ResponseForRequest> | null;
/**
* The most recent reason for aborting the request
*/
abortErrorReason(): Protocol.Network.ErrorReason | null;
/**
* 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;
/**
* Is `true` if the intercept resolution has already been handled,
* `false` otherwise.
*/
isInterceptResolutionHandled(): boolean;
/**
* 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;
/**
* @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.
*/
finalizeInterceptions(): Promise<void>;
/**
* 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;
/**
* The request's post body, if any.
*/
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;
/**
* 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.
*/
continue(overrides?: ContinueRequestOverrides, priority?: number): Promise<void>;
/**
* 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.
*/
respond(response: Partial<ResponseForRequest>, priority?: number): Promise<void>;
/**
* 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.
*/
abort(errorCode?: ErrorCode, priority?: number): Promise<void>;
/**
* @internal
*/
static getResponse(body: string | Uint8Array): {
contentLength: number;
base64: string;
};
}
/**
* @public
*/
export declare 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 declare function headersArray(headers: Record<string, string | string[]>): Array<{
name: string;
value: string;
}>;
/**
* @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 declare const STATUS_TEXTS: Record<string, string>;
/**
* @internal
*/
export declare function handleError(error: ProtocolError): void;
//# sourceMappingURL=HTTPRequest.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTTPRequest.d.ts","sourceRoot":"","sources":["../../../../src/api/HTTPRequest.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,468 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.STATUS_TEXTS = exports.InterceptResolutionAction = exports.HTTPRequest = exports.DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = void 0;
exports.headersArray = headersArray;
exports.handleError = handleError;
const util_js_1 = require("../common/util.js");
const assert_js_1 = require("../util/assert.js");
const encoding_js_1 = require("../util/encoding.js");
/**
* The default cooperative request interception resolution priority
*
* @public
*/
exports.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
*/
class HTTPRequest {
/**
* @internal
*/
_interceptionId;
/**
* @internal
*/
_failureText = null;
/**
* @internal
*/
_response = null;
/**
* @internal
*/
_fromMemoryCache = false;
/**
* @internal
*/
_redirectChain = [];
/**
* @internal
*/
interception = {
enabled: false,
handled: false,
handlers: [],
resolutionState: {
action: InterceptResolutionAction.None,
},
requestOverrides: {},
response: null,
abortReason: null,
};
/**
* @internal
*/
constructor() { }
/**
* The `ContinueRequestOverrides` that will be used
* if the interception is allowed to continue (ie, `abort()` and
* `respond()` aren't called).
*/
continueRequestOverrides() {
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
return this.interception.requestOverrides;
}
/**
* The `ResponseForRequest` that gets used if the
* interception is allowed to respond (ie, `abort()` is not called).
*/
responseForRequest() {
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
return this.interception.response;
}
/**
* The most recent reason for aborting the request
*/
abortErrorReason() {
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
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() {
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() {
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) {
this.interception.handlers.push(pendingHandler);
}
/**
* Awaits pending interception handlers and then decides how to fulfill
* the request interception.
*/
async finalizeInterceptions() {
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);
}
}
#canBeIntercepted() {
return !this.url().startsWith('data:') && !this._fromMemoryCache;
}
/**
* 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 = {}, priority) {
if (!this.#canBeIntercepted()) {
return;
}
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
(0, assert_js_1.assert)(!this.interception.handled, 'Request is already handled!');
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, priority) {
if (!this.#canBeIntercepted()) {
return;
}
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
(0, assert_js_1.assert)(!this.interception.handled, 'Request is already handled!');
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 = 'failed', priority) {
if (!this.#canBeIntercepted()) {
return;
}
const errorReason = errorReasons[errorCode];
(0, assert_js_1.assert)(errorReason, 'Unknown error code: ' + errorCode);
(0, assert_js_1.assert)(this.interception.enabled, 'Request Interception is not enabled!');
(0, assert_js_1.assert)(!this.interception.handled, 'Request is already handled!');
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) {
// Needed to get the correct byteLength
const byteBody = (0, util_js_1.isString)(body)
? new TextEncoder().encode(body)
: body;
return {
contentLength: byteBody.byteLength,
base64: (0, encoding_js_1.typedArrayToBase64)(byteBody),
};
}
}
exports.HTTPRequest = HTTPRequest;
/**
* @public
*/
var InterceptResolutionAction;
(function (InterceptResolutionAction) {
InterceptResolutionAction["Abort"] = "abort";
InterceptResolutionAction["Respond"] = "respond";
InterceptResolutionAction["Continue"] = "continue";
InterceptResolutionAction["Disabled"] = "disabled";
InterceptResolutionAction["None"] = "none";
InterceptResolutionAction["AlreadyHandled"] = "already-handled";
})(InterceptResolutionAction || (exports.InterceptResolutionAction = InterceptResolutionAction = {}));
/**
* @internal
*/
function headersArray(headers) {
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.
*/
exports.STATUS_TEXTS = {
'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',
};
const errorReasons = {
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',
};
/**
* @internal
*/
function handleError(error) {
// Firefox throws an invalid argument error with a message starting with
// 'Expected "header" [...]'.
if (error.originalMessage.includes('Invalid 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.
(0, util_js_1.debugError)(error);
}
//# sourceMappingURL=HTTPRequest.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,111 @@
/**
* @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 declare 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;
/**
* 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}
*/
buffer(): Promise<Buffer>;
/**
* Promise which resolves to a text (utf8) representation of response body.
*/
text(): Promise<string>;
/**
* 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`.
*/
json(): Promise<any>;
/**
* 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;
}
//# sourceMappingURL=HTTPResponse.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTTPResponse.d.ts","sourceRoot":"","sources":["../../../../src/api/HTTPResponse.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAElE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,8BAAsB,YAAY;IAChC;;OAEG;;IAGH;;;OAGG;IACH,QAAQ,CAAC,aAAa,IAAI,aAAa;IAEvC;;OAEG;IACH,QAAQ,CAAC,GAAG,IAAI,MAAM;IAEtB;;OAEG;IACH,EAAE,IAAI,OAAO;IAMb;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,MAAM;IAEzB;;;OAGG;IACH,QAAQ,CAAC,UAAU,IAAI,MAAM;IAE7B;;;OAGG;IACH,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,eAAe,IAAI,eAAe,GAAG,IAAI;IAElD;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,cAAc,GAAG,IAAI;IAEzD;;;;;;;;;OASG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAEvC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAI/B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAK7B;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC;IAK1B;;OAEG;IACH,QAAQ,CAAC,OAAO,IAAI,WAAW;IAE/B;;;OAGG;IACH,QAAQ,CAAC,SAAS,IAAI,OAAO;IAE7B;;OAEG;IACH,QAAQ,CAAC,iBAAiB,IAAI,OAAO;IAErC;;;OAGG;IACH,QAAQ,CAAC,KAAK,IAAI,KAAK,GAAG,IAAI;CAC/B"}

View File

@@ -0,0 +1,56 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.HTTPResponse = void 0;
/**
* The HTTPResponse class represents responses which are received by the
* {@link Page} class.
*
* @public
*/
class HTTPResponse {
/**
* @internal
*/
constructor() { }
/**
* True if the response was successful (status in the range 200-299).
*/
ok() {
// TODO: document === 0 case?
const status = this.status();
return status === 0 || (status >= 200 && status <= 299);
}
/**
* {@inheritDoc HTTPResponse.content}
*/
async buffer() {
const content = await this.content();
return Buffer.from(content);
}
/**
* Promise which resolves to a text (utf8) representation of response body.
*/
async text() {
const content = await this.content();
return new TextDecoder().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() {
const content = await this.text();
return JSON.parse(content);
}
}
exports.HTTPResponse = HTTPResponse;
//# sourceMappingURL=HTTPResponse.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTTPResponse.js","sourceRoot":"","sources":["../../../../src/api/HTTPResponse.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAiBH;;;;;GAKG;AACH,MAAsB,YAAY;IAChC;;OAEG;IACH,gBAAe,CAAC;IAahB;;OAEG;IACH,EAAE;QACA,6BAA6B;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;IAC1D,CAAC;IA0CD;;OAEG;IACH,KAAK,CAAC,MAAM;QACV,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;CAuBF;AAnHD,oCAmHC"}

View File

@@ -0,0 +1,485 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Protocol } from 'devtools-protocol';
import type { KeyInput } from '../common/USKeyboardLayout.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 declare 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 declare const MouseButton: Readonly<{
Left: "left";
Right: "right";
Middle: "middle";
Back: "back";
Forward: "forward";
}>;
/**
* @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 declare 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 declare abstract class Touchscreen {
/**
* @internal
*/
idGenerator: import("../util/incremental-id-generator.js").GetIdFn;
/**
* @internal
*/
touches: TouchHandle[];
/**
* @internal
*/
constructor();
/**
* @internal
*/
removeHandle(handle: TouchHandle): void;
/**
* Dispatches a `touchstart` and `touchend` event.
* @param x - Horizontal position of the tap.
* @param y - Vertical position of the tap.
*/
tap(x: number, y: number): Promise<void>;
/**
* 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.
*/
touchMove(x: number, y: number): Promise<void>;
/**
* Dispatches a `touchend` event on the first touch that is active.
*/
touchEnd(): Promise<void>;
}
//# sourceMappingURL=Input.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../../src/api/Input.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;AAGhD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,+BAA+B,CAAC;AAG5D,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,oBAAoB,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,8BAAsB,QAAQ;IAC5B;;OAEG;;IAGH;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,QAAQ,CAAC,IAAI,CACX,GAAG,EAAE,QAAQ,EACb,OAAO,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAEzC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,CAAC,IAAI,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,KAAK,CACZ,GAAG,EAAE,QAAQ,EACb,OAAO,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;;;;EAM+B,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,8BAAsB,KAAK;IACzB;;OAEG;;IAGH;;;OAGG;IACH,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/B;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CACX,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9D;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAE5D;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GACpC,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAEpE;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;IAE5E;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAChB,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC5B,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CACf,MAAM,EAAE,KAAK,EACb,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAC5B,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1E;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAClB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,KAAK,EACb,OAAO,CAAC,EAAE;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,GACzB,OAAO,CAAC,IAAI,CAAC;CACjB;AACD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C;;OAEG;IACH,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AACD;;;GAGG;AACH,8BAAsB,WAAW;IAC/B;;OAEG;IACH,WAAW,wDAAkC;IAC7C;;OAEG;IACH,OAAO,EAAE,WAAW,EAAE,CAAM;IAC5B;;OAEG;;IAGH;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAQvC;;;;OAIG;IACG,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAE/D;;;;;;;;;;;OAWG;IACG,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAOhC"}

View File

@@ -0,0 +1,217 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Touchscreen = exports.Mouse = exports.MouseButton = exports.Keyboard = void 0;
const Errors_js_1 = require("../common/Errors.js");
const incremental_id_generator_js_1 = require("../util/incremental-id-generator.js");
/**
* 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
*/
class Keyboard {
/**
* @internal
*/
constructor() { }
}
exports.Keyboard = Keyboard;
/**
* Enum of valid mouse buttons.
*
* @public
*/
exports.MouseButton = Object.freeze({
Left: 'left',
Right: 'right',
Middle: 'middle',
Back: 'back',
Forward: 'forward',
});
/**
* 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
*/
class Mouse {
/**
* @internal
*/
constructor() { }
}
exports.Mouse = Mouse;
/**
* The Touchscreen class exposes touchscreen events.
* @public
*/
class Touchscreen {
/**
* @internal
*/
idGenerator = (0, incremental_id_generator_js_1.createIncrementalIdGenerator)();
/**
* @internal
*/
touches = [];
/**
* @internal
*/
constructor() { }
/**
* @internal
*/
removeHandle(handle) {
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, y) {
const touch = await this.touchStart(x, y);
await touch.end();
}
/**
* 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, y) {
const touch = this.touches[0];
if (!touch) {
throw new Errors_js_1.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() {
const touch = this.touches.shift();
if (!touch) {
throw new Errors_js_1.TouchError('Must start a new Touch first');
}
await touch.end();
}
}
exports.Touchscreen = Touchscreen;
//# sourceMappingURL=Input.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/api/Input.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAIH,mDAA+C;AAE/C,qFAAiF;AA8BjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAsB,QAAQ;IAC5B;;OAEG;IACH,gBAAe,CAAC;CAmHjB;AAvHD,4BAuHC;AA2DD;;;;GAIG;AACU,QAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;CACnB,CAAsD,CAAC;AAOxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,MAAsB,KAAK;IACzB;;OAEG;IACH,gBAAe,CAAC;CAuHjB;AA3HD,sBA2HC;AAiBD;;;GAGG;AACH,MAAsB,WAAW;IAC/B;;OAEG;IACH,WAAW,GAAG,IAAA,0DAA4B,GAAE,CAAC;IAC7C;;OAEG;IACH,OAAO,GAAkB,EAAE,CAAC;IAC5B;;OAEG;IACH,gBAAe,CAAC;IAEhB;;OAEG;IACH,YAAY,CAAC,MAAmB;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAC,CAAS,EAAE,CAAS;QAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IAUD;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,SAAS,CAAC,CAAS,EAAE,CAAS;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,sBAAU,CAAC,8BAA8B,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,sBAAU,CAAC,8BAA8B,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;CACF;AAzED,kCAyEC"}

View File

@@ -0,0 +1,123 @@
/**
* @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 { 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
*/
export declare abstract class JSHandle<T = unknown> {
move: () => this;
/**
* Used for nominally typing {@link JSHandle}.
*/
_?: 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.
*/
evaluate<Params extends unknown[], Func extends EvaluateFuncWith<T, Params> = EvaluateFuncWith<T, Params>>(pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* Evaluates the given function with the current handle as its first argument.
*
*/
evaluateHandle<Params extends unknown[], Func extends EvaluateFuncWith<T, Params> = EvaluateFuncWith<T, Params>>(pageFunction: Func | string, ...args: Params): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
/**
* 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>>;
/**
* 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
* ```
*/
getProperties(): Promise<Map<string, JSHandle>>;
/**
* 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;
/** @internal */
[asyncDisposeSymbol](): Promise<void>;
}
//# sourceMappingURL=JSHandle.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"JSHandle.d.ts","sourceRoot":"","sources":["../../../../src/api/JSHandle.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAC,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAG9E,OAAO,EAAC,aAAa,EAAE,kBAAkB,EAAC,MAAM,uBAAuB,CAAC;AAExE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,8BACsB,QAAQ,CAAC,CAAC,GAAG,OAAO;IAChC,IAAI,EAAE,MAAM,IAAI,CAAC;IAEzB;;OAEG;IACK,CAAC,CAAC,EAAE,CAAC,CAAC;IAEd;;OAEG;;IAGH;;OAEG;IACH,QAAQ,KAAK,KAAK,IAAI,KAAK,CAAC;IAE5B;;OAEG;IACH,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC;IAEjC;;OAEG;IACG,QAAQ,CACZ,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,EAEtE,YAAY,EAAE,IAAI,GAAG,MAAM,EAC3B,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAQrC;;;OAGG;IACG,cAAc,CAClB,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,EAEtE,YAAY,EAAE,IAAI,GAAG,MAAM,EAC3B,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAQhD;;OAEG;IACH,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,EAC3B,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GACxB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAc7D;;;;;;;;;;;;;;;;;OAiBG;IAEG,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IA0BrD;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,CAAC,SAAS,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,IAAI;IAEhD;;OAEG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAEjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,IAAI,MAAM;IAE3B;;OAEG;IACH,QAAQ,KAAK,EAAE,IAAI,MAAM,GAAG,SAAS,CAAC;IAEtC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,OAAO,CAAC,YAAY;IAEtD,gBAAgB;IAChB,CAAC,aAAa,CAAC,IAAI,IAAI;IAIvB,gBAAgB;IAChB,CAAC,kBAAkB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGtC"}

View File

@@ -0,0 +1,230 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.JSHandle = void 0;
const util_js_1 = require("../common/util.js");
const decorators_js_1 = require("../util/decorators.js");
const disposable_js_1 = require("../util/disposable.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
*/
let JSHandle = (() => {
let _classDecorators = [decorators_js_1.moveable];
let _classDescriptor;
let _classExtraInitializers = [];
let _classThis;
let _instanceExtraInitializers = [];
let _getProperty_decorators;
let _getProperties_decorators;
var JSHandle = class {
static { _classThis = this; }
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
__esDecorate(this, null, _getProperty_decorators, { kind: "method", name: "getProperty", static: false, private: false, access: { has: obj => "getProperty" in obj, get: obj => obj.getProperty }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(this, null, _getProperties_decorators, { kind: "method", name: "getProperties", static: false, private: false, access: { has: obj => "getProperties" in obj, get: obj => obj.getProperties }, metadata: _metadata }, null, _instanceExtraInitializers);
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
JSHandle = _classThis = _classDescriptor.value;
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
__runInitializers(_classThis, _classExtraInitializers);
}
/**
* @internal
*/
constructor() {
__runInitializers(this, _instanceExtraInitializers);
}
/**
* Evaluates the given function with the current handle as its first argument.
*/
async evaluate(pageFunction, ...args) {
pageFunction = (0, util_js_1.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(pageFunction, ...args) {
pageFunction = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.evaluateHandle.name, pageFunction);
return await this.realm.evaluateHandle(pageFunction, this, ...args);
}
/**
* @internal
*/
async getProperty(propertyName) {
return await this.evaluateHandle((object, propertyName) => {
return object[propertyName];
}, 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
* ```
*/
async getProperties() {
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();
const results = await Promise.all(propertyNames.map(key => {
return this.getProperty(key);
}));
for (const [key, value] of Object.entries(propertyNames)) {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_1, results[key], false);
if (handle) {
map.set(value, handle.move());
}
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
return map;
}
/** @internal */
[(_getProperty_decorators = [(0, decorators_js_1.throwIfDisposed)()], _getProperties_decorators = [(0, decorators_js_1.throwIfDisposed)()], disposable_js_1.disposeSymbol)]() {
return void this.dispose().catch(util_js_1.debugError);
}
/** @internal */
[disposable_js_1.asyncDisposeSymbol]() {
return this.dispose();
}
};
return JSHandle = _classThis;
})();
exports.JSHandle = JSHandle;
//# sourceMappingURL=JSHandle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"JSHandle.js","sourceRoot":"","sources":["../../../../src/api/JSHandle.ts"],"names":[],"mappings":"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"}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1498
node_modules/puppeteer-core/lib/cjs/puppeteer/api/Page.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,39 @@
/**
* @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 } 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 declare abstract class Realm implements Disposable {
#private;
protected readonly timeoutSettings: TimeoutSettings;
readonly taskManager: TaskManager;
constructor(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>>>;
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>>>>;
abstract adoptBackendNode(backendNodeId?: number): Promise<JSHandle<Node>>;
get disposed(): boolean;
/** @internal */
dispose(): void;
/** @internal */
[disposeSymbol](): void;
}
//# sourceMappingURL=Realm.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Realm.d.ts","sourceRoot":"","sources":["../../../../src/api/Realm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,WAAW,EAAW,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAE5C;;GAEG;AACH,8BAAsB,KAAM,YAAW,UAAU;;IAC/C,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IACpD,QAAQ,CAAC,WAAW,cAAqB;gBAE7B,eAAe,EAAE,eAAe;IAI5C,QAAQ,KAAK,WAAW,IAAI,WAAW,CAAC;IAExC,QAAQ,CAAC,WAAW,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACrE,QAAQ,CAAC,cAAc,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IACxE,QAAQ,CAAC,cAAc,CACrB,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAExD,YAAY,EAAE,IAAI,GAAG,MAAM,EAC3B,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,QAAQ,CACf,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAExD,YAAY,EAAE,IAAI,GAAG,MAAM,EAC3B,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAE/B,eAAe,CACnB,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,YAAY,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,YAAY,CAC/D,eAAe,CAAC,MAAM,CAAC,CACxB,EAED,YAAY,EAAE,IAAI,GAAG,MAAM,EAC3B,OAAO,GAAE;QACP,OAAO,CAAC,EAAE,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;QACtC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;QAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;KACjB,EACN,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IA0BhD,QAAQ,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1E,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAGD,gBAAgB;IAChB,OAAO,IAAI,IAAI;IAMf,gBAAgB;IAChB,CAAC,aAAa,CAAC,IAAI,IAAI;CAGxB"}

View File

@@ -0,0 +1,48 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Realm = void 0;
const WaitTask_js_1 = require("../common/WaitTask.js");
const disposable_js_1 = require("../util/disposable.js");
/**
* @internal
*/
class Realm {
timeoutSettings;
taskManager = new WaitTask_js_1.TaskManager();
constructor(timeoutSettings) {
this.timeoutSettings = timeoutSettings;
}
async waitForFunction(pageFunction, options = {}, ...args) {
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_js_1.WaitTask(this, {
polling,
root,
timeout,
signal,
}, pageFunction, ...args);
return await waitTask.result;
}
get disposed() {
return this.#disposed;
}
#disposed = false;
/** @internal */
dispose() {
this.#disposed = true;
this.taskManager.terminateAll(new Error('waitForFunction failed: frame got detached.'));
}
/** @internal */
[disposable_js_1.disposeSymbol]() {
this.dispose();
}
}
exports.Realm = Realm;
//# sourceMappingURL=Realm.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Realm.js","sourceRoot":"","sources":["../../../../src/api/Realm.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAQH,uDAA4D;AAC5D,yDAAoD;AAMpD;;GAEG;AACH,MAAsB,KAAK;IACN,eAAe,CAAkB;IAC3C,WAAW,GAAG,IAAI,yBAAW,EAAE,CAAC;IAEzC,YAAY,eAAgC;QAC1C,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAqBD,KAAK,CAAC,eAAe,CAMnB,YAA2B,EAC3B,UAKI,EAAE,EACN,GAAG,IAAY;QAEf,MAAM,EACJ,OAAO,GAAG,KAAK,EACf,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,EACxC,IAAI,EACJ,MAAM,GACP,GAAG,OAAO,CAAC;QACZ,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,sBAAQ,CAC3B,IAAI,EACJ;YACE,OAAO;YACP,IAAI;YACJ,OAAO;YACP,MAAM;SACP,EACD,YAEU,EACV,GAAG,IAAI,CACR,CAAC;QACF,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC;IAC/B,CAAC;IAID,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,SAAS,GAAG,KAAK,CAAC;IAClB,gBAAgB;IAChB,OAAO;QACL,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,YAAY,CAC3B,IAAI,KAAK,CAAC,6CAA6C,CAAC,CACzD,CAAC;IACJ,CAAC;IACD,gBAAgB;IAChB,CAAC,6BAAa,CAAC;QACb,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;CACF;AArFD,sBAqFC"}

View File

@@ -0,0 +1,80 @@
/**
* @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 declare 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 declare abstract class Target {
/**
* @internal
*/
protected constructor();
/**
* If the target is not of type `"service_worker"` or `"shared_worker"`, returns `null`.
*/
worker(): Promise<WebWorker | null>;
/**
* If the target is not of type `"page"`, `"webview"` or `"background_page"`,
* returns `null`.
*/
page(): Promise<Page | 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;
}
//# sourceMappingURL=Target.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Target.d.ts","sourceRoot":"","sources":["../../../../src/api/Target.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAE9C;;GAEG;AACH,oBAAY,UAAU;IACpB,IAAI,SAAS;IACb,eAAe,oBAAoB;IACnC,cAAc,mBAAmB;IACjC,aAAa,kBAAkB;IAC/B,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf;;OAEG;IACH,GAAG,QAAQ;CACZ;AAED;;;;;;GAMG;AACH,8BAAsB,MAAM;IAC1B;;OAEG;IACH,SAAS;IAET;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIzC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAIlC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAEhC,QAAQ,CAAC,GAAG,IAAI,MAAM;IAEtB;;OAEG;IACH,QAAQ,CAAC,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC;IAEhD;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,IAAI,UAAU;IAE3B;;OAEG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO;IAE3B;;OAEG;IACH,QAAQ,CAAC,cAAc,IAAI,cAAc;IAEzC;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,MAAM,GAAG,SAAS;CACtC"}

View File

@@ -0,0 +1,53 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Target = exports.TargetType = void 0;
/**
* @public
*/
var TargetType;
(function (TargetType) {
TargetType["PAGE"] = "page";
TargetType["BACKGROUND_PAGE"] = "background_page";
TargetType["SERVICE_WORKER"] = "service_worker";
TargetType["SHARED_WORKER"] = "shared_worker";
TargetType["BROWSER"] = "browser";
TargetType["WEBVIEW"] = "webview";
TargetType["OTHER"] = "other";
/**
* @internal
*/
TargetType["TAB"] = "tab";
})(TargetType || (exports.TargetType = TargetType = {}));
/**
* 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
*/
class Target {
/**
* @internal
*/
constructor() { }
/**
* If the target is not of type `"service_worker"` or `"shared_worker"`, returns `null`.
*/
async worker() {
return null;
}
/**
* If the target is not of type `"page"`, `"webview"` or `"background_page"`,
* returns `null`.
*/
async page() {
return null;
}
}
exports.Target = Target;
//# sourceMappingURL=Target.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Target.js","sourceRoot":"","sources":["../../../../src/api/Target.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAQH;;GAEG;AACH,IAAY,UAYX;AAZD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,iDAAmC,CAAA;IACnC,+CAAiC,CAAA;IACjC,6CAA+B,CAAA;IAC/B,iCAAmB,CAAA;IACnB,iCAAmB,CAAA;IACnB,6BAAe,CAAA;IACf;;OAEG;IACH,yBAAW,CAAA;AACb,CAAC,EAZW,UAAU,0BAAV,UAAU,QAYrB;AAED;;;;;;GAMG;AACH,MAAsB,MAAM;IAC1B;;OAEG;IACH,gBAAyB,CAAC;IAE1B;;OAEG;IACH,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC;IACd,CAAC;CAuCF;AA1DD,wBA0DC"}

View File

@@ -0,0 +1,102 @@
/**
* @license
* Copyright 2018 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import { EventEmitter, type EventType } from '../common/EventEmitter.js';
import { TimeoutSettings } from '../common/TimeoutSettings.js';
import type { EvaluateFunc, HandleFor } from '../common/types.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 declare abstract class WebWorker extends EventEmitter<Record<EventType, unknown>> {
#private;
/**
* @internal
*/
readonly timeoutSettings: TimeoutSettings;
/**
* @internal
*/
constructor(url: string);
/**
* @internal
*/
abstract mainRealm(): Realm;
/**
* The URL of this web worker.
*/
url(): string;
/**
* 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`.
*/
evaluate<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(func: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
/**
* 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`.
*/
evaluateHandle<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(func: Func | string, ...args: Params): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
close(): Promise<void>;
}
//# sourceMappingURL=WebWorker.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"WebWorker.d.ts","sourceRoot":"","sources":["../../../../src/api/WebWorker.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAC,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAC,YAAY,EAAE,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAGhE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,YAAY,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,8BAAsB,SAAU,SAAQ,YAAY,CAClD,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAC3B;;IACC;;OAEG;IACH,QAAQ,CAAC,eAAe,kBAAyB;IAIjD;;OAEG;gBACS,GAAG,EAAE,MAAM;IAMvB;;OAEG;IACH,QAAQ,CAAC,SAAS,IAAI,KAAK;IAE3B;;OAEG;IACH,GAAG,IAAI,MAAM;IAIb;;OAEG;IACH,QAAQ,KAAK,MAAM,IAAI,UAAU,CAAC;IAElC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,QAAQ,CACZ,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EACxD,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAK3E;;;;;;;;;;;;;;;OAeG;IACG,cAAc,CAClB,MAAM,SAAS,OAAO,EAAE,EACxB,IAAI,SAAS,YAAY,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAExD,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,GAAG,IAAI,EAAE,MAAM,GACd,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAK1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}

View File

@@ -0,0 +1,110 @@
"use strict";
/**
* @license
* Copyright 2018 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebWorker = void 0;
const Errors_js_1 = require("../common/Errors.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const TimeoutSettings_js_1 = require("../common/TimeoutSettings.js");
const util_js_1 = require("../common/util.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
*/
class WebWorker extends EventEmitter_js_1.EventEmitter {
/**
* @internal
*/
timeoutSettings = new TimeoutSettings_js_1.TimeoutSettings();
#url;
/**
* @internal
*/
constructor(url) {
super();
this.#url = url;
}
/**
* The URL of this web worker.
*/
url() {
return this.#url;
}
/**
* 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(func, ...args) {
func = (0, util_js_1.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(func, ...args) {
func = (0, util_js_1.withSourcePuppeteerURLIfNone)(this.evaluateHandle.name, func);
return await this.mainRealm().evaluateHandle(func, ...args);
}
async close() {
throw new Errors_js_1.UnsupportedOperation('WebWorker.close() is not supported');
}
}
exports.WebWorker = WebWorker;
//# sourceMappingURL=WebWorker.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"WebWorker.js","sourceRoot":"","sources":["../../../../src/api/WebWorker.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,mDAAyD;AACzD,+DAAuE;AACvE,qEAA6D;AAE7D,+CAA+D;AAK/D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAsB,SAAU,SAAQ,8BAEvC;IACC;;OAEG;IACM,eAAe,GAAG,IAAI,oCAAe,EAAE,CAAC;IAExC,IAAI,CAAS;IAEtB;;OAEG;IACH,YAAY,GAAW;QACrB,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,CAAC;IAOD;;OAEG;IACH,GAAG;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAOD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,QAAQ,CAGZ,IAAmB,EAAE,GAAG,IAAY;QACpC,IAAI,GAAG,IAAA,sCAA4B,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9D,OAAO,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,cAAc,CAIlB,IAAmB,EACnB,GAAG,IAAY;QAEf,IAAI,GAAG,IAAA,sCAA4B,EAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACpE,OAAO,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,gCAAoB,CAAC,oCAAoC,CAAC,CAAC;IACvE,CAAC;CACF;AAjGD,8BAiGC"}

View File

@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
export * from './Browser.js';
export * from './BrowserContext.js';
export * from './CDPSession.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';
//# sourceMappingURL=api.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/api/api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,mBAAmB,kBAAkB,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC"}

View File

@@ -0,0 +1,37 @@
"use strict";
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./Browser.js"), exports);
__exportStar(require("./BrowserContext.js"), exports);
__exportStar(require("./CDPSession.js"), exports);
__exportStar(require("./Dialog.js"), exports);
__exportStar(require("./ElementHandle.js"), exports);
__exportStar(require("./Frame.js"), exports);
__exportStar(require("./HTTPRequest.js"), exports);
__exportStar(require("./HTTPResponse.js"), exports);
__exportStar(require("./Input.js"), exports);
__exportStar(require("./JSHandle.js"), exports);
__exportStar(require("./Page.js"), exports);
__exportStar(require("./Realm.js"), exports);
__exportStar(require("./Target.js"), exports);
__exportStar(require("./WebWorker.js"), exports);
__exportStar(require("./locators/locators.js"), exports);
//# sourceMappingURL=api.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../../src/api/api.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,sDAAoC;AACpC,kDAAgC;AAChC,8CAA4B;AAC5B,qDAAmC;AAEnC,6CAA2B;AAC3B,mDAAiC;AACjC,oDAAkC;AAClC,6CAA2B;AAC3B,gDAA8B;AAC9B,4CAA0B;AAC1B,6CAA2B;AAC3B,8CAA4B;AAC5B,iDAA+B;AAC/B,yDAAuC"}

View File

@@ -0,0 +1,311 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Observable, OperatorFunction } from '../../../third_party/rxjs/rxjs.js';
import type { EventType } from '../../common/EventEmitter.js';
import { EventEmitter } from '../../common/EventEmitter.js';
import type { Awaitable, HandleFor, NodeFor } from '../../common/types.js';
import type { ClickOptions } from '../ElementHandle.js';
import type { Frame } from '../Frame.js';
import type { Page } from '../Page.js';
/**
* Whether to wait for the element to be
* {@link ElementHandle.isVisible | visible} or
* {@link ElementHandle.isHidden | hidden}.
* `null` to disable visibility checks.
*
* @public
*/
export type VisibilityOption = 'hidden' | 'visible' | null;
/**
* @public
*/
export interface ActionOptions {
/**
* A signal to abort the locator action.
*/
signal?: AbortSignal;
}
/**
* @public
*/
export type LocatorClickOptions = ClickOptions & ActionOptions;
/**
* @public
*/
export interface LocatorScrollOptions extends ActionOptions {
scrollTop?: number;
scrollLeft?: number;
}
/**
* All the events that a locator instance may emit.
*
* @public
*/
export declare enum LocatorEvent {
/**
* Emitted every time before the locator performs an action on the located element(s).
*/
Action = "action"
}
/**
* @public
*/
export interface LocatorEvents extends Record<EventType, unknown> {
[LocatorEvent.Action]: undefined;
}
/**
* Locators describe a strategy of locating objects and performing an action on
* them. If the action fails because the object is not ready for the action, the
* whole operation is retried. Various preconditions for a successful action are
* checked automatically.
*
* See {@link https://pptr.dev/guides/page-interactions#locators} for details.
*
* @public
*/
export declare abstract class Locator<T> extends EventEmitter<LocatorEvents> {
#private;
/**
* Creates a race between multiple locators trying to locate elements in
* parallel but ensures that only a single element receives the action.
*
* @public
*/
static race<Locators extends readonly unknown[] | []>(locators: Locators): Locator<AwaitedLocator<Locators[number]>>;
/**
* Used for nominally typing {@link Locator}.
*/
_?: T;
/**
* @internal
*/
protected visibility: VisibilityOption;
/**
* @internal
*/
protected _timeout: number;
/**
* @internal
*/
protected operators: {
conditions: (conditions: Array<Action<T, never>>, signal?: AbortSignal) => OperatorFunction<HandleFor<T>, HandleFor<T>>;
retryAndRaceWithSignalAndTimer: <T_1>(signal?: AbortSignal, cause?: Error) => OperatorFunction<T_1, T_1>;
};
get timeout(): number;
/**
* Creates a new locator instance by cloning the current locator and setting
* the total timeout for the locator actions.
*
* Pass `0` to disable timeout.
*
* @defaultValue `Page.getDefaultTimeout()`
*/
setTimeout(timeout: number): Locator<T>;
/**
* Creates a new locator instance by cloning the current locator with the
* visibility property changed to the specified value.
*/
setVisibility<NodeType extends Node>(this: Locator<NodeType>, visibility: VisibilityOption): Locator<NodeType>;
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether to wait for input elements to become enabled before the
* action. Applicable to `click` and `fill` actions.
*
* @defaultValue `true`
*/
setWaitForEnabled<NodeType extends Node>(this: Locator<NodeType>, value: boolean): Locator<NodeType>;
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether the locator should scroll the element into viewport if
* it is not in the viewport already.
*
* @defaultValue `true`
*/
setEnsureElementIsInTheViewport<ElementType extends Element>(this: Locator<ElementType>, value: boolean): Locator<ElementType>;
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether the locator has to wait for the element's bounding box
* to be same between two consecutive animation frames.
*
* @defaultValue `true`
*/
setWaitForStableBoundingBox<ElementType extends Element>(this: Locator<ElementType>, value: boolean): Locator<ElementType>;
/**
* @internal
*/
copyOptions<T>(locator: Locator<T>): this;
/**
* @internal
*/
abstract _clone(): Locator<T>;
/**
* @internal
*/
abstract _wait(options?: Readonly<ActionOptions>): Observable<HandleFor<T>>;
/**
* Clones the locator.
*/
clone(): Locator<T>;
/**
* Waits for the locator to get a handle from the page.
*
* @public
*/
waitHandle(options?: Readonly<ActionOptions>): Promise<HandleFor<T>>;
/**
* Waits for the locator to get the serialized value from the page.
*
* Note this requires the value to be JSON-serializable.
*
* @public
*/
wait(options?: Readonly<ActionOptions>): Promise<T>;
/**
* Maps the locator using the provided mapper.
*
* @public
*/
map<To>(mapper: Mapper<T, To>): Locator<To>;
/**
* Creates an expectation that is evaluated against located values.
*
* If the expectations do not match, then the locator will retry.
*
* @public
*/
filter<S extends T>(predicate: Predicate<T, S>): Locator<S>;
/**
* Creates an expectation that is evaluated against located handles.
*
* If the expectations do not match, then the locator will retry.
*
* @internal
*/
filterHandle<S extends T>(predicate: Predicate<HandleFor<T>, HandleFor<S>>): Locator<S>;
/**
* Maps the locator using the provided mapper.
*
* @internal
*/
mapHandle<To>(mapper: HandleMapper<T, To>): Locator<To>;
/**
* Clicks the located element.
*/
click<ElementType extends Element>(this: Locator<ElementType>, options?: Readonly<LocatorClickOptions>): Promise<void>;
/**
* Fills out the input identified by the locator using the provided value. The
* type of the input is determined at runtime and the appropriate fill-out
* method is chosen based on the type. `contenteditable`, select, textarea and
* input elements are supported.
*/
fill<ElementType extends Element>(this: Locator<ElementType>, value: string, options?: Readonly<ActionOptions>): Promise<void>;
/**
* Hovers over the located element.
*/
hover<ElementType extends Element>(this: Locator<ElementType>, options?: Readonly<ActionOptions>): Promise<void>;
/**
* Scrolls the located element.
*/
scroll<ElementType extends Element>(this: Locator<ElementType>, options?: Readonly<LocatorScrollOptions>): Promise<void>;
}
/**
* @internal
*/
export declare class FunctionLocator<T> extends Locator<T> {
#private;
static create<Ret>(pageOrFrame: Page | Frame, func: () => Awaitable<Ret>): Locator<Ret>;
private constructor();
_clone(): FunctionLocator<T>;
_wait(options?: Readonly<ActionOptions>): Observable<HandleFor<T>>;
}
/**
* @public
*/
export type Predicate<From, To extends From = From> = ((value: From) => value is To) | ((value: From) => Awaitable<boolean>);
/**
* @internal
*/
export type HandlePredicate<From, To extends From = From> = ((value: HandleFor<From>, signal?: AbortSignal) => value is HandleFor<To>) | ((value: HandleFor<From>, signal?: AbortSignal) => Awaitable<boolean>);
/**
* @internal
*/
export declare abstract class DelegatedLocator<T, U> extends Locator<U> {
#private;
constructor(delegate: Locator<T>);
protected get delegate(): Locator<T>;
setTimeout(timeout: number): DelegatedLocator<T, U>;
setVisibility<ValueType extends Node, NodeType extends Node>(this: DelegatedLocator<ValueType, NodeType>, visibility: VisibilityOption): DelegatedLocator<ValueType, NodeType>;
setWaitForEnabled<ValueType extends Node, NodeType extends Node>(this: DelegatedLocator<ValueType, NodeType>, value: boolean): DelegatedLocator<ValueType, NodeType>;
setEnsureElementIsInTheViewport<ValueType extends Element, ElementType extends Element>(this: DelegatedLocator<ValueType, ElementType>, value: boolean): DelegatedLocator<ValueType, ElementType>;
setWaitForStableBoundingBox<ValueType extends Element, ElementType extends Element>(this: DelegatedLocator<ValueType, ElementType>, value: boolean): DelegatedLocator<ValueType, ElementType>;
abstract _clone(): DelegatedLocator<T, U>;
abstract _wait(): Observable<HandleFor<U>>;
}
/**
* @internal
*/
export declare class FilteredLocator<From, To extends From> extends DelegatedLocator<From, To> {
#private;
constructor(base: Locator<From>, predicate: HandlePredicate<From, To>);
_clone(): FilteredLocator<From, To>;
_wait(options?: Readonly<ActionOptions>): Observable<HandleFor<To>>;
}
/**
* @public
*/
export type Mapper<From, To> = (value: From) => Awaitable<To>;
/**
* @internal
*/
export type HandleMapper<From, To> = (value: HandleFor<From>, signal?: AbortSignal) => Awaitable<HandleFor<To>>;
/**
* @internal
*/
export declare class MappedLocator<From, To> extends DelegatedLocator<From, To> {
#private;
constructor(base: Locator<From>, mapper: HandleMapper<From, To>);
_clone(): MappedLocator<From, To>;
_wait(options?: Readonly<ActionOptions>): Observable<HandleFor<To>>;
}
/**
* @internal
*/
export type Action<T, U> = (element: HandleFor<T>, signal?: AbortSignal) => Observable<U>;
/**
* @internal
*/
export declare class NodeLocator<T extends Node> extends Locator<T> {
#private;
static create<Selector extends string>(pageOrFrame: Page | Frame, selector: Selector): Locator<NodeFor<Selector>>;
private constructor();
_clone(): NodeLocator<T>;
_wait(options?: Readonly<ActionOptions>): Observable<HandleFor<T>>;
}
/**
* @public
*/
export type AwaitedLocator<T> = T extends Locator<infer S> ? S : never;
/**
* @internal
*/
export declare class RaceLocator<T> extends Locator<T> {
#private;
static create<T extends readonly unknown[]>(locators: T): Locator<AwaitedLocator<T[number]>>;
constructor(locators: ReadonlyArray<Locator<T>>);
_clone(): RaceLocator<T>;
_wait(options?: Readonly<ActionOptions>): Observable<HandleFor<T>>;
}
/**
* For observables coming from promises, a delay is needed, otherwise RxJS will
* never yield in a permanent failure for a promise.
*
* We also don't want RxJS to do promise operations to often, so we bump the
* delay up to 100ms.
*
* @internal
*/
export declare const RETRY_DELAY = 100;
//# sourceMappingURL=locators.d.ts.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,747 @@
"use strict";
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.RETRY_DELAY = exports.RaceLocator = exports.NodeLocator = exports.MappedLocator = exports.FilteredLocator = exports.DelegatedLocator = exports.FunctionLocator = exports.Locator = exports.LocatorEvent = void 0;
const rxjs_js_1 = require("../../../third_party/rxjs/rxjs.js");
const EventEmitter_js_1 = require("../../common/EventEmitter.js");
const util_js_1 = require("../../common/util.js");
/**
* All the events that a locator instance may emit.
*
* @public
*/
var LocatorEvent;
(function (LocatorEvent) {
/**
* Emitted every time before the locator performs an action on the located element(s).
*/
LocatorEvent["Action"] = "action";
})(LocatorEvent || (exports.LocatorEvent = LocatorEvent = {}));
/**
* Locators describe a strategy of locating objects and performing an action on
* them. If the action fails because the object is not ready for the action, the
* whole operation is retried. Various preconditions for a successful action are
* checked automatically.
*
* See {@link https://pptr.dev/guides/page-interactions#locators} for details.
*
* @public
*/
class Locator extends EventEmitter_js_1.EventEmitter {
/**
* Creates a race between multiple locators trying to locate elements in
* parallel but ensures that only a single element receives the action.
*
* @public
*/
static race(locators) {
return RaceLocator.create(locators);
}
/**
* @internal
*/
visibility = null;
/**
* @internal
*/
_timeout = 30000;
#ensureElementIsInTheViewport = true;
#waitForEnabled = true;
#waitForStableBoundingBox = true;
/**
* @internal
*/
operators = {
conditions: (conditions, signal) => {
return (0, rxjs_js_1.mergeMap)((handle) => {
return (0, rxjs_js_1.merge)(...conditions.map(condition => {
return condition(handle, signal);
})).pipe((0, rxjs_js_1.defaultIfEmpty)(handle));
});
},
retryAndRaceWithSignalAndTimer: (signal, cause) => {
const candidates = [];
if (signal) {
candidates.push((0, util_js_1.fromAbortSignal)(signal, cause));
}
candidates.push((0, util_js_1.timeout)(this._timeout, cause));
return (0, rxjs_js_1.pipe)((0, rxjs_js_1.retry)({ delay: exports.RETRY_DELAY }), (0, rxjs_js_1.raceWith)(...candidates));
},
};
// Determines when the locator will timeout for actions.
get timeout() {
return this._timeout;
}
/**
* Creates a new locator instance by cloning the current locator and setting
* the total timeout for the locator actions.
*
* Pass `0` to disable timeout.
*
* @defaultValue `Page.getDefaultTimeout()`
*/
setTimeout(timeout) {
const locator = this._clone();
locator._timeout = timeout;
return locator;
}
/**
* Creates a new locator instance by cloning the current locator with the
* visibility property changed to the specified value.
*/
setVisibility(visibility) {
const locator = this._clone();
locator.visibility = visibility;
return locator;
}
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether to wait for input elements to become enabled before the
* action. Applicable to `click` and `fill` actions.
*
* @defaultValue `true`
*/
setWaitForEnabled(value) {
const locator = this._clone();
locator.#waitForEnabled = value;
return locator;
}
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether the locator should scroll the element into viewport if
* it is not in the viewport already.
*
* @defaultValue `true`
*/
setEnsureElementIsInTheViewport(value) {
const locator = this._clone();
locator.#ensureElementIsInTheViewport = value;
return locator;
}
/**
* Creates a new locator instance by cloning the current locator and
* specifying whether the locator has to wait for the element's bounding box
* to be same between two consecutive animation frames.
*
* @defaultValue `true`
*/
setWaitForStableBoundingBox(value) {
const locator = this._clone();
locator.#waitForStableBoundingBox = value;
return locator;
}
/**
* @internal
*/
copyOptions(locator) {
this._timeout = locator._timeout;
this.visibility = locator.visibility;
this.#waitForEnabled = locator.#waitForEnabled;
this.#ensureElementIsInTheViewport = locator.#ensureElementIsInTheViewport;
this.#waitForStableBoundingBox = locator.#waitForStableBoundingBox;
return this;
}
/**
* If the element has a "disabled" property, wait for the element to be
* enabled.
*/
#waitForEnabledIfNeeded = (handle, signal) => {
if (!this.#waitForEnabled) {
return rxjs_js_1.EMPTY;
}
return (0, rxjs_js_1.from)(handle.frame.waitForFunction(element => {
if (!(element instanceof HTMLElement)) {
return true;
}
const isNativeFormControl = [
'BUTTON',
'INPUT',
'SELECT',
'TEXTAREA',
'OPTION',
'OPTGROUP',
].includes(element.nodeName);
return !isNativeFormControl || !element.hasAttribute('disabled');
}, {
timeout: this._timeout,
signal,
}, handle)).pipe((0, rxjs_js_1.ignoreElements)());
};
/**
* Compares the bounding box of the element for two consecutive animation
* frames and waits till they are the same.
*/
#waitForStableBoundingBoxIfNeeded = (handle) => {
if (!this.#waitForStableBoundingBox) {
return rxjs_js_1.EMPTY;
}
return (0, rxjs_js_1.defer)(() => {
// Note we don't use waitForFunction because that relies on RAF.
return (0, rxjs_js_1.from)(handle.evaluate(element => {
return new Promise(resolve => {
window.requestAnimationFrame(() => {
const rect1 = element.getBoundingClientRect();
window.requestAnimationFrame(() => {
const rect2 = element.getBoundingClientRect();
resolve([
{
x: rect1.x,
y: rect1.y,
width: rect1.width,
height: rect1.height,
},
{
x: rect2.x,
y: rect2.y,
width: rect2.width,
height: rect2.height,
},
]);
});
});
});
}));
}).pipe((0, rxjs_js_1.first)(([rect1, rect2]) => {
return (rect1.x === rect2.x &&
rect1.y === rect2.y &&
rect1.width === rect2.width &&
rect1.height === rect2.height);
}), (0, rxjs_js_1.retry)({ delay: exports.RETRY_DELAY }), (0, rxjs_js_1.ignoreElements)());
};
/**
* Checks if the element is in the viewport and auto-scrolls it if it is not.
*/
#ensureElementIsInTheViewportIfNeeded = (handle) => {
if (!this.#ensureElementIsInTheViewport) {
return rxjs_js_1.EMPTY;
}
return (0, rxjs_js_1.from)(handle.isIntersectingViewport({ threshold: 0 })).pipe((0, rxjs_js_1.filter)(isIntersectingViewport => {
return !isIntersectingViewport;
}), (0, rxjs_js_1.mergeMap)(() => {
return (0, rxjs_js_1.from)(handle.scrollIntoView());
}), (0, rxjs_js_1.mergeMap)(() => {
return (0, rxjs_js_1.defer)(() => {
return (0, rxjs_js_1.from)(handle.isIntersectingViewport({ threshold: 0 }));
}).pipe((0, rxjs_js_1.first)(rxjs_js_1.identity), (0, rxjs_js_1.retry)({ delay: exports.RETRY_DELAY }), (0, rxjs_js_1.ignoreElements)());
}));
};
#click(options) {
const signal = options?.signal;
const cause = new Error('Locator.click');
return this._wait(options).pipe(this.operators.conditions([
this.#ensureElementIsInTheViewportIfNeeded,
this.#waitForStableBoundingBoxIfNeeded,
this.#waitForEnabledIfNeeded,
], signal), (0, rxjs_js_1.tap)(() => {
return this.emit(LocatorEvent.Action, undefined);
}), (0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(handle.click(options)).pipe((0, rxjs_js_1.catchError)(err => {
void handle.dispose().catch(util_js_1.debugError);
throw err;
}));
}), this.operators.retryAndRaceWithSignalAndTimer(signal, cause));
}
#fill(value, options) {
const signal = options?.signal;
const cause = new Error('Locator.fill');
return this._wait(options).pipe(this.operators.conditions([
this.#ensureElementIsInTheViewportIfNeeded,
this.#waitForStableBoundingBoxIfNeeded,
this.#waitForEnabledIfNeeded,
], signal), (0, rxjs_js_1.tap)(() => {
return this.emit(LocatorEvent.Action, undefined);
}), (0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(handle.evaluate(el => {
if (el instanceof HTMLSelectElement) {
return 'select';
}
if (el instanceof HTMLTextAreaElement) {
return 'typeable-input';
}
if (el instanceof HTMLInputElement) {
if (new Set([
'textarea',
'text',
'url',
'tel',
'search',
'password',
'number',
'email',
]).has(el.type)) {
return 'typeable-input';
}
else {
return 'other-input';
}
}
if (el.isContentEditable) {
return 'contenteditable';
}
return 'unknown';
}))
.pipe((0, rxjs_js_1.mergeMap)(inputType => {
switch (inputType) {
case 'select':
return (0, rxjs_js_1.from)(handle.select(value).then(rxjs_js_1.noop));
case 'contenteditable':
case 'typeable-input':
return (0, rxjs_js_1.from)(handle.evaluate((input, newValue) => {
const currentValue = input.isContentEditable
? input.innerText
: input.value;
// Clear the input if the current value does not match the filled
// out value.
if (newValue.length <= currentValue.length ||
!newValue.startsWith(input.value)) {
if (input.isContentEditable) {
input.innerText = '';
}
else {
input.value = '';
}
return newValue;
}
const originalValue = input.isContentEditable
? input.innerText
: input.value;
// If the value is partially filled out, only type the rest. Move
// cursor to the end of the common prefix.
if (input.isContentEditable) {
input.innerText = '';
input.innerText = originalValue;
}
else {
input.value = '';
input.value = originalValue;
}
return newValue.substring(originalValue.length);
}, value)).pipe((0, rxjs_js_1.mergeMap)(textToType => {
return (0, rxjs_js_1.from)(handle.type(textToType));
}));
case 'other-input':
return (0, rxjs_js_1.from)(handle.focus()).pipe((0, rxjs_js_1.mergeMap)(() => {
return (0, rxjs_js_1.from)(handle.evaluate((input, value) => {
input.value = value;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
}, value));
}));
case 'unknown':
throw new Error(`Element cannot be filled out.`);
}
}))
.pipe((0, rxjs_js_1.catchError)(err => {
void handle.dispose().catch(util_js_1.debugError);
throw err;
}));
}), this.operators.retryAndRaceWithSignalAndTimer(signal, cause));
}
#hover(options) {
const signal = options?.signal;
const cause = new Error('Locator.hover');
return this._wait(options).pipe(this.operators.conditions([
this.#ensureElementIsInTheViewportIfNeeded,
this.#waitForStableBoundingBoxIfNeeded,
], signal), (0, rxjs_js_1.tap)(() => {
return this.emit(LocatorEvent.Action, undefined);
}), (0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(handle.hover()).pipe((0, rxjs_js_1.catchError)(err => {
void handle.dispose().catch(util_js_1.debugError);
throw err;
}));
}), this.operators.retryAndRaceWithSignalAndTimer(signal, cause));
}
#scroll(options) {
const signal = options?.signal;
const cause = new Error('Locator.scroll');
return this._wait(options).pipe(this.operators.conditions([
this.#ensureElementIsInTheViewportIfNeeded,
this.#waitForStableBoundingBoxIfNeeded,
], signal), (0, rxjs_js_1.tap)(() => {
return this.emit(LocatorEvent.Action, undefined);
}), (0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(handle.evaluate((el, scrollTop, scrollLeft) => {
if (scrollTop !== undefined) {
el.scrollTop = scrollTop;
}
if (scrollLeft !== undefined) {
el.scrollLeft = scrollLeft;
}
}, options?.scrollTop, options?.scrollLeft)).pipe((0, rxjs_js_1.catchError)(err => {
void handle.dispose().catch(util_js_1.debugError);
throw err;
}));
}), this.operators.retryAndRaceWithSignalAndTimer(signal, cause));
}
/**
* Clones the locator.
*/
clone() {
return this._clone();
}
/**
* Waits for the locator to get a handle from the page.
*
* @public
*/
async waitHandle(options) {
const cause = new Error('Locator.waitHandle');
return await (0, rxjs_js_1.firstValueFrom)(this._wait(options).pipe(this.operators.retryAndRaceWithSignalAndTimer(options?.signal, cause)));
}
/**
* Waits for the locator to get the serialized value from the page.
*
* Note this requires the value to be JSON-serializable.
*
* @public
*/
async wait(options) {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const handle = __addDisposableResource(env_1, await this.waitHandle(options), false);
return await handle.jsonValue();
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
/**
* Maps the locator using the provided mapper.
*
* @public
*/
map(mapper) {
return new MappedLocator(this._clone(), handle => {
// SAFETY: TypeScript cannot deduce the type.
return handle.evaluateHandle(mapper);
});
}
/**
* Creates an expectation that is evaluated against located values.
*
* If the expectations do not match, then the locator will retry.
*
* @public
*/
filter(predicate) {
return new FilteredLocator(this._clone(), async (handle, signal) => {
await handle.frame.waitForFunction(predicate, { signal, timeout: this._timeout }, handle);
return true;
});
}
/**
* Creates an expectation that is evaluated against located handles.
*
* If the expectations do not match, then the locator will retry.
*
* @internal
*/
filterHandle(predicate) {
return new FilteredLocator(this._clone(), predicate);
}
/**
* Maps the locator using the provided mapper.
*
* @internal
*/
mapHandle(mapper) {
return new MappedLocator(this._clone(), mapper);
}
/**
* Clicks the located element.
*/
click(options) {
return (0, rxjs_js_1.firstValueFrom)(this.#click(options));
}
/**
* Fills out the input identified by the locator using the provided value. The
* type of the input is determined at runtime and the appropriate fill-out
* method is chosen based on the type. `contenteditable`, select, textarea and
* input elements are supported.
*/
fill(value, options) {
return (0, rxjs_js_1.firstValueFrom)(this.#fill(value, options));
}
/**
* Hovers over the located element.
*/
hover(options) {
return (0, rxjs_js_1.firstValueFrom)(this.#hover(options));
}
/**
* Scrolls the located element.
*/
scroll(options) {
return (0, rxjs_js_1.firstValueFrom)(this.#scroll(options));
}
}
exports.Locator = Locator;
/**
* @internal
*/
class FunctionLocator extends Locator {
static create(pageOrFrame, func) {
return new FunctionLocator(pageOrFrame, func).setTimeout('getDefaultTimeout' in pageOrFrame
? pageOrFrame.getDefaultTimeout()
: pageOrFrame.page().getDefaultTimeout());
}
#pageOrFrame;
#func;
constructor(pageOrFrame, func) {
super();
this.#pageOrFrame = pageOrFrame;
this.#func = func;
}
_clone() {
return new FunctionLocator(this.#pageOrFrame, this.#func);
}
_wait(options) {
const signal = options?.signal;
return (0, rxjs_js_1.defer)(() => {
return (0, rxjs_js_1.from)(this.#pageOrFrame.waitForFunction(this.#func, {
timeout: this.timeout,
signal,
}));
}).pipe((0, rxjs_js_1.throwIfEmpty)());
}
}
exports.FunctionLocator = FunctionLocator;
/**
* @internal
*/
class DelegatedLocator extends Locator {
#delegate;
constructor(delegate) {
super();
this.#delegate = delegate;
this.copyOptions(this.#delegate);
}
get delegate() {
return this.#delegate;
}
setTimeout(timeout) {
const locator = super.setTimeout(timeout);
locator.#delegate = this.#delegate.setTimeout(timeout);
return locator;
}
setVisibility(visibility) {
const locator = super.setVisibility(visibility);
locator.#delegate = locator.#delegate.setVisibility(visibility);
return locator;
}
setWaitForEnabled(value) {
const locator = super.setWaitForEnabled(value);
locator.#delegate = this.#delegate.setWaitForEnabled(value);
return locator;
}
setEnsureElementIsInTheViewport(value) {
const locator = super.setEnsureElementIsInTheViewport(value);
locator.#delegate = this.#delegate.setEnsureElementIsInTheViewport(value);
return locator;
}
setWaitForStableBoundingBox(value) {
const locator = super.setWaitForStableBoundingBox(value);
locator.#delegate = this.#delegate.setWaitForStableBoundingBox(value);
return locator;
}
}
exports.DelegatedLocator = DelegatedLocator;
/**
* @internal
*/
class FilteredLocator extends DelegatedLocator {
#predicate;
constructor(base, predicate) {
super(base);
this.#predicate = predicate;
}
_clone() {
return new FilteredLocator(this.delegate.clone(), this.#predicate).copyOptions(this);
}
_wait(options) {
return this.delegate._wait(options).pipe((0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(Promise.resolve(this.#predicate(handle, options?.signal))).pipe((0, rxjs_js_1.filter)(value => {
return value;
}), (0, rxjs_js_1.map)(() => {
// SAFETY: It passed the predicate, so this is correct.
return handle;
}));
}), (0, rxjs_js_1.throwIfEmpty)());
}
}
exports.FilteredLocator = FilteredLocator;
/**
* @internal
*/
class MappedLocator extends DelegatedLocator {
#mapper;
constructor(base, mapper) {
super(base);
this.#mapper = mapper;
}
_clone() {
return new MappedLocator(this.delegate.clone(), this.#mapper).copyOptions(this);
}
_wait(options) {
return this.delegate._wait(options).pipe((0, rxjs_js_1.mergeMap)(handle => {
return (0, rxjs_js_1.from)(Promise.resolve(this.#mapper(handle, options?.signal)));
}));
}
}
exports.MappedLocator = MappedLocator;
/**
* @internal
*/
class NodeLocator extends Locator {
static create(pageOrFrame, selector) {
return new NodeLocator(pageOrFrame, selector).setTimeout('getDefaultTimeout' in pageOrFrame
? pageOrFrame.getDefaultTimeout()
: pageOrFrame.page().getDefaultTimeout());
}
#pageOrFrame;
#selector;
constructor(pageOrFrame, selector) {
super();
this.#pageOrFrame = pageOrFrame;
this.#selector = selector;
}
/**
* Waits for the element to become visible or hidden. visibility === 'visible'
* means that the element has a computed style, the visibility property other
* than 'hidden' or 'collapse' and non-empty bounding box. visibility ===
* 'hidden' means the opposite of that.
*/
#waitForVisibilityIfNeeded = (handle) => {
if (!this.visibility) {
return rxjs_js_1.EMPTY;
}
return (() => {
switch (this.visibility) {
case 'hidden':
return (0, rxjs_js_1.defer)(() => {
return (0, rxjs_js_1.from)(handle.isHidden());
});
case 'visible':
return (0, rxjs_js_1.defer)(() => {
return (0, rxjs_js_1.from)(handle.isVisible());
});
}
})().pipe((0, rxjs_js_1.first)(rxjs_js_1.identity), (0, rxjs_js_1.retry)({ delay: exports.RETRY_DELAY }), (0, rxjs_js_1.ignoreElements)());
};
_clone() {
return new NodeLocator(this.#pageOrFrame, this.#selector).copyOptions(this);
}
_wait(options) {
const signal = options?.signal;
return (0, rxjs_js_1.defer)(() => {
return (0, rxjs_js_1.from)(this.#pageOrFrame.waitForSelector(this.#selector, {
visible: false,
timeout: this._timeout,
signal,
}));
}).pipe((0, rxjs_js_1.filter)((value) => {
return value !== null;
}), (0, rxjs_js_1.throwIfEmpty)(), this.operators.conditions([this.#waitForVisibilityIfNeeded], signal));
}
}
exports.NodeLocator = NodeLocator;
function checkLocatorArray(locators) {
for (const locator of locators) {
if (!(locator instanceof Locator)) {
throw new Error('Unknown locator for race candidate');
}
}
return locators;
}
/**
* @internal
*/
class RaceLocator extends Locator {
static create(locators) {
const array = checkLocatorArray(locators);
return new RaceLocator(array);
}
#locators;
constructor(locators) {
super();
this.#locators = locators;
}
_clone() {
return new RaceLocator(this.#locators.map(locator => {
return locator.clone();
})).copyOptions(this);
}
_wait(options) {
return (0, rxjs_js_1.race)(...this.#locators.map(locator => {
return locator._wait(options);
}));
}
}
exports.RaceLocator = RaceLocator;
/**
* For observables coming from promises, a delay is needed, otherwise RxJS will
* never yield in a permanent failure for a promise.
*
* We also don't want RxJS to do promise operations to often, so we bump the
* delay up to 100ms.
*
* @internal
*/
exports.RETRY_DELAY = 100;
//# sourceMappingURL=locators.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Connection as CdpConnection } from '../cdp/Connection.js';
import { BidiConnection } from './Connection.js';
/**
* @internal
*/
export declare function connectBidiOverCdp(cdp: CdpConnection): Promise<BidiConnection>;
//# sourceMappingURL=BidiOverCdp.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BidiOverCdp.d.ts","sourceRoot":"","sources":["../../../../src/bidi/BidiOverCdp.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAC,UAAU,IAAI,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAKtE,OAAO,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAM/C;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,cAAc,CAAC,CAoCzB"}

View File

@@ -0,0 +1,182 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.connectBidiOverCdp = connectBidiOverCdp;
const BidiMapper = __importStar(require("chromium-bidi/lib/cjs/bidiMapper/BidiMapper.js"));
const Debug_js_1 = require("../common/Debug.js");
const Errors_js_1 = require("../common/Errors.js");
const Connection_js_1 = require("./Connection.js");
const bidiServerLogger = (prefix, ...args) => {
(0, Debug_js_1.debug)(`bidi:${prefix}`)(args);
};
/**
* @internal
*/
async function connectBidiOverCdp(cdp) {
const transportBiDi = new NoOpTransport();
const cdpConnectionAdapter = new CdpConnectionAdapter(cdp);
const pptrTransport = {
send(message) {
// Forwards a BiDi command sent by Puppeteer to the input of the BidiServer.
transportBiDi.emitMessage(JSON.parse(message));
},
close() {
bidiServer.close();
cdpConnectionAdapter.close();
cdp.dispose();
},
onmessage(_message) {
// The method is overridden by the Connection.
},
};
transportBiDi.on('bidiResponse', (message) => {
// Forwards a BiDi event sent by BidiServer to Puppeteer.
pptrTransport.onmessage(JSON.stringify(message));
});
const pptrBiDiConnection = new Connection_js_1.BidiConnection(cdp.url(), pptrTransport, cdp.delay, cdp.timeout);
const bidiServer = await BidiMapper.BidiServer.createAndStart(transportBiDi, cdpConnectionAdapter, cdpConnectionAdapter.browserClient(),
/* selfTargetId= */ '', undefined, bidiServerLogger);
return pptrBiDiConnection;
}
/**
* Manages CDPSessions for BidiServer.
* @internal
*/
class CdpConnectionAdapter {
#cdp;
#adapters = new Map();
#browserCdpConnection;
constructor(cdp) {
this.#cdp = cdp;
this.#browserCdpConnection = new CDPClientAdapter(cdp);
}
browserClient() {
return this.#browserCdpConnection;
}
getCdpClient(id) {
const session = this.#cdp.session(id);
if (!session) {
throw new Error(`Unknown CDP session with id ${id}`);
}
if (!this.#adapters.has(session)) {
const adapter = new CDPClientAdapter(session, id, this.#browserCdpConnection);
this.#adapters.set(session, adapter);
return adapter;
}
return this.#adapters.get(session);
}
close() {
this.#browserCdpConnection.close();
for (const adapter of this.#adapters.values()) {
adapter.close();
}
}
}
/**
* Wrapper on top of CDPSession/CDPConnection to satisfy CDP interface that
* BidiServer needs.
*
* @internal
*/
class CDPClientAdapter extends BidiMapper.EventEmitter {
#closed = false;
#client;
sessionId = undefined;
#browserClient;
constructor(client, sessionId, browserClient) {
super();
this.#client = client;
this.sessionId = sessionId;
this.#browserClient = browserClient;
this.#client.on('*', this.#forwardMessage);
}
browserClient() {
return this.#browserClient;
}
#forwardMessage = (method, event) => {
this.emit(method, event);
};
async sendCommand(method, ...params) {
if (this.#closed) {
return;
}
try {
return await this.#client.send(method, ...params);
}
catch (err) {
if (this.#closed) {
return;
}
throw err;
}
}
close() {
this.#client.off('*', this.#forwardMessage);
this.#closed = true;
}
isCloseError(error) {
return error instanceof Errors_js_1.TargetCloseError;
}
}
/**
* This transport is given to the BiDi server instance and allows Puppeteer
* to send and receive commands to the BiDiServer.
* @internal
*/
class NoOpTransport extends BidiMapper.EventEmitter {
#onMessage = async (_m) => {
return;
};
emitMessage(message) {
void this.#onMessage(message);
}
setOnMessage(onMessage) {
this.#onMessage = onMessage;
}
async sendMessage(message) {
this.emit('bidiResponse', message);
}
close() {
this.#onMessage = async (_m) => {
return;
};
}
}
//# sourceMappingURL=BidiOverCdp.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BidiOverCdp.js","sourceRoot":"","sources":["../../../../src/bidi/BidiOverCdp.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { ChildProcess } from 'child_process';
import * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import { Browser, type BrowserCloseCallback, type BrowserContextOptions, type DebugInfo } from '../api/Browser.js';
import type { Page } from '../api/Page.js';
import type { Target } from '../api/Target.js';
import type { Connection as CdpConnection } from '../cdp/Connection.js';
import type { SupportedWebDriverCapabilities } from '../common/ConnectOptions.js';
import type { Viewport } from '../common/Viewport.js';
import { BidiBrowserContext } from './BrowserContext.js';
import type { BidiConnection } from './Connection.js';
import { BidiBrowserTarget } from './Target.js';
/**
* @internal
*/
export interface BidiBrowserOptions {
process?: ChildProcess;
closeCallback?: BrowserCloseCallback;
connection: BidiConnection;
cdpConnection?: CdpConnection;
defaultViewport: Viewport | null;
acceptInsecureCerts?: boolean;
capabilities?: SupportedWebDriverCapabilities;
}
/**
* @internal
*/
export declare class BidiBrowser extends Browser {
#private;
readonly protocol = "webDriverBiDi";
static readonly subscribeModules: [string, ...string[]];
static readonly subscribeCdpEvents: Bidi.Cdp.EventNames[];
static create(opts: BidiBrowserOptions): Promise<BidiBrowser>;
private constructor();
get cdpSupported(): boolean;
get cdpConnection(): CdpConnection | undefined;
userAgent(): Promise<string>;
get connection(): BidiConnection;
wsEndpoint(): string;
close(): Promise<void>;
get connected(): boolean;
process(): ChildProcess | null;
createBrowserContext(_options?: BrowserContextOptions): Promise<BidiBrowserContext>;
version(): Promise<string>;
browserContexts(): BidiBrowserContext[];
defaultBrowserContext(): BidiBrowserContext;
newPage(): Promise<Page>;
targets(): Target[];
target(): BidiBrowserTarget;
disconnect(): Promise<void>;
get debugInfo(): DebugInfo;
}
//# sourceMappingURL=Browser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../../../../src/bidi/Browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,IAAI,MAAM,4CAA4C,CAAC;AAGnE,OAAO,EACL,OAAO,EAEP,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAC,UAAU,IAAI,aAAa,EAAC,MAAM,sBAAsB,CAAC;AACtE,OAAO,KAAK,EAAC,8BAA8B,EAAC,MAAM,6BAA6B,CAAC;AAGhF,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAGpD,OAAO,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAIpD,OAAO,EAAC,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,8BAA8B,CAAC;CAC/C;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,OAAO;;IACtC,QAAQ,CAAC,QAAQ,mBAAmB;IAEpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAKrD;IACF,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAWvD;WAEW,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC;IAwCnE,OAAO;IAgCP,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,IAAI,aAAa,IAAI,aAAa,GAAG,SAAS,CAE7C;IAEc,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAgC3C,IAAI,UAAU,IAAI,cAAc,CAG/B;IAEQ,UAAU,IAAI,MAAM;IAId,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBrC,IAAa,SAAS,IAAI,OAAO,CAEhC;IAEQ,OAAO,IAAI,YAAY,GAAG,IAAI;IAIxB,oBAAoB,CACjC,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,OAAO,CAAC,kBAAkB,CAAC;IAKf,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAIhC,eAAe,IAAI,kBAAkB,EAAE;IAMvC,qBAAqB,IAAI,kBAAkB;IAI3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,OAAO,IAAI,MAAM,EAAE;IASnB,MAAM,IAAI,iBAAiB;IAIrB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW1C,IAAa,SAAS,IAAI,SAAS,CAIlC;CACF"}

View File

@@ -0,0 +1,254 @@
"use strict";
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiBrowser = void 0;
const Browser_js_1 = require("../api/Browser.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const decorators_js_1 = require("../util/decorators.js");
const BrowserContext_js_1 = require("./BrowserContext.js");
const Session_js_1 = require("./core/Session.js");
const Target_js_1 = require("./Target.js");
/**
* @internal
*/
let BidiBrowser = (() => {
let _classSuper = Browser_js_1.Browser;
let _private_trustedEmitter_decorators;
let _private_trustedEmitter_initializers = [];
let _private_trustedEmitter_extraInitializers = [];
let _private_trustedEmitter_descriptor;
return class BidiBrowser extends _classSuper {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_private_trustedEmitter_decorators = [(0, decorators_js_1.bubble)()];
__esDecorate(this, _private_trustedEmitter_descriptor = { get: __setFunctionName(function () { return this.#trustedEmitter_accessor_storage; }, "#trustedEmitter", "get"), set: __setFunctionName(function (value) { this.#trustedEmitter_accessor_storage = value; }, "#trustedEmitter", "set") }, _private_trustedEmitter_decorators, { kind: "accessor", name: "#trustedEmitter", static: false, private: true, access: { has: obj => #trustedEmitter in obj, get: obj => obj.#trustedEmitter, set: (obj, value) => { obj.#trustedEmitter = value; } }, metadata: _metadata }, _private_trustedEmitter_initializers, _private_trustedEmitter_extraInitializers);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
protocol = 'webDriverBiDi';
static subscribeModules = [
'browsingContext',
'network',
'log',
'script',
];
static subscribeCdpEvents = [
// Coverage
'cdp.Debugger.scriptParsed',
'cdp.CSS.styleSheetAdded',
'cdp.Runtime.executionContextsCleared',
// Tracing
'cdp.Tracing.tracingComplete',
// TODO: subscribe to all CDP events in the future.
'cdp.Network.requestWillBeSent',
'cdp.Debugger.scriptParsed',
'cdp.Page.screencastFrame',
];
static async create(opts) {
const session = await Session_js_1.Session.from(opts.connection, {
firstMatch: opts.capabilities?.firstMatch,
alwaysMatch: {
...opts.capabilities?.alwaysMatch,
// Capabilities that come from Puppeteer's API take precedence.
acceptInsecureCerts: opts.acceptInsecureCerts,
unhandledPromptBehavior: {
default: "ignore" /* Bidi.Session.UserPromptHandlerType.Ignore */,
},
webSocketUrl: true,
// Puppeteer with WebDriver BiDi does not support prerendering
// yet because WebDriver BiDi behavior is not specified. See
// https://github.com/w3c/webdriver-bidi/issues/321.
'goog:prerenderingDisabled': true,
},
});
await session.subscribe(session.capabilities.browserName.toLocaleLowerCase().includes('firefox')
? BidiBrowser.subscribeModules
: [...BidiBrowser.subscribeModules, ...BidiBrowser.subscribeCdpEvents]);
const browser = new BidiBrowser(session.browser, opts);
browser.#initialize();
return browser;
}
#trustedEmitter_accessor_storage = __runInitializers(this, _private_trustedEmitter_initializers, new EventEmitter_js_1.EventEmitter());
get #trustedEmitter() { return _private_trustedEmitter_descriptor.get.call(this); }
set #trustedEmitter(value) { return _private_trustedEmitter_descriptor.set.call(this, value); }
#process = __runInitializers(this, _private_trustedEmitter_extraInitializers);
#closeCallback;
#browserCore;
#defaultViewport;
#browserContexts = new WeakMap();
#target = new Target_js_1.BidiBrowserTarget(this);
#cdpConnection;
constructor(browserCore, opts) {
super();
this.#process = opts.process;
this.#closeCallback = opts.closeCallback;
this.#browserCore = browserCore;
this.#defaultViewport = opts.defaultViewport;
this.#cdpConnection = opts.cdpConnection;
}
#initialize() {
// Initializing existing contexts.
for (const userContext of this.#browserCore.userContexts) {
this.#createBrowserContext(userContext);
}
this.#browserCore.once('disconnected', () => {
this.#trustedEmitter.emit("disconnected" /* BrowserEvent.Disconnected */, undefined);
this.#trustedEmitter.removeAllListeners();
});
this.#process?.once('close', () => {
this.#browserCore.dispose('Browser process exited.', true);
this.connection.dispose();
});
}
get #browserName() {
return this.#browserCore.session.capabilities.browserName;
}
get #browserVersion() {
return this.#browserCore.session.capabilities.browserVersion;
}
get cdpSupported() {
return this.#cdpConnection !== undefined;
}
get cdpConnection() {
return this.#cdpConnection;
}
async userAgent() {
return this.#browserCore.session.capabilities.userAgent;
}
#createBrowserContext(userContext) {
const browserContext = BrowserContext_js_1.BidiBrowserContext.from(this, userContext, {
defaultViewport: this.#defaultViewport,
});
this.#browserContexts.set(userContext, browserContext);
browserContext.trustedEmitter.on("targetcreated" /* BrowserContextEvent.TargetCreated */, target => {
this.#trustedEmitter.emit("targetcreated" /* BrowserEvent.TargetCreated */, target);
});
browserContext.trustedEmitter.on("targetchanged" /* BrowserContextEvent.TargetChanged */, target => {
this.#trustedEmitter.emit("targetchanged" /* BrowserEvent.TargetChanged */, target);
});
browserContext.trustedEmitter.on("targetdestroyed" /* BrowserContextEvent.TargetDestroyed */, target => {
this.#trustedEmitter.emit("targetdestroyed" /* BrowserEvent.TargetDestroyed */, target);
});
return browserContext;
}
get connection() {
// SAFETY: We only have one implementation.
return this.#browserCore.session.connection;
}
wsEndpoint() {
return this.connection.url;
}
async close() {
if (this.connection.closed) {
return;
}
try {
await this.#browserCore.close();
await this.#closeCallback?.call(null);
}
catch (error) {
// Fail silently.
(0, util_js_1.debugError)(error);
}
finally {
this.connection.dispose();
}
}
get connected() {
return !this.#browserCore.disconnected;
}
process() {
return this.#process ?? null;
}
async createBrowserContext(_options) {
const userContext = await this.#browserCore.createUserContext();
return this.#createBrowserContext(userContext);
}
async version() {
return `${this.#browserName}/${this.#browserVersion}`;
}
browserContexts() {
return [...this.#browserCore.userContexts].map(context => {
return this.#browserContexts.get(context);
});
}
defaultBrowserContext() {
return this.#browserContexts.get(this.#browserCore.defaultUserContext);
}
newPage() {
return this.defaultBrowserContext().newPage();
}
targets() {
return [
this.#target,
...this.browserContexts().flatMap(context => {
return context.targets();
}),
];
}
target() {
return this.#target;
}
async disconnect() {
try {
await this.#browserCore.session.end();
}
catch (error) {
// Fail silently.
(0, util_js_1.debugError)(error);
}
finally {
this.connection.dispose();
}
}
get debugInfo() {
return {
pendingProtocolErrors: this.connection.getPendingProtocolErrors(),
};
}
};
})();
exports.BidiBrowser = BidiBrowser;
//# sourceMappingURL=Browser.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { ConnectionTransport } from '../common/ConnectionTransport.js';
import type { ConnectOptions } from '../common/ConnectOptions.js';
import type { BidiBrowser } from './Browser.js';
/**
* Users should never call this directly; it's called when calling `puppeteer.connect`
* with `protocol: 'webDriverBiDi'`. This method attaches Puppeteer to an existing browser
* instance. First it tries to connect to the browser using pure BiDi. If the protocol is
* not supported, connects to the browser using BiDi over CDP.
*
* @internal
*/
export declare function _connectToBiDiBrowser(connectionTransport: ConnectionTransport, url: string, options: ConnectOptions): Promise<BidiBrowser>;
//# sourceMappingURL=BrowserConnector.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowserConnector.d.ts","sourceRoot":"","sources":["../../../../src/bidi/BrowserConnector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAC;AAIhE,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAG9C;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,mBAAmB,EAAE,mBAAmB,EACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,WAAW,CAAC,CAiBtB"}

View File

@@ -0,0 +1,117 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports._connectToBiDiBrowser = _connectToBiDiBrowser;
const Connection_js_1 = require("../cdp/Connection.js");
const Errors_js_1 = require("../common/Errors.js");
const util_js_1 = require("../common/util.js");
/**
* Users should never call this directly; it's called when calling `puppeteer.connect`
* with `protocol: 'webDriverBiDi'`. This method attaches Puppeteer to an existing browser
* instance. First it tries to connect to the browser using pure BiDi. If the protocol is
* not supported, connects to the browser using BiDi over CDP.
*
* @internal
*/
async function _connectToBiDiBrowser(connectionTransport, url, options) {
const { acceptInsecureCerts = false, defaultViewport = util_js_1.DEFAULT_VIEWPORT } = options;
const { bidiConnection, cdpConnection, closeCallback } = await getBiDiConnection(connectionTransport, url, options);
const BiDi = await Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ './bidi.js')));
const bidiBrowser = await BiDi.BidiBrowser.create({
connection: bidiConnection,
cdpConnection,
closeCallback,
process: undefined,
defaultViewport: defaultViewport,
acceptInsecureCerts: acceptInsecureCerts,
capabilities: options.capabilities,
});
return bidiBrowser;
}
/**
* Returns a BiDiConnection established to the endpoint specified by the options and a
* callback closing the browser. Callback depends on whether the connection is pure BiDi
* or BiDi over CDP.
* The method tries to connect to the browser using pure BiDi protocol, and falls back
* to BiDi over CDP.
*/
async function getBiDiConnection(connectionTransport, url, options) {
const BiDi = await Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ './bidi.js')));
const { slowMo = 0, protocolTimeout } = options;
// Try pure BiDi first.
const pureBidiConnection = new BiDi.BidiConnection(url, connectionTransport, slowMo, protocolTimeout);
try {
const result = await pureBidiConnection.send('session.status', {});
if ('type' in result && result.type === 'success') {
// The `browserWSEndpoint` points to an endpoint supporting pure WebDriver BiDi.
return {
bidiConnection: pureBidiConnection,
closeCallback: async () => {
await pureBidiConnection.send('browser.close', {}).catch(util_js_1.debugError);
},
};
}
}
catch (e) {
if (!(e instanceof Errors_js_1.ProtocolError)) {
// Unexpected exception not related to BiDi / CDP. Rethrow.
throw e;
}
}
// Unbind the connection to avoid memory leaks.
pureBidiConnection.unbind();
// Fall back to CDP over BiDi reusing the WS connection.
const cdpConnection = new Connection_js_1.Connection(url, connectionTransport, slowMo, protocolTimeout,
/* rawErrors= */ true);
const version = await cdpConnection.send('Browser.getVersion');
if (version.product.toLowerCase().includes('firefox')) {
throw new Errors_js_1.UnsupportedOperation('Firefox is not supported in BiDi over CDP mode.');
}
const bidiOverCdpConnection = await BiDi.connectBidiOverCdp(cdpConnection);
return {
cdpConnection,
bidiConnection: bidiOverCdpConnection,
closeCallback: async () => {
// In case of BiDi over CDP, we need to close browser via CDP.
await cdpConnection.send('Browser.close').catch(util_js_1.debugError);
},
};
}
//# sourceMappingURL=BrowserConnector.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowserConnector.js","sourceRoot":"","sources":["../../../../src/bidi/BrowserConnector.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,43 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Permission } from '../api/Browser.js';
import type { BrowserContextEvents } from '../api/BrowserContext.js';
import { BrowserContext } from '../api/BrowserContext.js';
import { type Page } from '../api/Page.js';
import type { Target } from '../api/Target.js';
import type { Cookie, CookieData } from '../common/Cookie.js';
import { EventEmitter } from '../common/EventEmitter.js';
import type { Viewport } from '../common/Viewport.js';
import type { BidiBrowser } from './Browser.js';
import { UserContext } from './core/UserContext.js';
import { BidiPage } from './Page.js';
/**
* @internal
*/
export interface BidiBrowserContextOptions {
defaultViewport: Viewport | null;
}
/**
* @internal
*/
export declare class BidiBrowserContext extends BrowserContext {
#private;
static from(browser: BidiBrowser, userContext: UserContext, options: BidiBrowserContextOptions): BidiBrowserContext;
accessor trustedEmitter: EventEmitter<BrowserContextEvents>;
readonly userContext: UserContext;
private constructor();
targets(): Target[];
newPage(): Promise<Page>;
close(): Promise<void>;
browser(): BidiBrowser;
pages(): Promise<BidiPage[]>;
overridePermissions(origin: string, permissions: Permission[]): Promise<void>;
clearPermissionOverrides(): Promise<void>;
get id(): string | undefined;
cookies(): Promise<Cookie[]>;
setCookie(...cookies: CookieData[]): Promise<void>;
}
//# sourceMappingURL=BrowserContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowserContext.d.ts","sourceRoot":"","sources":["../../../../src/bidi/BrowserContext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAC,cAAc,EAAsB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAY,KAAK,IAAI,EAAC,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAC,MAAM,EAAE,UAAU,EAAC,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAEvD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAIpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AAElD,OAAO,EACL,QAAQ,EAMT,MAAM,WAAW,CAAC;AAKnB;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,cAAc;;IACpD,MAAM,CAAC,IAAI,CACT,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,yBAAyB,GACjC,kBAAkB;IAOrB,QAAQ,CAAC,cAAc,qCAA4C;IAKnE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAYlC,OAAO;IAqGE,OAAO,IAAI,MAAM,EAAE;IAMb,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B,OAAO,IAAI,WAAW;IAIhB,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM5B,mBAAmB,CAChC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,UAAU,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC;IAmCD,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBxD,IAAa,EAAE,IAAI,MAAM,GAAG,SAAS,CAKpC;IAEc,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAO5B,SAAS,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiClE"}

View File

@@ -0,0 +1,344 @@
"use strict";
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
var _, done = false;
for (var i = decorators.length - 1; i >= 0; i--) {
var context = {};
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
if (kind === "accessor") {
if (result === void 0) continue;
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
if (_ = accept(result.get)) descriptor.get = _;
if (_ = accept(result.set)) descriptor.set = _;
if (_ = accept(result.init)) initializers.unshift(_);
}
else if (_ = accept(result)) {
if (kind === "field") initializers.unshift(_);
else descriptor[key] = _;
}
}
if (target) Object.defineProperty(target, contextIn.name, descriptor);
done = true;
};
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
var useValue = arguments.length > 2;
for (var i = 0; i < initializers.length; i++) {
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
}
return useValue ? value : void 0;
};
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
if (value !== null && value !== void 0) {
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
var dispose, inner;
if (async) {
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
dispose = value[Symbol.asyncDispose];
}
if (dispose === void 0) {
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
dispose = value[Symbol.dispose];
if (async) inner = dispose;
}
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
env.stack.push({ value: value, dispose: dispose, async: async });
}
else if (async) {
env.stack.push({ async: true });
}
return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
return function (env) {
function fail(e) {
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
env.hasError = true;
}
var r, s = 0;
function next() {
while (r = env.stack.pop()) {
try {
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
if (r.dispose) {
var result = r.dispose.call(r.value);
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
else s |= 1;
}
catch (e) {
fail(e);
}
}
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
if (env.hasError) throw env.error;
}
return next();
};
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiBrowserContext = void 0;
const Browser_js_1 = require("../api/Browser.js");
const BrowserContext_js_1 = require("../api/BrowserContext.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const assert_js_1 = require("../util/assert.js");
const decorators_js_1 = require("../util/decorators.js");
const UserContext_js_1 = require("./core/UserContext.js");
const Page_js_1 = require("./Page.js");
const Target_js_1 = require("./Target.js");
const Target_js_2 = require("./Target.js");
/**
* @internal
*/
let BidiBrowserContext = (() => {
let _classSuper = BrowserContext_js_1.BrowserContext;
let _trustedEmitter_decorators;
let _trustedEmitter_initializers = [];
let _trustedEmitter_extraInitializers = [];
return class BidiBrowserContext extends _classSuper {
static {
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
_trustedEmitter_decorators = [(0, decorators_js_1.bubble)()];
__esDecorate(this, null, _trustedEmitter_decorators, { kind: "accessor", name: "trustedEmitter", static: false, private: false, access: { has: obj => "trustedEmitter" in obj, get: obj => obj.trustedEmitter, set: (obj, value) => { obj.trustedEmitter = value; } }, metadata: _metadata }, _trustedEmitter_initializers, _trustedEmitter_extraInitializers);
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
}
static from(browser, userContext, options) {
const context = new BidiBrowserContext(browser, userContext, options);
context.#initialize();
return context;
}
#trustedEmitter_accessor_storage = __runInitializers(this, _trustedEmitter_initializers, new EventEmitter_js_1.EventEmitter());
get trustedEmitter() { return this.#trustedEmitter_accessor_storage; }
set trustedEmitter(value) { this.#trustedEmitter_accessor_storage = value; }
#browser = __runInitializers(this, _trustedEmitter_extraInitializers);
#defaultViewport;
// This is public because of cookies.
userContext;
#pages = new WeakMap();
#targets = new Map();
#overrides = [];
constructor(browser, userContext, options) {
super();
this.#browser = browser;
this.userContext = userContext;
this.#defaultViewport = options.defaultViewport;
}
#initialize() {
// Create targets for existing browsing contexts.
for (const browsingContext of this.userContext.browsingContexts) {
this.#createPage(browsingContext);
}
this.userContext.on('browsingcontext', ({ browsingContext }) => {
const page = this.#createPage(browsingContext);
// We need to wait for the DOMContentLoaded as the
// browsingContext still may be navigating from the about:blank
if (browsingContext.originalOpener) {
for (const context of this.userContext.browsingContexts) {
if (context.id === browsingContext.originalOpener) {
this.#pages
.get(context)
.trustedEmitter.emit("popup" /* PageEvent.Popup */, page);
}
}
}
});
this.userContext.on('closed', () => {
this.trustedEmitter.removeAllListeners();
});
}
#createPage(browsingContext) {
const page = Page_js_1.BidiPage.from(this, browsingContext);
this.#pages.set(browsingContext, page);
page.trustedEmitter.on("close" /* PageEvent.Close */, () => {
this.#pages.delete(browsingContext);
});
// -- Target stuff starts here --
const pageTarget = new Target_js_2.BidiPageTarget(page);
const pageTargets = new Map();
this.#targets.set(page, [pageTarget, pageTargets]);
page.trustedEmitter.on("frameattached" /* PageEvent.FrameAttached */, frame => {
const bidiFrame = frame;
const target = new Target_js_2.BidiFrameTarget(bidiFrame);
pageTargets.set(bidiFrame, target);
this.trustedEmitter.emit("targetcreated" /* BrowserContextEvent.TargetCreated */, target);
});
page.trustedEmitter.on("framenavigated" /* PageEvent.FrameNavigated */, frame => {
const bidiFrame = frame;
const target = pageTargets.get(bidiFrame);
// If there is no target, then this is the page's frame.
if (target === undefined) {
this.trustedEmitter.emit("targetchanged" /* BrowserContextEvent.TargetChanged */, pageTarget);
}
else {
this.trustedEmitter.emit("targetchanged" /* BrowserContextEvent.TargetChanged */, target);
}
});
page.trustedEmitter.on("framedetached" /* PageEvent.FrameDetached */, frame => {
const bidiFrame = frame;
const target = pageTargets.get(bidiFrame);
if (target === undefined) {
return;
}
pageTargets.delete(bidiFrame);
this.trustedEmitter.emit("targetdestroyed" /* BrowserContextEvent.TargetDestroyed */, target);
});
page.trustedEmitter.on("workercreated" /* PageEvent.WorkerCreated */, worker => {
const bidiWorker = worker;
const target = new Target_js_1.BidiWorkerTarget(bidiWorker);
pageTargets.set(bidiWorker, target);
this.trustedEmitter.emit("targetcreated" /* BrowserContextEvent.TargetCreated */, target);
});
page.trustedEmitter.on("workerdestroyed" /* PageEvent.WorkerDestroyed */, worker => {
const bidiWorker = worker;
const target = pageTargets.get(bidiWorker);
if (target === undefined) {
return;
}
pageTargets.delete(worker);
this.trustedEmitter.emit("targetdestroyed" /* BrowserContextEvent.TargetDestroyed */, target);
});
page.trustedEmitter.on("close" /* PageEvent.Close */, () => {
this.#targets.delete(page);
this.trustedEmitter.emit("targetdestroyed" /* BrowserContextEvent.TargetDestroyed */, pageTarget);
});
this.trustedEmitter.emit("targetcreated" /* BrowserContextEvent.TargetCreated */, pageTarget);
// -- Target stuff ends here --
return page;
}
targets() {
return [...this.#targets.values()].flatMap(([target, frames]) => {
return [target, ...frames.values()];
});
}
async newPage() {
const env_1 = { stack: [], error: void 0, hasError: false };
try {
const _guard = __addDisposableResource(env_1, await this.waitForScreenshotOperations(), false);
const context = await this.userContext.createBrowsingContext("tab" /* Bidi.BrowsingContext.CreateType.Tab */);
const page = this.#pages.get(context);
if (!page) {
throw new Error('Page is not found');
}
if (this.#defaultViewport) {
try {
await page.setViewport(this.#defaultViewport);
}
catch {
// No support for setViewport in Firefox.
}
}
return page;
}
catch (e_1) {
env_1.error = e_1;
env_1.hasError = true;
}
finally {
__disposeResources(env_1);
}
}
async close() {
(0, assert_js_1.assert)(this.userContext.id !== UserContext_js_1.UserContext.DEFAULT, 'Default BrowserContext cannot be closed!');
try {
await this.userContext.remove();
}
catch (error) {
(0, util_js_1.debugError)(error);
}
this.#targets.clear();
}
browser() {
return this.#browser;
}
async pages() {
return [...this.userContext.browsingContexts].map(context => {
return this.#pages.get(context);
});
}
async overridePermissions(origin, permissions) {
const permissionsSet = new Set(permissions.map(permission => {
const protocolPermission = Browser_js_1.WEB_PERMISSION_TO_PROTOCOL_PERMISSION.get(permission);
if (!protocolPermission) {
throw new Error('Unknown permission: ' + permission);
}
return permission;
}));
await Promise.all(Array.from(Browser_js_1.WEB_PERMISSION_TO_PROTOCOL_PERMISSION.keys()).map(permission => {
const result = this.userContext.setPermissions(origin, {
name: permission,
}, permissionsSet.has(permission)
? "granted" /* Bidi.Permissions.PermissionState.Granted */
: "denied" /* Bidi.Permissions.PermissionState.Denied */);
this.#overrides.push({ origin, permission });
// TODO: some permissions are outdated and setting them to denied does
// not work.
if (!permissionsSet.has(permission)) {
return result.catch(util_js_1.debugError);
}
return result;
}));
}
async clearPermissionOverrides() {
const promises = this.#overrides.map(({ permission, origin }) => {
return this.userContext
.setPermissions(origin, {
name: permission,
}, "prompt" /* Bidi.Permissions.PermissionState.Prompt */)
.catch(util_js_1.debugError);
});
this.#overrides = [];
await Promise.all(promises);
}
get id() {
if (this.userContext.id === UserContext_js_1.UserContext.DEFAULT) {
return undefined;
}
return this.userContext.id;
}
async cookies() {
const cookies = await this.userContext.getCookies();
return cookies.map(cookie => {
return (0, Page_js_1.bidiToPuppeteerCookie)(cookie, true);
});
}
async setCookie(...cookies) {
await Promise.all(cookies.map(async (cookie) => {
const bidiCookie = {
domain: cookie.domain,
name: cookie.name,
value: {
type: 'string',
value: cookie.value,
},
...(cookie.path !== undefined ? { path: cookie.path } : {}),
...(cookie.httpOnly !== undefined ? { httpOnly: cookie.httpOnly } : {}),
...(cookie.secure !== undefined ? { secure: cookie.secure } : {}),
...(cookie.sameSite !== undefined
? { sameSite: (0, Page_js_1.convertCookiesSameSiteCdpToBiDi)(cookie.sameSite) }
: {}),
...{ expiry: (0, Page_js_1.convertCookiesExpiryCdpToBiDi)(cookie.expires) },
// Chrome-specific properties.
...(0, Page_js_1.cdpSpecificCookiePropertiesFromPuppeteerToBidi)(cookie, 'sameParty', 'sourceScheme', 'priority', 'url'),
};
return await this.userContext.setCookie(bidiCookie, (0, Page_js_1.convertCookiesPartitionKeyFromPuppeteerToBiDi)(cookie.partitionKey));
}));
}
};
})();
exports.BidiBrowserContext = BidiBrowserContext;
//# sourceMappingURL=BrowserContext.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
/**
* @license
* Copyright 2024 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type ProtocolMapping from 'devtools-protocol/types/protocol-mapping.js';
import type { CommandOptions } from '../api/CDPSession.js';
import { CDPSession } from '../api/CDPSession.js';
import type { Connection as CdpConnection } from '../cdp/Connection.js';
import type { BidiFrame } from './Frame.js';
/**
* @internal
*/
export declare class BidiCdpSession extends CDPSession {
#private;
static sessions: Map<string, BidiCdpSession>;
readonly frame: BidiFrame;
constructor(frame: BidiFrame, sessionId?: string);
connection(): CdpConnection | undefined;
send<T extends keyof ProtocolMapping.Commands>(method: T, params?: ProtocolMapping.Commands[T]['paramsType'][0], options?: CommandOptions): Promise<ProtocolMapping.Commands[T]['returnType']>;
detach(): Promise<void>;
/**
* @internal
*/
onClose: () => void;
id(): string;
}
//# sourceMappingURL=CDPSession.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CDPSession.d.ts","sourceRoot":"","sources":["../../../../src/bidi/CDPSession.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,eAAe,MAAM,6CAA6C,CAAC;AAE/E,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,EAAC,UAAU,IAAI,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAKtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,qBAAa,cAAe,SAAQ,UAAU;;IAC5C,MAAM,CAAC,QAAQ,8BAAqC;IAKpD,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;gBAEd,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM;IA+BvC,UAAU,IAAI,aAAa,GAAG,SAAS;IAIjC,IAAI,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EAC1D,MAAM,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EACrD,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAwBtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBtC;;OAEG;IACH,OAAO,QAAO,IAAI,CAGhB;IAEO,EAAE,IAAI,MAAM;CAItB"}

View File

@@ -0,0 +1,91 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiCdpSession = void 0;
const CDPSession_js_1 = require("../api/CDPSession.js");
const Errors_js_1 = require("../common/Errors.js");
const Deferred_js_1 = require("../util/Deferred.js");
/**
* @internal
*/
class BidiCdpSession extends CDPSession_js_1.CDPSession {
static sessions = new Map();
#detached = false;
#connection;
#sessionId = Deferred_js_1.Deferred.create();
frame;
constructor(frame, sessionId) {
super();
this.frame = frame;
if (!this.frame.page().browser().cdpSupported) {
return;
}
const connection = this.frame.page().browser().connection;
this.#connection = connection;
if (sessionId) {
this.#sessionId.resolve(sessionId);
BidiCdpSession.sessions.set(sessionId, this);
}
else {
(async () => {
try {
const { result } = await connection.send('cdp.getSession', {
context: frame._id,
});
this.#sessionId.resolve(result.session);
BidiCdpSession.sessions.set(result.session, this);
}
catch (error) {
this.#sessionId.reject(error);
}
})();
}
// SAFETY: We never throw #sessionId.
BidiCdpSession.sessions.set(this.#sessionId.value(), this);
}
connection() {
return undefined;
}
async send(method, params, options) {
if (this.#connection === undefined) {
throw new Errors_js_1.UnsupportedOperation('CDP support is required for this feature. The current browser does not support CDP.');
}
if (this.#detached) {
throw new Errors_js_1.TargetCloseError(`Protocol error (${method}): Session closed. Most likely the page has been closed.`);
}
const session = await this.#sessionId.valueOrThrow();
const { result } = await this.#connection.send('cdp.sendCommand', {
method: method,
params: params,
session,
}, options?.timeout);
return result.result;
}
async detach() {
if (this.#connection === undefined ||
this.#connection.closed ||
this.#detached) {
return;
}
try {
await this.frame.client.send('Target.detachFromTarget', {
sessionId: this.id(),
});
}
finally {
this.onClose();
}
}
/**
* @internal
*/
onClose = () => {
BidiCdpSession.sessions.delete(this.id());
this.#detached = true;
};
id() {
const value = this.#sessionId.value();
return typeof value === 'string' ? value : '';
}
}
exports.BidiCdpSession = BidiCdpSession;
//# sourceMappingURL=CDPSession.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CDPSession.js","sourceRoot":"","sources":["../../../../src/bidi/CDPSession.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,57 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import type { ConnectionTransport } from '../common/ConnectionTransport.js';
import type { EventsWithWildcard } from '../common/EventEmitter.js';
import { EventEmitter } from '../common/EventEmitter.js';
import type { Commands as BidiCommands, BidiEvents, Connection } from './core/Connection.js';
/**
* @internal
*/
export interface Commands extends BidiCommands {
'cdp.sendCommand': {
params: Bidi.Cdp.SendCommandParameters;
returnType: Bidi.Cdp.SendCommandResult;
};
'cdp.getSession': {
params: Bidi.Cdp.GetSessionParameters;
returnType: Bidi.Cdp.GetSessionResult;
};
'cdp.resolveRealm': {
params: Bidi.Cdp.ResolveRealmParameters;
returnType: Bidi.Cdp.ResolveRealmResult;
};
}
/**
* @internal
*/
export declare class BidiConnection extends EventEmitter<BidiEvents> implements Connection {
#private;
constructor(url: string, transport: ConnectionTransport, delay?: number, timeout?: number);
get closed(): boolean;
get url(): string;
pipeTo<Events extends BidiEvents>(emitter: EventEmitter<Events>): void;
emit<Key extends keyof EventsWithWildcard<BidiEvents>>(type: Key, event: EventsWithWildcard<BidiEvents>[Key]): boolean;
send<T extends keyof Commands>(method: T, params: Commands[T]['params'], timeout?: number): Promise<{
result: Commands[T]['returnType'];
}>;
/**
* @internal
*/
protected onMessage(message: string): Promise<void>;
/**
* Unbinds the connection, but keeps the transport open. Useful when the transport will
* be reused by other connection e.g. with different protocol.
* @internal
*/
unbind(): void;
/**
* Unbinds the connection and closes the transport.
*/
dispose(): void;
getPendingProtocolErrors(): Error[];
}
//# sourceMappingURL=Connection.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Connection.d.ts","sourceRoot":"","sources":["../../../../src/bidi/Connection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,4CAA4C,CAAC;AAGxE,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AAE1E,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAKvD,OAAO,KAAK,EACV,QAAQ,IAAI,YAAY,EACxB,UAAU,EACV,UAAU,EACX,MAAM,sBAAsB,CAAC;AAK9B;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,YAAY;IAC5C,iBAAiB,EAAE;QACjB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC;QACvC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC;KACxC,CAAC;IACF,gBAAgB,EAAE;QAChB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACtC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;KACvC,CAAC;IACF,kBAAkB,EAAE;QAClB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC;QACxC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC;KACzC,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,cACX,SAAQ,YAAY,CAAC,UAAU,CAC/B,YAAW,UAAU;;gBAWnB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,mBAAmB,EAC9B,KAAK,SAAI,EACT,OAAO,CAAC,EAAE,MAAM;IAYlB,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,MAAM,CAAC,MAAM,SAAS,UAAU,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,IAAI;IAI7D,IAAI,CAAC,GAAG,SAAS,MAAM,kBAAkB,CAAC,UAAU,CAAC,EAC5D,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GACzC,OAAO;IAOV,IAAI,CAAC,CAAC,SAAS,MAAM,QAAQ,EAC3B,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAC7B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;QAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAA;KAAC,CAAC;IAc/C;;OAEG;cACa,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDzD;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAYd;;OAEG;IACH,OAAO,IAAI,IAAI;IAKf,wBAAwB,IAAI,KAAK,EAAE;CAGpC"}

View File

@@ -0,0 +1,145 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiConnection = void 0;
const CallbackRegistry_js_1 = require("../common/CallbackRegistry.js");
const Debug_js_1 = require("../common/Debug.js");
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const assert_js_1 = require("../util/assert.js");
const CDPSession_js_1 = require("./CDPSession.js");
const debugProtocolSend = (0, Debug_js_1.debug)('puppeteer:webDriverBiDi:SEND ►');
const debugProtocolReceive = (0, Debug_js_1.debug)('puppeteer:webDriverBiDi:RECV ◀');
/**
* @internal
*/
class BidiConnection extends EventEmitter_js_1.EventEmitter {
#url;
#transport;
#delay;
#timeout = 0;
#closed = false;
#callbacks = new CallbackRegistry_js_1.CallbackRegistry();
#emitters = [];
constructor(url, transport, delay = 0, timeout) {
super();
this.#url = url;
this.#delay = delay;
this.#timeout = timeout ?? 180_000;
this.#transport = transport;
this.#transport.onmessage = this.onMessage.bind(this);
this.#transport.onclose = this.unbind.bind(this);
}
get closed() {
return this.#closed;
}
get url() {
return this.#url;
}
pipeTo(emitter) {
this.#emitters.push(emitter);
}
emit(type, event) {
for (const emitter of this.#emitters) {
emitter.emit(type, event);
}
return super.emit(type, event);
}
send(method, params, timeout) {
(0, assert_js_1.assert)(!this.#closed, 'Protocol error: Connection closed.');
return this.#callbacks.create(method, timeout ?? this.#timeout, id => {
const stringifiedMessage = JSON.stringify({
id,
method,
params,
});
debugProtocolSend(stringifiedMessage);
this.#transport.send(stringifiedMessage);
});
}
/**
* @internal
*/
async onMessage(message) {
if (this.#delay) {
await new Promise(f => {
return setTimeout(f, this.#delay);
});
}
debugProtocolReceive(message);
const object = JSON.parse(message);
if ('type' in object) {
switch (object.type) {
case 'success':
this.#callbacks.resolve(object.id, object);
return;
case 'error':
if (object.id === null) {
break;
}
this.#callbacks.reject(object.id, createProtocolError(object), `${object.error}: ${object.message}`);
return;
case 'event':
if (isCdpEvent(object)) {
CDPSession_js_1.BidiCdpSession.sessions
.get(object.params.session)
?.emit(object.params.event, object.params.params);
return;
}
// SAFETY: We know the method and parameter still match here.
this.emit(object.method, object.params);
return;
}
}
// Even if the response in not in BiDi protocol format but `id` is provided, reject
// the callback. This can happen if the endpoint supports CDP instead of BiDi.
if ('id' in object) {
this.#callbacks.reject(object.id, `Protocol Error. Message is not in BiDi protocol format: '${message}'`, object.message);
}
(0, util_js_1.debugError)(object);
}
/**
* Unbinds the connection, but keeps the transport open. Useful when the transport will
* be reused by other connection e.g. with different protocol.
* @internal
*/
unbind() {
if (this.#closed) {
return;
}
this.#closed = true;
// Both may still be invoked and produce errors
this.#transport.onmessage = () => { };
this.#transport.onclose = () => { };
this.#callbacks.clear();
}
/**
* Unbinds the connection and closes the transport.
*/
dispose() {
this.unbind();
this.#transport.close();
}
getPendingProtocolErrors() {
return this.#callbacks.getPendingProtocolErrors();
}
}
exports.BidiConnection = BidiConnection;
/**
* @internal
*/
function createProtocolError(object) {
let message = `${object.error} ${object.message}`;
if (object.stacktrace) {
message += ` ${object.stacktrace}`;
}
return message;
}
function isCdpEvent(event) {
return event.method.startsWith('cdp.');
}
//# sourceMappingURL=Connection.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Connection.js","sourceRoot":"","sources":["../../../../src/bidi/Connection.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,14 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
/**
* @internal
*/
export declare class BidiDeserializer {
#private;
static deserialize(result: Bidi.Script.RemoteValue): any;
}
//# sourceMappingURL=Deserializer.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Deserializer.d.ts","sourceRoot":"","sources":["../../../../src/bidi/Deserializer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,KAAK,IAAI,MAAM,4CAA4C,CAAC;AAIxE;;GAEG;AACH,qBAAa,gBAAgB;;IAC3B,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG;CA6EzD"}

View File

@@ -0,0 +1,84 @@
"use strict";
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiDeserializer = void 0;
const util_js_1 = require("../common/util.js");
/**
* @internal
*/
class BidiDeserializer {
static deserialize(result) {
if (!result) {
(0, util_js_1.debugError)('Service did not produce a result.');
return undefined;
}
switch (result.type) {
case 'array':
return result.value?.map(value => {
return this.deserialize(value);
});
case 'set':
return result.value?.reduce((acc, value) => {
return acc.add(this.deserialize(value));
}, new Set());
case 'object':
return result.value?.reduce((acc, tuple) => {
const { key, value } = this.#deserializeTuple(tuple);
acc[key] = value;
return acc;
}, {});
case 'map':
return result.value?.reduce((acc, tuple) => {
const { key, value } = this.#deserializeTuple(tuple);
return acc.set(key, value);
}, new Map());
case 'promise':
return {};
case 'regexp':
return new RegExp(result.value.pattern, result.value.flags);
case 'date':
return new Date(result.value);
case 'undefined':
return undefined;
case 'null':
return null;
case 'number':
return this.#deserializeNumber(result.value);
case 'bigint':
return BigInt(result.value);
case 'boolean':
return Boolean(result.value);
case 'string':
return result.value;
}
(0, util_js_1.debugError)(`Deserialization of type ${result.type} not supported.`);
return undefined;
}
static #deserializeNumber(value) {
switch (value) {
case '-0':
return -0;
case 'NaN':
return NaN;
case 'Infinity':
return Infinity;
case '-Infinity':
return -Infinity;
default:
return value;
}
}
static #deserializeTuple([serializedKey, serializedValue]) {
const key = typeof serializedKey === 'string'
? serializedKey
: this.deserialize(serializedKey);
const value = this.deserialize(serializedValue);
return { key, value };
}
}
exports.BidiDeserializer = BidiDeserializer;
//# sourceMappingURL=Deserializer.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Deserializer.js","sourceRoot":"","sources":["../../../../src/bidi/Deserializer.ts"],"names":[],"mappings":"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"}

Some files were not shown because too many files have changed in this diff Show More