tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Page.ts (99372B)


      1 /**
      2 * @license
      3 * Copyright 2017 Google Inc.
      4 * SPDX-License-Identifier: Apache-2.0
      5 */
      6 
      7 import type {Protocol} from 'devtools-protocol';
      8 
      9 import {
     10  concat,
     11  EMPTY,
     12  filter,
     13  first,
     14  firstValueFrom,
     15  from,
     16  map,
     17  merge,
     18  mergeMap,
     19  mergeScan,
     20  of,
     21  raceWith,
     22  ReplaySubject,
     23  startWith,
     24  switchMap,
     25  take,
     26  takeUntil,
     27  timer,
     28  type Observable,
     29 } from '../../third_party/rxjs/rxjs.js';
     30 import type {HTTPRequest} from '../api/HTTPRequest.js';
     31 import type {HTTPResponse} from '../api/HTTPResponse.js';
     32 import type {Accessibility} from '../cdp/Accessibility.js';
     33 import type {Coverage} from '../cdp/Coverage.js';
     34 import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js';
     35 import type {NetworkConditions} from '../cdp/NetworkManager.js';
     36 import type {Tracing} from '../cdp/Tracing.js';
     37 import type {ConsoleMessage} from '../common/ConsoleMessage.js';
     38 import type {
     39  Cookie,
     40  CookieParam,
     41  DeleteCookiesRequest,
     42 } from '../common/Cookie.js';
     43 import type {Device} from '../common/Device.js';
     44 import {TargetCloseError} from '../common/Errors.js';
     45 import {
     46  EventEmitter,
     47  type EventsWithWildcard,
     48  type EventType,
     49  type Handler,
     50 } from '../common/EventEmitter.js';
     51 import type {FileChooser} from '../common/FileChooser.js';
     52 import type {PDFOptions} from '../common/PDFOptions.js';
     53 import {TimeoutSettings} from '../common/TimeoutSettings.js';
     54 import type {
     55  Awaitable,
     56  AwaitablePredicate,
     57  EvaluateFunc,
     58  EvaluateFuncWith,
     59  HandleFor,
     60  NodeFor,
     61 } from '../common/types.js';
     62 import {
     63  debugError,
     64  fromEmitterEvent,
     65  filterAsync,
     66  isString,
     67  NETWORK_IDLE_TIME,
     68  timeout,
     69  withSourcePuppeteerURLIfNone,
     70  fromAbortSignal,
     71 } from '../common/util.js';
     72 import type {Viewport} from '../common/Viewport.js';
     73 import {environment} from '../environment.js';
     74 import type {ScreenRecorder} from '../node/ScreenRecorder.js';
     75 import {guarded} from '../util/decorators.js';
     76 import {
     77  AsyncDisposableStack,
     78  asyncDisposeSymbol,
     79  DisposableStack,
     80  disposeSymbol,
     81 } from '../util/disposable.js';
     82 import {stringToTypedArray} from '../util/encoding.js';
     83 
     84 import type {Browser} from './Browser.js';
     85 import type {BrowserContext} from './BrowserContext.js';
     86 import type {CDPSession} from './CDPSession.js';
     87 import type {Dialog} from './Dialog.js';
     88 import type {
     89  BoundingBox,
     90  ClickOptions,
     91  ElementHandle,
     92 } from './ElementHandle.js';
     93 import type {
     94  Frame,
     95  FrameAddScriptTagOptions,
     96  FrameAddStyleTagOptions,
     97  FrameWaitForFunctionOptions,
     98  GoToOptions,
     99  WaitForOptions,
    100 } from './Frame.js';
    101 import type {
    102  Keyboard,
    103  KeyboardTypeOptions,
    104  Mouse,
    105  Touchscreen,
    106 } from './Input.js';
    107 import type {JSHandle} from './JSHandle.js';
    108 import {
    109  FunctionLocator,
    110  Locator,
    111  NodeLocator,
    112  type AwaitedLocator,
    113 } from './locators/locators.js';
    114 import type {Target} from './Target.js';
    115 import type {WebWorker} from './WebWorker.js';
    116 
    117 /**
    118 * @public
    119 */
    120 export interface Metrics {
    121  Timestamp?: number;
    122  Documents?: number;
    123  Frames?: number;
    124  JSEventListeners?: number;
    125  Nodes?: number;
    126  LayoutCount?: number;
    127  RecalcStyleCount?: number;
    128  LayoutDuration?: number;
    129  RecalcStyleDuration?: number;
    130  ScriptDuration?: number;
    131  TaskDuration?: number;
    132  JSHeapUsedSize?: number;
    133  JSHeapTotalSize?: number;
    134 }
    135 
    136 /**
    137 * @public
    138 */
    139 export interface Credentials {
    140  username: string;
    141  password: string;
    142 }
    143 
    144 /**
    145 * @public
    146 */
    147 export interface WaitForNetworkIdleOptions extends WaitTimeoutOptions {
    148  /**
    149   * Time (in milliseconds) the network should be idle.
    150   *
    151   * @defaultValue `500`
    152   */
    153  idleTime?: number;
    154  /**
    155   * Maximum number concurrent of network connections to be considered inactive.
    156   *
    157   * @defaultValue `0`
    158   */
    159  concurrency?: number;
    160 }
    161 
    162 /**
    163 * @public
    164 */
    165 export interface WaitTimeoutOptions {
    166  /**
    167   * Maximum wait time in milliseconds. Pass 0 to disable the timeout.
    168   *
    169   * The default value can be changed by using the
    170   * {@link Page.setDefaultTimeout} method.
    171   *
    172   * @defaultValue `30_000`
    173   */
    174  timeout?: number;
    175  /**
    176   * A signal object that allows you to cancel a waitFor call.
    177   */
    178  signal?: AbortSignal;
    179 }
    180 
    181 /**
    182 * @public
    183 */
    184 export interface WaitForSelectorOptions {
    185  /**
    186   * Wait for the selected element to be present in DOM and to be visible. See
    187   * {@link ElementHandle.isVisible} for the definition of element visibility.
    188   *
    189   * @defaultValue `false`
    190   */
    191  visible?: boolean;
    192  /**
    193   * Wait for the selected element to not be found in the DOM or to be hidden.
    194   * See {@link ElementHandle.isHidden} for the definition of element
    195   * invisibility.
    196   *
    197   * @defaultValue `false`
    198   */
    199  hidden?: boolean;
    200  /**
    201   * Maximum time to wait in milliseconds. Pass `0` to disable timeout.
    202   *
    203   * The default value can be changed by using {@link Page.setDefaultTimeout}
    204   *
    205   * @defaultValue `30_000` (30 seconds)
    206   */
    207  timeout?: number;
    208  /**
    209   * A signal object that allows you to cancel a waitForSelector call.
    210   */
    211  signal?: AbortSignal;
    212 }
    213 
    214 /**
    215 * @public
    216 */
    217 export interface GeolocationOptions {
    218  /**
    219   * Latitude between `-90` and `90`.
    220   */
    221  longitude: number;
    222  /**
    223   * Longitude between `-180` and `180`.
    224   */
    225  latitude: number;
    226  /**
    227   * Optional non-negative accuracy value.
    228   */
    229  accuracy?: number;
    230 }
    231 
    232 /**
    233 * A media feature to emulate.
    234 *
    235 * @public
    236 */
    237 export interface MediaFeature {
    238  /**
    239   * A name of the feature, for example, 'prefers-reduced-motion'.
    240   */
    241  name: string;
    242  /**
    243   * A value for the feature, for example, 'reduce'.
    244   */
    245  value: string;
    246 }
    247 
    248 /**
    249 * @public
    250 */
    251 export interface ScreenshotClip extends BoundingBox {
    252  /**
    253   * @defaultValue `1`
    254   */
    255  scale?: number;
    256 }
    257 
    258 /**
    259 * @public
    260 */
    261 export type ImageFormat = 'png' | 'jpeg' | 'webp';
    262 
    263 /**
    264 * @public
    265 */
    266 export type VideoFormat = 'webm' | 'gif' | 'mp4';
    267 
    268 /**
    269 * @public
    270 */
    271 export interface ScreenshotOptions {
    272  /**
    273   * @defaultValue `false`
    274   */
    275  optimizeForSpeed?: boolean;
    276  /**
    277   * @defaultValue `'png'`
    278   */
    279  type?: ImageFormat;
    280  /**
    281   * Quality of the image, between 0-100. Not applicable to `png` images.
    282   */
    283  quality?: number;
    284  /**
    285   * Capture the screenshot from the surface, rather than the view.
    286   *
    287   * @defaultValue `true`
    288   */
    289  fromSurface?: boolean;
    290  /**
    291   * When `true`, takes a screenshot of the full page.
    292   *
    293   * @defaultValue `false`
    294   */
    295  fullPage?: boolean;
    296  /**
    297   * Hides default white background and allows capturing screenshots with transparency.
    298   *
    299   * @defaultValue `false`
    300   */
    301  omitBackground?: boolean;
    302  /**
    303   * The file path to save the image to. The screenshot type will be inferred
    304   * from file extension. If path is a relative path, then it is resolved
    305   * relative to current working directory. If no path is provided, the image
    306   * won't be saved to the disk.
    307   */
    308  path?: `${string}.${ImageFormat}`;
    309  /**
    310   * Specifies the region of the page/element to clip.
    311   */
    312  clip?: ScreenshotClip;
    313  /**
    314   * Encoding of the image.
    315   *
    316   * @defaultValue `'binary'`
    317   */
    318  encoding?: 'base64' | 'binary';
    319  /**
    320   * Capture the screenshot beyond the viewport.
    321   *
    322   * @defaultValue `false` if there is no `clip`. `true` otherwise.
    323   */
    324  captureBeyondViewport?: boolean;
    325 }
    326 
    327 /**
    328 * @public
    329 * @experimental
    330 */
    331 export interface ScreencastOptions {
    332  /**
    333   * File path to save the screencast to.
    334   */
    335  path?: `${string}.${VideoFormat}`;
    336  /**
    337   * Specifies whether to overwrite output file,
    338   * or exit immediately if it already exists.
    339   *
    340   * @defaultValue `true`
    341   */
    342  overwrite?: boolean;
    343  /**
    344   * Specifies the output file format.
    345   *
    346   * @defaultValue `'webm'`
    347   */
    348  format?: VideoFormat;
    349  /**
    350   * Specifies the region of the viewport to crop.
    351   */
    352  crop?: BoundingBox;
    353  /**
    354   * Scales the output video.
    355   *
    356   * For example, `0.5` will shrink the width and height of the output video by
    357   * half. `2` will double the width and height of the output video.
    358   *
    359   * @defaultValue `1`
    360   */
    361  scale?: number;
    362  /**
    363   * Specifies the speed to record at.
    364   *
    365   * For example, `0.5` will slowdown the output video by 50%. `2` will double the
    366   * speed of the output video.
    367   *
    368   * @defaultValue `1`
    369   */
    370  speed?: number;
    371  /**
    372   * Specifies the frame rate in frames per second.
    373   *
    374   * @defaultValue `30` (`20` for GIF)
    375   */
    376  fps?: number;
    377  /**
    378   * Specifies the number of times to loop playback, from `0` to `Infinity`.
    379   * A value of `0` or `undefined` will disable looping.
    380   *
    381   * @defaultValue `undefined`
    382   */
    383  loop?: number;
    384  /**
    385   * Specifies the delay between iterations of a loop, in ms.
    386   * `-1` is a special value to re-use the previous delay.
    387   *
    388   * @defaultValue `-1`
    389   */
    390  delay?: number;
    391  /**
    392   * Specifies the recording
    393   * {@link https://trac.ffmpeg.org/wiki/Encode/VP9#constantq | quality}
    394   * Constant Rate Factor between `0`–`63`. Lower values mean better quality.
    395   *
    396   * @defaultValue `30`
    397   */
    398  quality?: number;
    399  /**
    400   * Specifies the maximum number of
    401   * {@link https://ffmpeg.org/ffmpeg-filters.html#palettegen | palette}
    402   * colors to quantize, with GIF limited to `256`.
    403   * Restrict the palette to only necessary colors to reduce output file size.
    404   *
    405   * @defaultValue `256`
    406   */
    407  colors?: number;
    408  /**
    409   * Path to the {@link https://ffmpeg.org/ | ffmpeg}.
    410   *
    411   * Required if `ffmpeg` is not in your PATH.
    412   *
    413   * @defaultValue `'ffmpeg'`
    414   */
    415  ffmpegPath?: string;
    416 }
    417 
    418 /**
    419 * @public
    420 */
    421 export interface QueryOptions {
    422  /**
    423   * Whether to run the query in isolation. When returning many elements
    424   * from {@link Page.$$} or similar methods, it might be useful to turn
    425   * off the isolation to improve performance. By default, the querying
    426   * code will be executed in a separate sandbox realm.
    427   *
    428   * @defaultValue `true`
    429   */
    430  isolate: boolean;
    431 }
    432 
    433 /**
    434 * All the events that a page instance may emit.
    435 *
    436 * @public
    437 */
    438 export const enum PageEvent {
    439  /**
    440   * Emitted when the page closes.
    441   */
    442  Close = 'close',
    443  /**
    444   * Emitted when JavaScript within the page calls one of console API methods,
    445   * e.g. `console.log` or `console.dir`. Also emitted if the page throws an
    446   * error or a warning.
    447   *
    448   * @remarks
    449   * A `console` event provides a {@link ConsoleMessage} representing the
    450   * console message that was logged.
    451   *
    452   * @example
    453   * An example of handling `console` event:
    454   *
    455   * ```ts
    456   * page.on('console', msg => {
    457   *   for (let i = 0; i < msg.args().length; ++i)
    458   *     console.log(`${i}: ${msg.args()[i]}`);
    459   * });
    460   * page.evaluate(() => console.log('hello', 5, {foo: 'bar'}));
    461   * ```
    462   */
    463  Console = 'console',
    464  /**
    465   * Emitted when a JavaScript dialog appears, such as `alert`, `prompt`,
    466   * `confirm` or `beforeunload`. Puppeteer can respond to the dialog via
    467   * {@link Dialog.accept} or {@link Dialog.dismiss}.
    468   */
    469  Dialog = 'dialog',
    470  /**
    471   * Emitted when the JavaScript
    472   * {@link https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded | DOMContentLoaded }
    473   * event is dispatched.
    474   */
    475  DOMContentLoaded = 'domcontentloaded',
    476  /**
    477   * Emitted when the page crashes. Will contain an `Error`.
    478   */
    479  Error = 'error',
    480  /** Emitted when a frame is attached. Will contain a {@link Frame}. */
    481  FrameAttached = 'frameattached',
    482  /** Emitted when a frame is detached. Will contain a {@link Frame}. */
    483  FrameDetached = 'framedetached',
    484  /**
    485   * Emitted when a frame is navigated to a new URL. Will contain a
    486   * {@link Frame}.
    487   */
    488  FrameNavigated = 'framenavigated',
    489  /**
    490   * Emitted when the JavaScript
    491   * {@link https://developer.mozilla.org/en-US/docs/Web/Events/load | load}
    492   * event is dispatched.
    493   */
    494  Load = 'load',
    495  /**
    496   * Emitted when the JavaScript code makes a call to `console.timeStamp`. For
    497   * the list of metrics see {@link Page.metrics | page.metrics}.
    498   *
    499   * @remarks
    500   * Contains an object with two properties:
    501   *
    502   * - `title`: the title passed to `console.timeStamp`
    503   * - `metrics`: object containing metrics as key/value pairs. The values will
    504   *   be `number`s.
    505   */
    506  Metrics = 'metrics',
    507  /**
    508   * Emitted when an uncaught exception happens within the page. Contains an
    509   * `Error`.
    510   */
    511  PageError = 'pageerror',
    512  /**
    513   * Emitted when the page opens a new tab or window.
    514   *
    515   * Contains a {@link Page} corresponding to the popup window.
    516   *
    517   * @example
    518   *
    519   * ```ts
    520   * const [popup] = await Promise.all([
    521   *   new Promise(resolve => page.once('popup', resolve)),
    522   *   page.click('a[target=_blank]'),
    523   * ]);
    524   * ```
    525   *
    526   * ```ts
    527   * const [popup] = await Promise.all([
    528   *   new Promise(resolve => page.once('popup', resolve)),
    529   *   page.evaluate(() => window.open('https://example.com')),
    530   * ]);
    531   * ```
    532   */
    533  Popup = 'popup',
    534  /**
    535   * Emitted when a page issues a request and contains a {@link HTTPRequest}.
    536   *
    537   * @remarks
    538   * The object is readonly. See {@link Page.setRequestInterception} for
    539   * intercepting and mutating requests.
    540   */
    541  Request = 'request',
    542  /**
    543   * Emitted when a request ended up loading from cache. Contains a
    544   * {@link HTTPRequest}.
    545   *
    546   * @remarks
    547   * For certain requests, might contain undefined.
    548   * {@link https://crbug.com/750469}
    549   */
    550  RequestServedFromCache = 'requestservedfromcache',
    551  /**
    552   * Emitted when a request fails, for example by timing out.
    553   *
    554   * Contains a {@link HTTPRequest}.
    555   *
    556   * @remarks
    557   * HTTP Error responses, such as 404 or 503, are still successful responses
    558   * from HTTP standpoint, so request will complete with `requestfinished` event
    559   * and not with `requestfailed`.
    560   */
    561  RequestFailed = 'requestfailed',
    562  /**
    563   * Emitted when a request finishes successfully. Contains a
    564   * {@link HTTPRequest}.
    565   */
    566  RequestFinished = 'requestfinished',
    567  /**
    568   * Emitted when a response is received. Contains a {@link HTTPResponse}.
    569   */
    570  Response = 'response',
    571  /**
    572   * Emitted when a dedicated
    573   * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}
    574   * is spawned by the page.
    575   */
    576  WorkerCreated = 'workercreated',
    577  /**
    578   * Emitted when a dedicated
    579   * {@link https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API | WebWorker}
    580   * is destroyed by the page.
    581   */
    582  WorkerDestroyed = 'workerdestroyed',
    583 }
    584 
    585 /**
    586 * Denotes the objects received by callback functions for page events.
    587 *
    588 * See {@link PageEvent} for more detail on the events and when they are
    589 * emitted.
    590 *
    591 * @public
    592 */
    593 export interface PageEvents extends Record<EventType, unknown> {
    594  [PageEvent.Close]: undefined;
    595  [PageEvent.Console]: ConsoleMessage;
    596  [PageEvent.Dialog]: Dialog;
    597  [PageEvent.DOMContentLoaded]: undefined;
    598  [PageEvent.Error]: Error;
    599  [PageEvent.FrameAttached]: Frame;
    600  [PageEvent.FrameDetached]: Frame;
    601  [PageEvent.FrameNavigated]: Frame;
    602  [PageEvent.Load]: undefined;
    603  [PageEvent.Metrics]: {title: string; metrics: Metrics};
    604  [PageEvent.PageError]: Error;
    605  [PageEvent.Popup]: Page | null;
    606  [PageEvent.Request]: HTTPRequest;
    607  [PageEvent.Response]: HTTPResponse;
    608  [PageEvent.RequestFailed]: HTTPRequest;
    609  [PageEvent.RequestFinished]: HTTPRequest;
    610  [PageEvent.RequestServedFromCache]: HTTPRequest;
    611  [PageEvent.WorkerCreated]: WebWorker;
    612  [PageEvent.WorkerDestroyed]: WebWorker;
    613 }
    614 
    615 /**
    616 * @public
    617 */
    618 export interface NewDocumentScriptEvaluation {
    619  identifier: string;
    620 }
    621 
    622 /**
    623 * @internal
    624 */
    625 export function setDefaultScreenshotOptions(options: ScreenshotOptions): void {
    626  options.optimizeForSpeed ??= false;
    627  options.type ??= 'png';
    628  options.fromSurface ??= true;
    629  options.fullPage ??= false;
    630  options.omitBackground ??= false;
    631  options.encoding ??= 'binary';
    632  options.captureBeyondViewport ??= true;
    633 }
    634 
    635 /**
    636 * Page provides methods to interact with a single tab or
    637 * {@link https://developer.chrome.com/extensions/background_pages | extension background page}
    638 * in the browser.
    639 *
    640 * :::note
    641 *
    642 * One Browser instance might have multiple Page instances.
    643 *
    644 * :::
    645 *
    646 * @example
    647 * This example creates a page, navigates it to a URL, and then saves a screenshot:
    648 *
    649 * ```ts
    650 * import puppeteer from 'puppeteer';
    651 *
    652 * (async () => {
    653 *   const browser = await puppeteer.launch();
    654 *   const page = await browser.newPage();
    655 *   await page.goto('https://example.com');
    656 *   await page.screenshot({path: 'screenshot.png'});
    657 *   await browser.close();
    658 * })();
    659 * ```
    660 *
    661 * The Page class extends from Puppeteer's {@link EventEmitter} class and will
    662 * emit various events which are documented in the {@link PageEvent} enum.
    663 *
    664 * @example
    665 * This example logs a message for a single page `load` event:
    666 *
    667 * ```ts
    668 * page.once('load', () => console.log('Page loaded!'));
    669 * ```
    670 *
    671 * To unsubscribe from events use the {@link EventEmitter.off} method:
    672 *
    673 * ```ts
    674 * function logRequest(interceptedRequest) {
    675 *   console.log('A request was made:', interceptedRequest.url());
    676 * }
    677 * page.on('request', logRequest);
    678 * // Sometime later...
    679 * page.off('request', logRequest);
    680 * ```
    681 *
    682 * @public
    683 */
    684 export abstract class Page extends EventEmitter<PageEvents> {
    685  /**
    686   * @internal
    687   */
    688  _isDragging = false;
    689  /**
    690   * @internal
    691   */
    692  _timeoutSettings = new TimeoutSettings();
    693 
    694  #requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
    695 
    696  #inflight$ = new ReplaySubject<number>(1);
    697 
    698  /**
    699   * @internal
    700   */
    701  constructor() {
    702    super();
    703 
    704    fromEmitterEvent(this, PageEvent.Request)
    705      .pipe(
    706        mergeMap(originalRequest => {
    707          return concat(
    708            of(1),
    709            merge(
    710              fromEmitterEvent(this, PageEvent.RequestFailed),
    711              fromEmitterEvent(this, PageEvent.RequestFinished),
    712              fromEmitterEvent(this, PageEvent.Response).pipe(
    713                map(response => {
    714                  return response.request();
    715                }),
    716              ),
    717            ).pipe(
    718              filter(request => {
    719                return request.id === originalRequest.id;
    720              }),
    721              take(1),
    722              map(() => {
    723                return -1;
    724              }),
    725            ),
    726          );
    727        }),
    728        mergeScan((acc, addend) => {
    729          return of(acc + addend);
    730        }, 0),
    731        takeUntil(fromEmitterEvent(this, PageEvent.Close)),
    732        startWith(0),
    733      )
    734      .subscribe(this.#inflight$);
    735  }
    736 
    737  /**
    738   * `true` if the service worker are being bypassed, `false` otherwise.
    739   */
    740  abstract isServiceWorkerBypassed(): boolean;
    741 
    742  /**
    743   * `true` if drag events are being intercepted, `false` otherwise.
    744   *
    745   * @deprecated We no longer support intercepting drag payloads. Use the new
    746   * drag APIs found on {@link ElementHandle} to drag (or just use the
    747   * {@link Page.mouse}).
    748   */
    749  abstract isDragInterceptionEnabled(): boolean;
    750 
    751  /**
    752   * `true` if the page has JavaScript enabled, `false` otherwise.
    753   */
    754  abstract isJavaScriptEnabled(): boolean;
    755 
    756  /**
    757   * Listen to page events.
    758   *
    759   * @remarks
    760   * This method exists to define event typings and handle proper wireup of
    761   * cooperative request interception. Actual event listening and dispatching is
    762   * delegated to {@link EventEmitter}.
    763   *
    764   * @internal
    765   */
    766  override on<K extends keyof EventsWithWildcard<PageEvents>>(
    767    type: K,
    768    handler: (event: EventsWithWildcard<PageEvents>[K]) => void,
    769  ): this {
    770    if (type !== PageEvent.Request) {
    771      return super.on(type, handler);
    772    }
    773    let wrapper = this.#requestHandlers.get(
    774      handler as (event: PageEvents[PageEvent.Request]) => void,
    775    );
    776    if (wrapper === undefined) {
    777      wrapper = (event: HTTPRequest) => {
    778        event.enqueueInterceptAction(() => {
    779          return handler(event as EventsWithWildcard<PageEvents>[K]);
    780        });
    781      };
    782      this.#requestHandlers.set(
    783        handler as (event: PageEvents[PageEvent.Request]) => void,
    784        wrapper,
    785      );
    786    }
    787    return super.on(
    788      type,
    789      wrapper as (event: EventsWithWildcard<PageEvents>[K]) => void,
    790    );
    791  }
    792 
    793  /**
    794   * @internal
    795   */
    796  override off<K extends keyof EventsWithWildcard<PageEvents>>(
    797    type: K,
    798    handler: (event: EventsWithWildcard<PageEvents>[K]) => void,
    799  ): this {
    800    if (type === PageEvent.Request) {
    801      handler =
    802        (this.#requestHandlers.get(
    803          handler as (
    804            event: EventsWithWildcard<PageEvents>[PageEvent.Request],
    805          ) => void,
    806        ) as (event: EventsWithWildcard<PageEvents>[K]) => void) || handler;
    807    }
    808    return super.off(type, handler);
    809  }
    810 
    811  /**
    812   * This method is typically coupled with an action that triggers file
    813   * choosing.
    814   *
    815   * :::caution
    816   *
    817   * This must be called before the file chooser is launched. It will not return
    818   * a currently active file chooser.
    819   *
    820   * :::
    821   *
    822   * :::caution
    823   *
    824   * Interception of file dialogs triggered via DOM APIs such as
    825   * window.showOpenFilePicker is currently not supported.
    826   *
    827   * :::
    828   *
    829   * @remarks
    830   * In the "headful" browser, this method results in the native file picker
    831   * dialog `not showing up` for the user.
    832   *
    833   * @example
    834   * The following example clicks a button that issues a file chooser
    835   * and then responds with `/tmp/myfile.pdf` as if a user has selected this file.
    836   *
    837   * ```ts
    838   * const [fileChooser] = await Promise.all([
    839   *   page.waitForFileChooser(),
    840   *   page.click('#upload-file-button'),
    841   *   // some button that triggers file selection
    842   * ]);
    843   * await fileChooser.accept(['/tmp/myfile.pdf']);
    844   * ```
    845   */
    846  abstract waitForFileChooser(
    847    options?: WaitTimeoutOptions,
    848  ): Promise<FileChooser>;
    849 
    850  /**
    851   * Sets the page's geolocation.
    852   *
    853   * @remarks
    854   * Consider using {@link BrowserContext.overridePermissions} to grant
    855   * permissions for the page to read its geolocation.
    856   *
    857   * @example
    858   *
    859   * ```ts
    860   * await page.setGeolocation({latitude: 59.95, longitude: 30.31667});
    861   * ```
    862   */
    863  abstract setGeolocation(options: GeolocationOptions): Promise<void>;
    864 
    865  /**
    866   * A target this page was created from.
    867   *
    868   * @deprecated Use {@link Page.createCDPSession} directly.
    869   */
    870  abstract target(): Target;
    871 
    872  /**
    873   * Get the browser the page belongs to.
    874   */
    875  abstract browser(): Browser;
    876 
    877  /**
    878   * Get the browser context that the page belongs to.
    879   */
    880  abstract browserContext(): BrowserContext;
    881 
    882  /**
    883   * The page's main frame.
    884   */
    885  abstract mainFrame(): Frame;
    886 
    887  /**
    888   * Creates a Chrome Devtools Protocol session attached to the page.
    889   */
    890  abstract createCDPSession(): Promise<CDPSession>;
    891 
    892  /**
    893   * {@inheritDoc Keyboard}
    894   */
    895  abstract get keyboard(): Keyboard;
    896 
    897  /**
    898   * {@inheritDoc Touchscreen}
    899   */
    900  abstract get touchscreen(): Touchscreen;
    901 
    902  /**
    903   * {@inheritDoc Coverage}
    904   */
    905  abstract get coverage(): Coverage;
    906 
    907  /**
    908   * {@inheritDoc Tracing}
    909   */
    910  abstract get tracing(): Tracing;
    911 
    912  /**
    913   * {@inheritDoc Accessibility}
    914   */
    915  get accessibility(): Accessibility {
    916    return this.mainFrame().accessibility;
    917  }
    918 
    919  /**
    920   * An array of all frames attached to the page.
    921   */
    922  abstract frames(): Frame[];
    923 
    924  /**
    925   * All of the dedicated {@link
    926   * https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API |
    927   * WebWorkers} associated with the page.
    928   *
    929   * @remarks
    930   * This does not contain ServiceWorkers
    931   */
    932  abstract workers(): WebWorker[];
    933 
    934  /**
    935   * Activating request interception enables {@link HTTPRequest.abort},
    936   * {@link HTTPRequest.continue} and {@link HTTPRequest.respond} methods. This
    937   * provides the capability to modify network requests that are made by a page.
    938   *
    939   * Once request interception is enabled, every request will stall unless it's
    940   * continued, responded or aborted; or completed using the browser cache.
    941   *
    942   * See the
    943   * {@link https://pptr.dev/guides/network-interception|Request interception guide}
    944   * for more details.
    945   *
    946   * @example
    947   * An example of a naïve request interceptor that aborts all image requests:
    948   *
    949   * ```ts
    950   * import puppeteer from 'puppeteer';
    951   * (async () => {
    952   *   const browser = await puppeteer.launch();
    953   *   const page = await browser.newPage();
    954   *   await page.setRequestInterception(true);
    955   *   page.on('request', interceptedRequest => {
    956   *     if (
    957   *       interceptedRequest.url().endsWith('.png') ||
    958   *       interceptedRequest.url().endsWith('.jpg')
    959   *     )
    960   *       interceptedRequest.abort();
    961   *     else interceptedRequest.continue();
    962   *   });
    963   *   await page.goto('https://example.com');
    964   *   await browser.close();
    965   * })();
    966   * ```
    967   *
    968   * @param value - Whether to enable request interception.
    969   */
    970  abstract setRequestInterception(value: boolean): Promise<void>;
    971 
    972  /**
    973   * Toggles ignoring of service worker for each request.
    974   *
    975   * @param bypass - Whether to bypass service worker and load from network.
    976   */
    977  abstract setBypassServiceWorker(bypass: boolean): Promise<void>;
    978 
    979  /**
    980   * @param enabled - Whether to enable drag interception.
    981   *
    982   * @deprecated We no longer support intercepting drag payloads. Use the new
    983   * drag APIs found on {@link ElementHandle} to drag (or just use the
    984   * {@link Page.mouse}).
    985   */
    986  abstract setDragInterception(enabled: boolean): Promise<void>;
    987 
    988  /**
    989   * Sets the network connection to offline.
    990   *
    991   * It does not change the parameters used in {@link Page.emulateNetworkConditions}
    992   *
    993   * @param enabled - When `true`, enables offline mode for the page.
    994   */
    995  abstract setOfflineMode(enabled: boolean): Promise<void>;
    996 
    997  /**
    998   * This does not affect WebSockets and WebRTC PeerConnections (see
    999   * https://crbug.com/563644). To set the page offline, you can use
   1000   * {@link Page.setOfflineMode}.
   1001   *
   1002   * A list of predefined network conditions can be used by importing
   1003   * {@link PredefinedNetworkConditions}.
   1004   *
   1005   * @example
   1006   *
   1007   * ```ts
   1008   * import {PredefinedNetworkConditions} from 'puppeteer';
   1009   * const slow3G = PredefinedNetworkConditions['Slow 3G'];
   1010   *
   1011   * (async () => {
   1012   *   const browser = await puppeteer.launch();
   1013   *   const page = await browser.newPage();
   1014   *   await page.emulateNetworkConditions(slow3G);
   1015   *   await page.goto('https://www.google.com');
   1016   *   // other actions...
   1017   *   await browser.close();
   1018   * })();
   1019   * ```
   1020   *
   1021   * @param networkConditions - Passing `null` disables network condition
   1022   * emulation.
   1023   */
   1024  abstract emulateNetworkConditions(
   1025    networkConditions: NetworkConditions | null,
   1026  ): Promise<void>;
   1027 
   1028  /**
   1029   * This setting will change the default maximum navigation time for the
   1030   * following methods and related shortcuts:
   1031   *
   1032   * - {@link Page.goBack | page.goBack(options)}
   1033   *
   1034   * - {@link Page.goForward | page.goForward(options)}
   1035   *
   1036   * - {@link Page.goto | page.goto(url,options)}
   1037   *
   1038   * - {@link Page.reload | page.reload(options)}
   1039   *
   1040   * - {@link Page.setContent | page.setContent(html,options)}
   1041   *
   1042   * - {@link Page.waitForNavigation | page.waitForNavigation(options)}
   1043   *   @param timeout - Maximum navigation time in milliseconds.
   1044   */
   1045  abstract setDefaultNavigationTimeout(timeout: number): void;
   1046 
   1047  /**
   1048   * @param timeout - Maximum time in milliseconds.
   1049   */
   1050  abstract setDefaultTimeout(timeout: number): void;
   1051 
   1052  /**
   1053   * Maximum time in milliseconds.
   1054   */
   1055  abstract getDefaultTimeout(): number;
   1056 
   1057  /**
   1058   * Maximum navigation time in milliseconds.
   1059   */
   1060  abstract getDefaultNavigationTimeout(): number;
   1061 
   1062  /**
   1063   * Creates a locator for the provided selector. See {@link Locator} for
   1064   * details and supported actions.
   1065   *
   1066   * @param selector -
   1067   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1068   * to query the page for.
   1069   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1070   * can be passed as-is and a
   1071   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1072   * allows querying by
   1073   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1074   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1075   * and
   1076   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1077   * and
   1078   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1079   * Alternatively, you can specify the selector type using a
   1080   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1081   */
   1082  locator<Selector extends string>(
   1083    selector: Selector,
   1084  ): Locator<NodeFor<Selector>>;
   1085 
   1086  /**
   1087   * Creates a locator for the provided function. See {@link Locator} for
   1088   * details and supported actions.
   1089   *
   1090   * @param selector -
   1091   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1092   * to query the page for.
   1093   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1094   * can be passed as-is and a
   1095   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1096   * allows querying by
   1097   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1098   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1099   * and
   1100   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1101   * and
   1102   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1103   * Alternatively, you can specify the selector type using a
   1104   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1105   */
   1106  locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>;
   1107  locator<Selector extends string, Ret>(
   1108    selectorOrFunc: Selector | (() => Awaitable<Ret>),
   1109  ): Locator<NodeFor<Selector>> | Locator<Ret> {
   1110    if (typeof selectorOrFunc === 'string') {
   1111      return NodeLocator.create(this, selectorOrFunc);
   1112    } else {
   1113      return FunctionLocator.create(this, selectorOrFunc);
   1114    }
   1115  }
   1116 
   1117  /**
   1118   * A shortcut for {@link Locator.race} that does not require static imports.
   1119   *
   1120   * @internal
   1121   */
   1122  locatorRace<Locators extends readonly unknown[] | []>(
   1123    locators: Locators,
   1124  ): Locator<AwaitedLocator<Locators[number]>> {
   1125    return Locator.race(locators);
   1126  }
   1127 
   1128  /**
   1129   * Finds the first element that matches the selector. If no element matches
   1130   * the selector, the return value resolves to `null`.
   1131   *
   1132   * @param selector -
   1133   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1134   * to query the page for.
   1135   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1136   * can be passed as-is and a
   1137   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1138   * allows querying by
   1139   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1140   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1141   * and
   1142   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1143   * and
   1144   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1145   * Alternatively, you can specify the selector type using a
   1146   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1147   *
   1148   * @remarks
   1149   *
   1150   * Shortcut for {@link Frame.$ | Page.mainFrame().$(selector) }.
   1151   */
   1152  async $<Selector extends string>(
   1153    selector: Selector,
   1154  ): Promise<ElementHandle<NodeFor<Selector>> | null> {
   1155    return await this.mainFrame().$(selector);
   1156  }
   1157 
   1158  /**
   1159   * Finds elements on the page that match the selector. If no elements
   1160   * match the selector, the return value resolves to `[]`.
   1161   *
   1162   * @param selector -
   1163   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1164   * to query the page for.
   1165   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1166   * can be passed as-is and a
   1167   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1168   * allows querying by
   1169   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1170   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1171   * and
   1172   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1173   * and
   1174   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1175   * Alternatively, you can specify the selector type using a
   1176   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1177   *
   1178   * @remarks
   1179   *
   1180   * Shortcut for {@link Frame.$$ | Page.mainFrame().$$(selector) }.
   1181   */
   1182  async $$<Selector extends string>(
   1183    selector: Selector,
   1184    options?: QueryOptions,
   1185  ): Promise<Array<ElementHandle<NodeFor<Selector>>>> {
   1186    return await this.mainFrame().$$(selector, options);
   1187  }
   1188 
   1189  /**
   1190   * @remarks
   1191   *
   1192   * The only difference between {@link Page.evaluate | page.evaluate} and
   1193   * `page.evaluateHandle` is that `evaluateHandle` will return the value
   1194   * wrapped in an in-page object.
   1195   *
   1196   * If the function passed to `page.evaluateHandle` returns a Promise, the
   1197   * function will wait for the promise to resolve and return its value.
   1198   *
   1199   * You can pass a string instead of a function (although functions are
   1200   * recommended as they are easier to debug and use with TypeScript):
   1201   *
   1202   * @example
   1203   *
   1204   * ```ts
   1205   * const aHandle = await page.evaluateHandle('document');
   1206   * ```
   1207   *
   1208   * @example
   1209   * {@link JSHandle} instances can be passed as arguments to the `pageFunction`:
   1210   *
   1211   * ```ts
   1212   * const aHandle = await page.evaluateHandle(() => document.body);
   1213   * const resultHandle = await page.evaluateHandle(
   1214   *   body => body.innerHTML,
   1215   *   aHandle,
   1216   * );
   1217   * console.log(await resultHandle.jsonValue());
   1218   * await resultHandle.dispose();
   1219   * ```
   1220   *
   1221   * Most of the time this function returns a {@link JSHandle},
   1222   * but if `pageFunction` returns a reference to an element,
   1223   * you instead get an {@link ElementHandle} back:
   1224   *
   1225   * @example
   1226   *
   1227   * ```ts
   1228   * const button = await page.evaluateHandle(() =>
   1229   *   document.querySelector('button'),
   1230   * );
   1231   * // can call `click` because `button` is an `ElementHandle`
   1232   * await button.click();
   1233   * ```
   1234   *
   1235   * The TypeScript definitions assume that `evaluateHandle` returns
   1236   * a `JSHandle`, but if you know it's going to return an
   1237   * `ElementHandle`, pass it as the generic argument:
   1238   *
   1239   * ```ts
   1240   * const button = await page.evaluateHandle<ElementHandle>(...);
   1241   * ```
   1242   *
   1243   * @param pageFunction - a function that is run within the page
   1244   * @param args - arguments to be passed to the pageFunction
   1245   */
   1246  async evaluateHandle<
   1247    Params extends unknown[],
   1248    Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
   1249  >(
   1250    pageFunction: Func | string,
   1251    ...args: Params
   1252  ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
   1253    pageFunction = withSourcePuppeteerURLIfNone(
   1254      this.evaluateHandle.name,
   1255      pageFunction,
   1256    );
   1257    return await this.mainFrame().evaluateHandle(pageFunction, ...args);
   1258  }
   1259 
   1260  /**
   1261   * This method iterates the JavaScript heap and finds all objects with the
   1262   * given prototype.
   1263   *
   1264   * @example
   1265   *
   1266   * ```ts
   1267   * // Create a Map object
   1268   * await page.evaluate(() => (window.map = new Map()));
   1269   * // Get a handle to the Map object prototype
   1270   * const mapPrototype = await page.evaluateHandle(() => Map.prototype);
   1271   * // Query all map instances into an array
   1272   * const mapInstances = await page.queryObjects(mapPrototype);
   1273   * // Count amount of map objects in heap
   1274   * const count = await page.evaluate(maps => maps.length, mapInstances);
   1275   * await mapInstances.dispose();
   1276   * await mapPrototype.dispose();
   1277   * ```
   1278   *
   1279   * @param prototypeHandle - a handle to the object prototype.
   1280   * @returns Promise which resolves to a handle to an array of objects with
   1281   * this prototype.
   1282   */
   1283  abstract queryObjects<Prototype>(
   1284    prototypeHandle: JSHandle<Prototype>,
   1285  ): Promise<JSHandle<Prototype[]>>;
   1286 
   1287  /**
   1288   * This method finds the first element within the page that matches the selector
   1289   * and passes the result as the first argument to the `pageFunction`.
   1290   *
   1291   * @remarks
   1292   *
   1293   * If no element is found matching `selector`, the method will throw an error.
   1294   *
   1295   * If `pageFunction` returns a promise `$eval` will wait for the promise to
   1296   * resolve and then return its value.
   1297   *
   1298   * @example
   1299   *
   1300   * ```ts
   1301   * const searchValue = await page.$eval('#search', el => el.value);
   1302   * const preloadHref = await page.$eval('link[rel=preload]', el => el.href);
   1303   * const html = await page.$eval('.main-container', el => el.outerHTML);
   1304   * ```
   1305   *
   1306   * If you are using TypeScript, you may have to provide an explicit type to the
   1307   * first argument of the `pageFunction`.
   1308   * By default it is typed as `Element`, but you may need to provide a more
   1309   * specific sub-type:
   1310   *
   1311   * @example
   1312   *
   1313   * ```ts
   1314   * // if you don't provide HTMLInputElement here, TS will error
   1315   * // as `value` is not on `Element`
   1316   * const searchValue = await page.$eval(
   1317   *   '#search',
   1318   *   (el: HTMLInputElement) => el.value,
   1319   * );
   1320   * ```
   1321   *
   1322   * The compiler should be able to infer the return type
   1323   * from the `pageFunction` you provide. If it is unable to, you can use the generic
   1324   * type to tell the compiler what return type you expect from `$eval`:
   1325   *
   1326   * @example
   1327   *
   1328   * ```ts
   1329   * // The compiler can infer the return type in this case, but if it can't
   1330   * // or if you want to be more explicit, provide it as the generic type.
   1331   * const searchValue = await page.$eval<string>(
   1332   *   '#search',
   1333   *   (el: HTMLInputElement) => el.value,
   1334   * );
   1335   * ```
   1336   *
   1337   * @param selector -
   1338   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1339   * to query the page for.
   1340   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1341   * can be passed as-is and a
   1342   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1343   * allows querying by
   1344   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1345   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1346   * and
   1347   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1348   * and
   1349   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1350   * Alternatively, you can specify the selector type using a
   1351   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1352   * @param pageFunction - the function to be evaluated in the page context.
   1353   * Will be passed the result of the element matching the selector as its
   1354   * first argument.
   1355   * @param args - any additional arguments to pass through to `pageFunction`.
   1356   *
   1357   * @returns The result of calling `pageFunction`. If it returns an element it
   1358   * is wrapped in an {@link ElementHandle}, else the raw value itself is
   1359   * returned.
   1360   */
   1361  async $eval<
   1362    Selector extends string,
   1363    Params extends unknown[],
   1364    Func extends EvaluateFuncWith<NodeFor<Selector>, Params> = EvaluateFuncWith<
   1365      NodeFor<Selector>,
   1366      Params
   1367    >,
   1368  >(
   1369    selector: Selector,
   1370    pageFunction: Func | string,
   1371    ...args: Params
   1372  ): Promise<Awaited<ReturnType<Func>>> {
   1373    pageFunction = withSourcePuppeteerURLIfNone(this.$eval.name, pageFunction);
   1374    return await this.mainFrame().$eval(selector, pageFunction, ...args);
   1375  }
   1376 
   1377  /**
   1378   * This method returns all elements matching the selector and passes the
   1379   * resulting array as the first argument to the `pageFunction`.
   1380   *
   1381   * @remarks
   1382   * If `pageFunction` returns a promise `$$eval` will wait for the promise to
   1383   * resolve and then return its value.
   1384   *
   1385   * @example
   1386   *
   1387   * ```ts
   1388   * // get the amount of divs on the page
   1389   * const divCount = await page.$$eval('div', divs => divs.length);
   1390   *
   1391   * // get the text content of all the `.options` elements:
   1392   * const options = await page.$$eval('div > span.options', options => {
   1393   *   return options.map(option => option.textContent);
   1394   * });
   1395   * ```
   1396   *
   1397   * If you are using TypeScript, you may have to provide an explicit type to the
   1398   * first argument of the `pageFunction`.
   1399   * By default it is typed as `Element[]`, but you may need to provide a more
   1400   * specific sub-type:
   1401   *
   1402   * @example
   1403   *
   1404   * ```ts
   1405   * await page.$$eval('input', elements => {
   1406   *   return elements.map(e => e.value);
   1407   * });
   1408   * ```
   1409   *
   1410   * The compiler should be able to infer the return type
   1411   * from the `pageFunction` you provide. If it is unable to, you can use the generic
   1412   * type to tell the compiler what return type you expect from `$$eval`:
   1413   *
   1414   * @example
   1415   *
   1416   * ```ts
   1417   * const allInputValues = await page.$$eval('input', elements =>
   1418   *   elements.map(e => e.textContent),
   1419   * );
   1420   * ```
   1421   *
   1422   * @param selector -
   1423   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   1424   * to query the page for.
   1425   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   1426   * can be passed as-is and a
   1427   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   1428   * allows querying by
   1429   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   1430   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   1431   * and
   1432   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   1433   * and
   1434   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   1435   * Alternatively, you can specify the selector type using a
   1436   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   1437   * @param pageFunction - the function to be evaluated in the page context.
   1438   * Will be passed an array of matching elements as its first argument.
   1439   * @param args - any additional arguments to pass through to `pageFunction`.
   1440   *
   1441   * @returns The result of calling `pageFunction`. If it returns an element it
   1442   * is wrapped in an {@link ElementHandle}, else the raw value itself is
   1443   * returned.
   1444   */
   1445  async $$eval<
   1446    Selector extends string,
   1447    Params extends unknown[],
   1448    Func extends EvaluateFuncWith<
   1449      Array<NodeFor<Selector>>,
   1450      Params
   1451    > = EvaluateFuncWith<Array<NodeFor<Selector>>, Params>,
   1452  >(
   1453    selector: Selector,
   1454    pageFunction: Func | string,
   1455    ...args: Params
   1456  ): Promise<Awaited<ReturnType<Func>>> {
   1457    pageFunction = withSourcePuppeteerURLIfNone(this.$$eval.name, pageFunction);
   1458    return await this.mainFrame().$$eval(selector, pageFunction, ...args);
   1459  }
   1460 
   1461  /**
   1462   * If no URLs are specified, this method returns cookies for the
   1463   * current page URL. If URLs are specified, only cookies for those
   1464   * URLs are returned.
   1465   *
   1466   * @deprecated Page-level cookie API is deprecated. Use
   1467   * {@link Browser.cookies} or {@link BrowserContext.cookies} instead.
   1468   */
   1469  abstract cookies(...urls: string[]): Promise<Cookie[]>;
   1470 
   1471  /**
   1472   * @deprecated Page-level cookie API is deprecated. Use
   1473   * {@link Browser.deleteCookie} or {@link BrowserContext.deleteCookie}
   1474   * instead.
   1475   */
   1476  abstract deleteCookie(...cookies: DeleteCookiesRequest[]): Promise<void>;
   1477 
   1478  /**
   1479   * @example
   1480   *
   1481   *```ts
   1482   * await page.setCookie(cookieObject1, cookieObject2);
   1483   *```
   1484   *
   1485   * @deprecated Page-level cookie API is deprecated. Use
   1486   * {@link Browser.setCookie} or {@link BrowserContext.setCookie}
   1487   * instead.
   1488   */
   1489  abstract setCookie(...cookies: CookieParam[]): Promise<void>;
   1490 
   1491  /**
   1492   * Adds a `<script>` tag into the page with the desired URL or content.
   1493   *
   1494   * @remarks
   1495   * Shortcut for
   1496   * {@link Frame.addScriptTag | page.mainFrame().addScriptTag(options)}.
   1497   *
   1498   * @param options - Options for the script.
   1499   * @returns An {@link ElementHandle | element handle} to the injected
   1500   * `<script>` element.
   1501   */
   1502  async addScriptTag(
   1503    options: FrameAddScriptTagOptions,
   1504  ): Promise<ElementHandle<HTMLScriptElement>> {
   1505    return await this.mainFrame().addScriptTag(options);
   1506  }
   1507 
   1508  /**
   1509   * Adds a `<link rel="stylesheet">` tag into the page with the desired URL or
   1510   * a `<style type="text/css">` tag with the content.
   1511   *
   1512   * Shortcut for
   1513   * {@link Frame.(addStyleTag:2) | page.mainFrame().addStyleTag(options)}.
   1514   *
   1515   * @returns An {@link ElementHandle | element handle} to the injected `<link>`
   1516   * or `<style>` element.
   1517   */
   1518  async addStyleTag(
   1519    options: Omit<FrameAddStyleTagOptions, 'url'>,
   1520  ): Promise<ElementHandle<HTMLStyleElement>>;
   1521  async addStyleTag(
   1522    options: FrameAddStyleTagOptions,
   1523  ): Promise<ElementHandle<HTMLLinkElement>>;
   1524  async addStyleTag(
   1525    options: FrameAddStyleTagOptions,
   1526  ): Promise<ElementHandle<HTMLStyleElement | HTMLLinkElement>> {
   1527    return await this.mainFrame().addStyleTag(options);
   1528  }
   1529 
   1530  /**
   1531   * The method adds a function called `name` on the page's `window` object.
   1532   * When called, the function executes `puppeteerFunction` in node.js and
   1533   * returns a `Promise` which resolves to the return value of
   1534   * `puppeteerFunction`.
   1535   *
   1536   * If the puppeteerFunction returns a `Promise`, it will be awaited.
   1537   *
   1538   * :::note
   1539   *
   1540   * Functions installed via `page.exposeFunction` survive navigations.
   1541   *
   1542   * :::
   1543   *
   1544   * @example
   1545   * An example of adding an `md5` function into the page:
   1546   *
   1547   * ```ts
   1548   * import puppeteer from 'puppeteer';
   1549   * import crypto from 'crypto';
   1550   *
   1551   * (async () => {
   1552   *   const browser = await puppeteer.launch();
   1553   *   const page = await browser.newPage();
   1554   *   page.on('console', msg => console.log(msg.text()));
   1555   *   await page.exposeFunction('md5', text =>
   1556   *     crypto.createHash('md5').update(text).digest('hex'),
   1557   *   );
   1558   *   await page.evaluate(async () => {
   1559   *     // use window.md5 to compute hashes
   1560   *     const myString = 'PUPPETEER';
   1561   *     const myHash = await window.md5(myString);
   1562   *     console.log(`md5 of ${myString} is ${myHash}`);
   1563   *   });
   1564   *   await browser.close();
   1565   * })();
   1566   * ```
   1567   *
   1568   * @example
   1569   * An example of adding a `window.readfile` function into the page:
   1570   *
   1571   * ```ts
   1572   * import puppeteer from 'puppeteer';
   1573   * import fs from 'node:fs';
   1574   *
   1575   * (async () => {
   1576   *   const browser = await puppeteer.launch();
   1577   *   const page = await browser.newPage();
   1578   *   page.on('console', msg => console.log(msg.text()));
   1579   *   await page.exposeFunction('readfile', async filePath => {
   1580   *     return new Promise((resolve, reject) => {
   1581   *       fs.readFile(filePath, 'utf8', (err, text) => {
   1582   *         if (err) reject(err);
   1583   *         else resolve(text);
   1584   *       });
   1585   *     });
   1586   *   });
   1587   *   await page.evaluate(async () => {
   1588   *     // use window.readfile to read contents of a file
   1589   *     const content = await window.readfile('/etc/hosts');
   1590   *     console.log(content);
   1591   *   });
   1592   *   await browser.close();
   1593   * })();
   1594   * ```
   1595   *
   1596   * @param name - Name of the function on the window object
   1597   * @param pptrFunction - Callback function which will be called in Puppeteer's
   1598   * context.
   1599   */
   1600  abstract exposeFunction(
   1601    name: string,
   1602    // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
   1603    pptrFunction: Function | {default: Function},
   1604  ): Promise<void>;
   1605 
   1606  /**
   1607   * The method removes a previously added function via ${@link Page.exposeFunction}
   1608   * called `name` from the page's `window` object.
   1609   */
   1610  abstract removeExposedFunction(name: string): Promise<void>;
   1611 
   1612  /**
   1613   * Provide credentials for `HTTP authentication`.
   1614   *
   1615   * :::note
   1616   *
   1617   * Request interception will be turned on behind the scenes to
   1618   * implement authentication. This might affect performance.
   1619   *
   1620   * :::
   1621   *
   1622   * @remarks
   1623   * To disable authentication, pass `null`.
   1624   */
   1625  abstract authenticate(credentials: Credentials | null): Promise<void>;
   1626 
   1627  /**
   1628   * The extra HTTP headers will be sent with every request the page initiates.
   1629   *
   1630   * :::tip
   1631   *
   1632   * All HTTP header names are lowercased. (HTTP headers are
   1633   * case-insensitive, so this shouldn’t impact your server code.)
   1634   *
   1635   * :::
   1636   *
   1637   * :::note
   1638   *
   1639   * page.setExtraHTTPHeaders does not guarantee the order of headers in
   1640   * the outgoing requests.
   1641   *
   1642   * :::
   1643   *
   1644   * @param headers - An object containing additional HTTP headers to be sent
   1645   * with every request. All header values must be strings.
   1646   */
   1647  abstract setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;
   1648 
   1649  /**
   1650   * @param userAgent - Specific user agent to use in this page
   1651   * @param userAgentData - Specific user agent client hint data to use in this
   1652   * page
   1653   * @returns Promise which resolves when the user agent is set.
   1654   */
   1655  abstract setUserAgent(
   1656    userAgent: string,
   1657    userAgentMetadata?: Protocol.Emulation.UserAgentMetadata,
   1658  ): Promise<void>;
   1659 
   1660  /**
   1661   * Object containing metrics as key/value pairs.
   1662   *
   1663   * @returns
   1664   *
   1665   * - `Timestamp` : The timestamp when the metrics sample was taken.
   1666   *
   1667   * - `Documents` : Number of documents in the page.
   1668   *
   1669   * - `Frames` : Number of frames in the page.
   1670   *
   1671   * - `JSEventListeners` : Number of events in the page.
   1672   *
   1673   * - `Nodes` : Number of DOM nodes in the page.
   1674   *
   1675   * - `LayoutCount` : Total number of full or partial page layout.
   1676   *
   1677   * - `RecalcStyleCount` : Total number of page style recalculations.
   1678   *
   1679   * - `LayoutDuration` : Combined durations of all page layouts.
   1680   *
   1681   * - `RecalcStyleDuration` : Combined duration of all page style
   1682   *   recalculations.
   1683   *
   1684   * - `ScriptDuration` : Combined duration of JavaScript execution.
   1685   *
   1686   * - `TaskDuration` : Combined duration of all tasks performed by the browser.
   1687   *
   1688   * - `JSHeapUsedSize` : Used JavaScript heap size.
   1689   *
   1690   * - `JSHeapTotalSize` : Total JavaScript heap size.
   1691   *
   1692   * @remarks
   1693   * All timestamps are in monotonic time: monotonically increasing time
   1694   * in seconds since an arbitrary point in the past.
   1695   */
   1696  abstract metrics(): Promise<Metrics>;
   1697 
   1698  /**
   1699   * The page's URL.
   1700   *
   1701   * @remarks
   1702   *
   1703   * Shortcut for {@link Frame.url | page.mainFrame().url()}.
   1704   */
   1705  url(): string {
   1706    return this.mainFrame().url();
   1707  }
   1708 
   1709  /**
   1710   * The full HTML contents of the page, including the DOCTYPE.
   1711   */
   1712  async content(): Promise<string> {
   1713    return await this.mainFrame().content();
   1714  }
   1715 
   1716  /**
   1717   * Set the content of the page.
   1718   *
   1719   * @param html - HTML markup to assign to the page.
   1720   * @param options - Parameters that has some properties.
   1721   */
   1722  async setContent(html: string, options?: WaitForOptions): Promise<void> {
   1723    await this.mainFrame().setContent(html, options);
   1724  }
   1725 
   1726  /**
   1727   * {@inheritDoc Frame.goto}
   1728   */
   1729  async goto(url: string, options?: GoToOptions): Promise<HTTPResponse | null> {
   1730    return await this.mainFrame().goto(url, options);
   1731  }
   1732 
   1733  /**
   1734   * Reloads the page.
   1735   *
   1736   * @param options - Options to configure waiting behavior.
   1737   * @returns A promise which resolves to the main resource response. In case of
   1738   * multiple redirects, the navigation will resolve with the response of the
   1739   * last redirect.
   1740   */
   1741  abstract reload(options?: WaitForOptions): Promise<HTTPResponse | null>;
   1742 
   1743  /**
   1744   * Waits for the page to navigate to a new URL or to reload. It is useful when
   1745   * you run code that will indirectly cause the page to navigate.
   1746   *
   1747   * @example
   1748   *
   1749   * ```ts
   1750   * const [response] = await Promise.all([
   1751   *   page.waitForNavigation(), // The promise resolves after navigation has finished
   1752   *   page.click('a.my-link'), // Clicking the link will indirectly cause a navigation
   1753   * ]);
   1754   * ```
   1755   *
   1756   * @remarks
   1757   *
   1758   * Usage of the
   1759   * {@link https://developer.mozilla.org/en-US/docs/Web/API/History_API | History API}
   1760   * to change the URL is considered a navigation.
   1761   *
   1762   * @param options - Navigation parameters which might have the following
   1763   * properties:
   1764   * @returns A `Promise` which resolves to the main resource response.
   1765   *
   1766   * - In case of multiple redirects, the navigation will resolve with the
   1767   *   response of the last redirect.
   1768   * - In case of navigation to a different anchor or navigation due to History
   1769   *   API usage, the navigation will resolve with `null`.
   1770   */
   1771  async waitForNavigation(
   1772    options: WaitForOptions = {},
   1773  ): Promise<HTTPResponse | null> {
   1774    return await this.mainFrame().waitForNavigation(options);
   1775  }
   1776 
   1777  /**
   1778   * @param urlOrPredicate - A URL or predicate to wait for
   1779   * @param options - Optional waiting parameters
   1780   * @returns Promise which resolves to the matched request
   1781   * @example
   1782   *
   1783   * ```ts
   1784   * const firstRequest = await page.waitForRequest(
   1785   *   'https://example.com/resource',
   1786   * );
   1787   * const finalRequest = await page.waitForRequest(
   1788   *   request => request.url() === 'https://example.com',
   1789   * );
   1790   * return finalRequest.response()?.ok();
   1791   * ```
   1792   *
   1793   * @remarks
   1794   * Optional Waiting Parameters have:
   1795   *
   1796   * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds, pass
   1797   *   `0` to disable the timeout. The default value can be changed by using the
   1798   *   {@link Page.setDefaultTimeout} method.
   1799   */
   1800  waitForRequest(
   1801    urlOrPredicate: string | AwaitablePredicate<HTTPRequest>,
   1802    options: WaitTimeoutOptions = {},
   1803  ): Promise<HTTPRequest> {
   1804    const {timeout: ms = this._timeoutSettings.timeout(), signal} = options;
   1805    if (typeof urlOrPredicate === 'string') {
   1806      const url = urlOrPredicate;
   1807      urlOrPredicate = (request: HTTPRequest) => {
   1808        return request.url() === url;
   1809      };
   1810    }
   1811    const observable$ = fromEmitterEvent(this, PageEvent.Request).pipe(
   1812      filterAsync(urlOrPredicate),
   1813      raceWith(
   1814        timeout(ms),
   1815        fromAbortSignal(signal),
   1816        fromEmitterEvent(this, PageEvent.Close).pipe(
   1817          map(() => {
   1818            throw new TargetCloseError('Page closed!');
   1819          }),
   1820        ),
   1821      ),
   1822    );
   1823    return firstValueFrom(observable$);
   1824  }
   1825 
   1826  /**
   1827   * @param urlOrPredicate - A URL or predicate to wait for.
   1828   * @param options - Optional waiting parameters
   1829   * @returns Promise which resolves to the matched response.
   1830   * @example
   1831   *
   1832   * ```ts
   1833   * const firstResponse = await page.waitForResponse(
   1834   *   'https://example.com/resource',
   1835   * );
   1836   * const finalResponse = await page.waitForResponse(
   1837   *   response =>
   1838   *     response.url() === 'https://example.com' && response.status() === 200,
   1839   * );
   1840   * const finalResponse = await page.waitForResponse(async response => {
   1841   *   return (await response.text()).includes('<html>');
   1842   * });
   1843   * return finalResponse.ok();
   1844   * ```
   1845   *
   1846   * @remarks
   1847   * Optional Parameter have:
   1848   *
   1849   * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds,
   1850   *   pass `0` to disable the timeout. The default value can be changed by using
   1851   *   the {@link Page.setDefaultTimeout} method.
   1852   */
   1853  waitForResponse(
   1854    urlOrPredicate: string | AwaitablePredicate<HTTPResponse>,
   1855    options: WaitTimeoutOptions = {},
   1856  ): Promise<HTTPResponse> {
   1857    const {timeout: ms = this._timeoutSettings.timeout(), signal} = options;
   1858    if (typeof urlOrPredicate === 'string') {
   1859      const url = urlOrPredicate;
   1860      urlOrPredicate = (response: HTTPResponse) => {
   1861        return response.url() === url;
   1862      };
   1863    }
   1864    const observable$ = fromEmitterEvent(this, PageEvent.Response).pipe(
   1865      filterAsync(urlOrPredicate),
   1866      raceWith(
   1867        timeout(ms),
   1868        fromAbortSignal(signal),
   1869        fromEmitterEvent(this, PageEvent.Close).pipe(
   1870          map(() => {
   1871            throw new TargetCloseError('Page closed!');
   1872          }),
   1873        ),
   1874      ),
   1875    );
   1876    return firstValueFrom(observable$);
   1877  }
   1878 
   1879  /**
   1880   * Waits for the network to be idle.
   1881   *
   1882   * @param options - Options to configure waiting behavior.
   1883   * @returns A promise which resolves once the network is idle.
   1884   */
   1885  waitForNetworkIdle(options: WaitForNetworkIdleOptions = {}): Promise<void> {
   1886    return firstValueFrom(this.waitForNetworkIdle$(options));
   1887  }
   1888 
   1889  /**
   1890   * @internal
   1891   */
   1892  waitForNetworkIdle$(
   1893    options: WaitForNetworkIdleOptions = {},
   1894  ): Observable<void> {
   1895    const {
   1896      timeout: ms = this._timeoutSettings.timeout(),
   1897      idleTime = NETWORK_IDLE_TIME,
   1898      concurrency = 0,
   1899      signal,
   1900    } = options;
   1901 
   1902    return this.#inflight$.pipe(
   1903      switchMap(inflight => {
   1904        if (inflight > concurrency) {
   1905          return EMPTY;
   1906        }
   1907        return timer(idleTime);
   1908      }),
   1909      map(() => {}),
   1910      raceWith(
   1911        timeout(ms),
   1912        fromAbortSignal(signal),
   1913        fromEmitterEvent(this, PageEvent.Close).pipe(
   1914          map(() => {
   1915            throw new TargetCloseError('Page closed!');
   1916          }),
   1917        ),
   1918      ),
   1919    );
   1920  }
   1921 
   1922  /**
   1923   * Waits for a frame matching the given conditions to appear.
   1924   *
   1925   * @example
   1926   *
   1927   * ```ts
   1928   * const frame = await page.waitForFrame(async frame => {
   1929   *   const frameElement = await frame.frameElement();
   1930   *   if (!frameElement) {
   1931   *     return false;
   1932   *   }
   1933   *   const name = await frameElement.evaluate(el => el.getAttribute('name'));
   1934   *   return name === 'test';
   1935   * });
   1936   * ```
   1937   */
   1938  async waitForFrame(
   1939    urlOrPredicate: string | ((frame: Frame) => Awaitable<boolean>),
   1940    options: WaitTimeoutOptions = {},
   1941  ): Promise<Frame> {
   1942    const {timeout: ms = this.getDefaultTimeout(), signal} = options;
   1943 
   1944    const predicate = isString(urlOrPredicate)
   1945      ? (frame: Frame) => {
   1946          return urlOrPredicate === frame.url();
   1947        }
   1948      : urlOrPredicate;
   1949 
   1950    return await firstValueFrom(
   1951      merge(
   1952        fromEmitterEvent(this, PageEvent.FrameAttached),
   1953        fromEmitterEvent(this, PageEvent.FrameNavigated),
   1954        from(this.frames()),
   1955      ).pipe(
   1956        filterAsync(predicate),
   1957        first(),
   1958        raceWith(
   1959          timeout(ms),
   1960          fromAbortSignal(signal),
   1961          fromEmitterEvent(this, PageEvent.Close).pipe(
   1962            map(() => {
   1963              throw new TargetCloseError('Page closed.');
   1964            }),
   1965          ),
   1966        ),
   1967      ),
   1968    );
   1969  }
   1970 
   1971  /**
   1972   * This method navigate to the previous page in history.
   1973   * @param options - Navigation parameters
   1974   * @returns Promise which resolves to the main resource response. In case of
   1975   * multiple redirects, the navigation will resolve with the response of the
   1976   * last redirect. If can not go back, resolves to `null`.
   1977   */
   1978  abstract goBack(options?: WaitForOptions): Promise<HTTPResponse | null>;
   1979 
   1980  /**
   1981   * This method navigate to the next page in history.
   1982   * @param options - Navigation Parameter
   1983   * @returns Promise which resolves to the main resource response. In case of
   1984   * multiple redirects, the navigation will resolve with the response of the
   1985   * last redirect. If can not go forward, resolves to `null`.
   1986   */
   1987  abstract goForward(options?: WaitForOptions): Promise<HTTPResponse | null>;
   1988 
   1989  /**
   1990   * Brings page to front (activates tab).
   1991   */
   1992  abstract bringToFront(): Promise<void>;
   1993 
   1994  /**
   1995   * Emulates a given device's metrics and user agent.
   1996   *
   1997   * To aid emulation, Puppeteer provides a list of known devices that can be
   1998   * via {@link KnownDevices}.
   1999   *
   2000   * @remarks
   2001   * This method is a shortcut for calling two methods:
   2002   * {@link Page.setUserAgent} and {@link Page.setViewport}.
   2003   *
   2004   * This method will resize the page. A lot of websites don't expect phones to
   2005   * change size, so you should emulate before navigating to the page.
   2006   *
   2007   * @example
   2008   *
   2009   * ```ts
   2010   * import {KnownDevices} from 'puppeteer';
   2011   * const iPhone = KnownDevices['iPhone 15 Pro'];
   2012   *
   2013   * (async () => {
   2014   *   const browser = await puppeteer.launch();
   2015   *   const page = await browser.newPage();
   2016   *   await page.emulate(iPhone);
   2017   *   await page.goto('https://www.google.com');
   2018   *   // other actions...
   2019   *   await browser.close();
   2020   * })();
   2021   * ```
   2022   */
   2023  async emulate(device: Device): Promise<void> {
   2024    await Promise.all([
   2025      this.setUserAgent(device.userAgent),
   2026      this.setViewport(device.viewport),
   2027    ]);
   2028  }
   2029 
   2030  /**
   2031   * @param enabled - Whether or not to enable JavaScript on the page.
   2032   * @remarks
   2033   * NOTE: changing this value won't affect scripts that have already been run.
   2034   * It will take full effect on the next navigation.
   2035   */
   2036  abstract setJavaScriptEnabled(enabled: boolean): Promise<void>;
   2037 
   2038  /**
   2039   * Toggles bypassing page's Content-Security-Policy.
   2040   * @param enabled - sets bypassing of page's Content-Security-Policy.
   2041   * @remarks
   2042   * NOTE: CSP bypassing happens at the moment of CSP initialization rather than
   2043   * evaluation. Usually, this means that `page.setBypassCSP` should be called
   2044   * before navigating to the domain.
   2045   */
   2046  abstract setBypassCSP(enabled: boolean): Promise<void>;
   2047 
   2048  /**
   2049   * @param type - Changes the CSS media type of the page. The only allowed
   2050   * values are `screen`, `print` and `null`. Passing `null` disables CSS media
   2051   * emulation.
   2052   * @example
   2053   *
   2054   * ```ts
   2055   * await page.evaluate(() => matchMedia('screen').matches);
   2056   * // → true
   2057   * await page.evaluate(() => matchMedia('print').matches);
   2058   * // → false
   2059   *
   2060   * await page.emulateMediaType('print');
   2061   * await page.evaluate(() => matchMedia('screen').matches);
   2062   * // → false
   2063   * await page.evaluate(() => matchMedia('print').matches);
   2064   * // → true
   2065   *
   2066   * await page.emulateMediaType(null);
   2067   * await page.evaluate(() => matchMedia('screen').matches);
   2068   * // → true
   2069   * await page.evaluate(() => matchMedia('print').matches);
   2070   * // → false
   2071   * ```
   2072   */
   2073  abstract emulateMediaType(type?: string): Promise<void>;
   2074 
   2075  /**
   2076   * Enables CPU throttling to emulate slow CPUs.
   2077   * @param factor - slowdown factor (1 is no throttle, 2 is 2x slowdown, etc).
   2078   */
   2079  abstract emulateCPUThrottling(factor: number | null): Promise<void>;
   2080 
   2081  /**
   2082   * @param features - `<?Array<Object>>` Given an array of media feature
   2083   * objects, emulates CSS media features on the page. Each media feature object
   2084   * must have the following properties:
   2085   * @example
   2086   *
   2087   * ```ts
   2088   * await page.emulateMediaFeatures([
   2089   *   {name: 'prefers-color-scheme', value: 'dark'},
   2090   * ]);
   2091   * await page.evaluate(
   2092   *   () => matchMedia('(prefers-color-scheme: dark)').matches,
   2093   * );
   2094   * // → true
   2095   * await page.evaluate(
   2096   *   () => matchMedia('(prefers-color-scheme: light)').matches,
   2097   * );
   2098   * // → false
   2099   *
   2100   * await page.emulateMediaFeatures([
   2101   *   {name: 'prefers-reduced-motion', value: 'reduce'},
   2102   * ]);
   2103   * await page.evaluate(
   2104   *   () => matchMedia('(prefers-reduced-motion: reduce)').matches,
   2105   * );
   2106   * // → true
   2107   * await page.evaluate(
   2108   *   () => matchMedia('(prefers-reduced-motion: no-preference)').matches,
   2109   * );
   2110   * // → false
   2111   *
   2112   * await page.emulateMediaFeatures([
   2113   *   {name: 'prefers-color-scheme', value: 'dark'},
   2114   *   {name: 'prefers-reduced-motion', value: 'reduce'},
   2115   * ]);
   2116   * await page.evaluate(
   2117   *   () => matchMedia('(prefers-color-scheme: dark)').matches,
   2118   * );
   2119   * // → true
   2120   * await page.evaluate(
   2121   *   () => matchMedia('(prefers-color-scheme: light)').matches,
   2122   * );
   2123   * // → false
   2124   * await page.evaluate(
   2125   *   () => matchMedia('(prefers-reduced-motion: reduce)').matches,
   2126   * );
   2127   * // → true
   2128   * await page.evaluate(
   2129   *   () => matchMedia('(prefers-reduced-motion: no-preference)').matches,
   2130   * );
   2131   * // → false
   2132   *
   2133   * await page.emulateMediaFeatures([{name: 'color-gamut', value: 'p3'}]);
   2134   * await page.evaluate(() => matchMedia('(color-gamut: srgb)').matches);
   2135   * // → true
   2136   * await page.evaluate(() => matchMedia('(color-gamut: p3)').matches);
   2137   * // → true
   2138   * await page.evaluate(() => matchMedia('(color-gamut: rec2020)').matches);
   2139   * // → false
   2140   * ```
   2141   */
   2142  abstract emulateMediaFeatures(features?: MediaFeature[]): Promise<void>;
   2143 
   2144  /**
   2145   * @param timezoneId - Changes the timezone of the page. See
   2146   * {@link https://source.chromium.org/chromium/chromium/deps/icu.git/+/faee8bc70570192d82d2978a71e2a615788597d1:source/data/misc/metaZones.txt | ICU’s metaZones.txt}
   2147   * for a list of supported timezone IDs. Passing
   2148   * `null` disables timezone emulation.
   2149   */
   2150  abstract emulateTimezone(timezoneId?: string): Promise<void>;
   2151 
   2152  /**
   2153   * Emulates the idle state.
   2154   * If no arguments set, clears idle state emulation.
   2155   *
   2156   * @example
   2157   *
   2158   * ```ts
   2159   * // set idle emulation
   2160   * await page.emulateIdleState({isUserActive: true, isScreenUnlocked: false});
   2161   *
   2162   * // do some checks here
   2163   * ...
   2164   *
   2165   * // clear idle emulation
   2166   * await page.emulateIdleState();
   2167   * ```
   2168   *
   2169   * @param overrides - Mock idle state. If not set, clears idle overrides
   2170   */
   2171  abstract emulateIdleState(overrides?: {
   2172    isUserActive: boolean;
   2173    isScreenUnlocked: boolean;
   2174  }): Promise<void>;
   2175 
   2176  /**
   2177   * Simulates the given vision deficiency on the page.
   2178   *
   2179   * @example
   2180   *
   2181   * ```ts
   2182   * import puppeteer from 'puppeteer';
   2183   *
   2184   * (async () => {
   2185   *   const browser = await puppeteer.launch();
   2186   *   const page = await browser.newPage();
   2187   *   await page.goto('https://v8.dev/blog/10-years');
   2188   *
   2189   *   await page.emulateVisionDeficiency('achromatopsia');
   2190   *   await page.screenshot({path: 'achromatopsia.png'});
   2191   *
   2192   *   await page.emulateVisionDeficiency('deuteranopia');
   2193   *   await page.screenshot({path: 'deuteranopia.png'});
   2194   *
   2195   *   await page.emulateVisionDeficiency('blurredVision');
   2196   *   await page.screenshot({path: 'blurred-vision.png'});
   2197   *
   2198   *   await page.emulateVisionDeficiency('reducedContrast');
   2199   *   await page.screenshot({path: 'reduced-contrast.png'});
   2200   *
   2201   *   await browser.close();
   2202   * })();
   2203   * ```
   2204   *
   2205   * @param type - the type of deficiency to simulate, or `'none'` to reset.
   2206   */
   2207  abstract emulateVisionDeficiency(
   2208    type?: Protocol.Emulation.SetEmulatedVisionDeficiencyRequest['type'],
   2209  ): Promise<void>;
   2210 
   2211  /**
   2212   * `page.setViewport` will resize the page. A lot of websites don't expect
   2213   * phones to change size, so you should set the viewport before navigating to
   2214   * the page.
   2215   *
   2216   * In the case of multiple pages in a single browser, each page can have its
   2217   * own viewport size. Setting the viewport to `null` resets the viewport to
   2218   * its default value.
   2219   *
   2220   * @example
   2221   *
   2222   * ```ts
   2223   * const page = await browser.newPage();
   2224   * await page.setViewport({
   2225   *   width: 640,
   2226   *   height: 480,
   2227   *   deviceScaleFactor: 1,
   2228   * });
   2229   * await page.goto('https://example.com');
   2230   * ```
   2231   *
   2232   * @param viewport -
   2233   * @remarks
   2234   * NOTE: in certain cases, setting viewport will reload the page in order to
   2235   * set the isMobile or hasTouch properties.
   2236   */
   2237  abstract setViewport(viewport: Viewport | null): Promise<void>;
   2238 
   2239  /**
   2240   * Returns the current page viewport settings without checking the actual page
   2241   * viewport.
   2242   *
   2243   * This is either the viewport set with the previous {@link Page.setViewport}
   2244   * call or the default viewport set via
   2245   * {@link ConnectOptions.defaultViewport |
   2246   * ConnectOptions.defaultViewport}.
   2247   */
   2248  abstract viewport(): Viewport | null;
   2249 
   2250  /**
   2251   * Evaluates a function in the page's context and returns the result.
   2252   *
   2253   * If the function passed to `page.evaluate` returns a Promise, the
   2254   * function will wait for the promise to resolve and return its value.
   2255   *
   2256   * @example
   2257   *
   2258   * ```ts
   2259   * const result = await frame.evaluate(() => {
   2260   *   return Promise.resolve(8 * 7);
   2261   * });
   2262   * console.log(result); // prints "56"
   2263   * ```
   2264   *
   2265   * You can pass a string instead of a function (although functions are
   2266   * recommended as they are easier to debug and use with TypeScript):
   2267   *
   2268   * @example
   2269   *
   2270   * ```ts
   2271   * const aHandle = await page.evaluate('1 + 2');
   2272   * ```
   2273   *
   2274   * To get the best TypeScript experience, you should pass in as the
   2275   * generic the type of `pageFunction`:
   2276   *
   2277   * ```ts
   2278   * const aHandle = await page.evaluate(() => 2);
   2279   * ```
   2280   *
   2281   * @example
   2282   *
   2283   * {@link ElementHandle} instances (including {@link JSHandle}s) can be passed
   2284   * as arguments to the `pageFunction`:
   2285   *
   2286   * ```ts
   2287   * const bodyHandle = await page.$('body');
   2288   * const html = await page.evaluate(body => body.innerHTML, bodyHandle);
   2289   * await bodyHandle.dispose();
   2290   * ```
   2291   *
   2292   * @param pageFunction - a function that is run within the page
   2293   * @param args - arguments to be passed to the pageFunction
   2294   *
   2295   * @returns the return value of `pageFunction`.
   2296   */
   2297  async evaluate<
   2298    Params extends unknown[],
   2299    Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
   2300  >(
   2301    pageFunction: Func | string,
   2302    ...args: Params
   2303  ): Promise<Awaited<ReturnType<Func>>> {
   2304    pageFunction = withSourcePuppeteerURLIfNone(
   2305      this.evaluate.name,
   2306      pageFunction,
   2307    );
   2308    return await this.mainFrame().evaluate(pageFunction, ...args);
   2309  }
   2310 
   2311  /**
   2312   * Adds a function which would be invoked in one of the following scenarios:
   2313   *
   2314   * - whenever the page is navigated
   2315   *
   2316   * - whenever the child frame is attached or navigated. In this case, the
   2317   *   function is invoked in the context of the newly attached frame.
   2318   *
   2319   * The function is invoked after the document was created but before any of
   2320   * its scripts were run. This is useful to amend the JavaScript environment,
   2321   * e.g. to seed `Math.random`.
   2322   * @param pageFunction - Function to be evaluated in browser context
   2323   * @param args - Arguments to pass to `pageFunction`
   2324   * @example
   2325   * An example of overriding the navigator.languages property before the page loads:
   2326   *
   2327   * ```ts
   2328   * // preload.js
   2329   *
   2330   * // overwrite the `languages` property to use a custom getter
   2331   * Object.defineProperty(navigator, 'languages', {
   2332   *   get: function () {
   2333   *     return ['en-US', 'en', 'bn'];
   2334   *   },
   2335   * });
   2336   *
   2337   * // In your puppeteer script, assuming the preload.js file is
   2338   * // in same folder of our script.
   2339   * const preloadFile = fs.readFileSync('./preload.js', 'utf8');
   2340   * await page.evaluateOnNewDocument(preloadFile);
   2341   * ```
   2342   */
   2343  abstract evaluateOnNewDocument<
   2344    Params extends unknown[],
   2345    Func extends (...args: Params) => unknown = (...args: Params) => unknown,
   2346  >(
   2347    pageFunction: Func | string,
   2348    ...args: Params
   2349  ): Promise<NewDocumentScriptEvaluation>;
   2350 
   2351  /**
   2352   * Removes script that injected into page by Page.evaluateOnNewDocument.
   2353   *
   2354   * @param identifier - script identifier
   2355   */
   2356  abstract removeScriptToEvaluateOnNewDocument(
   2357    identifier: string,
   2358  ): Promise<void>;
   2359 
   2360  /**
   2361   * Toggles ignoring cache for each request based on the enabled state. By
   2362   * default, caching is enabled.
   2363   * @param enabled - sets the `enabled` state of cache
   2364   * @defaultValue `true`
   2365   */
   2366  abstract setCacheEnabled(enabled?: boolean): Promise<void>;
   2367 
   2368  /**
   2369   * @internal
   2370   */
   2371  async _maybeWriteTypedArrayToFile(
   2372    path: string | undefined,
   2373    typedArray: Uint8Array,
   2374  ): Promise<void> {
   2375    if (!path) {
   2376      return;
   2377    }
   2378 
   2379    await environment.value.fs.promises.writeFile(path, typedArray);
   2380  }
   2381 
   2382  /**
   2383   * Captures a screencast of this {@link Page | page}.
   2384   *
   2385   * @example
   2386   * Recording a {@link Page | page}:
   2387   *
   2388   * ```
   2389   * import puppeteer from 'puppeteer';
   2390   *
   2391   * // Launch a browser
   2392   * const browser = await puppeteer.launch();
   2393   *
   2394   * // Create a new page
   2395   * const page = await browser.newPage();
   2396   *
   2397   * // Go to your site.
   2398   * await page.goto("https://www.example.com");
   2399   *
   2400   * // Start recording.
   2401   * const recorder = await page.screencast({path: 'recording.webm'});
   2402   *
   2403   * // Do something.
   2404   *
   2405   * // Stop recording.
   2406   * await recorder.stop();
   2407   *
   2408   * browser.close();
   2409   * ```
   2410   *
   2411   * @param options - Configures screencast behavior.
   2412   *
   2413   * @experimental
   2414   *
   2415   * @remarks
   2416   *
   2417   * By default, all recordings will be {@link https://www.webmproject.org/ | WebM} format using
   2418   * the {@link https://www.webmproject.org/vp9/ | VP9} video codec, with a frame rate of 30 FPS.
   2419   *
   2420   * You must have {@link https://ffmpeg.org/ | ffmpeg} installed on your system.
   2421   */
   2422  async screencast(
   2423    options: Readonly<ScreencastOptions> = {},
   2424  ): Promise<ScreenRecorder> {
   2425    const ScreenRecorder = environment.value.ScreenRecorder;
   2426    const [width, height, devicePixelRatio] =
   2427      await this.#getNativePixelDimensions();
   2428    let crop: BoundingBox | undefined;
   2429    if (options.crop) {
   2430      const {
   2431        x,
   2432        y,
   2433        width: cropWidth,
   2434        height: cropHeight,
   2435      } = roundRectangle(normalizeRectangle(options.crop));
   2436      if (x < 0 || y < 0) {
   2437        throw new Error(
   2438          `\`crop.x\` and \`crop.y\` must be greater than or equal to 0.`,
   2439        );
   2440      }
   2441      if (cropWidth <= 0 || cropHeight <= 0) {
   2442        throw new Error(
   2443          `\`crop.height\` and \`crop.width\` must be greater than or equal to 0.`,
   2444        );
   2445      }
   2446 
   2447      const viewportWidth = width / devicePixelRatio;
   2448      const viewportHeight = height / devicePixelRatio;
   2449      if (x + cropWidth > viewportWidth) {
   2450        throw new Error(
   2451          `\`crop.width\` cannot be larger than the viewport width (${viewportWidth}).`,
   2452        );
   2453      }
   2454      if (y + cropHeight > viewportHeight) {
   2455        throw new Error(
   2456          `\`crop.height\` cannot be larger than the viewport height (${viewportHeight}).`,
   2457        );
   2458      }
   2459 
   2460      crop = {
   2461        x: x * devicePixelRatio,
   2462        y: y * devicePixelRatio,
   2463        width: cropWidth * devicePixelRatio,
   2464        height: cropHeight * devicePixelRatio,
   2465      };
   2466    }
   2467    if (options.speed !== undefined && options.speed <= 0) {
   2468      throw new Error(`\`speed\` must be greater than 0.`);
   2469    }
   2470    if (options.scale !== undefined && options.scale <= 0) {
   2471      throw new Error(`\`scale\` must be greater than 0.`);
   2472    }
   2473 
   2474    const recorder = new ScreenRecorder(this, width, height, {
   2475      ...options,
   2476      crop,
   2477    });
   2478    try {
   2479      await this._startScreencast();
   2480    } catch (error) {
   2481      void recorder.stop();
   2482      throw error;
   2483    }
   2484    if (options.path) {
   2485      const {createWriteStream} = environment.value.fs;
   2486      const stream = createWriteStream(options.path, 'binary');
   2487      recorder.pipe(stream);
   2488    }
   2489    return recorder;
   2490  }
   2491 
   2492  #screencastSessionCount = 0;
   2493  #startScreencastPromise: Promise<void> | undefined;
   2494 
   2495  /**
   2496   * @internal
   2497   */
   2498  async _startScreencast(): Promise<void> {
   2499    ++this.#screencastSessionCount;
   2500    if (!this.#startScreencastPromise) {
   2501      this.#startScreencastPromise = this.mainFrame()
   2502        .client.send('Page.startScreencast', {format: 'png'})
   2503        .then(() => {
   2504          // Wait for the first frame.
   2505          return new Promise(resolve => {
   2506            return this.mainFrame().client.once('Page.screencastFrame', () => {
   2507              return resolve();
   2508            });
   2509          });
   2510        });
   2511    }
   2512    await this.#startScreencastPromise;
   2513  }
   2514 
   2515  /**
   2516   * @internal
   2517   */
   2518  async _stopScreencast(): Promise<void> {
   2519    --this.#screencastSessionCount;
   2520    if (!this.#startScreencastPromise) {
   2521      return;
   2522    }
   2523    this.#startScreencastPromise = undefined;
   2524    if (this.#screencastSessionCount === 0) {
   2525      await this.mainFrame().client.send('Page.stopScreencast');
   2526    }
   2527  }
   2528 
   2529  /**
   2530   * Gets the native, non-emulated dimensions of the viewport.
   2531   */
   2532  async #getNativePixelDimensions(): Promise<
   2533    readonly [width: number, height: number, devicePixelRatio: number]
   2534  > {
   2535    const viewport = this.viewport();
   2536    using stack = new DisposableStack();
   2537    if (viewport && viewport.deviceScaleFactor !== 0) {
   2538      await this.setViewport({...viewport, deviceScaleFactor: 0});
   2539      stack.defer(() => {
   2540        void this.setViewport(viewport).catch(debugError);
   2541      });
   2542    }
   2543    return await this.mainFrame()
   2544      .isolatedRealm()
   2545      .evaluate(() => {
   2546        return [
   2547          window.visualViewport!.width * window.devicePixelRatio,
   2548          window.visualViewport!.height * window.devicePixelRatio,
   2549          window.devicePixelRatio,
   2550        ] as const;
   2551      });
   2552  }
   2553 
   2554  /**
   2555   * Captures a screenshot of this {@link Page | page}.
   2556   *
   2557   * @param options - Configures screenshot behavior.
   2558   *
   2559   * @remarks
   2560   *
   2561   * While a screenshot is being taken in a {@link BrowserContext}, the
   2562   * following methods will automatically wait for the screenshot to
   2563   * finish to prevent interference with the screenshot process:
   2564   * {@link BrowserContext.newPage}, {@link Browser.newPage},
   2565   * {@link Page.close}.
   2566   *
   2567   * Calling {@link Page.bringToFront} will not wait for existing
   2568   * screenshot operations.
   2569   *
   2570   */
   2571  async screenshot(
   2572    options: Readonly<ScreenshotOptions> & {encoding: 'base64'},
   2573  ): Promise<string>;
   2574  async screenshot(options?: Readonly<ScreenshotOptions>): Promise<Uint8Array>;
   2575  @guarded(function () {
   2576    return this.browser();
   2577  })
   2578  async screenshot(
   2579    userOptions: Readonly<ScreenshotOptions> = {},
   2580  ): Promise<Uint8Array | string> {
   2581    using _guard = await this.browserContext().startScreenshot();
   2582 
   2583    const options = {
   2584      ...userOptions,
   2585      clip: userOptions.clip
   2586        ? {
   2587            ...userOptions.clip,
   2588          }
   2589        : undefined,
   2590    };
   2591    if (options.type === undefined && options.path !== undefined) {
   2592      const filePath = options.path;
   2593      // Note we cannot use Node.js here due to browser compatibility.
   2594      const extension = filePath
   2595        .slice(filePath.lastIndexOf('.') + 1)
   2596        .toLowerCase();
   2597      switch (extension) {
   2598        case 'png':
   2599          options.type = 'png';
   2600          break;
   2601        case 'jpeg':
   2602        case 'jpg':
   2603          options.type = 'jpeg';
   2604          break;
   2605        case 'webp':
   2606          options.type = 'webp';
   2607          break;
   2608      }
   2609    }
   2610    if (options.quality !== undefined) {
   2611      if (options.quality < 0 || options.quality > 100) {
   2612        throw new Error(
   2613          `Expected 'quality' (${options.quality}) to be between 0 and 100, inclusive.`,
   2614        );
   2615      }
   2616      if (
   2617        options.type === undefined ||
   2618        !['jpeg', 'webp'].includes(options.type)
   2619      ) {
   2620        throw new Error(
   2621          `${options.type ?? 'png'} screenshots do not support 'quality'.`,
   2622        );
   2623      }
   2624    }
   2625    if (options.clip) {
   2626      if (options.clip.width <= 0) {
   2627        throw new Error("'width' in 'clip' must be positive.");
   2628      }
   2629      if (options.clip.height <= 0) {
   2630        throw new Error("'height' in 'clip' must be positive.");
   2631      }
   2632    }
   2633 
   2634    setDefaultScreenshotOptions(options);
   2635 
   2636    await using stack = new AsyncDisposableStack();
   2637    if (options.clip) {
   2638      if (options.fullPage) {
   2639        throw new Error("'clip' and 'fullPage' are mutually exclusive");
   2640      }
   2641 
   2642      options.clip = roundRectangle(normalizeRectangle(options.clip));
   2643    } else {
   2644      if (options.fullPage) {
   2645        // If `captureBeyondViewport` is `false`, then we set the viewport to
   2646        // capture the full page. Note this may be affected by on-page CSS and
   2647        // JavaScript.
   2648        if (!options.captureBeyondViewport) {
   2649          const scrollDimensions = await this.mainFrame()
   2650            .isolatedRealm()
   2651            .evaluate(() => {
   2652              const element = document.documentElement;
   2653              return {
   2654                width: element.scrollWidth,
   2655                height: element.scrollHeight,
   2656              };
   2657            });
   2658          const viewport = this.viewport();
   2659          await this.setViewport({
   2660            ...viewport,
   2661            ...scrollDimensions,
   2662          });
   2663          stack.defer(async () => {
   2664            await this.setViewport(viewport).catch(debugError);
   2665          });
   2666        }
   2667      } else {
   2668        options.captureBeyondViewport = false;
   2669      }
   2670    }
   2671 
   2672    const data = await this._screenshot(options);
   2673    if (options.encoding === 'base64') {
   2674      return data;
   2675    }
   2676 
   2677    const typedArray = stringToTypedArray(data, true);
   2678    await this._maybeWriteTypedArrayToFile(options.path, typedArray);
   2679    return typedArray;
   2680  }
   2681 
   2682  /**
   2683   * @internal
   2684   */
   2685  abstract _screenshot(options: Readonly<ScreenshotOptions>): Promise<string>;
   2686 
   2687  /**
   2688   * Generates a PDF of the page with the `print` CSS media type.
   2689   *
   2690   * @param options - options for generating the PDF.
   2691   *
   2692   * @remarks
   2693   *
   2694   * To generate a PDF with the `screen` media type, call
   2695   * {@link Page.emulateMediaType | `page.emulateMediaType('screen')`} before
   2696   * calling `page.pdf()`.
   2697   *
   2698   * By default, `page.pdf()` generates a pdf with modified colors for printing.
   2699   * Use the
   2700   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust | `-webkit-print-color-adjust`}
   2701   * property to force rendering of exact colors.
   2702   */
   2703  abstract createPDFStream(
   2704    options?: PDFOptions,
   2705  ): Promise<ReadableStream<Uint8Array>>;
   2706 
   2707  /**
   2708   * {@inheritDoc Page.createPDFStream}
   2709   */
   2710  abstract pdf(options?: PDFOptions): Promise<Uint8Array>;
   2711 
   2712  /**
   2713   * The page's title
   2714   *
   2715   * @remarks
   2716   *
   2717   * Shortcut for {@link Frame.title | page.mainFrame().title()}.
   2718   */
   2719  async title(): Promise<string> {
   2720    return await this.mainFrame().title();
   2721  }
   2722 
   2723  abstract close(options?: {runBeforeUnload?: boolean}): Promise<void>;
   2724 
   2725  /**
   2726   * Indicates that the page has been closed.
   2727   * @returns
   2728   */
   2729  abstract isClosed(): boolean;
   2730 
   2731  /**
   2732   * {@inheritDoc Mouse}
   2733   */
   2734  abstract get mouse(): Mouse;
   2735 
   2736  /**
   2737   * This method fetches an element with `selector`, scrolls it into view if
   2738   * needed, and then uses {@link Page.mouse} to click in the center of the
   2739   * element. If there's no element matching `selector`, the method throws an
   2740   * error.
   2741   *
   2742   * @remarks
   2743   *
   2744   * Bear in mind that if `click()` triggers a navigation event and
   2745   * there's a separate `page.waitForNavigation()` promise to be resolved, you
   2746   * may end up with a race condition that yields unexpected results. The
   2747   * correct pattern for click and wait for navigation is the following:
   2748   *
   2749   * ```ts
   2750   * const [response] = await Promise.all([
   2751   *   page.waitForNavigation(waitOptions),
   2752   *   page.click(selector, clickOptions),
   2753   * ]);
   2754   * ```
   2755   *
   2756   * Shortcut for {@link Frame.click | page.mainFrame().click(selector[, options]) }.
   2757   * @param selector -
   2758   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2759   * to query the page for.
   2760   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2761   * can be passed as-is and a
   2762   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2763   * allows querying by
   2764   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2765   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2766   * and
   2767   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2768   * and
   2769   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2770   * Alternatively, you can specify the selector type using a
   2771   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are
   2772   * multiple elements satisfying the `selector`, the first will be clicked
   2773   * @param options - `Object`
   2774   * @returns Promise which resolves when the element matching `selector` is
   2775   * successfully clicked. The Promise will be rejected if there is no element
   2776   * matching `selector`.
   2777   */
   2778  click(selector: string, options?: Readonly<ClickOptions>): Promise<void> {
   2779    return this.mainFrame().click(selector, options);
   2780  }
   2781 
   2782  /**
   2783   * This method fetches an element with `selector` and focuses it. If
   2784   * there's no element matching `selector`, the method throws an error.
   2785   * @param selector -
   2786   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2787   * to query the page for.
   2788   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2789   * can be passed as-is and a
   2790   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2791   * allows querying by
   2792   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2793   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2794   * and
   2795   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2796   * and
   2797   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2798   * Alternatively, you can specify the selector type using a
   2799   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   2800   * If there are multiple elements satisfying the selector, the first
   2801   * will be focused.
   2802   * @returns Promise which resolves when the element matching selector
   2803   * is successfully focused. The promise will be rejected if there is
   2804   * no element matching selector.
   2805   *
   2806   * @remarks
   2807   *
   2808   * Shortcut for
   2809   * {@link Frame.focus | page.mainFrame().focus(selector)}.
   2810   */
   2811  focus(selector: string): Promise<void> {
   2812    return this.mainFrame().focus(selector);
   2813  }
   2814 
   2815  /**
   2816   * This method fetches an element with `selector`, scrolls it into view if
   2817   * needed, and then uses {@link Page.mouse}
   2818   * to hover over the center of the element.
   2819   * If there's no element matching `selector`, the method throws an error.
   2820   * @param selector -
   2821   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2822   * to query the page for.
   2823   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2824   * can be passed as-is and a
   2825   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2826   * allows querying by
   2827   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2828   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2829   * and
   2830   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2831   * and
   2832   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2833   * Alternatively, you can specify the selector type using a
   2834   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are
   2835   * multiple elements satisfying the `selector`, the first will be hovered.
   2836   * @returns Promise which resolves when the element matching `selector` is
   2837   * successfully hovered. Promise gets rejected if there's no element matching
   2838   * `selector`.
   2839   *
   2840   * @remarks
   2841   *
   2842   * Shortcut for {@link Page.hover | page.mainFrame().hover(selector)}.
   2843   */
   2844  hover(selector: string): Promise<void> {
   2845    return this.mainFrame().hover(selector);
   2846  }
   2847 
   2848  /**
   2849   * Triggers a `change` and `input` event once all the provided options have been
   2850   * selected. If there's no `<select>` element matching `selector`, the method
   2851   * throws an error.
   2852   *
   2853   * @example
   2854   *
   2855   * ```ts
   2856   * page.select('select#colors', 'blue'); // single selection
   2857   * page.select('select#colors', 'red', 'green', 'blue'); // multiple selections
   2858   * ```
   2859   *
   2860   * @param selector -
   2861   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2862   * to query the page for.
   2863   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2864   * can be passed as-is and a
   2865   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2866   * allows querying by
   2867   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2868   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2869   * and
   2870   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2871   * and
   2872   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2873   * Alternatively, you can specify the selector type using a
   2874   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   2875   * @param values - Values of options to select. If the `<select>` has the
   2876   * `multiple` attribute, all values are considered, otherwise only the first one
   2877   * is taken into account.
   2878   * @returns
   2879   *
   2880   * @remarks
   2881   *
   2882   * Shortcut for {@link Frame.select | page.mainFrame().select()}
   2883   */
   2884  select(selector: string, ...values: string[]): Promise<string[]> {
   2885    return this.mainFrame().select(selector, ...values);
   2886  }
   2887 
   2888  /**
   2889   * This method fetches an element with `selector`, scrolls it into view if
   2890   * needed, and then uses {@link Page.touchscreen}
   2891   * to tap in the center of the element.
   2892   * If there's no element matching `selector`, the method throws an error.
   2893   * @param selector -
   2894   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2895   * to query the page for.
   2896   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2897   * can be passed as-is and a
   2898   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2899   * allows querying by
   2900   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2901   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2902   * and
   2903   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2904   * and
   2905   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2906   * Alternatively, you can specify the selector type using a
   2907   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}. If there are multiple elements satisfying the
   2908   * selector, the first will be tapped.
   2909   *
   2910   * @remarks
   2911   *
   2912   * Shortcut for {@link Frame.tap | page.mainFrame().tap(selector)}.
   2913   */
   2914  tap(selector: string): Promise<void> {
   2915    return this.mainFrame().tap(selector);
   2916  }
   2917 
   2918  /**
   2919   * Sends a `keydown`, `keypress/input`, and `keyup` event for each character
   2920   * in the text.
   2921   *
   2922   * To press a special key, like `Control` or `ArrowDown`, use {@link Keyboard.press}.
   2923   * @example
   2924   *
   2925   * ```ts
   2926   * await page.type('#mytextarea', 'Hello');
   2927   * // Types instantly
   2928   * await page.type('#mytextarea', 'World', {delay: 100});
   2929   * // Types slower, like a user
   2930   * ```
   2931   *
   2932   * @param selector -
   2933   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2934   * to query the page for.
   2935   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2936   * can be passed as-is and a
   2937   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2938   * allows querying by
   2939   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2940   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2941   * and
   2942   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   2943   * and
   2944   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   2945   * Alternatively, you can specify the selector type using a
   2946   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   2947   * @param text - A text to type into a focused element.
   2948   * @param options - have property `delay` which is the Time to wait between
   2949   * key presses in milliseconds. Defaults to `0`.
   2950   * @returns
   2951   */
   2952  type(
   2953    selector: string,
   2954    text: string,
   2955    options?: Readonly<KeyboardTypeOptions>,
   2956  ): Promise<void> {
   2957    return this.mainFrame().type(selector, text, options);
   2958  }
   2959 
   2960  /**
   2961   * Wait for the `selector` to appear in page. If at the moment of calling the
   2962   * method the `selector` already exists, the method will return immediately. If
   2963   * the `selector` doesn't appear after the `timeout` milliseconds of waiting, the
   2964   * function will throw.
   2965   *
   2966   * @example
   2967   * This method works across navigations:
   2968   *
   2969   * ```ts
   2970   * import puppeteer from 'puppeteer';
   2971   * (async () => {
   2972   *   const browser = await puppeteer.launch();
   2973   *   const page = await browser.newPage();
   2974   *   let currentURL;
   2975   *   page
   2976   *     .waitForSelector('img')
   2977   *     .then(() => console.log('First URL with image: ' + currentURL));
   2978   *   for (currentURL of [
   2979   *     'https://example.com',
   2980   *     'https://google.com',
   2981   *     'https://bbc.com',
   2982   *   ]) {
   2983   *     await page.goto(currentURL);
   2984   *   }
   2985   *   await browser.close();
   2986   * })();
   2987   * ```
   2988   *
   2989   * @param selector -
   2990   * {@link https://pptr.dev/guides/page-interactions#selectors | selector}
   2991   * to query the page for.
   2992   * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors | CSS selectors}
   2993   * can be passed as-is and a
   2994   * {@link https://pptr.dev/guides/page-interactions#non-css-selectors | Puppeteer-specific selector syntax}
   2995   * allows querying by
   2996   * {@link https://pptr.dev/guides/page-interactions#text-selectors--p-text | text},
   2997   * {@link https://pptr.dev/guides/page-interactions#aria-selectors--p-aria | a11y role and name},
   2998   * and
   2999   * {@link https://pptr.dev/guides/page-interactions#xpath-selectors--p-xpath | xpath}
   3000   * and
   3001   * {@link https://pptr.dev/guides/page-interactions#querying-elements-in-shadow-dom | combining these queries across shadow roots}.
   3002   * Alternatively, you can specify the selector type using a
   3003   * {@link https://pptr.dev/guides/page-interactions#prefixed-selector-syntax | prefix}.
   3004   * @param options - Optional waiting parameters
   3005   * @returns Promise which resolves when element specified by selector string
   3006   * is added to DOM. Resolves to `null` if waiting for hidden: `true` and
   3007   * selector is not found in DOM.
   3008   *
   3009   * @remarks
   3010   * The optional Parameter in Arguments `options` are:
   3011   *
   3012   * - `visible`: A boolean wait for element to be present in DOM and to be
   3013   *   visible, i.e. to not have `display: none` or `visibility: hidden` CSS
   3014   *   properties. Defaults to `false`.
   3015   *
   3016   * - `hidden`: Wait for element to not be found in the DOM or to be hidden,
   3017   *   i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to
   3018   *   `false`.
   3019   *
   3020   * - `timeout`: maximum time to wait for in milliseconds. Defaults to `30000`
   3021   *   (30 seconds). Pass `0` to disable timeout. The default value can be changed
   3022   *   by using the {@link Page.setDefaultTimeout} method.
   3023   */
   3024  async waitForSelector<Selector extends string>(
   3025    selector: Selector,
   3026    options: WaitForSelectorOptions = {},
   3027  ): Promise<ElementHandle<NodeFor<Selector>> | null> {
   3028    return await this.mainFrame().waitForSelector(selector, options);
   3029  }
   3030 
   3031  /**
   3032   * Waits for the provided function, `pageFunction`, to return a truthy value when
   3033   * evaluated in the page's context.
   3034   *
   3035   * @example
   3036   * {@link Page.waitForFunction} can be used to observe a viewport size change:
   3037   *
   3038   * ```ts
   3039   * import puppeteer from 'puppeteer';
   3040   * (async () => {
   3041   *   const browser = await puppeteer.launch();
   3042   *   const page = await browser.newPage();
   3043   *   const watchDog = page.waitForFunction('window.innerWidth < 100');
   3044   *   await page.setViewport({width: 50, height: 50});
   3045   *   await watchDog;
   3046   *   await browser.close();
   3047   * })();
   3048   * ```
   3049   *
   3050   * @example
   3051   * Arguments can be passed from Node.js to `pageFunction`:
   3052   *
   3053   * ```ts
   3054   * const selector = '.foo';
   3055   * await page.waitForFunction(
   3056   *   selector => !!document.querySelector(selector),
   3057   *   {},
   3058   *   selector,
   3059   * );
   3060   * ```
   3061   *
   3062   * @example
   3063   * The provided `pageFunction` can be asynchronous:
   3064   *
   3065   * ```ts
   3066   * const username = 'github-username';
   3067   * await page.waitForFunction(
   3068   *   async username => {
   3069   *     const githubResponse = await fetch(
   3070   *       `https://api.github.com/users/${username}`,
   3071   *     );
   3072   *     const githubUser = await githubResponse.json();
   3073   *     // show the avatar
   3074   *     const img = document.createElement('img');
   3075   *     img.src = githubUser.avatar_url;
   3076   *     // wait 3 seconds
   3077   *     await new Promise((resolve, reject) => setTimeout(resolve, 3000));
   3078   *     img.remove();
   3079   *   },
   3080   *   {},
   3081   *   username,
   3082   * );
   3083   * ```
   3084   *
   3085   * @param pageFunction - Function to be evaluated in browser context until it returns a
   3086   * truthy value.
   3087   * @param options - Options for configuring waiting behavior.
   3088   */
   3089  waitForFunction<
   3090    Params extends unknown[],
   3091    Func extends EvaluateFunc<Params> = EvaluateFunc<Params>,
   3092  >(
   3093    pageFunction: Func | string,
   3094    options?: FrameWaitForFunctionOptions,
   3095    ...args: Params
   3096  ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
   3097    return this.mainFrame().waitForFunction(pageFunction, options, ...args);
   3098  }
   3099 
   3100  /**
   3101   * This method is typically coupled with an action that triggers a device
   3102   * request from an api such as WebBluetooth.
   3103   *
   3104   * :::caution
   3105   *
   3106   * This must be called before the device request is made. It will not return a
   3107   * currently active device prompt.
   3108   *
   3109   * :::
   3110   *
   3111   * @example
   3112   *
   3113   * ```ts
   3114   * const [devicePrompt] = Promise.all([
   3115   *   page.waitForDevicePrompt(),
   3116   *   page.click('#connect-bluetooth'),
   3117   * ]);
   3118   * await devicePrompt.select(
   3119   *   await devicePrompt.waitForDevice(({name}) => name.includes('My Device')),
   3120   * );
   3121   * ```
   3122   */
   3123  abstract waitForDevicePrompt(
   3124    options?: WaitTimeoutOptions,
   3125  ): Promise<DeviceRequestPrompt>;
   3126 
   3127  /** @internal */
   3128  override [disposeSymbol](): void {
   3129    return void this.close().catch(debugError);
   3130  }
   3131 
   3132  /** @internal */
   3133  [asyncDisposeSymbol](): Promise<void> {
   3134    return this.close();
   3135  }
   3136 }
   3137 
   3138 /**
   3139 * @internal
   3140 */
   3141 export const supportedMetrics = new Set<string>([
   3142  'Timestamp',
   3143  'Documents',
   3144  'Frames',
   3145  'JSEventListeners',
   3146  'Nodes',
   3147  'LayoutCount',
   3148  'RecalcStyleCount',
   3149  'LayoutDuration',
   3150  'RecalcStyleDuration',
   3151  'ScriptDuration',
   3152  'TaskDuration',
   3153  'JSHeapUsedSize',
   3154  'JSHeapTotalSize',
   3155 ]);
   3156 
   3157 /** @see https://w3c.github.io/webdriver-bidi/#normalize-rect */
   3158 function normalizeRectangle<BoundingBoxType extends BoundingBox>(
   3159  clip: Readonly<BoundingBoxType>,
   3160 ): BoundingBoxType {
   3161  return {
   3162    ...clip,
   3163    ...(clip.width < 0
   3164      ? {
   3165          x: clip.x + clip.width,
   3166          width: -clip.width,
   3167        }
   3168      : {
   3169          x: clip.x,
   3170          width: clip.width,
   3171        }),
   3172    ...(clip.height < 0
   3173      ? {
   3174          y: clip.y + clip.height,
   3175          height: -clip.height,
   3176        }
   3177      : {
   3178          y: clip.y,
   3179          height: clip.height,
   3180        }),
   3181  };
   3182 }
   3183 
   3184 function roundRectangle<BoundingBoxType extends BoundingBox>(
   3185  clip: Readonly<BoundingBoxType>,
   3186 ): BoundingBoxType {
   3187  const x = Math.round(clip.x);
   3188  const y = Math.round(clip.y);
   3189  const width = Math.round(clip.width + clip.x - x);
   3190  const height = Math.round(clip.height + clip.y - y);
   3191  return {...clip, x, y, width, height};
   3192 }