Initial commit - Dutchie dispensary scraper

This commit is contained in:
Kelly
2025-11-28 19:45:44 -07:00
commit 5757a8e9bd
23375 changed files with 3788799 additions and 0 deletions

257
backend/node_modules/puppeteer-core/README.md generated vendored Normal file
View File

@@ -0,0 +1,257 @@
# Puppeteer
[![Build status](https://github.com/puppeteer/puppeteer/workflows/CI/badge.svg)](https://github.com/puppeteer/puppeteer/actions?query=workflow%3ACI)
[![npm puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer)
<img src="https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png" height="200" align="right"/>
#### [Guides](https://pptr.dev/category/guides) | [API](https://pptr.dev/api) | [FAQ](https://pptr.dev/faq) | [Contributing](https://pptr.dev/contributing) | [Troubleshooting](https://pptr.dev/troubleshooting)
> Puppeteer is a Node.js library which provides a high-level API to control
> Chrome/Chromium over the
> [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).
> Puppeteer runs in
> [headless](https://developer.chrome.com/articles/new-headless/)
> mode by default, but can be configured to run in full ("headful")
> Chrome/Chromium.
#### What can I do?
Most things that you can do manually in the browser can be done using Puppeteer!
Here are a few examples to get you started:
- Generate screenshots and PDFs of pages.
- Crawl a SPA (Single-Page Application) and generate pre-rendered content (i.e.
"SSR" (Server-Side Rendering)).
- Automate form submission, UI testing, keyboard input, etc.
- Create an automated testing environment using the latest JavaScript and
browser features.
- Capture a
[timeline trace](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference)
of your site to help diagnose performance issues.
- [Test Chrome Extensions](https://pptr.dev/guides/chrome-extensions).
## Getting Started
### Installation
To use Puppeteer in your project, run:
```bash
npm i puppeteer
# or using yarn
yarn add puppeteer
# or using pnpm
pnpm i puppeteer
```
When you install Puppeteer, it automatically downloads a recent version of
[Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (~170MB macOS, ~282MB Linux, ~280MB Windows) and a `chrome-headless-shell` binary (starting with Puppeteer v21.6.0) that is [guaranteed to
work](https://pptr.dev/faq#q-why-doesnt-puppeteer-vxxx-work-with-chromium-vyyy)
with Puppeteer. The browser is downloaded to the `$HOME/.cache/puppeteer` folder
by default (starting with Puppeteer v19.0.0). See [configuration](https://pptr.dev/api/puppeteer.configuration) for configuration options and environmental variables to control the download behavor.
If you deploy a project using Puppeteer to a hosting provider, such as Render or
Heroku, you might need to reconfigure the location of the cache to be within
your project folder (see an example below) because not all hosting providers
include `$HOME/.cache` into the project's deployment.
For a version of Puppeteer without the browser installation, see
[`puppeteer-core`](#puppeteer-core).
If used with TypeScript, the minimum supported TypeScript version is `4.7.4`.
#### Configuration
Puppeteer uses several defaults that can be customized through configuration
files.
For example, to change the default cache directory Puppeteer uses to install
browsers, you can add a `.puppeteerrc.cjs` (or `puppeteer.config.cjs`) at the
root of your application with the contents
```js
const {join} = require('path');
/**
* @type {import("puppeteer").Configuration}
*/
module.exports = {
// Changes the cache location for Puppeteer.
cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
};
```
After adding the configuration file, you will need to remove and reinstall
`puppeteer` for it to take effect.
See the [configuration guide](https://pptr.dev/guides/configuration) for more
information.
#### `puppeteer-core`
For every release since v1.7.0 we publish two packages:
- [`puppeteer`](https://www.npmjs.com/package/puppeteer)
- [`puppeteer-core`](https://www.npmjs.com/package/puppeteer-core)
`puppeteer` is a _product_ for browser automation. When installed, it downloads
a version of Chrome, which it then drives using `puppeteer-core`. Being an
end-user product, `puppeteer` automates several workflows using reasonable
defaults [that can be customized](https://pptr.dev/guides/configuration).
`puppeteer-core` is a _library_ to help drive anything that supports DevTools
protocol. Being a library, `puppeteer-core` is fully driven through its
programmatic interface implying no defaults are assumed and `puppeteer-core`
will not download Chrome when installed.
You should use `puppeteer-core` if you are
[connecting to a remote browser](https://pptr.dev/api/puppeteer.puppeteer.connect)
or [managing browsers yourself](https://pptr.dev/browsers-api/).
If you are managing browsers yourself, you will need to call
[`puppeteer.launch`](https://pptr.dev/api/puppeteer.puppeteernode.launch) with
an explicit
[`executablePath`](https://pptr.dev/api/puppeteer.launchoptions)
(or [`channel`](https://pptr.dev/api/puppeteer.launchoptions) if it's
installed in a standard location).
When using `puppeteer-core`, remember to change the import:
```ts
import puppeteer from 'puppeteer-core';
```
### Usage
Puppeteer follows the latest
[maintenance LTS](https://github.com/nodejs/Release#release-schedule) version of
Node.
Puppeteer will be familiar to people using other browser testing frameworks. You
[launch](https://pptr.dev/api/puppeteer.puppeteernode.launch)/[connect](https://pptr.dev/api/puppeteer.puppeteernode.connect)
a [browser](https://pptr.dev/api/puppeteer.browser),
[create](https://pptr.dev/api/puppeteer.browser.newpage) some
[pages](https://pptr.dev/api/puppeteer.page), and then manipulate them with
[Puppeteer's API](https://pptr.dev/api).
For more in-depth usage, check our [guides](https://pptr.dev/category/guides)
and [examples](https://github.com/puppeteer/puppeteer/tree/main/examples).
#### Example
The following example searches [developer.chrome.com](https://developer.chrome.com/) for blog posts with text "automate beyond recorder", click on the first result and print the full title of the blog post.
```ts
import puppeteer from 'puppeteer';
(async () => {
// Launch the browser and open a new blank page
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Navigate the page to a URL
await page.goto('https://developer.chrome.com/');
// Set screen size
await page.setViewport({width: 1080, height: 1024});
// Type into search box
await page.type('.devsite-search-field', 'automate beyond recorder');
// Wait and click on first result
const searchResultSelector = '.devsite-result-item-link';
await page.waitForSelector(searchResultSelector);
await page.click(searchResultSelector);
// Locate the full title with a unique string
const textSelector = await page.waitForSelector(
'text/Customize and automate'
);
const fullTitle = await textSelector?.evaluate(el => el.textContent);
// Print the full title
console.log('The title of this blog post is "%s".', fullTitle);
await browser.close();
})();
```
### Default runtime settings
**1. Uses Headless mode**
By default Puppeteer launches Chrome in
[old Headless mode](https://developer.chrome.com/articles/new-headless/).
```ts
const browser = await puppeteer.launch();
// Equivalent to
const browser = await puppeteer.launch({headless: true});
```
[Chrome 112 launched a new Headless mode](https://developer.chrome.com/articles/new-headless/) that might cause some differences in behavior compared to the old Headless implementation.
In the future Puppeteer will start defaulting to new implementation.
We recommend you try it out before the switch:
```ts
const browser = await puppeteer.launch({headless: 'new'});
```
To launch a "headful" version of Chrome, set the
[`headless`](https://pptr.dev/api/puppeteer.browserlaunchargumentoptions) to `false`
option when launching a browser:
```ts
const browser = await puppeteer.launch({headless: false});
```
**2. Runs a bundled version of Chrome**
By default, Puppeteer downloads and uses a specific version of Chrome so its
API is guaranteed to work out of the box. To use Puppeteer with a different
version of Chrome or Chromium, pass in the executable's path when creating a
`Browser` instance:
```ts
const browser = await puppeteer.launch({executablePath: '/path/to/Chrome'});
```
You can also use Puppeteer with Firefox. See
[status of cross-browser support](https://pptr.dev/faq/#q-what-is-the-status-of-cross-browser-support) for
more information.
See
[`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/)
for a description of the differences between Chromium and Chrome.
[`This article`](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/chromium_browser_vs_google_chrome.md)
describes some differences for Linux users.
**3. Creates a fresh user profile**
Puppeteer creates its own browser user profile which it **cleans up on every
run**.
#### Using Docker
See our [Docker guide](https://pptr.dev/guides/docker).
#### Using Chrome Extensions
See our [Chrome extensions guide](https://pptr.dev/guides/chrome-extensions).
## Resources
- [API Documentation](https://pptr.dev/api)
- [Guides](https://pptr.dev/category/guides)
- [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples)
- [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer)
## Contributing
Check out our [contributing guide](https://pptr.dev/contributing) to get an
overview of Puppeteer development.
## FAQ
Our [FAQ](https://pptr.dev/faq) has migrated to
[our site](https://pptr.dev/faq).

View File

@@ -0,0 +1,337 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/// <reference types="node" />
import type { ChildProcess } from 'child_process';
import type { Protocol } from 'devtools-protocol';
import type { ProtocolType } from '../common/ConnectOptions.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[];
}
/**
* @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;
}
/**
* 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 incognito 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 incognito 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 incognito browser
* contexts.
*/
TargetDestroyed = "targetdestroyed",
/**
* @internal
*/
TargetDiscovered = "targetdiscovered"
}
export {
/**
* @deprecated Use {@link BrowserEvent}.
*/
BrowserEvent as BrowserEmittedEvents, };
/**
* @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 | 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 incognito {@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 incognito browser context.
* const context = await browser.createIncognitoBrowserContext();
* // Create a new page in a pristine context.
* const page = await context.newPage();
* // Do stuff
* await page.goto('https://example.com');
* ```
*/
abstract createIncognitoBrowserContext(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 ar 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>;
/**
* 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,141 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
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 | 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 } = 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, rxjs_js_1.filterAsync)(predicate), (0, rxjs_js_1.raceWith)((0, util_js_1.timeout)(ms))));
}
/**
* Gets a list of all open {@link Page | pages} inside this {@link Browser}.
*
* If there ar 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);
}, []);
}
/**
* Whether Puppeteer is connected to this {@link Browser | browser}.
*
* @deprecated Use {@link Browser | Browser.connected}.
*/
isConnected() {
return this.connected;
}
/** @internal */
[disposable_js_1.disposeSymbol]() {
return void this.close().catch(util_js_1.debugError);
}
/** @internal */
[disposable_js_1.asyncDisposeSymbol]() {
return this.close();
}
}
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":";AAAA;;;;GAIG;;;AAMH,4DAMwC;AAExC,+DAAuE;AACvE,+CAAwE;AACxE,yDAAwE;AAmCxE;;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;AAiHH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAsB,OAAQ,SAAQ,8BAA2B;IAC/D;;OAEG;IACH;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAuFD;;;;;;;;;;;;;;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,mDAA6B,EAClD,IAAA,0BAAgB,EAAC,IAAI,mDAA6B,EAClD,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;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;;;;OAIG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAOD,gBAAgB;IAChB,CAAC,6BAAa,CAAC;QACb,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;CAkBF;AA1ND,0BA0NC"}

View File

@@ -0,0 +1,186 @@
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import { EventEmitter, type EventType } from '../common/EventEmitter.js';
import { asyncDisposeSymbol, disposeSymbol } from '../util/disposable.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"
}
export {
/**
* @deprecated Use {@link BrowserContextEvent}
*/
BrowserContextEvent as BrowserContextEmittedEvents, };
/**
* @public
*/
export interface BrowserContextEvents extends Record<EventType, unknown> {
[BrowserContextEvent.TargetChanged]: Target;
[BrowserContextEvent.TargetCreated]: Target;
[BrowserContextEvent.TargetDestroyed]: Target;
}
/**
* {@link BrowserContext} represents individual sessions within a
* {@link Browser | browser}.
*
* When a {@link Browser | browser} is launched, it has a single
* {@link BrowserContext | browser context} by default. Others can be created
* using {@link Browser.createIncognitoBrowserContext}.
*
* {@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 an incognito {@link BrowserContext | browser context}:
*
* ```ts
* // Create a new incognito browser context
* const context = await browser.createIncognitoBrowserContext();
* // 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();
* ```
*
* @public
*/
export declare abstract class BrowserContext extends EventEmitter<BrowserContextEvents> {
/**
* @internal
*/
constructor();
/**
* Gets all active {@link Target | targets} inside this
* {@link BrowserContext | browser context}.
*/
abstract targets(): 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 browserContext.waitForTarget(
* target => target.url() === 'https://www.example.com/'
* );
* ```
*/
abstract 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[]>;
/**
* Whether this {@link BrowserContext | browser context} is incognito.
*
* The {@link Browser.defaultBrowserContext | default browser context} is the
* only non-incognito browser context.
*/
abstract isIncognito(): boolean;
/**
* 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>;
/**
* 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":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,YAAY,EAAE,KAAK,SAAS,EAAC,MAAM,2BAA2B,CAAC;AAEvE,OAAO,EAAC,kBAAkB,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAExE,OAAO,KAAK,EAAC,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,0BAAkB,mBAAmB;IACnC;;;OAGG;IACH,aAAa,kBAAkB;IAE/B;;;;;;;OAOG;IACH,aAAa,kBAAkB;IAC/B;;;OAGG;IACH,eAAe,oBAAoB;CACpC;AAED,OAAO;AACL;;GAEG;AACH,mBAAmB,IAAI,2BAA2B,GACnD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;IACtE,CAAC,mBAAmB,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAC5C,CAAC,mBAAmB,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAC5C,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,8BAAsB,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IAC7E;;OAEG;;IAKH;;;OAGG;IACH,QAAQ,CAAC,OAAO,IAAI,MAAM,EAAE;IAE5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,aAAa,CACpB,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACpD,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAEjC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,IAAI,OAAO;IAE/B;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,mBAAmB,CAC1B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,UAAU,EAAE,GACxB,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAElD;;;OAGG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,OAAO,IAAI,OAAO;IAE3B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/B;;OAEG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;OAEG;IACH,IAAI,EAAE,IAAI,MAAM,GAAG,SAAS,CAE3B;IAED,gBAAgB;IAChB,CAAC,aAAa,CAAC,IAAI,IAAI;IAIvB,gBAAgB;IAChB,CAAC,kBAAkB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGtC"}

View File

@@ -0,0 +1,71 @@
"use strict";
/**
* @license
* Copyright 2017 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserContext = void 0;
const EventEmitter_js_1 = require("../common/EventEmitter.js");
const util_js_1 = require("../common/util.js");
const disposable_js_1 = require("../util/disposable.js");
/**
* {@link BrowserContext} represents individual sessions within a
* {@link Browser | browser}.
*
* When a {@link Browser | browser} is launched, it has a single
* {@link BrowserContext | browser context} by default. Others can be created
* using {@link Browser.createIncognitoBrowserContext}.
*
* {@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 an incognito {@link BrowserContext | browser context}:
*
* ```ts
* // Create a new incognito browser context
* const context = await browser.createIncognitoBrowserContext();
* // 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();
* ```
*
* @public
*/
class BrowserContext extends EventEmitter_js_1.EventEmitter {
/**
* @internal
*/
constructor() {
super();
}
/**
* 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,+DAAuE;AACvE,+CAA6C;AAC7C,yDAAwE;AAgDxE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAsB,cAAe,SAAQ,8BAAkC;IAC7E;;OAEG;IACH;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IA2GD;;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;IAChB,CAAC,6BAAa,CAAC;QACb,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;AAxID,wCAwIC"}

View File

@@ -0,0 +1,100 @@
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.target().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,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,mBAA6B,CAAC;IACnD,MAAM,eAAe,mBAA6B,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.target().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":";;;AAGA,+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,70 @@
/**
* @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
*/
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;;IAM1B;;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,93 @@
"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;
#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,QAAQ,GAAG,KAAK,CAAC;IAEjB;;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,QAAQ,EAAE,gDAAgD,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,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,QAAQ,EAAE,iDAAiD,CAAC,CAAC;QAC1E,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,IAAI,CAAC,MAAM,CAAC;YAChB,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;CACF;AA3ED,wBA2EC"}

View File

@@ -0,0 +1,632 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/// <reference types="node" />
import type { Protocol } from 'devtools-protocol';
import type { Frame } from '../api/Frame.js';
import type { 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 } from './Input.js';
import { JSHandle } from './JSHandle.js';
import type { 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;
}
/**
* 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;
/**
* 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
*/
static bindIsolatedHandle<This extends ElementHandle<Node>>(target: (this: This, ...args: any[]) => Promise<any>, _: unknown): typeof target;
/**
* @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 - The selector to query for.
* @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 - The selector to query for.
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
$$<Selector extends string>(selector: Selector): 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 - The selector to query for.
* @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 - The selector to query for.
* @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>>>;
/**
* @deprecated Use {@link ElementHandle.$$} with the `xpath` prefix.
*
* Example: `await elementHandle.$$('xpath/' + xpathExpression)`
*
* The method evaluates the XPath expression relative to the elementHandle.
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
*
* If there are no such elements, the method will resolve to an empty array.
* @param expression - Expression to {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate | evaluate}
*/
$x(expression: string): Promise<Array<ElementHandle<Node>>>;
/**
* 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>;
/**
* Checks if an element is visible using the same mechanism as
* {@link ElementHandle.waitForSelector}.
*/
isVisible(): Promise<boolean>;
/**
* Checks if an element is hidden using the same mechanism as
* {@link ElementHandle.waitForSelector}.
*/
isHidden(): Promise<boolean>;
/**
* @deprecated Use {@link ElementHandle.waitForSelector} with the `xpath`
* prefix.
*
* Example: `await elementHandle.waitForSelector('xpath/' + xpathExpression)`
*
* The method evaluates the XPath expression relative to the elementHandle.
*
* Wait for the `xpath` within the element. If at the moment of calling the
* method the `xpath` already exists, the method will return immediately. If
* the `xpath` doesn't appear after the `timeout` milliseconds of waiting, the
* function will throw.
*
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
*
* @example
* This method works across navigation.
*
* ```ts
* import puppeteer from 'puppeteer';
* (async () => {
* const browser = await puppeteer.launch();
* const page = await browser.newPage();
* let currentURL;
* page
* .waitForXPath('//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 xpath - A
* {@link https://developer.mozilla.org/en-US/docs/Web/XPath | xpath} of an
* element to wait for
* @param options - Optional waiting parameters
* @returns Promise which resolves when element specified by xpath string is
* added to DOM. Resolves to `null` if waiting for `hidden: true` and xpath is
* not found in DOM, otherwise resolves to `ElementHandle`.
* @remarks
* The optional Argument `options` have properties:
*
* - `visible`: A boolean to wait for element to be present in DOM and to be
* visible, i.e. to not have `display: none` or `visibility: hidden` CSS
* properties. Defaults to `false`.
*
* - `hidden`: A boolean wait for element to not be found in the DOM or to be
* hidden, i.e. have `display: none` or `visibility: hidden` CSS properties.
* Defaults to `false`.
*
* - `timeout`: A number which is maximum time to wait for in milliseconds.
* Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The
* default value can be changed by using the {@link Page.setDefaultTimeout}
* method.
*/
waitForXPath(xpath: string, options?: {
visible?: boolean;
hidden?: boolean;
timeout?: number;
}): Promise<ElementHandle<Node> | null>;
/**
* 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} 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 | 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>;
/**
* 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>;
touchStart(this: ElementHandle<Element>): Promise<void>;
touchMove(this: ElementHandle<Element>): 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<Buffer>;
/**
* @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>;
}
/**
* @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,747 @@
/**
* @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, WaitForSelectorOptions, WaitTimeoutOptions } from '../api/Page.js';
import type { DeviceRequestPrompt } from '../cdp/DeviceRequestPrompt.js';
import type { IsolatedWorldChart } from '../cdp/IsolatedWorld.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[];
}
/**
* @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
*/
worlds: IsolatedWorldChart;
/**
* @internal
*/
_name?: string;
/**
* @internal
*/
_hasStartedLoading: boolean;
/**
* @internal
*/
constructor();
/**
* The page associated with the frame.
*/
abstract page(): Page;
/**
* Is `true` if the frame is an out-of-process (OOP) frame. Otherwise,
* `false`.
*/
abstract isOOPFrame(): boolean;
/**
* Navigates the frame 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 mode doesn't support navigation to a PDF document. See the {@link
* https://bugs.chromium.org/p/chromium/issues/detail?id=761295 | upstream
* issue}.
*
* :::
*
* @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.
*
* 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}.
*/
abstract goto(url: string, options?: {
referer?: string;
referrerPolicy?: string;
timeout?: number;
waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
}): 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 mainRealm(): Realm;
/**
* @internal
*/
abstract isolatedRealm(): Realm;
/**
* Used to clear the document handle that has been destroyed.
*
* @internal
*/
clearDocumentHandle(): void;
/**
* @internal
*/
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
* 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.
*
* @remarks
* Locators API is experimental and we will not follow semver for breaking
* change in the Locators API.
*/
locator<Selector extends string>(selector: Selector): Locator<NodeFor<Selector>>;
/**
* Creates a locator for the provided function. See {@link Locator} for
* details and supported actions.
*
* @remarks
* Locators API is experimental and we will not follow semver for breaking
* change in the Locators API.
*/
locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>;
/**
* Queries the frame for an element matching the given selector.
*
* @param selector - The selector to query for.
* @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 - The selector to query for.
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
$$<Selector extends string>(selector: Selector): 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 - The selector to query for.
* @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 - The selector to query for.
* @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>>>;
/**
* @deprecated Use {@link Frame.$$} with the `xpath` prefix.
*
* Example: `await frame.$$('xpath/' + xpathExpression)`
*
* This method evaluates the given XPath expression and returns the results.
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
* @param expression - the XPath expression to evaluate.
*/
$x(expression: string): Promise<Array<ElementHandle<Node>>>;
/**
* 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>;
/**
* @deprecated Use {@link Frame.waitForSelector} with the `xpath` prefix.
*
* Example: `await frame.waitForSelector('xpath/' + xpathExpression)`
*
* The method evaluates the XPath expression relative to the Frame.
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
*
* Wait for the `xpath` to appear in page. If at the moment of calling the
* method the `xpath` already exists, the method will return immediately. If
* the xpath doesn't appear after the `timeout` milliseconds of waiting, the
* function will throw.
*
* For a code example, see the example for {@link Frame.waitForSelector}. That
* function behaves identically other than taking a CSS selector rather than
* an XPath.
*
* @param xpath - the XPath expression to wait for.
* @param options - options to configure the visibility of the element and how
* long to wait before timing out.
*/
waitForXPath(xpath: string, options?: WaitForSelectorOptions): Promise<ElementHandle<Node> | 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?: {
timeout?: number;
waitUntil?: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[];
}): 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.
*/
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>;
/**
* @deprecated Replace with `new Promise(r => setTimeout(r, milliseconds));`.
*
* Causes your script to wait for the given number of milliseconds.
*
* @remarks
* It's generally recommended to not wait for a number of seconds, but instead
* use {@link Frame.waitForSelector}, {@link Frame.waitForXPath} or
* {@link Frame.waitForFunction} to wait for exactly the conditions you want.
*
* @example
*
* Wait for 1 second:
*
* ```ts
* await frame.waitForTimeout(1000);
* ```
*
* @param milliseconds - the number of milliseconds to wait.
*/
waitForTimeout(milliseconds: number): 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,906 @@
"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;
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 (typeof dispose !== "function") throw new TypeError("Object not disposable.");
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;
}
function next() {
while (env.stack.length) {
var rec = env.stack.pop();
try {
var result = rec.dispose && rec.dispose.call(rec.value);
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
catch (e) {
fail(e);
}
}
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 LazyArg_js_1 = require("../common/LazyArg.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 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 _$x_decorators;
let _waitForSelector_decorators;
let _waitForXPath_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];
_$x_decorators = [exports.throwIfDetached];
_waitForSelector_decorators = [exports.throwIfDetached];
_waitForXPath_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, _$x_decorators, { kind: "method", name: "$x", static: false, private: false, access: { has: obj => "$x" in obj, get: obj => obj.$x }, 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, _waitForXPath_decorators, { kind: "method", name: "waitForXPath", static: false, private: false, access: { has: obj => "waitForXPath" in obj, get: obj => obj.waitForXPath }, 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), void 0);
/**
* @internal
*/
_parentId;
/**
* @internal
*/
worlds;
/**
* @internal
*/
_name;
/**
* @internal
*/
_hasStartedLoading = false;
/**
* @internal
*/
constructor() {
super();
}
#_document;
/**
* @internal
*/
#document() {
if (!this.#_document) {
this.#_document = this.isolatedRealm()
.evaluateHandle(() => {
return document;
})
.then(handle => {
return this.mainRealm().transferHandle(handle);
});
}
return this.#_document;
}
/**
* Used to clear the document handle that has been destroyed.
*
* @internal
*/
clearDocumentHandle() {
this.#_document = undefined;
}
/**
* @internal
*/
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');
}), 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 iframe.move();
}
}
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
* 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 - The selector to query for.
* @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 - The selector to query for.
* @returns An array of {@link ElementHandle | element handles} that point to
* elements matching the given selector.
*/
async $$(selector) {
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$$(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 - The selector to query for.
* @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 - The selector to query for.
* @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);
}
/**
* @deprecated Use {@link Frame.$$} with the `xpath` prefix.
*
* Example: `await frame.$$('xpath/' + xpathExpression)`
*
* This method evaluates the given XPath expression and returns the results.
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
* @param expression - the XPath expression to evaluate.
*/
async $x(expression) {
// eslint-disable-next-line rulesdir/use-using -- This is cached.
const document = await this.#document();
return await document.$x(expression);
}
/**
* 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 } = (0, GetQueryHandler_js_1.getQueryHandlerAndSelector)(selector);
return (await QueryHandler.waitFor(this, updatedSelector, options));
}
/**
* @deprecated Use {@link Frame.waitForSelector} with the `xpath` prefix.
*
* Example: `await frame.waitForSelector('xpath/' + xpathExpression)`
*
* The method evaluates the XPath expression relative to the Frame.
* If `xpath` starts with `//` instead of `.//`, the dot will be appended
* automatically.
*
* Wait for the `xpath` to appear in page. If at the moment of calling the
* method the `xpath` already exists, the method will return immediately. If
* the xpath doesn't appear after the `timeout` milliseconds of waiting, the
* function will throw.
*
* For a code example, see the example for {@link Frame.waitForSelector}. That
* function behaves identically other than taking a CSS selector rather than
* an XPath.
*
* @param xpath - the XPath expression to wait for.
* @param options - options to configure the visibility of the element and how
* long to wait before timing out.
*/
async waitForXPath(xpath, options = {}) {
if (xpath.startsWith('//')) {
xpath = `.${xpath}`;
}
return await this.waitForSelector(`xpath/${xpath}`, 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.
*/
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) {
const fs = await (0, util_js_1.importFSPromises)();
content = await fs.readFile(path, 'utf8');
content += `//# sourceURL=${path.replace(/\n/g, '')}`;
}
type = type ?? 'text/javascript';
return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ Deferred }, { url, id, type, content }) => {
const deferred = Deferred.create();
const script = document.createElement('script');
script.type = type;
script.text = content;
if (url) {
script.src = url;
script.addEventListener('load', () => {
return deferred.resolve();
}, { once: true });
script.addEventListener('error', event => {
deferred.reject(new Error(event.message ?? 'Could not load script'));
}, { once: true });
}
else {
deferred.resolve();
}
if (id) {
script.id = id;
}
document.head.appendChild(script);
await deferred.valueOrThrow();
return script;
}, LazyArg_js_1.LazyArg.create(context => {
return context.puppeteerUtil;
}), { ...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) {
const fs = await (0, util_js_1.importFSPromises)();
content = await fs.readFile(path, 'utf8');
content += '/*# sourceURL=' + path.replace(/\n/g, '') + '*/';
options.content = content;
}
return await this.mainRealm().transferHandle(await this.isolatedRealm().evaluateHandle(async ({ Deferred }, { url, content }) => {
const deferred = Deferred.create();
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', () => {
deferred.resolve();
}, { once: true });
element.addEventListener('error', event => {
deferred.reject(new Error(event.message ?? 'Could not load style'));
}, { once: true });
document.head.appendChild(element);
await deferred.valueOrThrow();
return element;
}, LazyArg_js_1.LazyArg.create(context => {
return context.puppeteerUtil;
}), 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);
}
}
/**
* @deprecated Replace with `new Promise(r => setTimeout(r, milliseconds));`.
*
* Causes your script to wait for the given number of milliseconds.
*
* @remarks
* It's generally recommended to not wait for a number of seconds, but instead
* use {@link Frame.waitForSelector}, {@link Frame.waitForXPath} or
* {@link Frame.waitForFunction} to wait for exactly the conditions you want.
*
* @example
*
* Wait for 1 second:
*
* ```ts
* await frame.waitForTimeout(1000);
* ```
*
* @param milliseconds - the number of milliseconds to wait.
*/
async waitForTimeout(milliseconds) {
return await new Promise(resolve => {
setTimeout(resolve, milliseconds);
});
}
/**
* 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,386 @@
/// <reference types="node" />
/**
* @license
* Copyright 2020 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { Protocol } from 'devtools-protocol';
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. All values are converted to strings.
*/
headers: Record<string, unknown>;
contentType: string;
body: string | Buffer;
}
/**
* 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 {
/**
* @internal
*/
_requestId: string;
/**
* @internal
*/
_interceptionId: string | undefined;
/**
* @internal
*/
_failureText: string | null;
/**
* @internal
*/
_response: HTTPResponse | null;
/**
* @internal
*/
_fromMemoryCache: boolean;
/**
* @internal
*/
_redirectChain: HTTPRequest[];
/**
* 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).
*/
abstract continueRequestOverrides(): ContinueRequestOverrides;
/**
* The `ResponseForRequest` that gets used if the
* interception is allowed to respond (ie, `abort()` is not called).
*/
abstract responseForRequest(): Partial<ResponseForRequest> | null;
/**
* The most recent reason for aborting the request
*/
abstract 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`.
*/
abstract interceptResolutionState(): InterceptResolutionState;
/**
* Is `true` if the intercept resolution has already been handled,
* `false` otherwise.
*/
abstract 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.
*/
abstract enqueueInterceptAction(pendingHandler: () => void | PromiseLike<unknown>): void;
/**
* Awaits pending interception handlers and then decides how to fulfill
* the request interception.
*/
abstract 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.
*/
abstract 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.
*/
abstract 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.
*/
abstract abort(errorCode?: ErrorCode, priority?: number): Promise<void>;
}
/**
* @public
*/
export declare enum InterceptResolutionAction {
Abort = "abort",
Respond = "respond",
Continue = "continue",
Disabled = "disabled",
None = "none",
AlreadyHandled = "already-handled"
}
/**
* @public
*
* @deprecated please use {@link InterceptResolutionAction} instead.
*/
export type InterceptResolutionStrategy = InterceptResolutionAction;
/**
* @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>;
//# 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,173 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.STATUS_TEXTS = exports.headersArray = exports.InterceptResolutionAction = exports.HTTPRequest = exports.DEFAULT_INTERCEPT_RESOLUTION_PRIORITY = void 0;
/**
* 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
*/
_requestId = '';
/**
* @internal
*/
_interceptionId;
/**
* @internal
*/
_failureText = null;
/**
* @internal
*/
_response = null;
/**
* @internal
*/
_fromMemoryCache = false;
/**
* @internal
*/
_redirectChain = [];
/**
* @internal
*/
constructor() { }
}
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;
}
exports.headersArray = headersArray;
/**
* @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',
};
//# sourceMappingURL=HTTPRequest.js.map

View File

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

View File

@@ -0,0 +1,101 @@
/**
* @license
* Copyright 2023 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/// <reference types="node" />
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.
*/
abstract buffer(): Promise<Buffer>;
/**
* Promise which resolves to a text 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;;OAEG;IACH,QAAQ,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAElC;;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,49 @@
"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);
}
/**
* Promise which resolves to a text representation of response body.
*/
async text() {
const content = await this.buffer();
return content.toString('utf8');
}
/**
* 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;IAmCD;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,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;AArGD,oCAqGC"}

View File

@@ -0,0 +1,455 @@
/**
* @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 [`page.mouse`](#pagemouse).
*
* @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 Touchscreen class exposes touchscreen events.
* @public
*/
export declare abstract class Touchscreen {
/**
* @internal
*/
constructor();
/**
* 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.
*/
abstract touchStart(x: number, y: number): Promise<void>;
/**
* Dispatches a `touchMove` event.
* @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.
*/
abstract touchMove(x: number, y: number): Promise<void>;
/**
* Dispatches a `touchend` event.
*/
abstract 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":"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"}

View File

@@ -0,0 +1,167 @@
"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;
/**
* 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 [`page.mouse`](#pagemouse).
*
* @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
*/
constructor() { }
/**
* Dispatches a `touchstart` and `touchend` event.
* @param x - Horizontal position of the tap.
* @param y - Vertical position of the tap.
*/
async tap(x, y) {
await this.touchStart(x, y);
await this.touchEnd();
}
}
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;;;AAkCH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsEG;AACH,MAAsB,KAAK;IACzB;;OAEG;IACH,gBAAe,CAAC;CAuHjB;AA3HD,sBA2HC;AAED;;;GAGG;AACH,MAAsB,WAAW;IAC/B;;OAEG;IACH,gBAAe,CAAC;IAEhB;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAC,CAAS,EAAE,CAAS;QAC5B,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;CA2BF;AAzCD,kCAyCC"}

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,223 @@
"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;
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 (typeof dispose !== "function") throw new TypeError("Object not disposable.");
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;
}
function next() {
while (env.stack.length) {
var rec = env.stack.pop();
try {
var result = rec.dispose && rec.dispose.call(rec.value);
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
catch (e) {
fail(e);
}
}
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":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKH,+CAA2E;AAC3E,yDAAgE;AAChE,yDAAwE;AAKxE;;;;;;;;;;;;;;;;;;;;GAoBG;IAEmB,QAAQ;4BAD7B,wBAAQ;;;;;;;;;;;YAuEP,oLAAM,WAAW,6DAMhB;YAqBD,0LAAM,aAAa,6DAwBlB;YAzHH,6KA6KC;;;YA7KqB,uDAAQ;;QAQ5B;;WAEG;QACH;;SAAgB;QAYhB;;WAEG;QACH,KAAK,CAAC,QAAQ,CAIZ,YAA2B,EAC3B,GAAG,IAAY;YAEf,YAAY,GAAG,IAAA,sCAA4B,EACzC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAClB,YAAY,CACb,CAAC;YACF,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;QAChE,CAAC;QAED;;;WAGG;QACH,KAAK,CAAC,cAAc,CAIlB,YAA2B,EAC3B,GAAG,IAAY;YAEf,YAAY,GAAG,IAAA,sCAA4B,EACzC,IAAI,CAAC,cAAc,CAAC,IAAI,EACxB,YAAY,CACb,CAAC;YACF,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;QACtE,CAAC;QAUD;;WAEG;QAEH,KAAK,CAAC,WAAW,CACf,YAAyB;YAEzB,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE;gBACxD,OAAO,MAAM,CAAC,YAAiB,CAAC,CAAC;YACnC,CAAC,EAAE,YAAY,CAAC,CAAC;QACnB,CAAC;QAED;;;;;;;;;;;;;;;;;WAiBG;QAEH,KAAK,CAAC,aAAa;YACjB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBACjD,MAAM,oBAAoB,GAAG,EAAE,CAAC;gBAChC,MAAM,WAAW,GAAG,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC;gBAC7D,KAAK,MAAM,YAAY,IAAI,WAAW,EAAE,CAAC;oBACvC,IAAI,WAAW,CAAC,YAAY,CAAC,EAAE,UAAU,EAAE,CAAC;wBAC1C,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBAC1C,CAAC;gBACH,CAAC;gBACD,OAAO,oBAAoB,CAAC;YAC9B,CAAC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;YACxC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBACtB,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC,CAAC,CACH,CAAC;YACF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;;;oBACzD,MAAM,MAAM,kCAAG,OAAO,CAAC,GAAU,CAAC,QAAA,CAAC;oBACnC,IAAI,MAAM,EAAE,CAAC;wBACX,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;oBAChC,CAAC;;;;;;;;;aACF;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QA2CD,gBAAgB;QAChB,6BAhGC,IAAA,+BAAe,GAAE,gCA2BjB,IAAA,+BAAe,GAAE,GAqEjB,6BAAa,EAAC;YACb,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;QAC/C,CAAC;QAED,gBAAgB;QAChB,CAAC,kCAAkB,CAAC;YAClB,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;;;;AA5KmB,4BAAQ"}

File diff suppressed because it is too large Load Diff

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,37 @@
/**
* @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 */
[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,CAAC,aAAa,CAAC,IAAI,IAAI;CAMxB"}

View File

@@ -0,0 +1,44 @@
"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 */
[disposable_js_1.disposeSymbol]() {
this.#disposed = true;
this.taskManager.terminateAll(new Error('waitForFunction failed: frame got detached.'));
}
}
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,CAAC,6BAAa,CAAC;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,YAAY,CAC3B,IAAI,KAAK,CAAC,6CAA6C,CAAC,CACzD,CAAC;IACJ,CAAC;CACF;AAjFD,sBAiFC"}

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,101 @@
/**
* @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>>>>;
}
//# 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;AAEH,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;CAIjD"}

View File

@@ -0,0 +1,106 @@
"use strict";
/**
* @license
* Copyright 2018 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.WebWorker = void 0;
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);
}
}
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,+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;CACF;AA7FD,8BA6FC"}

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 * 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,cAAc,kBAAkB,CAAC;AACjC,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,38 @@
"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("./Environment.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;AACnC,mDAAiC;AACjC,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,304 @@
/**
* @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';
/**
* @public
*/
export type VisibilityOption = 'hidden' | 'visible' | null;
/**
* @public
*/
export interface LocatorOptions {
/**
* Whether to wait for the element to be `visible` or `hidden`. `null` to
* disable visibility checks.
*/
visibility: VisibilityOption;
/**
* Total timeout for the entire locator operation.
*
* Pass `0` to disable timeout.
*
* @defaultValue `Page.getDefaultTimeout()`
*/
timeout: number;
/**
* Whether to scroll the element into viewport if not in the viewprot already.
* @defaultValue `true`
*/
ensureElementIsInTheViewport: boolean;
/**
* Whether to wait for input elements to become enabled before the action.
* Applicable to `click` and `fill` actions.
* @defaultValue `true`
*/
waitForEnabled: boolean;
/**
* Whether to wait for the element's bounding box to be same between two
* animation frames.
* @defaultValue `true`
*/
waitForStableBoundingBox: boolean;
}
/**
* @public
*/
export interface ActionOptions {
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"
}
export {
/**
* @deprecated Use {@link LocatorEvent}.
*/
LocatorEvent as LocatorEmittedEvents, };
/**
* @public
*/
export interface LocatorEvents extends Record<EventType, unknown> {
[LocatorEvent.Action]: undefined;
}
export type {
/**
* @deprecated Use {@link LocatorEvents}.
*/
LocatorEvents as LocatorEventObject, };
/**
* 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.
*
* @public
*/
export declare abstract class Locator<T> extends EventEmitter<LocatorEvents> {
#private;
/**
* Creates a race between multiple locators but ensures that only a single one
* acts.
*
* @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) => OperatorFunction<T_1, T_1>;
};
get timeout(): number;
setTimeout(timeout: number): Locator<T>;
setVisibility<NodeType extends Node>(this: Locator<NodeType>, visibility: VisibilityOption): Locator<NodeType>;
setWaitForEnabled<NodeType extends Node>(this: Locator<NodeType>, value: boolean): Locator<NodeType>;
setEnsureElementIsInTheViewport<ElementType extends Element>(this: Locator<ElementType>, value: boolean): Locator<ElementType>;
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>;
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, selector, inputs are
* supported.
*/
fill<ElementType extends Element>(this: Locator<ElementType>, value: string, options?: Readonly<ActionOptions>): Promise<void>;
hover<ElementType extends Element>(this: Locator<ElementType>, options?: Readonly<ActionOptions>): Promise<void>;
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,693 @@
"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;
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 (typeof dispose !== "function") throw new TypeError("Object not disposable.");
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;
}
function next() {
while (env.stack.length) {
var rec = env.stack.pop();
try {
var result = rec.dispose && rec.dispose.call(rec.value);
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
}
catch (e) {
fail(e);
}
}
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.LocatorEmittedEvents = 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.LocatorEmittedEvents = 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.
*
* @public
*/
class Locator extends EventEmitter_js_1.EventEmitter {
/**
* Creates a race between multiple locators but ensures that only a single one
* acts.
*
* @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) => {
const candidates = [];
if (signal) {
candidates.push((0, rxjs_js_1.fromEvent)(signal, 'abort').pipe((0, rxjs_js_1.map)(() => {
throw signal.reason;
})));
}
candidates.push((0, util_js_1.timeout)(this._timeout));
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;
}
setTimeout(timeout) {
const locator = this._clone();
locator._timeout = timeout;
return locator;
}
setVisibility(visibility) {
const locator = this._clone();
locator.visibility = visibility;
return locator;
}
setWaitForEnabled(value) {
const locator = this._clone();
locator.#waitForEnabled = value;
return locator;
}
setEnsureElementIsInTheViewport(value) {
const locator = this._clone();
locator.#ensureElementIsInTheViewport = value;
return locator;
}
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;
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));
}
#fill(value, options) {
const signal = options?.signal;
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));
}
#hover(options) {
const signal = options?.signal;
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));
}
#scroll(options) {
const signal = options?.signal;
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));
}
/**
* Clones the locator.
*/
clone() {
return this._clone();
}
/**
* Waits for the locator to get a handle from the page.
*
* @public
*/
async waitHandle(options) {
return await (0, rxjs_js_1.firstValueFrom)(this._wait(options).pipe(this.operators.retryAndRaceWithSignalAndTimer(options?.signal)));
}
/**
* 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);
}
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, selector, inputs are
* supported.
*/
fill(value, options) {
return (0, rxjs_js_1.firstValueFrom)(this.#fill(value, options));
}
hover(options) {
return (0, rxjs_js_1.firstValueFrom)(this.#hover(options));
}
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,14 @@
/**
* @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, options: {
acceptInsecureCerts: boolean;
}): 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,EAGlB,OAAO,EAAE;IAAC,mBAAmB,EAAE,OAAO,CAAA;CAAC,GACtC,OAAO,CAAC,cAAc,CAAC,CAiCzB"}

View File

@@ -0,0 +1,177 @@
"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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.connectBidiOverCdp = void 0;
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,
// TODO: replace with `BidiMapper.MapperOptions`, once it's exported in
// https://github.com/puppeteer/puppeteer/pull/11415.
options) {
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);
const bidiServer = await BidiMapper.BidiServer.createAndStart(transportBiDi, cdpConnectionAdapter,
// TODO: most likely need a little bit of refactoring
cdpConnectionAdapter.browserClient(), '', options, undefined, bidiServerLogger);
return pptrBiDiConnection;
}
exports.connectBidiOverCdp = connectBidiOverCdp;
/**
* 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,53 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
/// <reference types="node" />
import type { ChildProcess } from 'child_process';
import type * 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 { Viewport } from '../common/Viewport.js';
import { BidiBrowserContext } from './BrowserContext.js';
import type { BidiConnection } from './Connection.js';
import { type BidiTarget } from './Target.js';
/**
* @internal
*/
export interface BidiBrowserOptions {
process?: ChildProcess;
closeCallback?: BrowserCloseCallback;
connection: BidiConnection;
defaultViewport: Viewport | null;
ignoreHTTPSErrors?: boolean;
}
/**
* @internal
*/
export declare class BidiBrowser extends Browser {
#private;
readonly protocol = "webDriverBiDi";
static readonly subscribeModules: string[];
static readonly subscribeCdpEvents: Bidi.Cdp.EventNames[];
static create(opts: BidiBrowserOptions): Promise<BidiBrowser>;
private constructor();
userAgent(): never;
get connection(): BidiConnection;
wsEndpoint(): string;
close(): Promise<void>;
get connected(): boolean;
process(): ChildProcess | null;
createIncognitoBrowserContext(_options?: BrowserContextOptions): Promise<BidiBrowserContext>;
version(): Promise<string>;
browserContexts(): BidiBrowserContext[];
defaultBrowserContext(): BidiBrowserContext;
newPage(): Promise<Page>;
targets(): Target[];
_getTargetById(id: string): BidiTarget;
target(): Target;
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,KAAK,IAAI,MAAM,4CAA4C,CAAC;AAExE,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;AAI7C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAC,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAEvD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAIpD,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,aAAa,CAAC,EAAE,oBAAoB,CAAC;IACrC,UAAU,EAAE,cAAc,CAAC;IAC3B,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,OAAO;;IACtC,QAAQ,CAAC,QAAQ,mBAAmB;IAGpC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAKxC;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;IAuCnE,OAAO;IAiCE,SAAS,IAAI,KAAK;IAiF3B,IAAI,UAAU,IAAI,cAAc,CAG/B;IAEQ,UAAU,IAAI,MAAM;IAId,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBrC,IAAa,SAAS,IAAI,OAAO,CAEhC;IAEQ,OAAO,IAAI,YAAY,GAAG,IAAI;IAIxB,6BAA6B,CAC1C,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;IAI5B,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU;IAQ7B,MAAM,IAAI,MAAM;IAIV,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW1C,IAAa,SAAS,IAAI,SAAS,CAIlC;CACF"}

View File

@@ -0,0 +1,245 @@
"use strict";
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiBrowser = void 0;
const Browser_js_1 = require("../api/Browser.js");
const Errors_js_1 = require("../common/Errors.js");
const util_js_1 = require("../common/util.js");
const BrowserContext_js_1 = require("./BrowserContext.js");
const BrowsingContext_js_1 = require("./BrowsingContext.js");
const Session_js_1 = require("./core/Session.js");
const Target_js_1 = require("./Target.js");
/**
* @internal
*/
class BidiBrowser extends Browser_js_1.Browser {
protocol = 'webDriverBiDi';
// TODO: Update generator to include fully module
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, {
alwaysMatch: {
acceptInsecureCerts: opts.ignoreHTTPSErrors,
webSocketUrl: 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();
await browser.#getTree();
return browser;
}
#process;
#closeCallback;
#browserCore;
#defaultViewport;
#targets = new Map();
#browserContexts = new WeakMap();
#browserTarget;
#connectionEventHandlers = new Map([
['browsingContext.contextCreated', this.#onContextCreated.bind(this)],
['browsingContext.contextDestroyed', this.#onContextDestroyed.bind(this)],
['browsingContext.domContentLoaded', this.#onContextDomLoaded.bind(this)],
['browsingContext.fragmentNavigated', this.#onContextNavigation.bind(this)],
['browsingContext.navigationStarted', this.#onContextNavigation.bind(this)],
]);
constructor(browserCore, opts) {
super();
this.#process = opts.process;
this.#closeCallback = opts.closeCallback;
this.#browserCore = browserCore;
this.#defaultViewport = opts.defaultViewport;
this.#browserTarget = new Target_js_1.BiDiBrowserTarget(this);
for (const context of this.#browserCore.userContexts) {
this.#createBrowserContext(context);
}
}
#initialize() {
this.#browserCore.once('disconnected', () => {
this.emit("disconnected" /* BrowserEvent.Disconnected */, undefined);
});
this.#process?.once('close', () => {
this.#browserCore.dispose('Browser process exited.', true);
this.connection.dispose();
});
for (const [eventName, handler] of this.#connectionEventHandlers) {
this.connection.on(eventName, handler);
}
}
get #browserName() {
return this.#browserCore.session.capabilities.browserName;
}
get #browserVersion() {
return this.#browserCore.session.capabilities.browserVersion;
}
userAgent() {
throw new Errors_js_1.UnsupportedOperation();
}
#createBrowserContext(userContext) {
const browserContext = new BrowserContext_js_1.BidiBrowserContext(this, userContext, {
defaultViewport: this.#defaultViewport,
});
this.#browserContexts.set(userContext, browserContext);
return browserContext;
}
#onContextDomLoaded(event) {
const target = this.#targets.get(event.context);
if (target) {
this.emit("targetchanged" /* BrowserEvent.TargetChanged */, target);
target.browserContext().emit("targetchanged" /* BrowserContextEvent.TargetChanged */, target);
}
}
#onContextNavigation(event) {
const target = this.#targets.get(event.context);
if (target) {
this.emit("targetchanged" /* BrowserEvent.TargetChanged */, target);
target.browserContext().emit("targetchanged" /* BrowserContextEvent.TargetChanged */, target);
}
}
#onContextCreated(event) {
const context = new BrowsingContext_js_1.BrowsingContext(this.connection, event, this.#browserName);
this.connection.registerBrowsingContexts(context);
const browserContext = event.userContext === 'default'
? this.defaultBrowserContext()
: this.browserContexts().find(browserContext => {
return browserContext.id === event.userContext;
});
if (!browserContext) {
throw new Error('Missing browser contexts');
}
const target = !context.parent
? new Target_js_1.BiDiPageTarget(browserContext, context)
: new Target_js_1.BiDiBrowsingContextTarget(browserContext, context);
this.#targets.set(event.context, target);
this.emit("targetcreated" /* BrowserEvent.TargetCreated */, target);
target.browserContext().emit("targetcreated" /* BrowserContextEvent.TargetCreated */, target);
if (context.parent) {
const topLevel = this.connection.getTopLevelContext(context.parent);
topLevel.emit(BrowsingContext_js_1.BrowsingContextEvent.Created, context);
}
}
async #getTree() {
const { result } = await this.connection.send('browsingContext.getTree', {});
for (const context of result.contexts) {
this.#onContextCreated(context);
}
}
async #onContextDestroyed(event) {
const context = this.connection.getBrowsingContext(event.context);
const topLevelContext = this.connection.getTopLevelContext(event.context);
topLevelContext.emit(BrowsingContext_js_1.BrowsingContextEvent.Destroyed, context);
const target = this.#targets.get(event.context);
const page = await target?.page();
await page?.close().catch(util_js_1.debugError);
this.#targets.delete(event.context);
if (target) {
this.emit("targetdestroyed" /* BrowserEvent.TargetDestroyed */, target);
target.browserContext().emit("targetdestroyed" /* BrowserContextEvent.TargetDestroyed */, target);
}
}
get connection() {
// SAFETY: We only have one implementation.
return this.#browserCore.session.connection;
}
wsEndpoint() {
return this.connection.url;
}
async close() {
for (const [eventName, handler] of this.#connectionEventHandlers) {
this.connection.off(eventName, handler);
}
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.disposed;
}
process() {
return this.#process ?? null;
}
async createIncognitoBrowserContext(_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.#browserTarget, ...Array.from(this.#targets.values())];
}
_getTargetById(id) {
const target = this.#targets.get(id);
if (!target) {
throw new Error('Target not found');
}
return target;
}
target() {
return this.#browserTarget;
}
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 { BrowserConnectOptions, 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: BrowserConnectOptions & 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,EACV,qBAAqB,EACrB,cAAc,EACf,MAAM,6BAA6B,CAAC;AAIrC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAG9C;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,mBAAmB,EAAE,mBAAmB,EACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,qBAAqB,GAAG,cAAc,GAC9C,OAAO,CAAC,WAAW,CAAC,CAkBtB"}

View File

@@ -0,0 +1,107 @@
"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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports._connectToBiDiBrowser = void 0;
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 { ignoreHTTPSErrors = false, defaultViewport = util_js_1.DEFAULT_VIEWPORT } = options;
const { bidiConnection, 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,
closeCallback,
process: undefined,
defaultViewport: defaultViewport,
ignoreHTTPSErrors: ignoreHTTPSErrors,
});
return bidiBrowser;
}
exports._connectToBiDiBrowser = _connectToBiDiBrowser;
/**
* 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 { ignoreHTTPSErrors = false, 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);
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.');
}
// TODO: use other options too.
const bidiOverCdpConnection = await BiDi.connectBidiOverCdp(cdpConnection, {
acceptInsecureCerts: ignoreHTTPSErrors,
});
return {
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":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;AAGH,wDAAgD;AAMhD,mDAAwE;AACxE,+CAA+D;AAK/D;;;;;;;GAOG;AACI,KAAK,UAAU,qBAAqB,CACzC,mBAAwC,EACxC,GAAW,EACX,OAA+C;IAE/C,MAAM,EAAC,iBAAiB,GAAG,KAAK,EAAE,eAAe,GAAG,0BAAgB,EAAC,GACnE,OAAO,CAAC;IAEV,MAAM,EAAC,cAAc,EAAE,aAAa,EAAC,GAAG,MAAM,iBAAiB,CAC7D,mBAAmB,EACnB,GAAG,EACH,OAAO,CACR,CAAC;IACF,MAAM,IAAI,GAAG,wDAAa,yBAAyB,CAAC,WAAW,GAAC,CAAC;IACjE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAChD,UAAU,EAAE,cAAc;QAC1B,aAAa;QACb,OAAO,EAAE,SAAS;QAClB,eAAe,EAAE,eAAe;QAChC,iBAAiB,EAAE,iBAAiB;KACrC,CAAC,CAAC;IACH,OAAO,WAAW,CAAC;AACrB,CAAC;AAtBD,sDAsBC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,iBAAiB,CAC9B,mBAAwC,EACxC,GAAW,EACX,OAA8B;IAK9B,MAAM,IAAI,GAAG,wDAAa,yBAAyB,CAAC,WAAW,GAAC,CAAC;IACjE,MAAM,EAAC,iBAAiB,GAAG,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,eAAe,EAAC,GAAG,OAAO,CAAC;IAEzE,uBAAuB;IACvB,MAAM,kBAAkB,GAAG,IAAI,IAAI,CAAC,cAAc,CAChD,GAAG,EACH,mBAAmB,EACnB,MAAM,EACN,eAAe,CAChB,CAAC;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;QACnE,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAClD,gFAAgF;YAChF,OAAO;gBACL,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,KAAK,IAAI,EAAE;oBACxB,MAAM,kBAAkB,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;gBACvE,CAAC;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,CAAC,YAAY,yBAAa,CAAC,EAAE,CAAC;YAClC,2DAA2D;YAC3D,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,+CAA+C;IAC/C,kBAAkB,CAAC,MAAM,EAAE,CAAC;IAE5B,wDAAwD;IACxD,MAAM,aAAa,GAAG,IAAI,0BAAU,CAClC,GAAG,EACH,mBAAmB,EACnB,MAAM,EACN,eAAe,CAChB,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAC/D,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,gCAAoB,CAC5B,iDAAiD,CAClD,CAAC;IACJ,CAAC;IAED,+BAA+B;IAC/B,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE;QACzE,mBAAmB,EAAE,iBAAiB;KACvC,CAAC,CAAC;IACH,OAAO;QACL,cAAc,EAAE,qBAAqB;QACrC,aAAa,EAAE,KAAK,IAAI,EAAE;YACxB,8DAA8D;YAC9D,MAAM,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;QAC9D,CAAC;KACF,CAAC;AACJ,CAAC"}

View File

@@ -0,0 +1,39 @@
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
import type { WaitForTargetOptions } from '../api/Browser.js';
import { BrowserContext } from '../api/BrowserContext.js';
import type { Page } from '../api/Page.js';
import type { Target } from '../api/Target.js';
import type { Viewport } from '../common/Viewport.js';
import type { BidiBrowser } from './Browser.js';
import type { BidiConnection } from './Connection.js';
import { UserContext } from './core/UserContext.js';
import type { BidiPage } from './Page.js';
/**
* @internal
*/
export interface BidiBrowserContextOptions {
defaultViewport: Viewport | null;
}
/**
* @internal
*/
export declare class BidiBrowserContext extends BrowserContext {
#private;
constructor(browser: BidiBrowser, userContext: UserContext, options: BidiBrowserContextOptions);
targets(): Target[];
waitForTarget(predicate: (x: Target) => boolean | Promise<boolean>, options?: WaitForTargetOptions): Promise<Target>;
get connection(): BidiConnection;
newPage(): Promise<Page>;
close(): Promise<void>;
browser(): BidiBrowser;
pages(): Promise<BidiPage[]>;
isIncognito(): boolean;
overridePermissions(): never;
clearPermissionOverrides(): never;
get id(): string | undefined;
}
//# 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,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAC,cAAc,EAAC,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,eAAe,EAAE,QAAQ,GAAG,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,cAAc;;gBAOlD,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,yBAAyB;IAS3B,OAAO,IAAI,MAAM,EAAE;IAMnB,aAAa,CACpB,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,EACpD,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC;IAMlB,IAAI,UAAU,IAAI,cAAc,CAE/B;IAEc,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B,OAAO,IAAI,WAAW;IAIhB,KAAK,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAWlC,WAAW,IAAI,OAAO;IAItB,mBAAmB,IAAI,KAAK;IAI5B,wBAAwB,IAAI,KAAK;IAI1C,IAAa,EAAE,IAAI,MAAM,GAAG,SAAS,CAKpC;CACF"}

View File

@@ -0,0 +1,106 @@
"use strict";
/**
* @license
* Copyright 2022 Google Inc.
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BidiBrowserContext = void 0;
const BrowserContext_js_1 = require("../api/BrowserContext.js");
const Errors_js_1 = require("../common/Errors.js");
const util_js_1 = require("../common/util.js");
const UserContext_js_1 = require("./core/UserContext.js");
/**
* @internal
*/
class BidiBrowserContext extends BrowserContext_js_1.BrowserContext {
#browser;
#connection;
#defaultViewport;
#userContext;
constructor(browser, userContext, options) {
super();
this.#browser = browser;
this.#userContext = userContext;
this.#connection = this.#browser.connection;
this.#defaultViewport = options.defaultViewport;
}
targets() {
return this.#browser.targets().filter(target => {
return target.browserContext() === this;
});
}
waitForTarget(predicate, options = {}) {
return this.#browser.waitForTarget(target => {
return target.browserContext() === this && predicate(target);
}, options);
}
get connection() {
return this.#connection;
}
async newPage() {
const { result } = await this.#connection.send('browsingContext.create', {
type: "tab" /* Bidi.BrowsingContext.CreateType.Tab */,
userContext: this.#userContext.id,
});
const target = this.#browser._getTargetById(result.context);
// TODO: once BiDi has some concept matching BrowserContext, the newly
// created contexts should get automatically assigned to the right
// BrowserContext. For now, we assume that only explicitly created pages go
// to the current BrowserContext. Otherwise, the contexts get assigned to
// the default BrowserContext by the Browser.
target._setBrowserContext(this);
const page = await target.page();
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;
}
async close() {
if (!this.isIncognito()) {
throw new Error('Default context cannot be closed!');
}
try {
await this.#userContext.remove();
}
catch (error) {
(0, util_js_1.debugError)(error);
}
}
browser() {
return this.#browser;
}
async pages() {
const results = await Promise.all([...this.targets()].map(t => {
return t.page();
}));
return results.filter((p) => {
return p !== null;
});
}
isIncognito() {
return this.#userContext.id !== UserContext_js_1.UserContext.DEFAULT;
}
overridePermissions() {
throw new Errors_js_1.UnsupportedOperation();
}
clearPermissionOverrides() {
throw new Errors_js_1.UnsupportedOperation();
}
get id() {
if (this.#userContext.id === 'default') {
return undefined;
}
return this.#userContext.id;
}
}
exports.BidiBrowserContext = BidiBrowserContext;
//# sourceMappingURL=BrowserContext.js.map

View File

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

View File

@@ -0,0 +1,61 @@
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import type ProtocolMapping from 'devtools-protocol/types/protocol-mapping.js';
import { CDPSession } from '../api/CDPSession.js';
import type { Connection as CdpConnection } from '../cdp/Connection.js';
import type { EventType } from '../common/EventEmitter.js';
import type { BidiConnection } from './Connection.js';
import { BidiRealm } from './Realm.js';
/**
* @internal
*/
export declare const cdpSessions: Map<string, CdpSessionWrapper>;
/**
* @internal
*/
export declare class CdpSessionWrapper extends CDPSession {
#private;
constructor(context: BrowsingContext, sessionId?: string);
connection(): CdpConnection | undefined;
send<T extends keyof ProtocolMapping.Commands>(method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType']): Promise<ProtocolMapping.Commands[T]['returnType']>;
detach(): Promise<void>;
id(): string;
}
/**
* Internal events that the BrowsingContext class emits.
*
* @internal
*/
export declare namespace BrowsingContextEvent {
/**
* Emitted on the top-level context, when a descendant context is created.
*/
const Created: unique symbol;
/**
* Emitted on the top-level context, when a descendant context or the
* top-level context itself is destroyed.
*/
const Destroyed: unique symbol;
}
/**
* @internal
*/
export interface BrowsingContextEvents extends Record<EventType, unknown> {
[BrowsingContextEvent.Created]: BrowsingContext;
[BrowsingContextEvent.Destroyed]: BrowsingContext;
}
/**
* @internal
*/
export declare class BrowsingContext extends BidiRealm {
#private;
constructor(connection: BidiConnection, info: Bidi.BrowsingContext.Info, browserName: string);
supportsCdp(): boolean;
createRealmForSandbox(): BidiRealm;
get url(): string;
get id(): string;
get parent(): string | undefined | null;
get cdpSession(): CDPSession;
sendCdpCommand<T extends keyof ProtocolMapping.Commands>(method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType']): Promise<ProtocolMapping.Commands[T]['returnType']>;
dispose(): void;
}
//# sourceMappingURL=BrowsingContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowsingContext.d.ts","sourceRoot":"","sources":["../../../../src/bidi/BrowsingContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,IAAI,MAAM,4CAA4C,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,6CAA6C,CAAC;AAE/E,OAAO,EAAC,UAAU,EAAC,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,EAAC,UAAU,IAAI,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,2BAA2B,CAAC;AAIzD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,WAAW,gCAAuC,CAAC;AAEhE;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;;gBAKnC,OAAO,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM;IAwB/C,UAAU,IAAI,aAAa,GAAG,SAAS;IAIjC,IAAI,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EAC1D,MAAM,EAAE,CAAC,EACT,GAAG,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GACtD,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAoBtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAU7B,EAAE,IAAI,MAAM;CAItB;AAED;;;;GAIG;AAEH,yBAAiB,oBAAoB,CAAC;IACpC;;OAEG;IACI,MAAM,OAAO,eAAoC,CAAC;IACzD;;;OAGG;IACI,MAAM,SAAS,eAAsC,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;IACvE,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IAChD,CAAC,oBAAoB,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;CACnD;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;;gBAQ1C,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,EAC/B,WAAW,EAAE,MAAM;IAcrB,WAAW,IAAI,OAAO;IAQtB,qBAAqB,IAAI,SAAS;IAIlC,IAAI,GAAG,IAAI,MAAM,CAEhB;IAED,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,GAAG,IAAI,CAEtC;IAED,IAAI,UAAU,IAAI,UAAU,CAE3B;IAEK,cAAc,CAAC,CAAC,SAAS,MAAM,eAAe,CAAC,QAAQ,EAC3D,MAAM,EAAE,CAAC,EACT,GAAG,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GACtD,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAIrD,OAAO,IAAI,IAAI;CAKhB"}

View File

@@ -0,0 +1,146 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowsingContext = exports.BrowsingContextEvent = exports.CdpSessionWrapper = exports.cdpSessions = void 0;
const CDPSession_js_1 = require("../api/CDPSession.js");
const Errors_js_1 = require("../common/Errors.js");
const util_js_1 = require("../common/util.js");
const Deferred_js_1 = require("../util/Deferred.js");
const Realm_js_1 = require("./Realm.js");
/**
* @internal
*/
exports.cdpSessions = new Map();
/**
* @internal
*/
class CdpSessionWrapper extends CDPSession_js_1.CDPSession {
#context;
#sessionId = Deferred_js_1.Deferred.create();
#detached = false;
constructor(context, sessionId) {
super();
this.#context = context;
if (!this.#context.supportsCdp()) {
return;
}
if (sessionId) {
this.#sessionId.resolve(sessionId);
exports.cdpSessions.set(sessionId, this);
}
else {
context.connection
.send('cdp.getSession', {
context: context.id,
})
.then(session => {
this.#sessionId.resolve(session.result.session);
exports.cdpSessions.set(session.result.session, this);
})
.catch(err => {
this.#sessionId.reject(err);
});
}
}
connection() {
return undefined;
}
async send(method, ...paramArgs) {
if (!this.#context.supportsCdp()) {
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.#context.connection.send('cdp.sendCommand', {
method: method,
params: paramArgs[0],
session,
});
return result.result;
}
async detach() {
exports.cdpSessions.delete(this.id());
if (!this.#detached && this.#context.supportsCdp()) {
await this.#context.cdpSession.send('Target.detachFromTarget', {
sessionId: this.id(),
});
}
this.#detached = true;
}
id() {
const val = this.#sessionId.value();
return val instanceof Error || val === undefined ? '' : val;
}
}
exports.CdpSessionWrapper = CdpSessionWrapper;
/**
* Internal events that the BrowsingContext class emits.
*
* @internal
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var BrowsingContextEvent;
(function (BrowsingContextEvent) {
/**
* Emitted on the top-level context, when a descendant context is created.
*/
BrowsingContextEvent.Created = Symbol('BrowsingContext.created');
/**
* Emitted on the top-level context, when a descendant context or the
* top-level context itself is destroyed.
*/
BrowsingContextEvent.Destroyed = Symbol('BrowsingContext.destroyed');
})(BrowsingContextEvent || (exports.BrowsingContextEvent = BrowsingContextEvent = {}));
/**
* @internal
*/
class BrowsingContext extends Realm_js_1.BidiRealm {
#id;
#url;
#cdpSession;
#parent;
#browserName = '';
constructor(connection, info, browserName) {
super(connection);
this.#id = info.context;
this.#url = info.url;
this.#parent = info.parent;
this.#browserName = browserName;
this.#cdpSession = new CdpSessionWrapper(this, undefined);
this.on('browsingContext.domContentLoaded', this.#updateUrl.bind(this));
this.on('browsingContext.fragmentNavigated', this.#updateUrl.bind(this));
this.on('browsingContext.load', this.#updateUrl.bind(this));
}
supportsCdp() {
return !this.#browserName.toLowerCase().includes('firefox');
}
#updateUrl(info) {
this.#url = info.url;
}
createRealmForSandbox() {
return new Realm_js_1.BidiRealm(this.connection);
}
get url() {
return this.#url;
}
get id() {
return this.#id;
}
get parent() {
return this.#parent;
}
get cdpSession() {
return this.#cdpSession;
}
async sendCdpCommand(method, ...paramArgs) {
return await this.#cdpSession.send(method, ...paramArgs);
}
dispose() {
this.removeAllListeners();
this.connection.unregisterBrowsingContexts(this.#id);
void this.#cdpSession.detach().catch(util_js_1.debugError);
}
}
exports.BrowsingContext = BrowsingContext;
//# sourceMappingURL=BrowsingContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BrowsingContext.js","sourceRoot":"","sources":["../../../../src/bidi/BrowsingContext.ts"],"names":[],"mappings":";;;AAGA,wDAAgD;AAEhD,mDAA2E;AAE3E,+CAA6C;AAC7C,qDAA6C;AAG7C,yCAAqC;AAErC;;GAEG;AACU,QAAA,WAAW,GAAG,IAAI,GAAG,EAA6B,CAAC;AAEhE;;GAEG;AACH,MAAa,iBAAkB,SAAQ,0BAAU;IAC/C,QAAQ,CAAkB;IAC1B,UAAU,GAAG,sBAAQ,CAAC,MAAM,EAAU,CAAC;IACvC,SAAS,GAAG,KAAK,CAAC;IAElB,YAAY,OAAwB,EAAE,SAAkB;QACtD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACnC,mBAAW,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,UAAU;iBACf,IAAI,CAAC,gBAAgB,EAAE;gBACtB,OAAO,EAAE,OAAO,CAAC,EAAE;aACpB,CAAC;iBACD,IAAI,CAAC,OAAO,CAAC,EAAE;gBACd,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;gBACjD,mBAAW,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAQ,EAAE,IAAI,CAAC,CAAC;YACjD,CAAC,CAAC;iBACD,KAAK,CAAC,GAAG,CAAC,EAAE;gBACX,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC;IAEQ,UAAU;QACjB,OAAO,SAAS,CAAC;IACnB,CAAC;IAEQ,KAAK,CAAC,IAAI,CACjB,MAAS,EACT,GAAG,SAAoD;QAEvD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,gCAAoB,CAC5B,qFAAqF,CACtF,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,4BAAgB,CACxB,mBAAmB,MAAM,0DAA0D,CACpF,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC;QACrD,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE;YACtE,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;YACpB,OAAO;SACR,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAEQ,KAAK,CAAC,MAAM;QACnB,mBAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YACnD,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,yBAAyB,EAAE;gBAC7D,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE;aACrB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAEQ,EAAE;QACT,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,GAAG,YAAY,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;IAC9D,CAAC;CACF;AAtED,8CAsEC;AAED;;;;GAIG;AACH,2DAA2D;AAC3D,IAAiB,oBAAoB,CAUpC;AAVD,WAAiB,oBAAoB;IACnC;;OAEG;IACU,4BAAO,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACzD;;;OAGG;IACU,8BAAS,GAAG,MAAM,CAAC,2BAA2B,CAAC,CAAC;AAC/D,CAAC,EAVgB,oBAAoB,oCAApB,oBAAoB,QAUpC;AAUD;;GAEG;AACH,MAAa,eAAgB,SAAQ,oBAAS;IAC5C,GAAG,CAAS;IACZ,IAAI,CAAS;IACb,WAAW,CAAa;IACxB,OAAO,CAAiB;IACxB,YAAY,GAAG,EAAE,CAAC;IAElB,YACE,UAA0B,EAC1B,IAA+B,EAC/B,WAAmB;QAEnB,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,IAAI,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAE1D,IAAI,CAAC,EAAE,CAAC,kCAAkC,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,EAAE,CAAC,mCAAmC,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,EAAE,CAAC,sBAAsB,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,WAAW;QACT,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED,UAAU,CAAC,IAAyC;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACvB,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,oBAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,MAAS,EACT,GAAG,SAAoD;QAEvD,OAAO,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrD,KAAK,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAU,CAAC,CAAC;IACnD,CAAC;CACF;AAhED,0CAgEC"}

View File

@@ -0,0 +1,58 @@
/**
* @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 BrowsingContext } from './BrowsingContext.js';
import type { BidiEvents, Commands as BidiCommands, 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;
};
}
/**
* @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']): Promise<{
result: Commands[T]['returnType'];
}>;
/**
* @internal
*/
protected onMessage(message: string): Promise<void>;
registerBrowsingContexts(context: BrowsingContext): void;
getBrowsingContext(contextId: string): BrowsingContext;
getTopLevelContext(contextId: string): BrowsingContext;
unregisterBrowsingContexts(id: string): 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;AAIvD,OAAO,EAAc,KAAK,eAAe,EAAC,MAAM,sBAAsB,CAAC;AACvE,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,IAAI,YAAY,EACxB,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;CACH;AAED;;GAEG;AACH,qBAAa,cACX,SAAQ,YAAY,CAAC,UAAU,CAC/B,YAAW,UAAU;;gBAYnB,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,GAC5B,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;IAkEzD,wBAAwB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAIxD,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAQtD,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAetD,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5C;;;;OAIG;IACH,MAAM,IAAI,IAAI;IAad;;OAEG;IACH,OAAO,IAAI,IAAI;IAKf,wBAAwB,IAAI,KAAK,EAAE;CAGpC"}

View File

@@ -0,0 +1,188 @@
"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 BrowsingContext_js_1 = require("./BrowsingContext.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();
#browsingContexts = new Map();
#emitters = [];
constructor(url, transport, delay = 0, timeout) {
super();
this.#url = url;
this.#delay = delay;
this.#timeout = timeout ?? 180000;
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) {
(0, assert_js_1.assert)(!this.#closed, 'Protocol error: Connection closed.');
return this.#callbacks.create(method, 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.message);
return;
case 'event':
if (isCdpEvent(object)) {
BrowsingContext_js_1.cdpSessions
.get(object.params.session)
?.emit(object.params.event, object.params.params);
return;
}
this.#maybeEmitOnContext(object);
// 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);
}
#maybeEmitOnContext(event) {
let context;
// Context specific events
if ('context' in event.params && event.params.context !== null) {
context = this.#browsingContexts.get(event.params.context);
// `log.entryAdded` specific context
}
else if ('source' in event.params &&
event.params.source.context !== undefined) {
context = this.#browsingContexts.get(event.params.source.context);
}
context?.emit(event.method, event.params);
}
registerBrowsingContexts(context) {
this.#browsingContexts.set(context.id, context);
}
getBrowsingContext(contextId) {
const currentContext = this.#browsingContexts.get(contextId);
if (!currentContext) {
throw new Error(`BrowsingContext ${contextId} does not exist.`);
}
return currentContext;
}
getTopLevelContext(contextId) {
let currentContext = this.#browsingContexts.get(contextId);
if (!currentContext) {
throw new Error(`BrowsingContext ${contextId} does not exist.`);
}
while (currentContext.parent) {
contextId = currentContext.parent;
currentContext = this.#browsingContexts.get(contextId);
if (!currentContext) {
throw new Error(`BrowsingContext ${contextId} does not exist.`);
}
}
return currentContext;
}
unregisterBrowsingContexts(id) {
this.#browsingContexts.delete(id);
}
/**
* 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.#browsingContexts.clear();
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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,22 @@
/**
* @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 {
static deserializeNumber(value: Bidi.Script.SpecialNumber | number): number;
static deserializeLocalValue(result: Bidi.Script.RemoteValue): unknown;
static deserializeTuple([serializedKey, serializedValue]: [
Bidi.Script.RemoteValue | string,
Bidi.Script.RemoteValue
]): {
key: unknown;
value: unknown;
};
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,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,MAAM,GAAG,MAAM;IAe3E,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,OAAO;IA6CtE,MAAM,CAAC,gBAAgB,CAAC,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE;QACxD,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,MAAM;QAChC,IAAI,CAAC,MAAM,CAAC,WAAW;KACxB,GAAG;QAAC,GAAG,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC;IAUlC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG;CAQzD"}

View File

@@ -0,0 +1,87 @@
"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 deserializeNumber(value) {
switch (value) {
case '-0':
return -0;
case 'NaN':
return NaN;
case 'Infinity':
return Infinity;
case '-Infinity':
return -Infinity;
default:
return value;
}
}
static deserializeLocalValue(result) {
switch (result.type) {
case 'array':
return result.value?.map(value => {
return BidiDeserializer.deserializeLocalValue(value);
});
case 'set':
return result.value?.reduce((acc, value) => {
return acc.add(BidiDeserializer.deserializeLocalValue(value));
}, new Set());
case 'object':
return result.value?.reduce((acc, tuple) => {
const { key, value } = BidiDeserializer.deserializeTuple(tuple);
acc[key] = value;
return acc;
}, {});
case 'map':
return result.value?.reduce((acc, tuple) => {
const { key, value } = BidiDeserializer.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 BidiDeserializer.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 deserializeTuple([serializedKey, serializedValue]) {
const key = typeof serializedKey === 'string'
? serializedKey
: BidiDeserializer.deserializeLocalValue(serializedKey);
const value = BidiDeserializer.deserializeLocalValue(serializedValue);
return { key, value };
}
static deserialize(result) {
if (!result) {
(0, util_js_1.debugError)('Service did not produce a result.');
return undefined;
}
return BidiDeserializer.deserializeLocalValue(result);
}
}
exports.BidiDeserializer = BidiDeserializer;
//# sourceMappingURL=Deserializer.js.map

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