/**
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import type { Readable } from 'stream' ; import { EventEmitter , Handler } from './EventEmitter.js' ; import { Connection , CDPSession , CDPSessionEmittedEvents , } from './Connection.js' ; import { Dialog } from './Dialog.js' ; import { EmulationManager } from './EmulationManager.js' ; import { Frame , FrameManager , FrameManagerEmittedEvents , } from './FrameManager.js' ; import { Keyboard , Mouse , Touchscreen , MouseButton } from './Input.js' ; import { Tracing } from './Tracing.js' ; import { assert , assertNever } from './assert.js' ; import { helper , debugError } from './helper.js' ; import { Coverage } from './Coverage.js' ; import { WebWorker } from './WebWorker.js' ; import { Browser , BrowserContext } from './Browser.js' ; import { Target } from './Target.js' ; import { createJSHandle , JSHandle , ElementHandle } from './JSHandle.js' ; import { Viewport } from './PuppeteerViewport.js' ; import { Credentials , NetworkConditions , NetworkManagerEmittedEvents , } from './NetworkManager.js' ; import { HTTPRequest } from './HTTPRequest.js' ; import { HTTPResponse } from './HTTPResponse.js' ; import { Accessibility } from './Accessibility.js' ; import { TimeoutSettings } from './TimeoutSettings.js' ; import { FileChooser } from './FileChooser.js' ; import { ConsoleMessage , ConsoleMessageType } from './ConsoleMessage.js' ; import { PuppeteerLifeCycleEvent } from './LifecycleWatcher.js' ; import { Protocol } from 'devtools-protocol' ; import { SerializableOrJSHandle , EvaluateHandleFn , WrapElementHandle , EvaluateFn , EvaluateFnReturnType , UnwrapPromiseLike , } from './EvalTypes.js' ; import { PDFOptions , paperFormats } from './PDFOptions.js' ; import { isNode } from '../environment.js' ; import { TaskQueue } from './TaskQueue.js' ; public export interface Metrics { Timestamp ? : number ; Documents ? : number ; Frames ? : number ; JSEventListeners ? : number ; Nodes ? : number ; LayoutCount ? : number ; RecalcStyleCount ? : number ; LayoutDuration ? : number ; RecalcStyleDuration ? : number ; ScriptDuration ? : number ; TaskDuration ? : number ; JSHeapUsedSize ? : number ; JSHeapTotalSize ? : number ; } public export interface WaitTimeoutOptions { remarks The default value can be changed by using the
     *  Page . setDefaultTimeout method.
      timeout ? : number ; } public export interface WaitForOptions { remarks The default value can be changed by using the
     *  Page . setDefaultTimeout or  Page . setDefaultNavigationTimeout * methods.
      timeout ? : number ; waitUntil ? : PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent [ ] ; } public export interface GeolocationOptions { /**
     * Latitude between -90 and 90.
     */ longitude : number ; /**
     * Longitude between -180 and 180.
     */ latitude : number ; /**
     * Optional non-negative accuracy value.
     */ accuracy ? : number ; } public export interface MediaFeature { name : string ; value : string ; } public export interface ScreenshotClip { x : number ; y : number ; width : number ; height : number ; } public export interface ScreenshotOptions { defaultValue type ? : 'png' | 'jpeg' | 'webp' ; /**
     * The file path to save the image to. The screenshot type will be inferred
     * from file extension. If path is a relative path, then it is resolved
     * relative to current working directory. If no path is provided, the image
     * won't be saved to the disk.
     */ path ? : string ; defaultValue fullPage ? : boolean ; /**
     * An object which specifies the clipping region of the page.
     */ clip ? : ScreenshotClip ; /**
     * Quality of the image, between 0-100. Not applicable to `png` images.
     */ quality ? : number ; defaultValue omitBackground ? : boolean ; defaultValue encoding ? : 'base64' | 'binary' ; defaultValue captureBeyondViewport ? : boolean ; } public export const enum PageEmittedEvents { eventProperty Close = 'close' , remarks A `console` event provides a  ConsoleMessage representing the
     * console message that was logged.
     *
     *  example Console = 'console' , /**
     * Emitted when a JavaScript dialog appears, such as `alert`, `prompt`,
     * `confirm` or `beforeunload`. Puppeteer can respond to the dialog via
     *  Dialog . accept or  Dialog . dismiss .
      Dialog = 'dialog' , /**
     * Emitted when the JavaScript
     *  https event is dispatched.
      DOMContentLoaded = 'domcontentloaded' , /**
     * Emitted when the page crashes. Will contain an `Error`.
     */ Error = 'error' , /** Emitted when a frame is attached. Will contain a  Frame .  FrameAttached = 'frameattached' , /** Emitted when a frame is detached. Will contain a  Frame .  FrameDetached = 'framedetached' , /** Emitted when a frame is navigated to a new URL. Will contain a  Frame .  FrameNavigated = 'framenavigated' , /**
     * Emitted when the JavaScript
     *  https * event is dispatched.
      Load = 'load' , /**
     * Emitted when the JavaScript code makes a call to `console.timeStamp`. For
     * the list of metrics see  Page . metrics .
     *
     *  remarks Metrics = 'metrics' , /**
     * Emitted when an uncaught exception happens within the page.
     * Contains an `Error`.
     */ PageError = 'pageerror' , /**
     * Emitted when the page opens a new tab or window.
     *
     * Contains a  Page corresponding to the popup window.
     *
     *  example Popup = 'popup' , /**
     * Emitted when a page issues a request and contains a  HTTPRequest .
     *
     *  remarks The object is readonly. See  Page . setRequestInterception for intercepting
     * and mutating requests.
      Request = 'request' , /**
     * Emitted when a request ended up loading from cache. Contains a  HTTPRequest .
     *
     *  remarks For certain requests, might contain undefined.
     *  https RequestServedFromCache = 'requestservedfromcache' , /**
     * Emitted when a request fails, for example by timing out.
     *
     * Contains a  HTTPRequest .
     *
     *  remarks RequestFailed = 'requestfailed' , /**
     * Emitted when a request finishes successfully. Contains a  HTTPRequest .
      RequestFinished = 'requestfinished' , /**
     * Emitted when a response is received. Contains a  HTTPResponse .
      Response = 'response' , /**
     * Emitted when a dedicated
     *  https * is spawned by the page.
      WorkerCreated = 'workercreated' , /**
     * Emitted when a dedicated
     *  https * is destroyed by the page.
      WorkerDestroyed = 'workerdestroyed' } /**
 * Denotes the objects received by callback functions for page events.
 *
 * See  PageEmittedEvents for more detail on the events and when they are
 * emitted.
 *  public export interface PageEventObject { close : never ; console : ConsoleMessage ; dialog : Dialog ; domcontentloaded : never ; error : Error ; frameattached : Frame ; framedetached : Frame ; framenavigated : Frame ; load : never ; metrics : { title : string ; metrics : Metrics ; } ; pageerror : Error ; popup : Page ; request : HTTPRequest ; response : HTTPResponse ; requestfailed : HTTPRequest ; requestfinished : HTTPRequest ; requestservedfromcache : HTTPRequest ; workercreated : WebWorker ; workerdestroyed : WebWorker ; } /**
 * Page provides methods to interact with a single tab or
 *  https in Chromium.
 *
 *  remarks example This example creates a page, navigates it to a URL, and then * saves a screenshot:
 * ```js
 * const puppeteer = require('puppeteer');
 *
 * (async () => {
 *   const browser = await puppeteer.launch();
 *   const page = await browser.newPage();
 *   await page.goto('https://example.com');
 *   await page.screenshot({path: 'screenshot.png'});
 *   await browser.close();
 * })();
 * ```
 *
 * The Page class extends from Puppeteer's  EventEmitter class and will
 * emit various events which are documented in the  PageEmittedEvents enum.
 *
 *  example public export class Page extends EventEmitter { internal static async create ( client , target , ignoreHTTPSErrors , defaultViewport , screenshotTaskQueue ) { const page = new Page ( client , target , ignoreHTTPSErrors , screenshotTaskQueue ) ; await page . _initialize ( ) ; if ( defaultViewport ) await page . setViewport ( defaultViewport ) ; return page ; } private _closed = false ; private _client : CDPSession ; private _target : Target ; private _keyboard : Keyboard ; private _mouse : Mouse ; private _timeoutSettings = new TimeoutSettings ( ) ; private _touchscreen : Touchscreen ; private _accessibility : Accessibility ; private _frameManager : FrameManager ; private _emulationManager : EmulationManager ; private _tracing : Tracing ; private _pageBindings = new Map < string , Function > ( ) ; private _coverage : Coverage ; private _javascriptEnabled = true ; private _viewport : Viewport | null ; private _screenshotTaskQueue : TaskQueue ; private _workers = new Map < string , WebWorker > ( ) ; private _fileChooserInterceptors = new Set < Function > ( ) ; private _disconnectPromise ? : Promise < Error > ; private _userDragInterceptionEnabled = false ; private _handlerMap = new WeakMap < Handler , Handler > ( ) ; internal constructor ( client , target , ignoreHTTPSErrors , screenshotTaskQueue ) { super ( ) ; this . _client = client ; this . _target = target ; this . _keyboard = new Keyboard ( client ) ; this . _mouse = new Mouse ( client , this . _keyboard ) ; this . _touchscreen = new Touchscreen ( client , this . _keyboard ) ; this . _accessibility = new Accessibility ( client ) ; this . _frameManager = new FrameManager ( client , this , ignoreHTTPSErrors , this . _timeoutSettings ) ; this . _emulationManager = new EmulationManager ( client ) ; this . _tracing = new Tracing ( client ) ; this . _coverage = new Coverage ( client ) ; this . _screenshotTaskQueue = screenshotTaskQueue ; this . _viewport = null ; client . on ( 'Target.attachedToTarget' , ( event ) => { if ( event . targetInfo . type !== 'worker' && event . targetInfo . type !== 'iframe' ) { client . send ( 'Target.detachFromTarget' , { sessionId : event . sessionId , } ) . catch ( debugError ) ; return ; } if ( event . targetInfo . type === 'worker' ) { const session = Connection . fromSession ( client ) . session ( event . sessionId ) ; const worker = new WebWorker ( session , event . targetInfo . url , this . _addConsoleMessage . bind ( this ) , this . _handleException . bind ( this ) ) ; this . _workers . set ( event . sessionId , worker ) ; this . emit ( PageEmittedEvents . WorkerCreated , worker ) ; } } ) ; client . on ( 'Target.detachedFromTarget' , ( event ) => { const worker = this . _workers . get ( event . sessionId ) ; if ( ! worker ) return ; this . _workers . delete ( event . sessionId ) ; this . emit ( PageEmittedEvents . WorkerDestroyed , worker ) ; } ) ; this . _frameManager . on ( FrameManagerEmittedEvents . FrameAttached , ( event ) => this . emit ( PageEmittedEvents . FrameAttached , event ) ) ; this . _frameManager . on ( FrameManagerEmittedEvents . FrameDetached , ( event ) => this . emit ( PageEmittedEvents . FrameDetached , event ) ) ; this . _frameManager . on ( FrameManagerEmittedEvents . FrameNavigated , ( event ) => this . emit ( PageEmittedEvents . FrameNavigated , event ) ) ; const networkManager = this . _frameManager . networkManager ( ) ; networkManager . on ( NetworkManagerEmittedEvents . Request , ( event ) => this . emit ( PageEmittedEvents . Request , event ) ) ; networkManager . on ( NetworkManagerEmittedEvents . RequestServedFromCache , ( event ) => this . emit ( PageEmittedEvents . RequestServedFromCache , event ) ) ; networkManager . on ( NetworkManagerEmittedEvents . Response , ( event ) => this . emit ( PageEmittedEvents . Response , event ) ) ; networkManager . on ( NetworkManagerEmittedEvents . RequestFailed , ( event ) => this . emit ( PageEmittedEvents . RequestFailed , event ) ) ; networkManager . on ( NetworkManagerEmittedEvents . RequestFinished , ( event ) => this . emit ( PageEmittedEvents . RequestFinished , event ) ) ; this . _fileChooserInterceptors = new Set ( ) ; client . on ( 'Page.domContentEventFired' , ( ) => this . emit ( PageEmittedEvents . DOMContentLoaded ) ) ; client . on ( 'Page.loadEventFired' , ( ) => this . emit ( PageEmittedEvents . Load ) ) ; client . on ( 'Runtime.consoleAPICalled' , ( event ) => this . _onConsoleAPI ( event ) ) ; client . on ( 'Runtime.bindingCalled' , ( event ) => this . _onBindingCalled ( event ) ) ; client . on ( 'Page.javascriptDialogOpening' , ( event ) => this . _onDialog ( event ) ) ; client . on ( 'Runtime.exceptionThrown' , ( exception ) => this . _handleException ( exception . exceptionDetails ) ) ; client . on ( 'Inspector.targetCrashed' , ( ) => this . _onTargetCrashed ( ) ) ; client . on ( 'Performance.metrics' , ( event ) => this . _emitMetrics ( event ) ) ; client . on ( 'Log.entryAdded' , ( event ) => this . _onLogEntryAdded ( event ) ) ; client . on ( 'Page.fileChooserOpened' , ( event ) => this . _onFileChooser ( event ) ) ; this . _target . _isClosedPromise . then ( ( ) => { this . emit ( PageEmittedEvents . Close ) ; this . _closed = true ; } ) ; } private async _initialize ( ) { await Promise . all ( [ this . _frameManager . initialize ( ) , this . _client . send ( 'Target.setAutoAttach' , { autoAttach : true , waitForDebuggerOnStart : false , flatten : true , } ) , this . _client . send ( 'Performance.enable' ) , this . _client . send ( 'Log.enable' ) , ] ) ; } private async _onFileChooser ( event ) { if ( ! this . _fileChooserInterceptors . size ) return ; const frame = this . _frameManager . frame ( event . frameId ) ; const context = await frame . executionContext ( ) ; const element = await context . _adoptBackendNodeId ( event . backendNodeId ) ; const interceptors = Array . from ( this . _fileChooserInterceptors ) ; this . _fileChooserInterceptors . clear ( ) ; const fileChooser = new FileChooser ( element , event ) ; for ( const interceptor of interceptors ) interceptor . call ( null , fileChooser ) ; } returns isDragInterceptionEnabled ( ) { return this . _userDragInterceptionEnabled ; } returns public isJavaScriptEnabled ( ) { return this . _javascriptEnabled ; } /**
     * Listen to page events.
     */ public on < K extends keyof PageEventObject > ( eventName , handler ) { if ( eventName === 'request' ) { const wrap = ( event ) => { event . enqueueInterceptAction ( ( ) => handler ( event as PageEventObject [ K ] ) ) ; } ; this . _handlerMap . set ( handler , wrap ) ; return super . on ( eventName , wrap ) ; } return super . on ( eventName , handler ) ; } public once < K extends keyof PageEventObject > ( eventName , handler ) { return super . once ( eventName , handler ) ; } off < K extends keyof PageEventObject > ( eventName , handler ) { if ( eventName === 'request' ) { handler = this . _handlerMap . get ( handler ) || handler ; } return super . off ( eventName , handler ) ; } param options returns remarks async waitForFileChooser ( options = { } ) { if ( ! this . _fileChooserInterceptors . size ) await this . _client . send ( 'Page.setInterceptFileChooserDialog' , { enabled : true , } ) ; const { timeout = this . _timeoutSettings . timeout ( ) } = options ; let callback ; const promise = new Promise < FileChooser > ( ( x ) => ( callback = x ) ) ; this . _fileChooserInterceptors . add ( callback ) ; return helper . waitWithTimeout < FileChooser > ( promise , 'waiting for file chooser' , timeout ) . catch ( ( error ) => { this . _fileChooserInterceptors . delete ( callback ) ; throw error ; } ) ; } remarks NOTE: Consider using  BrowserContext . overridePermissions to grant
     * permissions for the page to read its geolocation.
     *  example async setGeolocation ( options ) { const { longitude , latitude , accuracy = 0 } = options ; if ( longitude < - 180 || longitude > 180 ) throw new Error ( `Invalid longitude "${ longitude }": precondition -180 <= LONGITUDE <= 180 failed.` ) ; if ( latitude < - 90 || latitude > 90 ) throw new Error ( `Invalid latitude "${ latitude }": precondition -90 <= LATITUDE <= 90 failed.` ) ; if ( accuracy < 0 ) throw new Error ( `Invalid accuracy "${ accuracy }": precondition 0 <= ACCURACY failed.` ) ; await this . _client . send ( 'Emulation.setGeolocationOverride' , { longitude , latitude , accuracy , } ) ; } returns target ( ) { return this . _target ; } internal client ( ) { return this . _client ; } /**
     * Get the browser the page belongs to.
     */ browser ( ) { return this . _target . browser ( ) ; } /**
     * Get the browser context that the page belongs to.
     */ browserContext ( ) { return this . _target . browserContext ( ) ; } private _onTargetCrashed ( ) { this . emit ( 'error' , new Error ( 'Page crashed!' ) ) ; } private _onLogEntryAdded ( event ) { const { level , text , args , source , url , lineNumber } = event . entry ; if ( args ) args . map ( ( arg ) => helper . releaseObject ( this . _client , arg ) ) ; if ( source !== 'worker' ) this . emit ( PageEmittedEvents . Console , new ConsoleMessage ( level , text , [ ] , [ { url , lineNumber } ] ) ) ; } returns remarks mainFrame ( ) { return this . _frameManager . mainFrame ( ) ; } get keyboard ( ) : Keyboard { return this . _keyboard ; } get touchscreen ( ) : Touchscreen { return this . _touchscreen ; } get coverage ( ) : Coverage { return this . _coverage ; } get tracing ( ) : Tracing { return this . _tracing ; } get accessibility ( ) : Accessibility { return this . _accessibility ; } returns frames ( ) { return this . _frameManager . frames ( ) ; } returns all of the dedicated
     *  https * WebWorkers}
     * associated with the page.
     *  remarks workers ( ) { return Array . from ( this . _workers . values ( ) ) ; } param value remarks Activating request interception enables  HTTPRequest . abort ,
     *  HTTPRequest . continue and  HTTPRequest . respond methods.  This
     * provides the capability to modify network requests that are made by a page.
     *
     * Once request interception is enabled, every request will stall unless it's
     * continued, responded or aborted; or completed using the browser cache.
     *
     *  example async setRequestInterception ( value ) { return this . _frameManager . networkManager ( ) . setRequestInterception ( value ) ; } param enabled remarks async setDragInterception ( enabled ) { this . _userDragInterceptionEnabled = enabled ; return this . _client . send ( 'Input.setInterceptDrags' , { enabled } ) ; } param enabled remarks setOfflineMode ( enabled ) { return this . _frameManager . networkManager ( ) . setOfflineMode ( enabled ) ; } param networkConditions example remarks emulateNetworkConditions ( networkConditions ) { return this . _frameManager . networkManager ( ) . emulateNetworkConditions ( networkConditions ) ; } /**
     * This setting will change the default maximum navigation time for the
     * following methods and related shortcuts:
     *
     * -  Page . goBack *
     * -  Page . goForward *
     * -  Page . goto *
     * -  Page . reload *
     * -  Page . setContent *
     * -  Page . waitForNavigation param timeout setDefaultNavigationTimeout ( timeout ) { this . _timeoutSettings . setDefaultNavigationTimeout ( timeout ) ; } param timeout setDefaultTimeout ( timeout ) { this . _timeoutSettings . setDefaultTimeout ( timeout ) ; } remarks Shortcut for  Frame . $ .
     *
     *  param selector - A `selector` to query page for
     *  https * to query page for.
      async $ < T extends Element = Element > ( selector ) { return this . mainFrame ( ) . $ < T > ( selector ) ; } remarks The only difference between  Page . evaluate and
     * `page.evaluateHandle` is that `evaluateHandle` will return the value
     * wrapped in an in-page object.
     *
     * If the function passed to `page.evaluteHandle` returns a Promise, the
     * function will wait for the promise to resolve and return its value.
     *
     * You can pass a string instead of a function (although functions are
     * recommended as they are easier to debug and use with TypeScript):
     *
     *  example example JSHandle instances can be passed as arguments to the `pageFunction`:
     * ```
     * const aHandle = await page.evaluateHandle(() => document.body);
     * const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);
     * console.log(await resultHandle.jsonValue());
     * await resultHandle.dispose();
     * ```
     *
     * Most of the time this function returns a  JSHandle ,
     * but if `pageFunction` returns a reference to an element,
     * you instead get an  ElementHandle back:
     *
     *  example param pageFunction param args async evaluateHandle < HandlerType extends JSHandle = JSHandle > ( pageFunction , ... args ) { const context = await this . mainFrame ( ) . executionContext ( ) ; return context . evaluateHandle < HandlerType > ( pageFunction , ... args ) ; } remarks Shortcut for
     *  ExecutionContext . queryObjects * page.mainFrame().executionContext().queryObjects(prototypeHandle)}.
     *
     *  example param prototypeHandle returns async queryObjects ( prototypeHandle ) { const context = await this . mainFrame ( ) . executionContext ( ) ; return context . queryObjects ( prototypeHandle ) ; } remarks example example example param selector - the
     *  https * to query for
     *  param pageFunction param args returns The result of calling `pageFunction`. If it returns an element it
     * is wrapped in an  ElementHandle , else the raw value itself is
     * returned.
      async $eval < ReturnType > ( selector , pageFunction , ... args ) { return this . mainFrame ( ) . $eval < ReturnType > ( selector , pageFunction , ... args ) ; } remarks example example example param selector - the
     *  https * to query for
     *  param pageFunction param args returns The result of calling `pageFunction`. If it returns an element it
     * is wrapped in an  ElementHandle , else the raw value itself is
     * returned.
      async $$eval < ReturnType > ( selector , pageFunction , ... args ) { return this . mainFrame ( ) . $$eval < ReturnType > ( selector , pageFunction , ... args ) ; } remarks Shortcut for  Frame . $$ .
     *  param selector async $$ < T extends Element = Element > ( selector ) { return this . mainFrame ( ) . $$ < T > ( selector ) ; } remarks Shortcut for  Frame . $x .
     *  param expression async $x ( expression ) { return this . mainFrame ( ) . $x ( expression ) ; } /**
     * If no URLs are specified, this method returns cookies for the current page
     * URL. If URLs are specified, only cookies for those URLs are returned.
     */ async cookies ( ... urls ) { const originalCookies = ( await this . _client . send ( 'Network.getCookies' , { urls : urls . length ? urls : [ this . url ( ) ] , } ) ) . cookies ; const unsupportedCookieAttributes = [ 'priority' ] ; const filterUnsupportedAttributes = ( cookie ) : Protocol . Network . Cookie => { for ( const attr of unsupportedCookieAttributes ) delete cookie [ attr ] ; return cookie ; } ; return originalCookies . map ( filterUnsupportedAttributes ) ; } async deleteCookie ( ... cookies ) { const pageURL = this . url ( ) ; for ( const cookie of cookies ) { const item = Object . assign ( { } , cookie ) ; if ( ! cookie . url && pageURL . startsWith ( 'http' ) ) item . url = pageURL ; await this . _client . send ( 'Network.deleteCookies' , item ) ; } } example async setCookie ( ... cookies ) { const pageURL = this . url ( ) ; const startsWithHTTP = pageURL . startsWith ( 'http' ) ; const items = cookies . map ( ( cookie ) => { const item = Object . assign ( { } , cookie ) ; if ( ! item . url && startsWithHTTP ) item . url = pageURL ; assert ( item . url !== 'about:blank' , `Blank page can not have cookie "${ item . name }"` ) ; assert ( ! String . prototype . startsWith . call ( item . url || '' , 'data:' ) , `Data URL page can not have cookie "${ item . name }"` ) ; return item ; } ) ; await this . deleteCookie ( ... items ) ; if ( items . length ) await this . _client . send ( 'Network.setCookies' , { cookies : items } ) ; } remarks Shortcut for  Frame . addScriptTag .
     *  returns async addScriptTag ( options ) { return this . mainFrame ( ) . addScriptTag ( options ) ; } returns async addStyleTag ( options ) { return this . mainFrame ( ) . addStyleTag ( options ) ; } param name param puppeteerFunction example async exposeFunction ( name , puppeteerFunction ) { if ( this . _pageBindings . has ( name ) ) throw new Error ( `Failed to add page binding with name ${ name }: window['${ name }'] already exists!` ) ; let exposedFunction ; if ( typeof puppeteerFunction === 'function' ) { exposedFunction = puppeteerFunction ; } else if ( typeof puppeteerFunction . default === 'function' ) { exposedFunction = puppeteerFunction . default ; } else { throw new Error ( `Failed to add page binding with name ${ name }: ${ puppeteerFunction } is not a function or a module with a default export.` ) ; } this . _pageBindings . set ( name , exposedFunction ) ; const expression = helper . pageBindingInitString ( 'exposedFun' , name ) ; await this . _client . send ( 'Runtime.addBinding' , { name : name } ) ; await this . _client . send ( 'Page.addScriptToEvaluateOnNewDocument' , { source : expression , } ) ; await Promise . all ( this . frames ( ) . map ( ( frame ) => frame . evaluate ( expression ) . catch ( debugError ) ) ) ; } remarks async authenticate ( credentials ) { return this . _frameManager . networkManager ( ) . authenticate ( credentials ) ; } param headers returns async setExtraHTTPHeaders ( headers ) { return this . _frameManager . networkManager ( ) . setExtraHTTPHeaders ( headers ) ; } param userAgent param userAgentData returns async setUserAgent ( userAgent , userAgentMetadata ? ) { return this . _frameManager . networkManager ( ) . setUserAgent ( userAgent , userAgentMetadata ) ; } returns remarks async metrics ( ) { const response = await this . _client . send ( 'Performance.getMetrics' ) ; return this . _buildMetricsObject ( response . metrics ) ; } private _emitMetrics ( event ) { this . emit ( PageEmittedEvents . Metrics , { title : event . title , metrics : this . _buildMetricsObject ( event . metrics ) , } ) ; } private _buildMetricsObject ( metrics ? ) { const result = { } ; for ( const metric of metrics || [ ] ) { if ( supportedMetrics . has ( metric . name ) ) result [ metric . name ] = metric . value ; } return result ; } private _handleException ( exceptionDetails ) { const message = helper . getExceptionMessage ( exceptionDetails ) ; const err = new Error ( message ) ; err . stack = '' ; this . emit ( PageEmittedEvents . PageError , err ) ; } private async _onConsoleAPI ( event ) { if ( event . executionContextId === 0 ) { return ; } const context = this . _frameManager . executionContextById ( event . executionContextId , this . _client ) ; const values = event . args . map ( ( arg ) => createJSHandle ( context , arg ) ) ; this . _addConsoleMessage ( event . type , values , event . stackTrace ) ; } private async _onBindingCalled ( event ) { let payload ; try { payload = JSON . parse ( event . payload ) ; } catch { return ; } const { type , name , seq , args } = payload ; if ( type !== 'exposedFun' || ! this . _pageBindings . has ( name ) ) return ; let expression = null ; try { const result = await this . _pageBindings . get ( name ) ( ... args ) ; expression = helper . pageBindingDeliverResultString ( name , seq , result ) ; } catch ( error ) { if ( error instanceof Error ) expression = helper . pageBindingDeliverErrorString ( name , seq , error . message , error . stack ) ; else expression = helper . pageBindingDeliverErrorValueString ( name , seq , error ) ; } this . _client . send ( 'Runtime.evaluate' , { expression , contextId : event . executionContextId , } ) . catch ( debugError ) ; } private _addConsoleMessage ( type , args , stackTrace ? ) { if ( ! this . listenerCount ( PageEmittedEvents . Console ) ) { args . forEach ( ( arg ) => arg . dispose ( ) ) ; return ; } const textTokens = [ ] ; for ( const arg of args ) { const remoteObject = arg . _remoteObject ; if ( remoteObject . objectId ) textTokens . push ( arg . toString ( ) ) ; else textTokens . push ( helper . valueFromRemoteObject ( remoteObject ) ) ; } const stackTraceLocations = [ ] ; if ( stackTrace ) { for ( const callFrame of stackTrace . callFrames ) { stackTraceLocations . push ( { url : callFrame . url , lineNumber : callFrame . lineNumber , columnNumber : callFrame . columnNumber , } ) ; } } const message = new ConsoleMessage ( type , textTokens . join ( ' ' ) , args , stackTraceLocations ) ; this . emit ( PageEmittedEvents . Console , message ) ; } private _onDialog ( event ) { let dialogType = null ; const validDialogTypes = new Set < Protocol . Page . DialogType > ( [ 'alert' , 'confirm' , 'prompt' , 'beforeunload' , ] ) ; if ( validDialogTypes . has ( event . type ) ) { dialogType = event . type as Protocol . Page . DialogType ; } assert ( dialogType , 'Unknown javascript dialog type: ' + event . type ) ; const dialog = new Dialog ( this . _client , dialogType , event . message , event . defaultPrompt ) ; this . emit ( PageEmittedEvents . Dialog , dialog ) ; } /**
     * Resets default white background
     */ private async _resetDefaultBackgroundColor ( ) { await this . _client . send ( 'Emulation.setDefaultBackgroundColorOverride' ) ; } /**
     * Hides default white background
     */ private async _setTransparentBackgroundColor ( ) { await this . _client . send ( 'Emulation.setDefaultBackgroundColorOverride' , { color : { r : 0 , g : 0 , b : 0 , a : 0 } , } ) ; } returns remarks Shortcut for
     *  Frame . url .
      url ( ) { return this . mainFrame ( ) . url ( ) ; } async content ( ) { return await this . _frameManager . mainFrame ( ) . content ( ) ; } param html param options remarks The parameter `options` might have the following options.
     *
     * - `timeout` : Maximum time in milliseconds for resources to load, defaults
     *   to 30 seconds, pass `0` to disable timeout. The default value can be
     *   changed by using the
     *    Page . setDefaultNavigationTimeout *   page.setDefaultNavigationTimeout(timeout)}
     *   or  Page . setDefaultTimeout *   methods.
     *
     * - `waitUntil`: When to consider setting markup succeeded, defaults to `load`.
     *    Given an array of event strings, setting content is considered to be
     *    successful after all events have been fired. Events can be either:<br/>
     *  - `load` : consider setting content to be finished when the `load` event is
     *    fired.<br/>
     *  - `domcontentloaded` : consider setting content to be finished when the
     *   `DOMContentLoaded` event is fired.<br/>
     *  - `networkidle0` : consider setting content to be finished when there are no
     *   more than 0 network connections for at least `500` ms.<br/>
     *  - `networkidle2` : consider setting content to be finished when there are no
     *   more than 2 network connections for at least `500` ms.
      async setContent ( html , options = { } ) { await this . _frameManager . mainFrame ( ) . setContent ( html , options ) ; } param url param options returns remarks The argument `options` might have the following properties:
     *
     * - `timeout` : Maximum navigation time in milliseconds, defaults to 30
     *   seconds, pass 0 to disable timeout. The default value can be changed by
     *   using the
     *    Page . setDefaultNavigationTimeout *   page.setDefaultNavigationTimeout(timeout)}
     *   or  Page . setDefaultTimeout *   methods.
     *
     * - `waitUntil`:When to consider navigation succeeded, defaults to `load`.
     *    Given an array of event strings, navigation is considered to be successful
     *    after all events have been fired. Events can be either:<br/>
     *  - `load` : consider navigation to be finished when the load event is
     *    fired.<br/>
     *  - `domcontentloaded` : consider navigation to be finished when the
     *    DOMContentLoaded event is fired.<br/>
     *  - `networkidle0` : consider navigation to be finished when there are no
     *    more than 0 network connections for at least `500` ms.<br/>
     *  - `networkidle2` : consider navigation to be finished when there are no
     *    more than 2 network connections for at least `500` ms.
     *
     * - `referer` : Referer header value. If provided it will take preference
     *   over the referer header value set by
     *    Page . setExtraHTTPHeaders .
     *
     * `page.goto` will throw an error if:
     * - there's an SSL error (e.g. in case of self-signed certificates).
     * - target URL is invalid.
     * - the timeout is exceeded during navigation.
     * - the remote server does not respond or is unreachable.
     * - the main resource failed to load.
     *
     * `page.goto` will not throw an error when any valid HTTP status code is
     *   returned by the remote server, including 404 "Not Found" and 500
     *   "Internal Server Error". The status code for such responses can be
     *   retrieved by calling response.status().
     *
     * NOTE: `page.goto` either throws an error or returns a main resource
     * response. The only exceptions are navigation to about:blank or navigation
     * to the same URL with a different hash, which would succeed and return null.
     *
     * NOTE: Headless mode doesn't support navigation to a PDF document. See the
     *  https * | upstream issue}.
     *
     * Shortcut for  Frame . goto .
      async goto ( url , options = { } ) { return await this . _frameManager . mainFrame ( ) . goto ( url , options ) ; } param options returns remarks The argument `options` might have the following properties:
     *
     * - `timeout` : Maximum navigation time in milliseconds, defaults to 30
     *   seconds, pass 0 to disable timeout. The default value can be changed by
     *   using the
     *    Page . setDefaultNavigationTimeout *   page.setDefaultNavigationTimeout(timeout)}
     *   or  Page . setDefaultTimeout *   methods.
     *
     * - `waitUntil`: When to consider navigation succeeded, defaults to `load`.
     *    Given an array of event strings, navigation is considered to be
     *    successful after all events have been fired. Events can be either:<br/>
     *  - `load` : consider navigation to be finished when the load event is fired.<br/>
     *  - `domcontentloaded` : consider navigation to be finished when the
     *   DOMContentLoaded event is fired.<br/>
     *  - `networkidle0` : consider navigation to be finished when there are no
     *   more than 0 network connections for at least `500` ms.<br/>
     *  - `networkidle2` : consider navigation to be finished when there are no
     *   more than 2 network connections for at least `500` ms.
      async reload ( options ? ) { const result = await Promise . all < HTTPResponse , void > ( [ this . waitForNavigation ( options ) , this . _client . send ( 'Page.reload' ) , ] ) ; return result [ 0 ] ; } param options returns remarks NOTE: Usage of the
     *  https * to change the URL is considered a navigation.
     *
     * Shortcut for
     *  Frame . waitForNavigation .
      async waitForNavigation ( options = { } ) { return await this . _frameManager . mainFrame ( ) . waitForNavigation ( options ) ; } private _sessionClosePromise ( ) { if ( ! this . _disconnectPromise ) this . _disconnectPromise = new Promise ( ( fulfill ) => this . _client . once ( CDPSessionEmittedEvents . Disconnected , ( ) => fulfill ( new Error ( 'Target closed' ) ) ) ) ; return this . _disconnectPromise ; } param urlOrPredicate param options returns example remarks Optional Waiting Parameters have:
     *
     * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds, pass
     * `0` to disable the timeout. The default value can be changed by using the
     *  Page . setDefaultTimeout method.
      async waitForRequest ( urlOrPredicate , options = { } ) { const { timeout = this . _timeoutSettings . timeout ( ) } = options ; return helper . waitForEvent ( this . _frameManager . networkManager ( ) , NetworkManagerEmittedEvents . Request , ( request ) => { if ( helper . isString ( urlOrPredicate ) ) return urlOrPredicate === request . url ( ) ; if ( typeof urlOrPredicate === 'function' ) return ! ! urlOrPredicate ( request ) ; return false ; } , timeout , this . _sessionClosePromise ( ) ) ; } param urlOrPredicate param options returns example remarks Optional Parameter have:
     *
     * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds,
     * pass `0` to disable the timeout. The default value can be changed by using
     * the  Page . setDefaultTimeout method.
      async waitForResponse ( urlOrPredicate , options = { } ) { const { timeout = this . _timeoutSettings . timeout ( ) } = options ; return helper . waitForEvent ( this . _frameManager . networkManager ( ) , NetworkManagerEmittedEvents . Response , async ( response ) => { if ( helper . isString ( urlOrPredicate ) ) return urlOrPredicate === response . url ( ) ; if ( typeof urlOrPredicate === 'function' ) return ! ! ( await urlOrPredicate ( response ) ) ; return false ; } , timeout , this . _sessionClosePromise ( ) ) ; } param options returns async waitForNetworkIdle ( options = { } ) { const { idleTime = 500 , timeout = this . _timeoutSettings . timeout ( ) } = options ; const networkManager = this . _frameManager . networkManager ( ) ; let idleResolveCallback ; const idlePromise = new Promise ( ( resolve ) => { idleResolveCallback = resolve ; } ) ; let abortRejectCallback ; const abortPromise = new Promise < Error > ( ( _ , reject ) => { abortRejectCallback = reject ; } ) ; let idleTimer ; const onIdle = ( ) => idleResolveCallback ( ) ; const cleanup = ( ) => { idleTimer && clearTimeout ( idleTimer ) ; abortRejectCallback ( new Error ( 'abort' ) ) ; } ; const evaluate = ( ) => { idleTimer && clearTimeout ( idleTimer ) ; if ( networkManager . numRequestsInProgress ( ) === 0 ) idleTimer = setTimeout ( onIdle , idleTime ) ; } ; evaluate ( ) ; const eventHandler = ( ) => { evaluate ( ) ; return false ; } ; const listenToEvent = ( event ) => helper . waitForEvent ( networkManager , event , eventHandler , timeout , abortPromise ) ; const eventPromises = [ listenToEvent ( NetworkManagerEmittedEvents . Request ) , listenToEvent ( NetworkManagerEmittedEvents . Response ) , ] ; await Promise . race ( [ idlePromise , ... eventPromises , this . _sessionClosePromise ( ) , ] ) . then ( ( r ) => { cleanup ( ) ; return r ; } , ( error ) => { cleanup ( ) ; throw error ; } ) ; } param urlOrPredicate param options returns example remarks Optional Parameter have:
     *
     * - `timeout`: Maximum wait time in milliseconds, defaults to `30` seconds,
     * pass `0` to disable the timeout. The default value can be changed by using
     * the  Page . setDefaultTimeout method.
      async waitForFrame ( urlOrPredicate , options = { } ) { const { timeout = this . _timeoutSettings . timeout ( ) } = options ; async function predicate ( frame ) { if ( helper . isString ( urlOrPredicate ) ) return urlOrPredicate === frame . url ( ) ; if ( typeof urlOrPredicate === 'function' ) return ! ! ( await urlOrPredicate ( frame ) ) ; return false ; } return Promise . race ( [ helper . waitForEvent ( this . _frameManager , FrameManagerEmittedEvents . FrameAttached , predicate , timeout , this . _sessionClosePromise ( ) ) , helper . waitForEvent ( this . _frameManager , FrameManagerEmittedEvents . FrameNavigated , predicate , timeout , this . _sessionClosePromise ( ) ) , ] ) ; } param options returns remarks The argument `options` might have the following properties:
     *
     * - `timeout` : Maximum navigation time in milliseconds, defaults to 30
     *   seconds, pass 0 to disable timeout. The default value can be changed by
     *   using the
     *    Page . setDefaultNavigationTimeout *   or  Page . setDefaultTimeout *   methods.
     *
     * - `waitUntil` : When to consider navigation succeeded, defaults to `load`.
     *    Given an array of event strings, navigation is considered to be
     *    successful after all events have been fired. Events can be either:<br/>
     *  - `load` : consider navigation to be finished when the load event is fired.<br/>
     *  - `domcontentloaded` : consider navigation to be finished when the
     *   DOMContentLoaded event is fired.<br/>
     *  - `networkidle0` : consider navigation to be finished when there are no
     *   more than 0 network connections for at least `500` ms.<br/>
     *  - `networkidle2` : consider navigation to be finished when there are no
     *   more than 2 network connections for at least `500` ms.
      async goBack ( options = { } ) { return this . _go ( - 1 , options ) ; } param options returns remarks The argument `options` might have the following properties:
     *
     * - `timeout` : Maximum navigation time in milliseconds, defaults to 30
     *   seconds, pass 0 to disable timeout. The default value can be changed by
     *   using the
     *    Page . setDefaultNavigationTimeout *   or  Page . setDefaultTimeout *   methods.
     *
     * - `waitUntil`: When to consider navigation succeeded, defaults to `load`.
     *    Given an array of event strings, navigation is considered to be
     *    successful after all events have been fired. Events can be either:<br/>
     *  - `load` : consider navigation to be finished when the load event is fired.<br/>
     *  - `domcontentloaded` : consider navigation to be finished when the
     *   DOMContentLoaded event is fired.<br/>
     *  - `networkidle0` : consider navigation to be finished when there are no
     *   more than 0 network connections for at least `500` ms.<br/>
     *  - `networkidle2` : consider navigation to be finished when there are no
     *   more than 2 network connections for at least `500` ms.
      async goForward ( options = { } ) { return this . _go ( + 1 , options ) ; } private async _go ( delta , options ) { const history = await this . _client . send ( 'Page.getNavigationHistory' ) ; const entry = history . entries [ history . currentIndex + delta ] ; if ( ! entry ) return null ; const result = await Promise . all ( [ this . waitForNavigation ( options ) , this . _client . send ( 'Page.navigateToHistoryEntry' , { entryId : entry . id } ) , ] ) ; return result [ 0 ] ; } /**
     * Brings page to front (activates tab).
     */ async bringToFront ( ) { await this . _client . send ( 'Page.bringToFront' ) ; } /**
     * Emulates given device metrics and user agent. This method is a shortcut for
     * calling two methods:  Page . setUserAgent and  Page . setViewport * To aid emulation, Puppeteer provides a list of device descriptors that can
     * be obtained via the  Puppeteer . devices `page.emulate` will resize
     * the page. A lot of websites don't expect phones to change size, so you
     * should emulate before navigating to the page.
     *  example remarks List of all available devices is available in the source code:
     *  https .
      async emulate ( options ) { await Promise . all ( [ this . setViewport ( options . viewport ) , this . setUserAgent ( options . userAgent ) , ] ) ; } param enabled returns remarks async setJavaScriptEnabled ( enabled ) { if ( this . _javascriptEnabled === enabled ) return ; this . _javascriptEnabled = enabled ; await this . _client . send ( 'Emulation.setScriptExecutionDisabled' , { value : ! enabled , } ) ; } param enabled remarks async setBypassCSP ( enabled ) { await this . _client . send ( 'Page.setBypassCSP' , { enabled } ) ; } param type example async emulateMediaType ( type ? ) { assert ( type === 'screen' || type === 'print' || type === null , 'Unsupported media type: ' + type ) ; await this . _client . send ( 'Emulation.setEmulatedMedia' , { media : type || '' , } ) ; } param factor async emulateCPUThrottling ( factor ) { assert ( factor === null || factor >= 1 , 'Throttling rate should be greater or equal to 1' ) ; await this . _client . send ( 'Emulation.setCPUThrottlingRate' , { rate : factor !== null ? factor : 1 , } ) ; } param features example async emulateMediaFeatures ( features ? ) { if ( features === null ) await this . _client . send ( 'Emulation.setEmulatedMedia' , { features : null } ) ; if ( Array . isArray ( features ) ) { features . every ( ( mediaFeature ) => { const name = mediaFeature . name ; assert ( /^(?:prefers-(?:color-scheme|reduced-motion)|color-gamut)$/ . test ( name ) , 'Unsupported media feature: ' + name ) ; return true ; } ) ; await this . _client . send ( 'Emulation.setEmulatedMedia' , { features : features , } ) ; } } param timezoneId - Changes the timezone of the page. See
     *  https * for a list of supported timezone IDs. Passing
     * `null` disables timezone emulation.
      async emulateTimezone ( timezoneId ? ) { try { await this . _client . send ( 'Emulation.setTimezoneOverride' , { timezoneId : timezoneId || '' , } ) ; } catch ( error ) { if ( error . message . includes ( 'Invalid timezone' ) ) throw new Error ( `Invalid timezone ID: ${ timezoneId }` ) ; throw error ; } } example param overrides async emulateIdleState ( overrides ? ) { if ( overrides ) { await this . _client . send ( 'Emulation.setIdleOverride' , { isUserActive : overrides . isUserActive , isScreenUnlocked : overrides . isScreenUnlocked , } ) ; } else { await this . _client . send ( 'Emulation.clearIdleOverride' ) ; } } example param type async emulateVisionDeficiency ( type ? ) { const visionDeficiencies = new Set < Protocol . Emulation . SetEmulatedVisionDeficiencyRequest [ 'type' ] > ( [ 'none' , 'achromatopsia' , 'blurredVision' , 'deuteranopia' , 'protanopia' , 'tritanopia' , ] ) ; try { assert ( ! type || visionDeficiencies . has ( type ) , `Unsupported vision deficiency: ${ type }` ) ; await this . _client . send ( 'Emulation.setEmulatedVisionDeficiency' , { type : type || 'none' , } ) ; } catch ( error ) { throw error ; } } example param viewport remarks async setViewport ( viewport ) { const needsReload = await this . _emulationManager . emulateViewport ( viewport ) ; this . _viewport = viewport ; if ( needsReload ) await this . reload ( ) ; } returns viewport ( ) { return this . _viewport ; } remarks example example example ElementHandle instances (including  JSHandle s) can be passed
     * as arguments to the `pageFunction`:
     *
     * ```
     * const bodyHandle = await page.$('body');
     * const html = await page.evaluate(body => body.innerHTML, bodyHandle);
     * await bodyHandle.dispose();
     * ```
     *
     *  param pageFunction param args returns async evaluate < T extends EvaluateFn > ( pageFunction , ... args ) { return this . _frameManager . mainFrame ( ) . evaluate < T > ( pageFunction , ... args ) ; } param pageFunction param args example async evaluateOnNewDocument ( pageFunction , ... args ) { const source = helper . evaluationString ( pageFunction , ... args ) ; await this . _client . send ( 'Page.addScriptToEvaluateOnNewDocument' , { source , } ) ; } param enabled async setCacheEnabled ( enabled = true ) { await this . _frameManager . networkManager ( ) . setCacheEnabled ( enabled ) ; } remarks Options object which might have the following properties:
     *
     * - `path` : The file path to save the image to. The screenshot type
     *   will be inferred from file extension. If `path` is a relative path, then
     *   it is resolved relative to
     *    https *   | current working directory}.
     *   If no path is provided, the image won't be saved to the disk.
     *
     * - `type` : Specify screenshot type, can be either `jpeg` or `png`.
     *   Defaults to 'png'.
     *
     * - `quality` : The quality of the image, between 0-100. Not
     *   applicable to `png` images.
     *
     * - `fullPage` : When true, takes a screenshot of the full
     *   scrollable page. Defaults to `false`
     *
     * - `clip` : An object which specifies clipping region of the page.
     *   Should have the following fields:<br/>
     *  - `x` : x-coordinate of top-left corner of clip area.<br/>
     *  - `y` :  y-coordinate of top-left corner of clip area.<br/>
     *  - `width` : width of clipping area.<br/>
     *  - `height` : height of clipping area.
     *
     * - `omitBackground` : Hides default white background and allows
     *   capturing screenshots with transparency. Defaults to `false`
     *
     * - `encoding` : The encoding of the image, can be either base64 or
     *   binary. Defaults to `binary`.
     *
     *
     * NOTE: Screenshots take at least 1/6 second on OS X. See
     *  https for discussion.
     *  returns async screenshot ( options = { } ) { let screenshotType = null ; if ( options . type ) { const type = options . type ; if ( type !== 'png' && type !== 'jpeg' && type !== 'webp' ) { assertNever ( type , 'Unknown options.type value: ' + type ) ; } screenshotType = options . type ; } else if ( options . path ) { const filePath = options . path ; const extension = filePath . slice ( filePath . lastIndexOf ( '.' ) + 1 ) . toLowerCase ( ) ; if ( extension === 'png' ) screenshotType = 'png' ; else if ( extension === 'jpg' || extension === 'jpeg' ) screenshotType = 'jpeg' ; else if ( extension === 'webp' ) screenshotType = 'webp' ; assert ( screenshotType , `Unsupported screenshot type for extension \`.${ extension }\`` ) ; } if ( ! screenshotType ) screenshotType = 'png' ; if ( options . quality ) { assert ( screenshotType === 'jpeg' || screenshotType === 'webp' , 'options.quality is unsupported for the ' + screenshotType + ' screenshots' ) ; assert ( typeof options . quality === 'number' , 'Expected options.quality to be a number but found ' + typeof options . quality ) ; assert ( Number . isInteger ( options . quality ) , 'Expected options.quality to be an integer' ) ; assert ( options . quality >= 0 && options . quality <= 100 , 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options . quality ) ; } assert ( ! options . clip || ! options . fullPage , 'options.clip and options.fullPage are exclusive' ) ; if ( options . clip ) { assert ( typeof options . clip . x === 'number' , 'Expected options.clip.x to be a number but found ' + typeof options . clip . x ) ; assert ( typeof options . clip . y === 'number' , 'Expected options.clip.y to be a number but found ' + typeof options . clip . y ) ; assert ( typeof options . clip . width === 'number' , 'Expected options.clip.width to be a number but found ' + typeof options . clip . width ) ; assert ( typeof options . clip . height === 'number' , 'Expected options.clip.height to be a number but found ' + typeof options . clip . height ) ; assert ( options . clip . width !== 0 , 'Expected options.clip.width not to be 0.' ) ; assert ( options . clip . height !== 0 , 'Expected options.clip.height not to be 0.' ) ; } return this . _screenshotTaskQueue . postTask ( ( ) => this . _screenshotTask ( screenshotType , options ) ) ; } private async _screenshotTask ( format , options ? ) { await this . _client . send ( 'Target.activateTarget' , { targetId : this . _target . _targetId , } ) ; let clip = options . clip ? processClip ( options . clip ) : undefined ; let { captureBeyondViewport = true } = options ; captureBeyondViewport = typeof captureBeyondViewport === 'boolean' ? captureBeyondViewport : true ; if ( options . fullPage ) { const metrics = await this . _client . send ( 'Page.getLayoutMetrics' ) ; const { width , height } = metrics . cssContentSize || metrics . contentSize ; clip = { x : 0 , y : 0 , width , height , scale : 1 } ; if ( ! captureBeyondViewport ) { const { isMobile = false , deviceScaleFactor = 1 , isLandscape = false , } = this . _viewport || { } ; const screenOrientation = isLandscape ? { angle : 90 , type : 'landscapePrimary' } : { angle : 0 , type : 'portraitPrimary' } ; await this . _client . send ( 'Emulation.setDeviceMetricsOverride' , { mobile : isMobile , width , height , deviceScaleFactor , screenOrientation , } ) ; } } const shouldSetDefaultBackground = options . omitBackground && ( format === 'png' || format === 'webp' ) ; if ( shouldSetDefaultBackground ) { await this . _setTransparentBackgroundColor ( ) ; } const result = await this . _client . send ( 'Page.captureScreenshot' , { format , quality : options . quality , clip , captureBeyondViewport , } ) ; if ( shouldSetDefaultBackground ) { await this . _resetDefaultBackgroundColor ( ) ; } if ( options . fullPage && this . _viewport ) await this . setViewport ( this . _viewport ) ; const buffer = options . encoding === 'base64' ? result . data : Buffer . from ( result . data , 'base64' ) ; if ( options . path ) { if ( ! isNode ) { throw new Error ( 'Screenshots can only be written to a file path in a Node environment.' ) ; } const fs = await helper . importFSModule ( ) ; await fs . promises . writeFile ( options . path , buffer ) ; } return buffer ; function processClip ( clip ) { const x = Math . round ( clip . x ) ; const y = Math . round ( clip . y ) ; const width = Math . round ( clip . width + clip . x - x ) ; const height = Math . round ( clip . height + clip . y - y ) ; return { x , y , width , height , scale : 1 } ; } } remarks NOTE: PDF generation is only supported in Chrome headless mode.
     *
     * To generate a PDF with the `screen` media type, call
     *  Page . emulateMediaType before
     * calling `page.pdf()`.
     *
     * By default, `page.pdf()` generates a pdf with modified colors for printing.
     * Use the
     *  https * property to force rendering of exact colors.
     *
     *
     *  param options async createPDFStream ( options = { } ) { const { scale = 1 , displayHeaderFooter = false , headerTemplate = '' , footerTemplate = '' , printBackground = false , landscape = false , pageRanges = '' , preferCSSPageSize = false , margin = { } , omitBackground = false , timeout = 30000 , } = options ; let paperWidth = 8.5 ; let paperHeight = 11 ; if ( options . format ) { const format = paperFormats [ options . format . toLowerCase ( ) ] ; assert ( format , 'Unknown paper format: ' + options . format ) ; paperWidth = format . width ; paperHeight = format . height ; } else { paperWidth = convertPrintParameterToInches ( options . width ) || paperWidth ; paperHeight = convertPrintParameterToInches ( options . height ) || paperHeight ; } const marginTop = convertPrintParameterToInches ( margin . top ) || 0 ; const marginLeft = convertPrintParameterToInches ( margin . left ) || 0 ; const marginBottom = convertPrintParameterToInches ( margin . bottom ) || 0 ; const marginRight = convertPrintParameterToInches ( margin . right ) || 0 ; if ( omitBackground ) { await this . _setTransparentBackgroundColor ( ) ; } const printCommandPromise = this . _client . send ( 'Page.printToPDF' , { transferMode : 'ReturnAsStream' , landscape , displayHeaderFooter , headerTemplate , footerTemplate , printBackground , scale , paperWidth , paperHeight , marginTop , marginBottom , marginLeft , marginRight , pageRanges , preferCSSPageSize , } ) ; const result = await helper . waitWithTimeout ( printCommandPromise , 'Page.printToPDF' , timeout ) ; if ( omitBackground ) { await this . _resetDefaultBackgroundColor ( ) ; } return helper . getReadableFromProtocolStream ( this . _client , result . stream ) ; } param options returns async pdf ( options = { } ) { const { path = undefined } = options ; const readable = await this . createPDFStream ( options ) ; return await helper . getReadableAsBuffer ( readable , path ) ; } returns remarks Shortcut for  Frame . title .
      async title ( ) { return this . mainFrame ( ) . title ( ) ; } async close ( options = { runBeforeUnload : undefined } ) { assert ( ! ! this . _client . _connection , 'Protocol error: Connection closed. Most likely the page has been closed.' ) ; const runBeforeUnload = ! ! options . runBeforeUnload ; if ( runBeforeUnload ) { await this . _client . send ( 'Page.close' ) ; } else { await this . _client . _connection . send ( 'Target.closeTarget' , { targetId : this . _target . _targetId , } ) ; await this . _target . _isClosedPromise ; } } returns isClosed ( ) { return this . _closed ; } get mouse ( ) : Mouse { return this . _mouse ; } /**
     * This method fetches an element with `selector`, scrolls it into view if
     * needed, and then uses  Page . mouse to click in the center of the
     * element. If there's no element matching `selector`, the method throws an
     * error.
     *  remarks Bear in mind that if `click()` triggers a navigation event and
     * there's a separate `page.waitForNavigation()` promise to be resolved, you
     * may end up with a race condition that yields unexpected results. The
     * correct pattern for click and wait for navigation is the following:
     * ```js
     * const [response] = await Promise.all([
     * page.waitForNavigation(waitOptions),
     * page.click(selector, clickOptions),
     * ]);
     * ```
     * Shortcut for  Frame . click .
     *  param selector param options returns click ( selector , options = { } ) { return this . mainFrame ( ) . click ( selector , options ) ; } param selector - A
     *  https * of an element to focus. If there are multiple elements satisfying the
     * selector, the first will be focused.
     *  returns remarks Shortcut for  Frame . focus .
      focus ( selector ) { return this . mainFrame ( ) . focus ( selector ) ; } /**
     * This method fetches an element with `selector`, scrolls it into view if
     * needed, and then uses  Page . mouse to hover over the center of the element.
     * If there's no element matching `selector`, the method throws an error.
     *  param selector - A
     *  https * to search for element to hover. If there are multiple elements satisfying
     * the selector, the first will be hovered.
     *  returns remarks Shortcut for  Page . hover .
      hover ( selector ) { return this . mainFrame ( ) . hover ( selector ) ; } example param selector - A
     *  https * to query the page for
     *  param values returns remarks Shortcut for  Frame . select select ( selector , ... values ) { return this . mainFrame ( ) . select ( selector , ... values ) ; } /**
     * This method fetches an element with `selector`, scrolls it into view if
     * needed, and then uses  Page . touchscreen to tap in the center of the element.
     * If there's no element matching `selector`, the method throws an error.
     *  param selector - A
     *  https * to search for element to tap. If there are multiple elements satisfying the
     * selector, the first will be tapped.
     *  returns remarks Shortcut for  Frame . tap .
      tap ( selector ) { return this . mainFrame ( ) . tap ( selector ) ; } /**
     * Sends a `keydown`, `keypress/input`, and `keyup` event for each character
     * in the text.
     *
     * To press a special key, like `Control` or `ArrowDown`, use  Keyboard . press .
     *  example param selector - A
     *  https * of an element to type into. If there are multiple elements satisfying the
     * selector, the first will be used.
     *  param text param options returns remarks type ( selector , text , options ? ) { return this . mainFrame ( ) . type ( selector , text , options ) ; } remarks This method behaves differently depending on the first parameter. If it's a
     * `string`, it will be treated as a `selector` or `xpath` (if the string
     * starts with `//`). This method then is a shortcut for
     *  Page . waitForSelector or  Page . waitForXPath .
     *
     * If the first argument is a function this method is a shortcut for
     *  Page . waitForFunction .
     *
     * If the first argument is a `number`, it's treated as a timeout in
     * milliseconds and the method returns a promise which resolves after the
     * timeout.
     *
     *  param selectorOrFunctionOrTimeout param options param args deprecated Don't use this method directly. Instead use the more explicit
     * methods available:  Page . waitForSelector ,
     *  Page . waitForXPath ,  Page . waitForFunction or
     *  Page . waitForTimeout .
      waitFor ( selectorOrFunctionOrTimeout , options = { } , ... args ) { return this . mainFrame ( ) . waitFor ( selectorOrFunctionOrTimeout , options , ... args ) ; } remarks It's generally recommended to not wait for a number of seconds, but instead
     * use  Page . waitForSelector ,  Page . waitForXPath or
     *  Page . waitForFunction to wait for exactly the conditions you want.
     *
     *  example param milliseconds waitForTimeout ( milliseconds ) { return this . mainFrame ( ) . waitForTimeout ( milliseconds ) ; } param selector - A
     *  https * of an element to wait for
     *  param options returns remarks The optional Parameter in Arguments `options` are :
     *
     * - `Visible`: A boolean wait for element to be present in DOM and to be
     * visible, i.e. to not have `display: none` or `visibility: hidden` CSS
     * properties. Defaults to `false`.
     *
     * - `hidden`: ait for element to not be found in the DOM or to be hidden,
     * i.e. have `display: none` or `visibility: hidden` CSS properties. Defaults to
     * `false`.
     *
     * - `timeout`: maximum time to wait for in milliseconds. Defaults to `30000`
     * (30 seconds). Pass `0` to disable timeout. The default value can be changed
     * by using the  Page . setDefaultTimeout method.
      waitForSelector ( selector , options = { } ) { return this . mainFrame ( ) . waitForSelector ( selector , options ) ; } param xpath - A
     *  https of an
     * element to wait for
     *  param options returns remarks The optional Argument `options` have properties:
     *
     * - `visible`: A boolean to wait for element to be present in DOM and to be
     * visible, i.e. to not have `display: none` or `visibility: hidden` CSS
     * properties. Defaults to `false`.
     *
     * - `hidden`: A boolean wait for element to not be found in the DOM or to be
     * hidden, i.e. have `display: none` or `visibility: hidden` CSS properties.
     * Defaults to `false`.
     *
     * - `timeout`: A number which is maximum time to wait for in milliseconds.
     * Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default
     * value can be changed by using the  Page . setDefaultTimeout method.
      waitForXPath ( xpath , options = { } ) { return this . mainFrame ( ) . waitForXPath ( xpath , options ) ; } param pageFunction param options param args returns Promise which resolves when the `pageFunction` returns a truthy
     * value. It resolves to a JSHandle of the truthy value.
     *
     * The optional waiting parameter can be:
     *
     * - `Polling`: An interval at which the `pageFunction` is executed, defaults to
     *   `raf`. If `polling` is a number, then it is treated as an interval in
     *   milliseconds at which the function would be executed. If polling is a
     *   string, then it can be one of the following values:<br/>
     *    - `raf`: to constantly execute `pageFunction` in `requestAnimationFrame`
     *      callback. This is the tightest polling mode which is suitable to
     *      observe styling changes.<br/>
     *    - `mutation`: to execute pageFunction on every DOM mutation.
     *
     * - `timeout`: maximum time to wait for in milliseconds. Defaults to `30000`
     * (30 seconds). Pass `0` to disable timeout. The default value can be changed
     * by using the
     *  Page . setDefaultTimeout method.
     *
      waitForFunction ( pageFunction , options = { } , ... args ) { return this . mainFrame ( ) . waitForFunction ( pageFunction , options , ... args ) ; } } const supportedMetrics = new Set < string > ( [ 'Timestamp' , 'Documents' , 'Frames' , 'JSEventListeners' , 'Nodes' , 'LayoutCount' , 'RecalcStyleCount' , 'LayoutDuration' , 'RecalcStyleDuration' , 'ScriptDuration' , 'TaskDuration' , 'JSHeapUsedSize' , 'JSHeapTotalSize' , ] ) ; const unitToPixels = { px : 1 , in : 96 , cm : 37.8 , mm : 3.78 , } ; function convertPrintParameterToInches ( parameter ? ) { if ( typeof parameter === 'undefined' ) return undefined ; let pixels ; if ( helper . isNumber ( parameter ) ) { pixels = parameter ; } else if ( helper . isString ( parameter ) ) { const text = parameter ; let unit = text . substring ( text . length - 2 ) . toLowerCase ( ) ; let valueText = '' ; if ( unitToPixels . hasOwnProperty ( unit ) ) { valueText = text . substring ( 0 , text . length - 2 ) ; } else { unit = 'px' ; valueText = text ; } const value = Number ( valueText ) ; assert ( ! isNaN ( value ) , 'Failed to parse parameter value: ' + text ) ; pixels = value * unitToPixels [ unit ] ; } else { throw new Error ( 'page.pdf() Cannot handle parameter type: ' + typeof parameter ) ; } return pixels / 96 ; }