diff --git a/.eslintrc.js b/.eslintrc.js index 3e40356283b..32b5d161149 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -96,6 +96,8 @@ module.exports = { "rules": { "no-unused-vars": 0, "@typescript-eslint/no-unused-vars": 2, + "func-call-spacing": 0, + "@typescript-eslint/func-call-spacing": 2, "semi": 0, "@typescript-eslint/semi": 2, "@typescript-eslint/no-empty-function": 0, diff --git a/README.md b/README.md index afbe88db882..7bd432809f2 100644 --- a/README.md +++ b/README.md @@ -292,9 +292,25 @@ Puppeteer creates its own browser user profile which it **cleans up on every run - debug your test inside chromium like a boss! - + + +## Usage with TypeScript + +We have recently completed a migration to move the Puppeteer source code from JavaScript to TypeScript and we're currently working on shipping type definitions for TypeScript with Puppeteer's npm package. + +Until this work is complete we recommend installing the Puppeteer type definitions from the [DefinitelyTyped](https://definitelytyped.org/) repository: + +```bash +npm install --save-dev @types/puppeteer +``` + +The types that you'll see appearing in the Puppeteer source code are based off the great work of those who have contributed to the `@types/puppeteer` package. We really appreciate the hard work those people put in to providing high quality TypeScript definitions for Puppeteer's users. + + + + ## Contributing to Puppeteer Check out [contributing guide](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) to get an overview of Puppeteer development. diff --git a/new-docs/puppeteer.elementhandle.__eval.md b/new-docs/puppeteer.elementhandle.__eval.md index 62184b0bf0c..f351b5ef70c 100644 --- a/new-docs/puppeteer.elementhandle.__eval.md +++ b/new-docs/puppeteer.elementhandle.__eval.md @@ -11,7 +11,7 @@ If `pageFunction` returns a Promise, then `frame.$$eval` would wait for the prom Signature: ```typescript -$$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -19,8 +19,8 @@ $$eval(selector: string, pageFunction: Function | string | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.elementhandle._eval.md b/new-docs/puppeteer.elementhandle._eval.md index 51719ae1bfd..f0c8b8717eb 100644 --- a/new-docs/puppeteer.elementhandle._eval.md +++ b/new-docs/puppeteer.elementhandle._eval.md @@ -11,7 +11,7 @@ If `pageFunction` returns a Promise, then `frame.$eval` would wait for the promi Signature: ```typescript -$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -19,8 +19,8 @@ $eval(selector: string, pageFunction: Function | string, | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.evaluatefn.md b/new-docs/puppeteer.evaluatefn.md new file mode 100644 index 00000000000..8647ef2b7d3 --- /dev/null +++ b/new-docs/puppeteer.evaluatefn.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [EvaluateFn](./puppeteer.evaluatefn.md) + +## EvaluateFn type + + +Signature: + +```typescript +export declare type EvaluateFn = string | ((arg1: T, ...args: any[]) => any); +``` diff --git a/new-docs/puppeteer.evaluatefnreturntype.md b/new-docs/puppeteer.evaluatefnreturntype.md new file mode 100644 index 00000000000..471823e316e --- /dev/null +++ b/new-docs/puppeteer.evaluatefnreturntype.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [EvaluateFnReturnType](./puppeteer.evaluatefnreturntype.md) + +## EvaluateFnReturnType type + + +Signature: + +```typescript +export declare type EvaluateFnReturnType = T extends (...args: any[]) => infer R ? R : unknown; +``` diff --git a/new-docs/puppeteer.frame.__eval.md b/new-docs/puppeteer.frame.__eval.md index 0a7d7a9e18d..889af679f5c 100644 --- a/new-docs/puppeteer.frame.__eval.md +++ b/new-docs/puppeteer.frame.__eval.md @@ -7,7 +7,7 @@ Signature: ```typescript -$$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -15,8 +15,8 @@ $$eval(selector: string, pageFunction: Function | string | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.frame._eval.md b/new-docs/puppeteer.frame._eval.md index 0d5d3066c14..6eb63bae943 100644 --- a/new-docs/puppeteer.frame._eval.md +++ b/new-docs/puppeteer.frame._eval.md @@ -7,7 +7,7 @@ Signature: ```typescript -$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -15,8 +15,8 @@ $eval(selector: string, pageFunction: Function | string, | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.jshandle.evaluate.md b/new-docs/puppeteer.jshandle.evaluate.md index fef1efe89fb..c8cd3227e22 100644 --- a/new-docs/puppeteer.jshandle.evaluate.md +++ b/new-docs/puppeteer.jshandle.evaluate.md @@ -9,19 +9,19 @@ This method passes this handle as the first argument to `pageFunction`. Signature: ```typescript -evaluate(pageFunction: Function | string, ...args: unknown[]): Promise; +evaluate(pageFunction: T | string, ...args: SerializableOrJSHandle[]): Promise>; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | T \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: -Promise<ReturnType> +Promise<[EvaluateFnReturnType](./puppeteer.evaluatefnreturntype.md)<T>> ## Example diff --git a/new-docs/puppeteer.jsonarray.md b/new-docs/puppeteer.jsonarray.md new file mode 100644 index 00000000000..fea5db9a721 --- /dev/null +++ b/new-docs/puppeteer.jsonarray.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [JSONArray](./puppeteer.jsonarray.md) + +## JSONArray type + + +Signature: + +```typescript +export declare type JSONArray = Serializable[]; +``` diff --git a/new-docs/puppeteer.jsonobject.md b/new-docs/puppeteer.jsonobject.md new file mode 100644 index 00000000000..609425b7804 --- /dev/null +++ b/new-docs/puppeteer.jsonobject.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [JSONObject](./puppeteer.jsonobject.md) + +## JSONObject interface + + +Signature: + +```typescript +export interface JSONObject +``` diff --git a/new-docs/puppeteer.md b/new-docs/puppeteer.md index 8b2c127a439..200dab24ddb 100644 --- a/new-docs/puppeteer.md +++ b/new-docs/puppeteer.md @@ -52,6 +52,7 @@ | [BrowserFetcherOptions](./puppeteer.browserfetcheroptions.md) | | | [ClickOptions](./puppeteer.clickoptions.md) | | | [ConsoleMessageLocation](./puppeteer.consolemessagelocation.md) | | +| [JSONObject](./puppeteer.jsonobject.md) | | | [KeyDefinition](./puppeteer.keydefinition.md) | 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 athttp://www.apache.org/licenses/LICENSE-2.0Unless 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. | | [Metrics](./puppeteer.metrics.md) | | | [PressOptions](./puppeteer.pressoptions.md) | | @@ -73,7 +74,12 @@ | Type Alias | Description | | --- | --- | | [ConsoleMessageType](./puppeteer.consolemessagetype.md) | The supported types for console messages. | +| [EvaluateFn](./puppeteer.evaluatefn.md) | | +| [EvaluateFnReturnType](./puppeteer.evaluatefnreturntype.md) | | +| [JSONArray](./puppeteer.jsonarray.md) | | | [KeyInput](./puppeteer.keyinput.md) | | | [MouseButtonInput](./puppeteer.mousebuttoninput.md) | | | [PuppeteerErrors](./puppeteer.puppeteererrors.md) | | +| [Serializable](./puppeteer.serializable.md) | | +| [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md) | | diff --git a/new-docs/puppeteer.page.__eval.md b/new-docs/puppeteer.page.__eval.md index 4c7800a5019..3bcb6aea428 100644 --- a/new-docs/puppeteer.page.__eval.md +++ b/new-docs/puppeteer.page.__eval.md @@ -7,7 +7,7 @@ Signature: ```typescript -$$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -15,8 +15,8 @@ $$eval(selector: string, pageFunction: Function | string | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.page._eval.md b/new-docs/puppeteer.page._eval.md index d5b18ad8e77..8b1c1d7d159 100644 --- a/new-docs/puppeteer.page._eval.md +++ b/new-docs/puppeteer.page._eval.md @@ -7,7 +7,7 @@ Signature: ```typescript -$eval(selector: string, pageFunction: Function | string, ...args: unknown[]): Promise; +$eval(selector: string, pageFunction: EvaluateFn | string, ...args: SerializableOrJSHandle[]): Promise; ``` ## Parameters @@ -15,8 +15,8 @@ $eval(selector: string, pageFunction: Function | string, | Parameter | Type | Description | | --- | --- | --- | | selector | string | | -| pageFunction | Function \| string | | -| args | unknown\[\] | | +| pageFunction | [EvaluateFn](./puppeteer.evaluatefn.md) \| string | | +| args | [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md)\[\] | | Returns: diff --git a/new-docs/puppeteer.serializable.md b/new-docs/puppeteer.serializable.md new file mode 100644 index 00000000000..8b7a7df8bf1 --- /dev/null +++ b/new-docs/puppeteer.serializable.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [Serializable](./puppeteer.serializable.md) + +## Serializable type + + +Signature: + +```typescript +export declare type Serializable = number | string | boolean | null | JSONArray | JSONObject; +``` diff --git a/new-docs/puppeteer.serializableorjshandle.md b/new-docs/puppeteer.serializableorjshandle.md new file mode 100644 index 00000000000..84ca6eed8e5 --- /dev/null +++ b/new-docs/puppeteer.serializableorjshandle.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [SerializableOrJSHandle](./puppeteer.serializableorjshandle.md) + +## SerializableOrJSHandle type + + +Signature: + +```typescript +export declare type SerializableOrJSHandle = Serializable | JSHandle; +``` diff --git a/src/api-docs-entry.ts b/src/api-docs-entry.ts index 8e8ac591378..4a04e31cfd6 100644 --- a/src/api-docs-entry.ts +++ b/src/api-docs-entry.ts @@ -48,3 +48,4 @@ export * from './common/Errors'; export * from './common/Tracing'; export * from './common/WebWorker'; export * from './common/USKeyboardLayout'; +export * from './common/EvalTypes'; diff --git a/src/common/DOMWorld.ts b/src/common/DOMWorld.ts index 5600e557f16..3ea66d50ccd 100644 --- a/src/common/DOMWorld.ts +++ b/src/common/DOMWorld.ts @@ -24,6 +24,7 @@ import { TimeoutSettings } from './TimeoutSettings'; import { MouseButtonInput } from './Input'; import { FrameManager, Frame } from './FrameManager'; import { getQueryHandlerAndSelector, QueryHandler } from './QueryHandler'; +import { EvaluateFn, SerializableOrJSHandle } from './EvalTypes'; import { isNode } from '../environment'; // This predicateQueryHandler is declared here so that TypeScript knows about it @@ -155,8 +156,8 @@ export class DOMWorld { async $eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { const document = await this._document(); return document.$eval(selector, pageFunction, ...args); @@ -164,8 +165,8 @@ export class DOMWorld { async $$eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { const document = await this._document(); const value = await document.$$eval( diff --git a/src/common/EvalTypes.ts b/src/common/EvalTypes.ts new file mode 100644 index 00000000000..c898d22be47 --- /dev/null +++ b/src/common/EvalTypes.ts @@ -0,0 +1,58 @@ +/** + * Copyright 2020 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 { JSHandle } from './JSHandle'; + +/** + * @public + */ +export type EvaluateFn = string | ((arg1: T, ...args: any[]) => any); +/** + * @public + */ +export type EvaluateFnReturnType = T extends ( + ...args: any[] +) => infer R + ? R + : unknown; + +/** + * @public + */ +export type Serializable = + | number + | string + | boolean + | null + | JSONArray + | JSONObject; + +/** + * @public + */ +export type JSONArray = Serializable[]; + +/** + * @public + */ +export interface JSONObject { + [key: string]: Serializable; +} + +/** + * @public + */ +export type SerializableOrJSHandle = Serializable | JSHandle; diff --git a/src/common/FrameManager.ts b/src/common/FrameManager.ts index 6e56c753329..859b649eaa9 100644 --- a/src/common/FrameManager.ts +++ b/src/common/FrameManager.ts @@ -29,6 +29,7 @@ import { MouseButtonInput } from './Input'; import { Page } from './Page'; import { HTTPResponse } from './HTTPResponse'; import Protocol from '../protocol'; +import { EvaluateFn, SerializableOrJSHandle } from './EvalTypes'; const UTILITY_WORLD_NAME = '__puppeteer_utility_world__'; @@ -454,16 +455,16 @@ export class Frame { async $eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { return this._mainWorld.$eval(selector, pageFunction, ...args); } async $$eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { return this._mainWorld.$$eval(selector, pageFunction, ...args); } diff --git a/src/common/JSHandle.ts b/src/common/JSHandle.ts index 4273db864cd..2a8f0265b72 100644 --- a/src/common/JSHandle.ts +++ b/src/common/JSHandle.ts @@ -23,6 +23,11 @@ import { KeyInput } from './USKeyboardLayout'; import { FrameManager, Frame } from './FrameManager'; import { getQueryHandlerAndSelector } from './QueryHandler'; import Protocol from '../protocol'; +import { + EvaluateFn, + SerializableOrJSHandle, + EvaluateFnReturnType, +} from './EvalTypes'; /** * @public @@ -113,11 +118,12 @@ export class JSHandle { * expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10'); * ``` */ - async evaluate( - pageFunction: Function | string, - ...args: unknown[] - ): Promise { - return await this.executionContext().evaluate( + + async evaluate( + pageFunction: T | string, + ...args: SerializableOrJSHandle[] + ): Promise> { + return await this.executionContext().evaluate>( pageFunction, this, ...args @@ -307,46 +313,48 @@ export class ElementHandle extends JSHandle { } private async _scrollIntoViewIfNeeded(): Promise { - const error = await this.evaluate>( - async (element: HTMLElement, pageJavascriptEnabled: boolean) => { - if (!element.isConnected) return 'Node is detached from document'; - if (element.nodeType !== Node.ELEMENT_NODE) - return 'Node is not of type HTMLElement'; - // force-scroll if page's javascript is disabled. - if (!pageJavascriptEnabled) { - element.scrollIntoView({ - block: 'center', - inline: 'center', - // Chrome still supports behavior: instant but it's not in the spec - // so TS shouts We don't want to make this breaking change in - // Puppeteer yet so we'll ignore the line. - // @ts-ignore - behavior: 'instant', - }); - return false; - } - const visibleRatio = await new Promise((resolve) => { - const observer = new IntersectionObserver((entries) => { - resolve(entries[0].intersectionRatio); - observer.disconnect(); - }); - observer.observe(element); + const error = await this.evaluate< + ( + element: HTMLElement, + pageJavascriptEnabled: boolean + ) => Promise + >(async (element, pageJavascriptEnabled) => { + if (!element.isConnected) return 'Node is detached from document'; + if (element.nodeType !== Node.ELEMENT_NODE) + return 'Node is not of type HTMLElement'; + // force-scroll if page's javascript is disabled. + if (!pageJavascriptEnabled) { + element.scrollIntoView({ + block: 'center', + inline: 'center', + // Chrome still supports behavior: instant but it's not in the spec + // so TS shouts We don't want to make this breaking change in + // Puppeteer yet so we'll ignore the line. + // @ts-ignore + behavior: 'instant', }); - if (visibleRatio !== 1.0) { - element.scrollIntoView({ - block: 'center', - inline: 'center', - // Chrome still supports behavior: instant but it's not in the spec - // so TS shouts We don't want to make this breaking change in - // Puppeteer yet so we'll ignore the line. - // @ts-ignore - behavior: 'instant', - }); - } return false; - }, - this._page.isJavaScriptEnabled() - ); + } + const visibleRatio = await new Promise((resolve) => { + const observer = new IntersectionObserver((entries) => { + resolve(entries[0].intersectionRatio); + observer.disconnect(); + }); + observer.observe(element); + }); + if (visibleRatio !== 1.0) { + element.scrollIntoView({ + block: 'center', + inline: 'center', + // Chrome still supports behavior: instant but it's not in the spec + // so TS shouts We don't want to make this breaking change in + // Puppeteer yet so we'll ignore the line. + // @ts-ignore + behavior: 'instant', + }); + } + return false; + }, this._page.isJavaScriptEnabled()); if (error) throw new Error(error); } @@ -491,9 +499,9 @@ export class ElementHandle extends JSHandle { * relative to the {@link https://nodejs.org/api/process.html#process_process_cwd | current working directory} */ async uploadFile(...filePaths: string[]): Promise { - const isMultiple = await this.evaluate( - (element: HTMLInputElement) => element.multiple - ); + const isMultiple = await this.evaluate< + (element: HTMLInputElement) => boolean + >((element) => element.multiple); assert( filePaths.length <= 1 || isMultiple, 'Multiple file uploads only work with ' @@ -772,15 +780,15 @@ export class ElementHandle extends JSHandle { */ async $eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { const elementHandle = await this.$(selector); if (!elementHandle) throw new Error( `Error: failed to find element matching selector "${selector}"` ); - const result = await elementHandle.evaluate( + const result = await elementHandle.evaluate<(...args: any[]) => ReturnType>( pageFunction, ...args ); @@ -813,8 +821,8 @@ export class ElementHandle extends JSHandle { */ async $$eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { const defaultHandler = (element: Element, selector: string) => Array.from(element.querySelectorAll(selector)); @@ -827,7 +835,7 @@ export class ElementHandle extends JSHandle { queryHandler, updatedSelector ); - const result = await arrayHandle.evaluate( + const result = await arrayHandle.evaluate<(...args: any[]) => ReturnType>( pageFunction, ...args ); @@ -868,16 +876,18 @@ export class ElementHandle extends JSHandle { * Resolves to true if the element is visible in the current viewport. */ async isIntersectingViewport(): Promise { - return await this.evaluate>(async (element) => { - const visibleRatio = await new Promise((resolve) => { - const observer = new IntersectionObserver((entries) => { - resolve(entries[0].intersectionRatio); - observer.disconnect(); + return await this.evaluate<(element: Element) => Promise>( + async (element) => { + const visibleRatio = await new Promise((resolve) => { + const observer = new IntersectionObserver((entries) => { + resolve(entries[0].intersectionRatio); + observer.disconnect(); + }); + observer.observe(element); }); - observer.observe(element); - }); - return visibleRatio > 0; - }); + return visibleRatio > 0; + } + ); } } diff --git a/src/common/Page.ts b/src/common/Page.ts index ebe5bdced27..0fd724fb022 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -42,6 +42,7 @@ import { FileChooser } from './FileChooser'; import { ConsoleMessage, ConsoleMessageType } from './ConsoleMessage'; import { PuppeteerLifeCycleEvent } from './LifecycleWatcher'; import Protocol from '../protocol'; +import { EvaluateFn, SerializableOrJSHandle } from './EvalTypes'; const writeFileAsync = promisify(fs.writeFile); @@ -514,16 +515,16 @@ export class Page extends EventEmitter { async $eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { return this.mainFrame().$eval(selector, pageFunction, ...args); } async $$eval( selector: string, - pageFunction: Function | string, - ...args: unknown[] + pageFunction: EvaluateFn | string, + ...args: SerializableOrJSHandle[] ): Promise { return this.mainFrame().$$eval(selector, pageFunction, ...args); }