fix: infer unioned handles (#8562)

This commit is contained in:
jrandolf 2022-06-24 08:40:08 +02:00 committed by GitHub
parent 23622c8d27
commit 8100cbb295
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 119 additions and 109 deletions

View File

@ -41,43 +41,43 @@ import {CustomQueryHandler} from './common/QueryHandler.js';
*/ */
export * from './common/Accessibility.js'; export * from './common/Accessibility.js';
export * from './common/Browser.js'; export * from './common/Browser.js';
export * from './node/BrowserFetcher.js'; export * from './common/BrowserConnector.js';
export * from './node/Puppeteer.js';
export * from './common/Coverage.js';
export * from './common/Connection.js'; export * from './common/Connection.js';
export * from './common/ConsoleMessage.js'; export * from './common/ConsoleMessage.js';
export * from './common/Coverage.js'; export * from './common/Coverage.js';
export * from './common/Coverage.js';
export * from './common/DeviceDescriptors.js'; export * from './common/DeviceDescriptors.js';
export * from './common/Dialog.js'; export * from './common/Dialog.js';
export * from './common/DOMWorld.js'; export * from './common/DOMWorld.js';
export * from './common/JSHandle.js'; export * from './common/Errors.js';
export * from './common/ExecutionContext.js';
export * from './common/EventEmitter.js'; export * from './common/EventEmitter.js';
export * from './common/ExecutionContext.js';
export * from './common/FileChooser.js'; export * from './common/FileChooser.js';
export * from './common/FrameManager.js'; export * from './common/FrameManager.js';
export * from './common/PuppeteerViewport.js';
export * from './common/Input.js';
export * from './common/Page.js';
export * from './common/Product.js';
export * from './common/Puppeteer.js';
export * from './common/BrowserConnector.js';
export * from './node/ProductLauncher.js';
export * from './node/LaunchOptions.js';
export * from './common/HTTPRequest.js'; export * from './common/HTTPRequest.js';
export * from './common/HTTPResponse.js'; export * from './common/HTTPResponse.js';
export * from './common/Input.js';
export * from './common/JSHandle.js';
export * from './common/LifecycleWatcher.js';
export * from './common/NetworkConditions.js';
export * from './common/NetworkManager.js';
export * from './common/Page.js';
export * from './common/PDFOptions.js';
export * from './common/Product.js';
export * from './common/Puppeteer.js';
export * from './common/PuppeteerViewport.js';
export * from './common/QueryHandler.js';
export * from './common/SecurityDetails.js'; export * from './common/SecurityDetails.js';
export * from './common/Target.js'; export * from './common/Target.js';
export * from './common/Errors.js';
export * from './common/Tracing.js';
export * from './common/NetworkManager.js';
export * from './common/WebWorker.js';
export * from './common/USKeyboardLayout.js';
export * from './common/types.js';
export * from './common/PDFOptions.js';
export * from './common/TimeoutSettings.js'; export * from './common/TimeoutSettings.js';
export * from './common/LifecycleWatcher.js'; export * from './common/Tracing.js';
export * from './common/QueryHandler.js'; export * from './common/types.js';
export * from './common/NetworkConditions.js'; export * from './common/USKeyboardLayout.js';
export * from './common/WebWorker.js';
export * from './node/BrowserFetcher.js';
export * from './node/LaunchOptions.js';
export * from './node/ProductLauncher.js';
export * from './node/Puppeteer.js';
export * from 'devtools-protocol/types/protocol'; export * from 'devtools-protocol/types/protocol';
/* /*

View File

@ -26,7 +26,7 @@ import {JSHandle} from './JSHandle.js';
import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js'; import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {_getQueryHandlerAndSelector} from './QueryHandler.js'; import {_getQueryHandlerAndSelector} from './QueryHandler.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {EvaluateFunc, EvaluateParams, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import { import {
debugError, debugError,
isNumber, isNumber,
@ -183,7 +183,7 @@ export class DOMWorld {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
const context = await this.executionContext(); const context = await this.executionContext();
return context.evaluateHandle(pageFunction, ...args); return context.evaluateHandle(pageFunction, ...args);
@ -194,7 +194,7 @@ export class DOMWorld {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const context = await this.executionContext(); const context = await this.executionContext();
return context.evaluate(pageFunction, ...args); return context.evaluate(pageFunction, ...args);
@ -253,7 +253,7 @@ export class DOMWorld {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -263,7 +263,7 @@ export class DOMWorld {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -273,7 +273,7 @@ export class DOMWorld {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const document = await this._document(); const document = await this._document();
return document.$eval(selector, pageFunction, ...args); return document.$eval(selector, pageFunction, ...args);
@ -288,7 +288,7 @@ export class DOMWorld {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -298,7 +298,7 @@ export class DOMWorld {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -308,7 +308,7 @@ export class DOMWorld {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const document = await this._document(); const document = await this._document();
const value = await document.$$eval(selector, pageFunction, ...args); const value = await document.$$eval(selector, pageFunction, ...args);

View File

@ -16,7 +16,7 @@ import {
} from './JSHandle.js'; } from './JSHandle.js';
import {Page, ScreenshotOptions} from './Page.js'; import {Page, ScreenshotOptions} from './Page.js';
import {_getQueryHandlerAndSelector} from './QueryHandler.js'; import {_getQueryHandlerAndSelector} from './QueryHandler.js';
import {EvaluateFunc, EvaluateParams} from './types.js'; import {EvaluateFunc} from './types.js';
import {KeyInput} from './USKeyboardLayout.js'; import {KeyInput} from './USKeyboardLayout.js';
import {debugError, isString} from './util.js'; import {debugError, isString} from './util.js';
@ -898,7 +898,7 @@ export class ElementHandle<
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -908,7 +908,7 @@ export class ElementHandle<
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -918,7 +918,7 @@ export class ElementHandle<
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const elementHandle = await this.$(selector); const elementHandle = await this.$(selector);
if (!elementHandle) { if (!elementHandle) {
@ -963,7 +963,7 @@ export class ElementHandle<
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -973,7 +973,7 @@ export class ElementHandle<
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -983,7 +983,7 @@ export class ElementHandle<
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
const {updatedSelector, queryHandler} = const {updatedSelector, queryHandler} =
_getQueryHandlerAndSelector(selector); _getQueryHandlerAndSelector(selector);

View File

@ -18,15 +18,15 @@ import {Protocol} from 'devtools-protocol';
import {assert} from './assert.js'; import {assert} from './assert.js';
import {CDPSession} from './Connection.js'; import {CDPSession} from './Connection.js';
import {DOMWorld} from './DOMWorld.js'; import {DOMWorld} from './DOMWorld.js';
import {EvaluateFunc, HandleFor, EvaluateParams} from './types.js'; import {ElementHandle} from './ElementHandle.js';
import {Frame} from './FrameManager.js'; import {Frame} from './FrameManager.js';
import {JSHandle} from './JSHandle.js'; import {JSHandle} from './JSHandle.js';
import {ElementHandle} from './ElementHandle.js'; import {EvaluateFunc, HandleFor} from './types.js';
import { import {
getExceptionMessage, getExceptionMessage,
_createJSHandle,
isString, isString,
valueFromRemoteObject, valueFromRemoteObject,
_createJSHandle,
} from './util.js'; } from './util.js';
/** /**
@ -145,7 +145,7 @@ export class ExecutionContext {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return await this.#evaluate(true, pageFunction, ...args); return await this.#evaluate(true, pageFunction, ...args);
} }
@ -197,7 +197,7 @@ export class ExecutionContext {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
return this.#evaluate(false, pageFunction, ...args); return this.#evaluate(false, pageFunction, ...args);
} }
@ -208,7 +208,7 @@ export class ExecutionContext {
>( >(
returnByValue: true, returnByValue: true,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async #evaluate< async #evaluate<
Params extends unknown[], Params extends unknown[],
@ -216,7 +216,7 @@ export class ExecutionContext {
>( >(
returnByValue: false, returnByValue: false,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>>; ): Promise<HandleFor<Awaited<ReturnType<Func>>>>;
async #evaluate< async #evaluate<
Params extends unknown[], Params extends unknown[],
@ -224,7 +224,7 @@ export class ExecutionContext {
>( >(
returnByValue: boolean, returnByValue: boolean,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>> | Awaited<ReturnType<Func>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>> | Awaited<ReturnType<Func>>> {
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`; const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`;

View File

@ -27,7 +27,7 @@ import {LifecycleWatcher, PuppeteerLifeCycleEvent} from './LifecycleWatcher.js';
import {NetworkManager} from './NetworkManager.js'; import {NetworkManager} from './NetworkManager.js';
import {Page} from './Page.js'; import {Page} from './Page.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {EvaluateFunc, EvaluateParams, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import {debugError, isErrorLike} from './util.js'; import {debugError, isErrorLike} from './util.js';
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__'; const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
@ -889,7 +889,7 @@ export class Frame {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
return this._mainWorld.evaluateHandle(pageFunction, ...args); return this._mainWorld.evaluateHandle(pageFunction, ...args);
} }
@ -908,7 +908,7 @@ export class Frame {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this._mainWorld.evaluate(pageFunction, ...args); return this._mainWorld.evaluate(pageFunction, ...args);
} }
@ -979,7 +979,7 @@ export class Frame {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -989,7 +989,7 @@ export class Frame {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -999,7 +999,7 @@ export class Frame {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this._mainWorld.$eval(selector, pageFunction, ...args); return this._mainWorld.$eval(selector, pageFunction, ...args);
} }
@ -1032,7 +1032,7 @@ export class Frame {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -1042,7 +1042,7 @@ export class Frame {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -1052,7 +1052,7 @@ export class Frame {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this._mainWorld.$$eval(selector, pageFunction, ...args); return this._mainWorld.$$eval(selector, pageFunction, ...args);
} }
@ -1440,7 +1440,7 @@ export class Frame {
>( >(
pageFunction: Func | string, pageFunction: Func | string,
options: FrameWaitForFunctionOptions = {}, options: FrameWaitForFunctionOptions = {},
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
// TODO: Fix when NodeHandle has been added. // TODO: Fix when NodeHandle has been added.
return this._mainWorld.waitForFunction( return this._mainWorld.waitForFunction(

View File

@ -17,7 +17,7 @@
import {Protocol} from 'devtools-protocol'; import {Protocol} from 'devtools-protocol';
import {assert} from './assert.js'; import {assert} from './assert.js';
import {CDPSession} from './Connection.js'; import {CDPSession} from './Connection.js';
import {EvaluateFunc, EvaluateParams, HandleFor, HandleOr} from './types.js'; import {EvaluateFunc, HandleFor, HandleOr} from './types.js';
import {ExecutionContext} from './ExecutionContext.js'; import {ExecutionContext} from './ExecutionContext.js';
import {MouseButton} from './Input.js'; import {MouseButton} from './Input.js';
import {releaseObject, valueFromRemoteObject, _createJSHandle} from './util.js'; import {releaseObject, valueFromRemoteObject, _createJSHandle} from './util.js';
@ -121,9 +121,9 @@ export class JSHandle<T = unknown> {
} }
/** /**
* This method passes this handle as the first argument to `pageFunction`. * This method passes this handle as the first argument to `pageFunction`. If
* If `pageFunction` returns a Promise, then `handle.evaluate` would wait * `pageFunction` returns a Promise, then `handle.evaluate` would wait for the
* for the promise to resolve and return its value. * promise to resolve and return its value.
* *
* @example * @example
* ```js * ```js
@ -134,11 +134,15 @@ export class JSHandle<T = unknown> {
async evaluate< async evaluate<
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc<[T, ...Params]> = EvaluateFunc<[T, ...Params]> Func extends EvaluateFunc<[this, ...Params]> = EvaluateFunc<
[this, ...Params]
>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): // @ts-expect-error Circularity here is okay because we only need the return
// type which doesn't use `this`.
Promise<Awaited<ReturnType<Func>>> {
return await this.executionContext().evaluate(pageFunction, this, ...args); return await this.executionContext().evaluate(pageFunction, this, ...args);
} }
@ -148,22 +152,26 @@ export class JSHandle<T = unknown> {
* @remarks * @remarks
* *
* The only difference between `jsHandle.evaluate` and * The only difference between `jsHandle.evaluate` and
* `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle` * `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle` returns an
* returns an in-page object (JSHandle). * in-page object (JSHandle).
* *
* If the function passed to `jsHandle.evaluateHandle` returns a Promise, * If the function passed to `jsHandle.evaluateHandle` returns a Promise, then
* then `evaluateHandle.evaluateHandle` waits for the promise to resolve and * `evaluateHandle.evaluateHandle` waits for the promise to resolve and
* returns its value. * returns its value.
* *
* See {@link Page.evaluateHandle} for more details. * See {@link Page.evaluateHandle} for more details.
*/ */
async evaluateHandle< async evaluateHandle<
Params extends unknown[], Params extends unknown[],
Func extends EvaluateFunc<[T, ...Params]> = EvaluateFunc<[T, ...Params]> Func extends EvaluateFunc<[this, ...Params]> = EvaluateFunc<
[this, ...Params]
>
>( >(
pageFunction: Func, pageFunction: Func,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): // @ts-expect-error Circularity here is okay because we only need the return
// type which doesn't use `this`.
Promise<HandleFor<Awaited<ReturnType<Func>>>> {
return await this.executionContext().evaluateHandle( return await this.executionContext().evaluateHandle(
pageFunction, pageFunction,
this, this,
@ -187,8 +195,8 @@ export class JSHandle<T = unknown> {
} }
/** /**
* The method returns a map with property names as keys and JSHandle * The method returns a map with property names as keys and JSHandle instances
* instances for the property values. * for the property values.
* *
* @example * @example
* ```js * ```js

View File

@ -49,7 +49,7 @@ import {Target} from './Target.js';
import {TaskQueue} from './TaskQueue.js'; import {TaskQueue} from './TaskQueue.js';
import {TimeoutSettings} from './TimeoutSettings.js'; import {TimeoutSettings} from './TimeoutSettings.js';
import {Tracing} from './Tracing.js'; import {Tracing} from './Tracing.js';
import {EvaluateFunc, EvaluateParams, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import { import {
debugError, debugError,
evaluationString, evaluationString,
@ -1083,7 +1083,7 @@ export class Page extends EventEmitter {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
const context = await this.mainFrame().executionContext(); const context = await this.mainFrame().executionContext();
return context.evaluateHandle(pageFunction, ...args); return context.evaluateHandle(pageFunction, ...args);
@ -1190,7 +1190,7 @@ export class Page extends EventEmitter {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -1200,7 +1200,7 @@ export class Page extends EventEmitter {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $eval< async $eval<
Params extends unknown[], Params extends unknown[],
@ -1210,7 +1210,7 @@ export class Page extends EventEmitter {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this.mainFrame().$eval(selector, pageFunction, ...args); return this.mainFrame().$eval(selector, pageFunction, ...args);
} }
@ -1286,7 +1286,7 @@ export class Page extends EventEmitter {
>( >(
selector: Selector, selector: Selector,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -1296,7 +1296,7 @@ export class Page extends EventEmitter {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>>; ): Promise<Awaited<ReturnType<Func>>>;
async $$eval< async $$eval<
Params extends unknown[], Params extends unknown[],
@ -1306,7 +1306,7 @@ export class Page extends EventEmitter {
>( >(
selector: string, selector: string,
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this.mainFrame().$$eval(selector, pageFunction, ...args); return this.mainFrame().$$eval(selector, pageFunction, ...args);
} }
@ -2683,7 +2683,7 @@ export class Page extends EventEmitter {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return this.#frameManager.mainFrame().evaluate(pageFunction, ...args); return this.#frameManager.mainFrame().evaluate(pageFunction, ...args);
} }
@ -3464,7 +3464,7 @@ export class Page extends EventEmitter {
timeout?: number; timeout?: number;
polling?: string | number; polling?: string | number;
} = {}, } = {},
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
return this.mainFrame().waitForFunction(pageFunction, options, ...args); return this.mainFrame().waitForFunction(pageFunction, options, ...args);
} }

View File

@ -16,7 +16,7 @@
import {Protocol} from 'devtools-protocol'; import {Protocol} from 'devtools-protocol';
import {CDPSession} from './Connection.js'; import {CDPSession} from './Connection.js';
import {ConsoleMessageType} from './ConsoleMessage.js'; import {ConsoleMessageType} from './ConsoleMessage.js';
import {EvaluateFunc, EvaluateParams, HandleFor} from './types.js'; import {EvaluateFunc, HandleFor} from './types.js';
import {EventEmitter} from './EventEmitter.js'; import {EventEmitter} from './EventEmitter.js';
import {ExecutionContext} from './ExecutionContext.js'; import {ExecutionContext} from './ExecutionContext.js';
import {JSHandle} from './JSHandle.js'; import {JSHandle} from './JSHandle.js';
@ -141,7 +141,7 @@ export class WebWorker extends EventEmitter {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<Awaited<ReturnType<Func>>> { ): Promise<Awaited<ReturnType<Func>>> {
return (await this.#executionContextPromise).evaluate( return (await this.#executionContextPromise).evaluate(
pageFunction, pageFunction,
@ -166,7 +166,7 @@ export class WebWorker extends EventEmitter {
Func extends EvaluateFunc<Params> = EvaluateFunc<Params> Func extends EvaluateFunc<Params> = EvaluateFunc<Params>
>( >(
pageFunction: Func | string, pageFunction: Func | string,
...args: EvaluateParams<Params> ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>>> { ): Promise<HandleFor<Awaited<ReturnType<Func>>>> {
return (await this.#executionContextPromise).evaluateHandle( return (await this.#executionContextPromise).evaluateHandle(
pageFunction, pageFunction,

View File

@ -22,12 +22,11 @@ export type Awaitable<T> = T | PromiseLike<T>;
export type HandleFor<T> = T extends Element ? ElementHandle<T> : JSHandle<T>; export type HandleFor<T> = T extends Element ? ElementHandle<T> : JSHandle<T>;
export type HandleOr<T> = HandleFor<T> | JSHandle<T> | T; export type HandleOr<T> = HandleFor<T> | JSHandle<T> | T;
export type EvaluateParams<T extends unknown[]> = { type FlattenHandle<T> = T extends HandleOr<infer U> ? U : never;
[K in keyof T]: T[K] extends HandleOr<unknown> ? T[K] : HandleOr<T[K]>;
};
export type InnerParams<T extends unknown[]> = { export type InnerParams<T extends unknown[]> = {
[K in keyof T]: T[K] extends HandleOr<infer U> ? U : never; [K in keyof T]: FlattenHandle<T[K]>;
}; };
export type EvaluateFunc<T extends unknown[]> = ( export type EvaluateFunc<T extends unknown[]> = (
...params: InnerParams<T> ...params: InnerParams<T>
) => Awaitable<unknown>; ) => Awaitable<unknown>;

View File

@ -557,8 +557,8 @@ describeChromeOnly('AriaQueryHandler', () => {
const waitForSelector = page.waitForSelector('aria/zombo'); const waitForSelector = page.waitForSelector('aria/zombo');
await page.setContent(`<div aria-label='zombo'>anything</div>`); await page.setContent(`<div aria-label='zombo'>anything</div>`);
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, await waitForSelector) }, await waitForSelector)
).toBe('anything'); ).toBe('anything');
}); });

View File

@ -419,8 +419,8 @@ describe('Evaluation specs', function () {
const bodyHandle = await page.frames()[1]!.$('body'); const bodyHandle = await page.frames()[1]!.$('body');
let error!: Error; let error!: Error;
await page await page
.evaluate((body: HTMLElement) => { .evaluate(body => {
return body.innerHTML; return body?.innerHTML;
}, bodyHandle) }, bodyHandle)
.catch(error_ => { .catch(error_ => {
return (error = error_); return (error = error_);

View File

@ -245,8 +245,8 @@ describe('JSHandle', function () {
const element = aHandle.asElement(); const element = aHandle.asElement();
expect(element).toBeTruthy(); expect(element).toBeTruthy();
expect( expect(
await page.evaluate((e: HTMLElement) => { await page.evaluate(e => {
return e.nodeType === Node.TEXT_NODE; return e?.nodeType === Node.TEXT_NODE;
}, element) }, element)
); );
}); });

View File

@ -284,8 +284,8 @@ describe('querySelector', function () {
const html = (await page.$('html'))!; const html = (await page.$('html'))!;
const second = (await html.$('.second'))!; const second = (await html.$('.second'))!;
const inner = await second.$('.inner'); const inner = await second.$('.inner');
const content = await page.evaluate((e: HTMLElement) => { const content = await page.evaluate(e => {
return e.textContent; return e?.textContent;
}, inner); }, inner);
expect(content).toBe('A'); expect(content).toBe('A');
}); });
@ -456,7 +456,10 @@ describe('querySelector', function () {
describe('QueryAll', function () { describe('QueryAll', function () {
const handler: CustomQueryHandler = { const handler: CustomQueryHandler = {
queryAll: (element, selector) => { queryAll: (element, selector) => {
return Array.from(element.querySelectorAll(selector)); if (element instanceof Document || element instanceof Element) {
return element.querySelectorAll(selector);
}
return [];
}, },
}; };
before(() => { before(() => {

View File

@ -433,8 +433,8 @@ describe('waittask specs', function () {
page.setContent(`<div class='zombo'>anything</div>`), page.setContent(`<div class='zombo'>anything</div>`),
]); ]);
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, handle) }, handle)
).toBe('anything'); ).toBe('anything');
}); });
@ -690,8 +690,8 @@ describe('waittask specs', function () {
const waitForSelector = page.waitForSelector('.zombo'); const waitForSelector = page.waitForSelector('.zombo');
await page.setContent(`<div class='zombo'>anything</div>`); await page.setContent(`<div class='zombo'>anything</div>`);
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, await waitForSelector) }, await waitForSelector)
).toBe('anything'); ).toBe('anything');
}); });
@ -721,8 +721,8 @@ describe('waittask specs', function () {
'//p[normalize-space(.)="hello world"]' '//p[normalize-space(.)="hello world"]'
); );
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, await waitForXPath) }, await waitForXPath)
).toBe('hello world '); ).toBe('hello world ');
}); });
@ -795,8 +795,8 @@ describe('waittask specs', function () {
const waitForXPath = page.waitForXPath('//*[@class="zombo"]'); const waitForXPath = page.waitForXPath('//*[@class="zombo"]');
await page.setContent(`<div class='zombo'>anything</div>`); await page.setContent(`<div class='zombo'>anything</div>`);
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, await waitForXPath) }, await waitForXPath)
).toBe('anything'); ).toBe('anything');
}); });
@ -815,8 +815,8 @@ describe('waittask specs', function () {
await page.setContent(`<div>some text</div>`); await page.setContent(`<div>some text</div>`);
const waitForXPath = page.waitForXPath('/html/body/div'); const waitForXPath = page.waitForXPath('/html/body/div');
expect( expect(
await page.evaluate((x: HTMLElement) => { await page.evaluate(x => {
return x.textContent; return x?.textContent;
}, await waitForXPath) }, await waitForXPath)
).toBe('some text'); ).toBe('some text');
}); });