Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: common types for evaluate functions #72

Merged
merged 1 commit into from
Nov 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/chromium/DOMWorld.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as fs from 'fs';
import * as types from '../types';
import { TimeoutError } from '../Errors';
import { ExecutionContext } from './ExecutionContext';
import { Frame } from './Frame';
Expand Down Expand Up @@ -79,14 +80,14 @@ export class DOMWorld {
return this._contextPromise;
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
evaluateHandle: types.EvaluateHandle<JSHandle> = async (pageFunction, ...args) => {
const context = await this.executionContext();
return context.evaluateHandle(pageFunction, ...args);
return context.evaluateHandle(pageFunction, ...args as any);
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
evaluate: types.Evaluate<JSHandle> = async (pageFunction, ...args) => {
const context = await this.executionContext();
return context.evaluate(pageFunction, ...args);
return context.evaluate(pageFunction, ...args as any);
}

async $(selector: string): Promise<ElementHandle | null> {
Expand All @@ -111,14 +112,14 @@ export class DOMWorld {
return value;
}

async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<any> {
$eval: types.$Eval<JSHandle> = async (selector, pageFunction, ...args) => {
const document = await this._document();
return document.$eval(selector, pageFunction, ...args);
return document.$eval(selector, pageFunction, ...args as any);
}

async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<any> {
$$eval: types.$$Eval<JSHandle> = async (selector, pageFunction, ...args) => {
const document = await this._document();
const value = await document.$$eval(selector, pageFunction, ...args);
const value = await document.$$eval(selector, pageFunction, ...args as any);
return value;
}

Expand Down Expand Up @@ -439,7 +440,7 @@ class WaitTask {
}
}

async function waitForPredicatePageFunction(predicateBody: string, polling: string, timeout: number, ...args): Promise<any> {
async function waitForPredicatePageFunction(predicateBody: string, polling: string | number, timeout: number, ...args): Promise<any> {
const predicate = new Function('...args', predicateBody);
let timedOut = false;
if (timeout)
Expand Down
9 changes: 5 additions & 4 deletions src/chromium/ExecutionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ import { Protocol } from './protocol';
import * as injectedSource from '../generated/injectedSource';
import * as cssSelectorEngineSource from '../generated/cssSelectorEngineSource';
import * as xpathSelectorEngineSource from '../generated/xpathSelectorEngineSource';
import * as types from '../types';

export const EVALUATION_SCRIPT_URL = '__playwright_evaluation_script__';
const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;

export class ExecutionContext {
export class ExecutionContext implements types.EvaluationContext<JSHandle> {
_client: CDPSession;
_world: DOMWorld;
private _injectedPromise: Promise<JSHandle> | null = null;
Expand All @@ -45,11 +46,11 @@ export class ExecutionContext {
return this._world ? this._world.frame() : null;
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
return await this._evaluateInternal(true /* returnByValue */, pageFunction, ...args);
evaluate: types.Evaluate<JSHandle> = (pageFunction, ...args) => {
return this._evaluateInternal(true /* returnByValue */, pageFunction, ...args);
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
evaluateHandle: types.EvaluateHandle<JSHandle> = (pageFunction, ...args) => {
return this._evaluateInternal(false /* returnByValue */, pageFunction, ...args);
}

Expand Down
17 changes: 9 additions & 8 deletions src/chromium/Frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

import * as types from '../types';
import { helper, assert } from '../helper';
import { ClickOptions, MultiClickOptions, PointerActionOptions, SelectOption } from '../input';
import { CDPSession } from './Connection';
Expand Down Expand Up @@ -68,12 +69,12 @@ export class Frame {
return this._mainWorld.executionContext();
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
return this._mainWorld.evaluateHandle(pageFunction, ...args);
evaluateHandle: types.EvaluateHandle<JSHandle> = (pageFunction, ...args) => {
return this._mainWorld.evaluateHandle(pageFunction, ...args as any);
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
return this._mainWorld.evaluate(pageFunction, ...args);
evaluate: types.Evaluate<JSHandle> = (pageFunction, ...args) => {
return this._mainWorld.evaluate(pageFunction, ...args as any);
}

async $(selector: string): Promise<ElementHandle | null> {
Expand All @@ -84,12 +85,12 @@ export class Frame {
return this._mainWorld.$x(expression);
}

async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> {
return this._mainWorld.$eval(selector, pageFunction, ...args);
$eval: types.$Eval<JSHandle> = (selector, pageFunction, ...args) => {
return this._mainWorld.$eval(selector, pageFunction, ...args as any);
}

async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> {
return this._mainWorld.$$eval(selector, pageFunction, ...args);
$$eval: types.$$Eval<JSHandle> = (selector, pageFunction, ...args) => {
return this._mainWorld.$$eval(selector, pageFunction, ...args as any);
}

async $$(selector: string): Promise<ElementHandle[]> {
Expand Down
17 changes: 9 additions & 8 deletions src/chromium/JSHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as path from 'path';
import * as types from '../types';
import { assert, debugError, helper } from '../helper';
import { ClickOptions, Modifier, MultiClickOptions, PointerActionOptions, SelectOption, selectFunction, fillFunction } from '../input';
import { CDPSession } from './Connection';
Expand Down Expand Up @@ -59,12 +60,12 @@ export class JSHandle {
return this._context;
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
return await this.executionContext().evaluate(pageFunction, this, ...args);
evaluate: types.EvaluateOn<JSHandle> = (pageFunction, ...args) => {
return this.executionContext().evaluate(pageFunction, this, ...args);
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
return await this.executionContext().evaluateHandle(pageFunction, this, ...args);
evaluateHandle: types.EvaluateHandleOn<JSHandle> = (pageFunction, ...args) => {
return this.executionContext().evaluateHandle(pageFunction, this, ...args);
}

async getProperty(propertyName: string): Promise<JSHandle | null> {
Expand Down Expand Up @@ -432,22 +433,22 @@ export class ElementHandle extends JSHandle {
return result;
}

async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<object | undefined> {
$eval: types.$Eval<JSHandle> = async (selector, pageFunction, ...args) => {
const elementHandle = await this.$(selector);
if (!elementHandle)
throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await elementHandle.evaluate(pageFunction, ...args);
const result = await elementHandle.evaluate(pageFunction, ...args as any);
await elementHandle.dispose();
return result;
}

async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<object | undefined> {
$$eval: types.$$Eval<JSHandle> = async (selector, pageFunction, ...args) => {
const arrayHandle = await this.evaluateHandle(
(root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root),
selector, await this._context._injected()
);

const result = await arrayHandle.evaluate(pageFunction, ...args);
const result = await arrayHandle.evaluate(pageFunction, ...args as any);
await arrayHandle.dispose();
return result;
}
Expand Down
17 changes: 9 additions & 8 deletions src/chromium/Page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { getExceptionMessage, releaseObject, valueFromRemoteObject } from './pro
import { Target } from './Target';
import { TaskQueue } from './TaskQueue';
import * as input from '../input';
import * as types from '../types';

const writeFileAsync = helper.promisify(fs.writeFile);

Expand Down Expand Up @@ -231,17 +232,17 @@ export class Page extends EventEmitter {
return this.mainFrame().$(selector);
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
evaluateHandle: types.EvaluateHandle<JSHandle> = async (pageFunction, ...args) => {
const context = await this.mainFrame().executionContext();
return context.evaluateHandle(pageFunction, ...args);
return context.evaluateHandle(pageFunction, ...args as any);
}

async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> {
return this.mainFrame().$eval(selector, pageFunction, ...args);
$eval: types.$Eval<JSHandle> = (selector, pageFunction, ...args) => {
return this.mainFrame().$eval(selector, pageFunction, ...args as any);
}

async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> {
return this.mainFrame().$$eval(selector, pageFunction, ...args);
$$eval: types.$$Eval<JSHandle> = (selector, pageFunction, ...args) => {
return this.mainFrame().$$eval(selector, pageFunction, ...args as any);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to cast to any here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, unfortunately I wasn't able to make the perfect forwarding work. Either I am holding it wrong, or typescript cannot figure out that Boxed<args, Handle> extends any[].

}

async $$(selector: string): Promise<ElementHandle[]> {
Expand Down Expand Up @@ -566,8 +567,8 @@ export class Page extends EventEmitter {
return this._viewport;
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
return this._frameManager.mainFrame().evaluate(pageFunction, ...args);
evaluate: types.Evaluate<JSHandle> = (pageFunction, ...args) => {
return this._frameManager.mainFrame().evaluate(pageFunction, ...args as any);
}

async evaluateOnNewDocument(pageFunction: Function | string, ...args: any[]) {
Expand Down
9 changes: 5 additions & 4 deletions src/chromium/features/workers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { debugError } from '../../helper';
import { JSHandle } from '../JSHandle';
import { Protocol } from '../protocol';
import { Events } from '../events';
import * as types from '../../types';

type AddToConsoleCallback = (type: string, args: JSHandle[], stackTrace: Protocol.Runtime.StackTrace | undefined) => void;
type HandleExceptionCallback = (exceptionDetails: Protocol.Runtime.ExceptionDetails) => void;
Expand Down Expand Up @@ -85,11 +86,11 @@ export class Worker extends EventEmitter {
return this._executionContextPromise;
}

async evaluate(pageFunction: Function | string, ...args: any[]): Promise<any> {
return (await this._executionContextPromise).evaluate(pageFunction, ...args);
evaluate: types.Evaluate<JSHandle> = async (pageFunction, ...args) => {
return (await this._executionContextPromise).evaluate(pageFunction, ...args as any);
}

async evaluateHandle(pageFunction: Function | string, ...args: any[]): Promise<JSHandle> {
return (await this._executionContextPromise).evaluateHandle(pageFunction, ...args);
evaluateHandle: types.EvaluateHandle<JSHandle> = async (pageFunction, ...args) => {
return (await this._executionContextPromise).evaluateHandle(pageFunction, ...args as any);
}
}
22 changes: 22 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

type Boxed<Args extends any[], Handle> = { [Index in keyof Args]: Args[Index] | Handle };
type PageFunction<Args extends any[], R = any> = string | ((...args: Args) => R | Promise<R>);
type PageFunctionOn<On, Args extends any[], R = any> = string | ((on: On, ...args: Args) => R | Promise<R>);

export type Evaluate<Handle> = <Args extends any[], R>(fn: PageFunction<Args, R>, ...args: Boxed<Args, Handle>) => Promise<R>;
export type EvaluateHandle<Handle> = <Args extends any[]>(fn: PageFunction<Args>, ...args: Boxed<Args, Handle>) => Promise<Handle>;
export type $Eval<Handle> = <Args extends any[], R>(selector: string, fn: PageFunctionOn<Element, Args, R>, ...args: Boxed<Args, Handle>) => Promise<R>;
export type $$Eval<Handle> = <Args extends any[], R>(selector: string, fn: PageFunctionOn<Element[], Args, R>, ...args: Boxed<Args, Handle>) => Promise<R>;
export type EvaluateOn<Handle> = <Args extends any[], R>(fn: PageFunctionOn<any, Args, R>, ...args: Boxed<Args, Handle>) => Promise<R>;
export type EvaluateHandleOn<Handle> = <Args extends any[]>(fn: PageFunctionOn<any, Args>, ...args: Boxed<Args, Handle>) => Promise<Handle>;

export interface EvaluationContext<Handle> {
evaluate: Evaluate<Handle>;
evaluateHandle: EvaluateHandle<Handle>;
}

export interface Handle {
dispose(): Promise<void>;
}