diff --git a/src/chromium/JSHandle.ts b/src/chromium/JSHandle.ts index c0dac2069c..1d47671f2d 100644 --- a/src/chromium/JSHandle.ts +++ b/src/chromium/JSHandle.ts @@ -27,6 +27,8 @@ import { Protocol } from './protocol'; import { releaseObject, valueFromRemoteObject } from './protocolHelper'; import Injected from '../injected/injected'; +type SelectorRoot = Element | ShadowRoot | Document; + type Point = { x: number; y: number; @@ -57,7 +59,7 @@ export class JSHandle { return this._context; } - async evaluate(pageFunction: Function | string, ...args: any[]): Promise<(any)> { + async evaluate(pageFunction: Function | string, ...args: any[]): Promise { return await this.executionContext().evaluate(pageFunction, this, ...args); } @@ -431,10 +433,8 @@ export class ElementHandle extends JSHandle { async $(selector: string): Promise { const handle = await this.evaluateHandle( - (element, selector, injected: Injected) => { - return injected.querySelector('css=' + selector, element); - }, - selector, await this._context._injected() + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelector('css=' + selector, root), + selector, await this._context._injected() ); const element = handle.asElement(); if (element) @@ -445,8 +445,8 @@ export class ElementHandle extends JSHandle { async $$(selector: string): Promise { const arrayHandle = await this.evaluateHandle( - (element, selector) => element.querySelectorAll(selector), - selector + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root), + selector, await this._context._injected() ); const properties = await arrayHandle.getProperties(); await arrayHandle.dispose(); @@ -459,7 +459,7 @@ export class ElementHandle extends JSHandle { return result; } - async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> { + async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise { const elementHandle = await this.$(selector); if (!elementHandle) throw new Error(`Error: failed to find element matching selector "${selector}"`); @@ -468,10 +468,10 @@ export class ElementHandle extends JSHandle { return result; } - async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> { + async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise { const arrayHandle = await this.evaluateHandle( - (element, selector) => Array.from(element.querySelectorAll(selector)), - selector + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root), + selector, await this._context._injected() ); const result = await arrayHandle.evaluate(pageFunction, ...args); diff --git a/src/firefox/DOMWorld.ts b/src/firefox/DOMWorld.ts index a7a71fa4f8..2df99d64a8 100644 --- a/src/firefox/DOMWorld.ts +++ b/src/firefox/DOMWorld.ts @@ -3,6 +3,7 @@ import {TimeoutError} from '../Errors'; import * as fs from 'fs'; import * as util from 'util'; import {ElementHandle, JSHandle} from './JSHandle'; +import { ExecutionContext } from './ExecutionContext'; const readFileAsync = util.promisify(fs.readFile); @@ -51,7 +52,7 @@ export class DOMWorld { waitTask.terminate(new Error('waitForFunction failed: frame got detached.')); } - async executionContext() { + async executionContext(): Promise { if (this._detached) throw new Error(`Execution Context is not available in detached frame "${this.url()}" (are you trying to evaluate?)`); return this._contextPromise; @@ -60,12 +61,12 @@ export class DOMWorld { throw new Error('Method not implemented.'); } - async evaluateHandle(pageFunction, ...args) { + async evaluateHandle(pageFunction, ...args): Promise { const context = await this.executionContext(); return context.evaluateHandle(pageFunction, ...args); } - async evaluate(pageFunction, ...args) { + async evaluate(pageFunction, ...args): Promise { const context = await this.executionContext(); return context.evaluate(pageFunction, ...args); } diff --git a/src/firefox/ExecutionContext.ts b/src/firefox/ExecutionContext.ts index 7532dd813d..6bec4f16bf 100644 --- a/src/firefox/ExecutionContext.ts +++ b/src/firefox/ExecutionContext.ts @@ -33,7 +33,7 @@ export class ExecutionContext { this._executionContextId = executionContextId; } - async evaluateHandle(pageFunction, ...args) { + async evaluateHandle(pageFunction, ...args): Promise { if (helper.isString(pageFunction)) { const payload = await this._session.send('Runtime.evaluate', { expression: pageFunction.trim(), @@ -105,7 +105,7 @@ export class ExecutionContext { return this._frame; } - async evaluate(pageFunction, ...args) { + async evaluate(pageFunction, ...args): Promise { try { const handle = await this.evaluateHandle(pageFunction, ...args); const result = await handle.jsonValue(); diff --git a/src/firefox/FrameManager.ts b/src/firefox/FrameManager.ts index 4a8dd79027..04cbb20a1f 100644 --- a/src/firefox/FrameManager.ts +++ b/src/firefox/FrameManager.ts @@ -352,7 +352,7 @@ export class Frame { return this._mainWorld.setContent(html); } - async evaluate(pageFunction, ...args) { + async evaluate(pageFunction, ...args): Promise { return this._mainWorld.evaluate(pageFunction, ...args); } @@ -376,7 +376,7 @@ export class Frame { return this._mainWorld.$x(expression); } - async evaluateHandle(pageFunction, ...args) { + async evaluateHandle(pageFunction, ...args): Promise { return this._mainWorld.evaluateHandle(pageFunction, ...args); } diff --git a/src/firefox/JSHandle.ts b/src/firefox/JSHandle.ts index cbb2b5c599..c67a84e8fa 100644 --- a/src/firefox/JSHandle.ts +++ b/src/firefox/JSHandle.ts @@ -23,6 +23,8 @@ import { JugglerSession } from './Connection'; import { MultiClickOptions, ClickOptions, selectFunction, SelectOption } from '../input'; import Injected from '../injected/injected'; +type SelectorRoot = Element | ShadowRoot | Document; + export class JSHandle { _context: ExecutionContext; protected _session: JugglerSession; @@ -203,9 +205,7 @@ export class ElementHandle extends JSHandle { async $(selector: string): Promise { const handle = await this._frame.evaluateHandle( - (element, selector, injected: Injected) => { - return injected.querySelector('css=' + selector, element); - }, + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelector('css=' + selector, root), this, selector, await this._context._injected() ); const element = handle.asElement(); @@ -215,10 +215,10 @@ export class ElementHandle extends JSHandle { return null; } - async $$(selector: string): Promise> { + async $$(selector: string): Promise { const arrayHandle = await this._frame.evaluateHandle( - (element, selector) => element.querySelectorAll(selector), - this, selector + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root), + this, selector, await this._context._injected() ); const properties = await arrayHandle.getProperties(); await arrayHandle.dispose(); @@ -231,7 +231,7 @@ export class ElementHandle extends JSHandle { return result; } - async $eval(selector: string, pageFunction: Function | string, ...args: Array): Promise<(object | undefined)> { + async $eval(selector: string, pageFunction: Function | string, ...args: Array): Promise { const elementHandle = await this.$(selector); if (!elementHandle) throw new Error(`Error: failed to find element matching selector "${selector}"`); @@ -240,10 +240,10 @@ export class ElementHandle extends JSHandle { return result; } - async $$eval(selector: string, pageFunction: Function | string, ...args: Array): Promise<(object | undefined)> { + async $$eval(selector: string, pageFunction: Function | string, ...args: Array): Promise { const arrayHandle = await this._frame.evaluateHandle( - (element, selector) => Array.from(element.querySelectorAll(selector)), - this, selector + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root), + this, selector, await this._context._injected() ); const result = await this._frame.evaluate(pageFunction, arrayHandle, ...args); diff --git a/src/injected/injected.ts b/src/injected/injected.ts index abd3db04ff..f4d6db4c53 100644 --- a/src/injected/injected.ts +++ b/src/injected/injected.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -import { SelectorEngine } from './selectorEngine'; +import { SelectorEngine, SelectorRoot } from './selectorEngine'; import { Utils } from './utils'; type ParsedSelector = { engine: SelectorEngine, selector: string }[]; @@ -17,25 +17,25 @@ export class Injected { this.engines.set(engine.name, engine); } - querySelector(selector: string, root: Element): Element | undefined { + querySelector(selector: string, root: SelectorRoot): Element | undefined { const parsed = this._parseSelector(selector); let element = root; for (const { engine, selector } of parsed) { - const next = engine.query(element.shadowRoot || element, selector); + const next = engine.query((element as Element).shadowRoot || element, selector); if (!next) return; element = next; } - return element; + return element as Element; } - querySelectorAll(selector: string, root: Element): Element[] { + querySelectorAll(selector: string, root: SelectorRoot): Element[] { const parsed = this._parseSelector(selector); - let set = new Set([ root ]); + let set = new Set([ root ]); for (const { engine, selector } of parsed) { const newSet = new Set(); for (const prev of set) { - for (const next of engine.queryAll(prev.shadowRoot || prev, selector)) { + for (const next of engine.queryAll((prev as Element).shadowRoot || prev, selector)) { if (newSet.has(next)) continue; newSet.add(next); @@ -43,7 +43,7 @@ export class Injected { } set = newSet; } - return Array.from(set); + return Array.from(set) as Element[]; } private _parseSelector(selector: string): ParsedSelector { diff --git a/src/webkit/JSHandle.ts b/src/webkit/JSHandle.ts index 2e0d16db0b..76d32ad2da 100644 --- a/src/webkit/JSHandle.ts +++ b/src/webkit/JSHandle.ts @@ -25,6 +25,8 @@ import { Protocol } from './protocol'; import { releaseObject, valueFromRemoteObject } from './protocolHelper'; import Injected from '../injected/injected'; +type SelectorRoot = Element | ShadowRoot | Document; + const writeFileAsync = helper.promisify(fs.writeFile); export function createJSHandle(context: ExecutionContext, remoteObject: Protocol.Runtime.RemoteObject) { @@ -52,7 +54,7 @@ export class JSHandle { return this._context; } - async evaluate(pageFunction: Function | string, ...args: any[]): Promise<(any)> { + async evaluate(pageFunction: Function | string, ...args: any[]): Promise { return await this.executionContext().evaluate(pageFunction, this, ...args); } @@ -310,9 +312,7 @@ export class ElementHandle extends JSHandle { async $(selector: string): Promise { const handle = await this.evaluateHandle( - (element, selector, injected: Injected) => { - return injected.querySelector('css=' + selector, element); - }, + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelector('css=' + selector, root), selector, await this._context._injected() ); const element = handle.asElement(); @@ -338,7 +338,7 @@ export class ElementHandle extends JSHandle { return result; } - async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> { + async $eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise { const elementHandle = await this.$(selector); if (!elementHandle) throw new Error(`Error: failed to find element matching selector "${selector}"`); @@ -347,10 +347,10 @@ export class ElementHandle extends JSHandle { return result; } - async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise<(object | undefined)> { + async $$eval(selector: string, pageFunction: Function | string, ...args: any[]): Promise { const arrayHandle = await this.evaluateHandle( - (element, selector) => Array.from(element.querySelectorAll(selector)), - selector + (root: SelectorRoot, selector: string, injected: Injected) => injected.querySelectorAll('css=' + selector, root), + selector, await this._context._injected() ); const result = await arrayHandle.evaluate(pageFunction, ...args);