chore(rpc): use channels types in dispatchers (#3549)

This ensures we actually implement channels as intended.
For example, this change found an issue with Route.fulfill.
This commit is contained in:
Dmitry Gozman 2020-08-20 11:25:33 -07:00 committed by GitHub
parent e32a496e2e
commit eab5ff4eae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 173 additions and 170 deletions

View file

@ -190,10 +190,15 @@ export class Route {
await this._delegate.abort(errorCode); await this._delegate.abort(errorCode);
} }
async fulfill(response: types.NormalizedFulfillResponse) { async fulfill(response: { status?: number, headers?: types.HeadersArray, body?: string, isBase64?: boolean }) {
assert(!this._handled, 'Route is already handled!'); assert(!this._handled, 'Route is already handled!');
this._handled = true; this._handled = true;
await this._delegate.fulfill(response); await this._delegate.fulfill({
status: response.status === undefined ? 200 : response.status,
headers: response.headers || [],
body: response.body || '',
isBase64: response.isBase64 || false,
});
} }
async continue(overrides: types.NormalizedContinueOverrides = {}) { async continue(overrides: types.NormalizedContinueOverrides = {}) {

View file

@ -16,14 +16,14 @@
import { Browser } from '../../browser'; import { Browser } from '../../browser';
import { Events } from '../../events'; import { Events } from '../../events';
import { BrowserChannel, BrowserContextChannel, BrowserInitializer, CDPSessionChannel, Binary, BrowserNewContextParams } from '../channels'; import * as channels from '../channels';
import { BrowserContextDispatcher } from './browserContextDispatcher'; import { BrowserContextDispatcher } from './browserContextDispatcher';
import { CDPSessionDispatcher } from './cdpSessionDispatcher'; import { CDPSessionDispatcher } from './cdpSessionDispatcher';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { CRBrowser } from '../../chromium/crBrowser'; import { CRBrowser } from '../../chromium/crBrowser';
import { PageDispatcher } from './pageDispatcher'; import { PageDispatcher } from './pageDispatcher';
export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> implements BrowserChannel { export class BrowserDispatcher extends Dispatcher<Browser, channels.BrowserInitializer> implements channels.BrowserChannel {
constructor(scope: DispatcherScope, browser: Browser, guid?: string) { constructor(scope: DispatcherScope, browser: Browser, guid?: string) {
super(scope, browser, 'Browser', { version: browser.version() }, true, guid); super(scope, browser, 'Browser', { version: browser.version() }, true, guid);
browser.on(Events.Browser.Disconnected, () => this._didClose()); browser.on(Events.Browser.Disconnected, () => this._didClose());
@ -34,7 +34,7 @@ export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> i
this._dispose(); this._dispose();
} }
async newContext(params: BrowserNewContextParams): Promise<{ context: BrowserContextChannel }> { async newContext(params: channels.BrowserNewContextParams): Promise<channels.BrowserNewContextResult> {
return { context: new BrowserContextDispatcher(this._scope, await this._object.newContext(params)) }; return { context: new BrowserContextDispatcher(this._scope, await this._object.newContext(params)) };
} }
@ -42,17 +42,17 @@ export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> i
await this._object.close(); await this._object.close();
} }
async crNewBrowserCDPSession(): Promise<{ session: CDPSessionChannel }> { async crNewBrowserCDPSession(): Promise<channels.BrowserCrNewBrowserCDPSessionResult> {
const crBrowser = this._object as CRBrowser; const crBrowser = this._object as CRBrowser;
return { session: new CDPSessionDispatcher(this._scope, await crBrowser.newBrowserCDPSession()) }; return { session: new CDPSessionDispatcher(this._scope, await crBrowser.newBrowserCDPSession()) };
} }
async crStartTracing(params: { page?: PageDispatcher, path?: string, screenshots?: boolean, categories?: string[] }): Promise<void> { async crStartTracing(params: channels.BrowserCrStartTracingParams): Promise<void> {
const crBrowser = this._object as CRBrowser; const crBrowser = this._object as CRBrowser;
await crBrowser.startTracing(params.page ? params.page._object : undefined, params); await crBrowser.startTracing(params.page ? (params.page as PageDispatcher)._object : undefined, params);
} }
async crStopTracing(): Promise<{ binary: Binary }> { async crStopTracing(): Promise<channels.BrowserCrStopTracingResult> {
const crBrowser = this._object as CRBrowser; const crBrowser = this._object as CRBrowser;
const buffer = await crBrowser.stopTracing(); const buffer = await crBrowser.stopTracing();
return { binary: buffer.toString('base64') }; return { binary: buffer.toString('base64') };

View file

@ -16,11 +16,11 @@
import { BrowserTypeBase, BrowserType } from '../../server/browserType'; import { BrowserTypeBase, BrowserType } from '../../server/browserType';
import { BrowserDispatcher } from './browserDispatcher'; import { BrowserDispatcher } from './browserDispatcher';
import { BrowserChannel, BrowserTypeChannel, BrowserContextChannel, BrowserTypeInitializer, BrowserTypeLaunchParams, BrowserTypeLaunchPersistentContextParams } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { BrowserContextDispatcher } from './browserContextDispatcher'; import { BrowserContextDispatcher } from './browserContextDispatcher';
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeInitializer> implements BrowserTypeChannel { export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.BrowserTypeInitializer> implements channels.BrowserTypeChannel {
constructor(scope: DispatcherScope, browserType: BrowserTypeBase) { constructor(scope: DispatcherScope, browserType: BrowserTypeBase) {
super(scope, browserType, 'BrowserType', { super(scope, browserType, 'BrowserType', {
executablePath: browserType.executablePath(), executablePath: browserType.executablePath(),
@ -28,12 +28,12 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeIn
}, true); }, true);
} }
async launch(params: BrowserTypeLaunchParams): Promise<{ browser: BrowserChannel }> { async launch(params: channels.BrowserTypeLaunchParams): Promise<channels.BrowserTypeLaunchResult> {
const browser = await this._object.launch(params); const browser = await this._object.launch(params);
return { browser: new BrowserDispatcher(this._scope, browser) }; return { browser: new BrowserDispatcher(this._scope, browser) };
} }
async launchPersistentContext(params: BrowserTypeLaunchPersistentContextParams): Promise<{ context: BrowserContextChannel }> { async launchPersistentContext(params: channels.BrowserTypeLaunchPersistentContextParams): Promise<channels.BrowserTypeLaunchPersistentContextResult> {
const browserContext = await this._object.launchPersistentContext(params.userDataDir, params); const browserContext = await this._object.launchPersistentContext(params.userDataDir, params);
return { context: new BrowserContextDispatcher(this._scope, browserContext) }; return { context: new BrowserContextDispatcher(this._scope, browserContext) };
} }

View file

@ -15,10 +15,10 @@
*/ */
import { CRSession, CRSessionEvents } from '../../chromium/crConnection'; import { CRSession, CRSessionEvents } from '../../chromium/crConnection';
import { CDPSessionChannel, CDPSessionInitializer } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
export class CDPSessionDispatcher extends Dispatcher<CRSession, CDPSessionInitializer> implements CDPSessionChannel { export class CDPSessionDispatcher extends Dispatcher<CRSession, channels.CDPSessionInitializer> implements channels.CDPSessionChannel {
constructor(scope: DispatcherScope, crSession: CRSession) { constructor(scope: DispatcherScope, crSession: CRSession) {
super(scope, crSession, 'CDPSession', {}, true); super(scope, crSession, 'CDPSession', {}, true);
crSession._eventListener = (method, params) => { crSession._eventListener = (method, params) => {
@ -27,7 +27,7 @@ export class CDPSessionDispatcher extends Dispatcher<CRSession, CDPSessionInitia
crSession.on(CRSessionEvents.Disconnected, () => this._dispose()); crSession.on(CRSessionEvents.Disconnected, () => this._dispose());
} }
async send(params: { method: string, params?: any }): Promise<{ result: any }> { async send(params: channels.CDPSessionSendParams): Promise<channels.CDPSessionSendResult> {
return { result: await this._object.send(params.method as any, params.params) }; return { result: await this._object.send(params.method as any, params.params) };
} }

View file

@ -15,11 +15,11 @@
*/ */
import { ConsoleMessage } from '../../console'; import { ConsoleMessage } from '../../console';
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { createHandle } from './elementHandlerDispatcher'; import { createHandle } from './elementHandlerDispatcher';
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, ConsoleMessageInitializer> implements ConsoleMessageChannel { export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, channels.ConsoleMessageInitializer> implements channels.ConsoleMessageChannel {
constructor(scope: DispatcherScope, message: ConsoleMessage) { constructor(scope: DispatcherScope, message: ConsoleMessage) {
super(scope, message, 'ConsoleMessage', { super(scope, message, 'ConsoleMessage', {
type: message.type(), type: message.type(),

View file

@ -15,10 +15,10 @@
*/ */
import { Dialog } from '../../dialog'; import { Dialog } from '../../dialog';
import { DialogChannel, DialogInitializer } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
export class DialogDispatcher extends Dispatcher<Dialog, DialogInitializer> implements DialogChannel { export class DialogDispatcher extends Dispatcher<Dialog, channels.DialogInitializer> implements channels.DialogChannel {
constructor(scope: DispatcherScope, dialog: Dialog) { constructor(scope: DispatcherScope, dialog: Dialog) {
super(scope, dialog, 'Dialog', { super(scope, dialog, 'Dialog', {
type: dialog.type(), type: dialog.type(),

View file

@ -16,7 +16,7 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { helper, debugAssert, assert } from '../../helper'; import { helper, debugAssert, assert } from '../../helper';
import { Channel } from '../channels'; import * as channels from '../channels';
import { serializeError } from '../serializers'; import { serializeError } from '../serializers';
import { createScheme, Validator, ValidationError } from '../validator'; import { createScheme, Validator, ValidationError } from '../validator';
@ -36,7 +36,7 @@ export function lookupNullableDispatcher<DispatcherType>(object: any | null): Di
return object ? lookupDispatcher(object) : undefined; return object ? lookupDispatcher(object) : undefined;
} }
export class Dispatcher<Type, Initializer> extends EventEmitter implements Channel { export class Dispatcher<Type, Initializer> extends EventEmitter implements channels.Channel {
private _connection: DispatcherConnection; private _connection: DispatcherConnection;
private _isScope: boolean; private _isScope: boolean;
// Parent is always "isScope". // Parent is always "isScope".

View file

@ -15,11 +15,11 @@
*/ */
import { Download } from '../../download'; import { Download } from '../../download';
import { DownloadChannel, DownloadInitializer, StreamChannel } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { StreamDispatcher } from './streamDispatcher'; import { StreamDispatcher } from './streamDispatcher';
export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer> implements DownloadChannel { export class DownloadDispatcher extends Dispatcher<Download, channels.DownloadInitializer> implements channels.DownloadChannel {
constructor(scope: DispatcherScope, download: Download) { constructor(scope: DispatcherScope, download: Download) {
super(scope, download, 'Download', { super(scope, download, 'Download', {
url: download.url(), url: download.url(),
@ -27,16 +27,16 @@ export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer
}); });
} }
async path(): Promise<{ value?: string }> { async path(): Promise<channels.DownloadPathResult> {
const path = await this._object.path(); const path = await this._object.path();
return { value: path || undefined }; return { value: path || undefined };
} }
async saveAs(params: { path: string }): Promise<void> { async saveAs(params: channels.DownloadSaveAsParams): Promise<void> {
await this._object.saveAs(params.path); await this._object.saveAs(params.path);
} }
async stream(): Promise<{ stream?: StreamChannel }> { async stream(): Promise<channels.DownloadStreamResult> {
const stream = await this._object.createReadStream(); const stream = await this._object.createReadStream();
if (!stream) if (!stream)
return {}; return {};
@ -44,7 +44,7 @@ export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer
return { stream: new StreamDispatcher(this._scope, stream) }; return { stream: new StreamDispatcher(this._scope, stream) };
} }
async failure(): Promise<{ error?: string }> { async failure(): Promise<channels.DownloadFailureResult> {
const error = await this._object.failure(); const error = await this._object.failure();
return { error: error || undefined }; return { error: error || undefined };
} }

View file

@ -16,24 +16,24 @@
import { Dispatcher, DispatcherScope, lookupDispatcher } from './dispatcher'; import { Dispatcher, DispatcherScope, lookupDispatcher } from './dispatcher';
import { Electron, ElectronApplication, ElectronEvents, ElectronPage } from '../../server/electron'; import { Electron, ElectronApplication, ElectronEvents, ElectronPage } from '../../server/electron';
import { ElectronApplicationChannel, ElectronApplicationInitializer, PageChannel, JSHandleChannel, ElectronInitializer, ElectronChannel, SerializedArgument, ElectronLaunchParams, SerializedValue } from '../channels'; import * as channels from '../channels';
import { BrowserContextDispatcher } from './browserContextDispatcher'; import { BrowserContextDispatcher } from './browserContextDispatcher';
import { PageDispatcher } from './pageDispatcher'; import { PageDispatcher } from './pageDispatcher';
import { parseArgument, serializeResult } from './jsHandleDispatcher'; import { parseArgument, serializeResult } from './jsHandleDispatcher';
import { createHandle } from './elementHandlerDispatcher'; import { createHandle } from './elementHandlerDispatcher';
export class ElectronDispatcher extends Dispatcher<Electron, ElectronInitializer> implements ElectronChannel { export class ElectronDispatcher extends Dispatcher<Electron, channels.ElectronInitializer> implements channels.ElectronChannel {
constructor(scope: DispatcherScope, electron: Electron) { constructor(scope: DispatcherScope, electron: Electron) {
super(scope, electron, 'Electron', {}, true); super(scope, electron, 'Electron', {}, true);
} }
async launch(params: ElectronLaunchParams): Promise<{ electronApplication: ElectronApplicationChannel }> { async launch(params: channels.ElectronLaunchParams): Promise<channels.ElectronLaunchResult> {
const electronApplication = await this._object.launch(params.executablePath, params); const electronApplication = await this._object.launch(params.executablePath, params);
return { electronApplication: new ElectronApplicationDispatcher(this._scope, electronApplication) }; return { electronApplication: new ElectronApplicationDispatcher(this._scope, electronApplication) };
} }
} }
export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplication, ElectronApplicationInitializer> implements ElectronApplicationChannel { export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplication, channels.ElectronApplicationInitializer> implements channels.ElectronApplicationChannel {
constructor(scope: DispatcherScope, electronApplication: ElectronApplication) { constructor(scope: DispatcherScope, electronApplication: ElectronApplication) {
super(scope, electronApplication, 'ElectronApplication', {}, true); super(scope, electronApplication, 'ElectronApplication', {}, true);
this._dispatchEvent('context', { context: new BrowserContextDispatcher(this._scope, electronApplication.context()) }); this._dispatchEvent('context', { context: new BrowserContextDispatcher(this._scope, electronApplication.context()) });
@ -49,17 +49,17 @@ export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplicatio
}); });
} }
async newBrowserWindow(params: { arg: SerializedArgument }): Promise<{ page: PageChannel }> { async newBrowserWindow(params: channels.ElectronApplicationNewBrowserWindowParams): Promise<channels.ElectronApplicationNewBrowserWindowResult> {
const page = await this._object.newBrowserWindow(parseArgument(params.arg)); const page = await this._object.newBrowserWindow(parseArgument(params.arg));
return { page: lookupDispatcher<PageChannel>(page) }; return { page: lookupDispatcher<PageDispatcher>(page) };
} }
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evaluateExpression(params: channels.ElectronApplicationEvaluateExpressionParams): Promise<channels.ElectronApplicationEvaluateExpressionResult> {
const handle = this._object._nodeElectronHandle!; const handle = this._object._nodeElectronHandle!;
return { value: serializeResult(await handle._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg))) }; return { value: serializeResult(await handle._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg))) };
} }
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ handle: JSHandleChannel }> { async evaluateExpressionHandle(params: channels.ElectronApplicationEvaluateExpressionHandleParams): Promise<channels.ElectronApplicationEvaluateExpressionHandleResult> {
const handle = this._object._nodeElectronHandle!; const handle = this._object._nodeElectronHandle!;
const result = await handle._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg)); const result = await handle._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg));
return { handle: createHandle(this._scope, result) }; return { handle: createHandle(this._scope, result) };

View file

@ -16,8 +16,7 @@
import { ElementHandle } from '../../dom'; import { ElementHandle } from '../../dom';
import * as js from '../../javascript'; import * as js from '../../javascript';
import * as types from '../../types'; import * as channels from '../channels';
import { ElementHandleChannel, FrameChannel, Binary, SerializedArgument, SerializedValue } from '../channels';
import { DispatcherScope, lookupNullableDispatcher } from './dispatcher'; import { DispatcherScope, lookupNullableDispatcher } from './dispatcher';
import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher'; import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher';
import { FrameDispatcher } from './frameDispatcher'; import { FrameDispatcher } from './frameDispatcher';
@ -26,7 +25,7 @@ export function createHandle(scope: DispatcherScope, handle: js.JSHandle): JSHan
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()!) : new JSHandleDispatcher(scope, handle); return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()!) : new JSHandleDispatcher(scope, handle);
} }
export class ElementHandleDispatcher extends JSHandleDispatcher implements ElementHandleChannel { export class ElementHandleDispatcher extends JSHandleDispatcher implements channels.ElementHandleChannel {
readonly _elementHandle: ElementHandle; readonly _elementHandle: ElementHandle;
static createNullable(scope: DispatcherScope, handle: ElementHandle | null): ElementHandleDispatcher | undefined { static createNullable(scope: DispatcherScope, handle: ElementHandle | null): ElementHandleDispatcher | undefined {
@ -40,121 +39,121 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
this._elementHandle = elementHandle; this._elementHandle = elementHandle;
} }
async ownerFrame(): Promise<{ frame?: FrameChannel }> { async ownerFrame(): Promise<channels.ElementHandleOwnerFrameResult> {
return { frame: lookupNullableDispatcher<FrameDispatcher>(await this._elementHandle.ownerFrame()) }; return { frame: lookupNullableDispatcher<FrameDispatcher>(await this._elementHandle.ownerFrame()) };
} }
async contentFrame(): Promise<{ frame?: FrameChannel }> { async contentFrame(): Promise<channels.ElementHandleContentFrameResult> {
return { frame: lookupNullableDispatcher<FrameDispatcher>(await this._elementHandle.contentFrame()) }; return { frame: lookupNullableDispatcher<FrameDispatcher>(await this._elementHandle.contentFrame()) };
} }
async getAttribute(params: { name: string }): Promise<{ value?: string }> { async getAttribute(params: channels.ElementHandleGetAttributeParams): Promise<channels.ElementHandleGetAttributeResult> {
const value = await this._elementHandle.getAttribute(params.name); const value = await this._elementHandle.getAttribute(params.name);
return { value: value === null ? undefined : value }; return { value: value === null ? undefined : value };
} }
async textContent(): Promise<{ value?: string }> { async textContent(): Promise<channels.ElementHandleTextContentResult> {
const value = await this._elementHandle.textContent(); const value = await this._elementHandle.textContent();
return { value: value === null ? undefined : value }; return { value: value === null ? undefined : value };
} }
async innerText(): Promise<{ value: string }> { async innerText(): Promise<channels.ElementHandleInnerTextResult> {
return { value: await this._elementHandle.innerText() }; return { value: await this._elementHandle.innerText() };
} }
async innerHTML(): Promise<{ value: string }> { async innerHTML(): Promise<channels.ElementHandleInnerHTMLResult> {
return { value: await this._elementHandle.innerHTML() }; return { value: await this._elementHandle.innerHTML() };
} }
async dispatchEvent(params: { type: string, eventInit: SerializedArgument }) { async dispatchEvent(params: channels.ElementHandleDispatchEventParams): Promise<void> {
await this._elementHandle.dispatchEvent(params.type, parseArgument(params.eventInit)); await this._elementHandle.dispatchEvent(params.type, parseArgument(params.eventInit));
} }
async scrollIntoViewIfNeeded(params: types.TimeoutOptions) { async scrollIntoViewIfNeeded(params: channels.ElementHandleScrollIntoViewIfNeededParams): Promise<void> {
await this._elementHandle.scrollIntoViewIfNeeded(params); await this._elementHandle.scrollIntoViewIfNeeded(params);
} }
async hover(params: types.PointerActionOptions & types.PointerActionWaitOptions) { async hover(params: channels.ElementHandleHoverParams): Promise<void> {
await this._elementHandle.hover(params); await this._elementHandle.hover(params);
} }
async click(params: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { async click(params: channels.ElementHandleClickParams): Promise<void> {
await this._elementHandle.click(params); await this._elementHandle.click(params);
} }
async dblclick(params: types.MouseMultiClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { async dblclick(params: channels.ElementHandleDblclickParams): Promise<void> {
await this._elementHandle.dblclick(params); await this._elementHandle.dblclick(params);
} }
async selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<{ values: string[] }> { async selectOption(params: channels.ElementHandleSelectOptionParams): Promise<channels.ElementHandleSelectOptionResult> {
const elements = (params.elements || []).map(e => (e as ElementHandleDispatcher)._elementHandle); const elements = (params.elements || []).map(e => (e as ElementHandleDispatcher)._elementHandle);
return { values: await this._elementHandle.selectOption(elements, params.options || [], params) }; return { values: await this._elementHandle.selectOption(elements, params.options || [], params) };
} }
async fill(params: { value: string } & types.NavigatingActionWaitOptions) { async fill(params: channels.ElementHandleFillParams): Promise<void> {
await this._elementHandle.fill(params.value, params); await this._elementHandle.fill(params.value, params);
} }
async selectText(params: types.TimeoutOptions) { async selectText(params: channels.ElementHandleSelectTextParams): Promise<void> {
await this._elementHandle.selectText(params); await this._elementHandle.selectText(params);
} }
async setInputFiles(params: { files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions) { async setInputFiles(params: channels.ElementHandleSetInputFilesParams): Promise<void> {
await this._elementHandle.setInputFiles(params.files, params); await this._elementHandle.setInputFiles(params.files, params);
} }
async focus() { async focus(): Promise<void> {
await this._elementHandle.focus(); await this._elementHandle.focus();
} }
async type(params: { text: string } & { delay?: number } & types.NavigatingActionWaitOptions) { async type(params: channels.ElementHandleTypeParams): Promise<void> {
await this._elementHandle.type(params.text, params); await this._elementHandle.type(params.text, params);
} }
async press(params: { key: string } & { delay?: number } & types.NavigatingActionWaitOptions) { async press(params: channels.ElementHandlePressParams): Promise<void> {
await this._elementHandle.press(params.key, params); await this._elementHandle.press(params.key, params);
} }
async check(params: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { async check(params: channels.ElementHandleCheckParams): Promise<void> {
await this._elementHandle.check(params); await this._elementHandle.check(params);
} }
async uncheck(params: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions) { async uncheck(params: channels.ElementHandleUncheckParams): Promise<void> {
await this._elementHandle.uncheck(params); await this._elementHandle.uncheck(params);
} }
async boundingBox(): Promise<{ value?: types.Rect }> { async boundingBox(): Promise<channels.ElementHandleBoundingBoxResult> {
const value = await this._elementHandle.boundingBox(); const value = await this._elementHandle.boundingBox();
return { value: value || undefined }; return { value: value || undefined };
} }
async screenshot(params: types.ElementScreenshotOptions): Promise<{ binary: Binary }> { async screenshot(params: channels.ElementHandleScreenshotParams): Promise<channels.ElementHandleScreenshotResult> {
return { binary: (await this._elementHandle.screenshot(params)).toString('base64') }; return { binary: (await this._elementHandle.screenshot(params)).toString('base64') };
} }
async querySelector(params: { selector: string }): Promise<{ element?: ElementHandleChannel }> { async querySelector(params: channels.ElementHandleQuerySelectorParams): Promise<channels.ElementHandleQuerySelectorResult> {
const handle = await this._elementHandle.$(params.selector); const handle = await this._elementHandle.$(params.selector);
return { element: handle ? new ElementHandleDispatcher(this._scope, handle) : undefined }; return { element: handle ? new ElementHandleDispatcher(this._scope, handle) : undefined };
} }
async querySelectorAll(params: { selector: string }): Promise<{ elements: ElementHandleChannel[] }> { async querySelectorAll(params: channels.ElementHandleQuerySelectorAllParams): Promise<channels.ElementHandleQuerySelectorAllResult> {
const elements = await this._elementHandle.$$(params.selector); const elements = await this._elementHandle.$$(params.selector);
return { elements: elements.map(e => new ElementHandleDispatcher(this._scope, e)) }; return { elements: elements.map(e => new ElementHandleDispatcher(this._scope, e)) };
} }
async evalOnSelector(params: { selector: string, expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evalOnSelector(params: channels.ElementHandleEvalOnSelectorParams): Promise<channels.ElementHandleEvalOnSelectorResult> {
return { value: serializeResult(await this._elementHandle._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._elementHandle._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async evalOnSelectorAll(params: { selector: string, expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evalOnSelectorAll(params: channels.ElementHandleEvalOnSelectorAllParams): Promise<channels.ElementHandleEvalOnSelectorAllResult> {
return { value: serializeResult(await this._elementHandle._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._elementHandle._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async waitForElementState(params: { state: 'visible' | 'hidden' | 'stable' | 'enabled' | 'disabled' } & types.TimeoutOptions): Promise<void> { async waitForElementState(params: channels.ElementHandleWaitForElementStateParams): Promise<void> {
await this._elementHandle.waitForElementState(params.state, params); await this._elementHandle.waitForElementState(params.state, params);
} }
async waitForSelector(params: { selector: string } & types.WaitForElementOptions): Promise<{ element?: ElementHandleChannel }> { async waitForSelector(params: channels.ElementHandleWaitForSelectorParams): Promise<channels.ElementHandleWaitForSelectorResult> {
return { element: ElementHandleDispatcher.createNullable(this._scope, await this._elementHandle.waitForSelector(params.selector, params)) }; return { element: ElementHandleDispatcher.createNullable(this._scope, await this._elementHandle.waitForSelector(params.selector, params)) };
} }
} }

View file

@ -16,13 +16,13 @@
import { Frame, kAddLifecycleEvent, kRemoveLifecycleEvent, kNavigationEvent, NavigationEvent } from '../../frames'; import { Frame, kAddLifecycleEvent, kRemoveLifecycleEvent, kNavigationEvent, NavigationEvent } from '../../frames';
import * as types from '../../types'; import * as types from '../../types';
import { ElementHandleChannel, FrameChannel, FrameInitializer, JSHandleChannel, ResponseChannel, SerializedArgument, FrameWaitForFunctionParams, SerializedValue } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher'; import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
import { ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher'; import { ElementHandleDispatcher, createHandle } from './elementHandlerDispatcher';
import { parseArgument, serializeResult } from './jsHandleDispatcher'; import { parseArgument, serializeResult } from './jsHandleDispatcher';
import { ResponseDispatcher, RequestDispatcher } from './networkDispatchers'; import { ResponseDispatcher, RequestDispatcher } from './networkDispatchers';
export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> implements FrameChannel { export class FrameDispatcher extends Dispatcher<Frame, channels.FrameInitializer> implements channels.FrameChannel {
private _frame: Frame; private _frame: Frame;
static from(scope: DispatcherScope, frame: Frame): FrameDispatcher { static from(scope: DispatcherScope, frame: Frame): FrameDispatcher {
@ -52,127 +52,127 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
}); });
} }
async goto(params: { url: string } & types.GotoOptions): Promise<{ response?: ResponseChannel }> { async goto(params: channels.FrameGotoParams): Promise<channels.FrameGotoResult> {
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._frame.goto(params.url, params)) }; return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._frame.goto(params.url, params)) };
} }
async frameElement(): Promise<{ element: ElementHandleChannel }> { async frameElement(): Promise<channels.FrameFrameElementResult> {
return { element: new ElementHandleDispatcher(this._scope, await this._frame.frameElement()) }; return { element: new ElementHandleDispatcher(this._scope, await this._frame.frameElement()) };
} }
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evaluateExpression(params: channels.FrameEvaluateExpressionParams): Promise<channels.FrameEvaluateExpressionResult> {
return { value: serializeResult(await this._frame._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._frame._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ handle: JSHandleChannel }> { async evaluateExpressionHandle(params: channels.FrameEvaluateExpressionHandleParams): Promise<channels.FrameEvaluateExpressionHandleResult> {
return { handle: createHandle(this._scope, await this._frame._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) }; return { handle: createHandle(this._scope, await this._frame._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async waitForSelector(params: { selector: string } & types.WaitForElementOptions): Promise<{ element?: ElementHandleChannel }> { async waitForSelector(params: channels.FrameWaitForSelectorParams): Promise<channels.FrameWaitForSelectorResult> {
return { element: ElementHandleDispatcher.createNullable(this._scope, await this._frame.waitForSelector(params.selector, params)) }; return { element: ElementHandleDispatcher.createNullable(this._scope, await this._frame.waitForSelector(params.selector, params)) };
} }
async dispatchEvent(params: { selector: string, type: string, eventInit: SerializedArgument } & types.TimeoutOptions): Promise<void> { async dispatchEvent(params: channels.FrameDispatchEventParams): Promise<void> {
return this._frame.dispatchEvent(params.selector, params.type, parseArgument(params.eventInit), params); return this._frame.dispatchEvent(params.selector, params.type, parseArgument(params.eventInit), params);
} }
async evalOnSelector(params: { selector: string, expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evalOnSelector(params: channels.FrameEvalOnSelectorParams): Promise<channels.FrameEvalOnSelectorResult> {
return { value: serializeResult(await this._frame._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._frame._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async evalOnSelectorAll(params: { selector: string, expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evalOnSelectorAll(params: channels.FrameEvalOnSelectorAllParams): Promise<channels.FrameEvalOnSelectorAllResult> {
return { value: serializeResult(await this._frame._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._frame._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async querySelector(params: { selector: string }): Promise<{ element?: ElementHandleChannel }> { async querySelector(params: channels.FrameQuerySelectorParams): Promise<channels.FrameQuerySelectorResult> {
return { element: ElementHandleDispatcher.createNullable(this._scope, await this._frame.$(params.selector)) }; return { element: ElementHandleDispatcher.createNullable(this._scope, await this._frame.$(params.selector)) };
} }
async querySelectorAll(params: { selector: string }): Promise<{ elements: ElementHandleChannel[] }> { async querySelectorAll(params: channels.FrameQuerySelectorAllParams): Promise<channels.FrameQuerySelectorAllResult> {
const elements = await this._frame.$$(params.selector); const elements = await this._frame.$$(params.selector);
return { elements: elements.map(e => new ElementHandleDispatcher(this._scope, e)) }; return { elements: elements.map(e => new ElementHandleDispatcher(this._scope, e)) };
} }
async content(): Promise<{ value: string }> { async content(): Promise<channels.FrameContentResult> {
return { value: await this._frame.content() }; return { value: await this._frame.content() };
} }
async setContent(params: { html: string } & types.NavigateOptions): Promise<void> { async setContent(params: channels.FrameSetContentParams): Promise<void> {
await this._frame.setContent(params.html, params); await this._frame.setContent(params.html, params);
} }
async addScriptTag(params: { url?: string, content?: string, type?: string }): Promise<{ element: ElementHandleChannel }> { async addScriptTag(params: channels.FrameAddScriptTagParams): Promise<channels.FrameAddScriptTagResult> {
return { element: new ElementHandleDispatcher(this._scope, await this._frame.addScriptTag(params)) }; return { element: new ElementHandleDispatcher(this._scope, await this._frame.addScriptTag(params)) };
} }
async addStyleTag(params: { url?: string, content?: string }): Promise<{ element: ElementHandleChannel }> { async addStyleTag(params: channels.FrameAddStyleTagParams): Promise<channels.FrameAddStyleTagResult> {
return { element: new ElementHandleDispatcher(this._scope, await this._frame.addStyleTag(params)) }; return { element: new ElementHandleDispatcher(this._scope, await this._frame.addStyleTag(params)) };
} }
async click(params: { selector: string } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }): Promise<void> { async click(params: channels.FrameClickParams): Promise<void> {
await this._frame.click(params.selector, params); await this._frame.click(params.selector, params);
} }
async dblclick(params: { selector: string } & types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }): Promise<void> { async dblclick(params: channels.FrameDblclickParams): Promise<void> {
await this._frame.dblclick(params.selector, params); await this._frame.dblclick(params.selector, params);
} }
async fill(params: { selector: string, value: string } & types.NavigatingActionWaitOptions): Promise<void> { async fill(params: channels.FrameFillParams): Promise<void> {
await this._frame.fill(params.selector, params.value, params); await this._frame.fill(params.selector, params.value, params);
} }
async focus(params: { selector: string } & types.TimeoutOptions): Promise<void> { async focus(params: channels.FrameFocusParams): Promise<void> {
await this._frame.focus(params.selector, params); await this._frame.focus(params.selector, params);
} }
async textContent(params: { selector: string } & types.TimeoutOptions): Promise<{ value?: string }> { async textContent(params: channels.FrameTextContentParams): Promise<channels.FrameTextContentResult> {
const value = await this._frame.textContent(params.selector, params); const value = await this._frame.textContent(params.selector, params);
return { value: value === null ? undefined : value }; return { value: value === null ? undefined : value };
} }
async innerText(params: { selector: string } & types.TimeoutOptions): Promise<{ value: string }> { async innerText(params: channels.FrameInnerTextParams): Promise<channels.FrameInnerTextResult> {
return { value: await this._frame.innerText(params.selector, params) }; return { value: await this._frame.innerText(params.selector, params) };
} }
async innerHTML(params: { selector: string } & types.TimeoutOptions): Promise<{ value: string }> { async innerHTML(params: channels.FrameInnerHTMLParams): Promise<channels.FrameInnerHTMLResult> {
return { value: await this._frame.innerHTML(params.selector, params) }; return { value: await this._frame.innerHTML(params.selector, params) };
} }
async getAttribute(params: { selector: string, name: string } & types.TimeoutOptions): Promise<{ value?: string }> { async getAttribute(params: channels.FrameGetAttributeParams): Promise<channels.FrameGetAttributeResult> {
const value = await this._frame.getAttribute(params.selector, params.name, params); const value = await this._frame.getAttribute(params.selector, params.name, params);
return { value: value === null ? undefined : value }; return { value: value === null ? undefined : value };
} }
async hover(params: { selector: string } & types.PointerActionOptions & types.TimeoutOptions & { force?: boolean }): Promise<void> { async hover(params: channels.FrameHoverParams): Promise<void> {
await this._frame.hover(params.selector, params); await this._frame.hover(params.selector, params);
} }
async selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<{ values: string[] }> { async selectOption(params: channels.FrameSelectOptionParams): Promise<channels.FrameSelectOptionResult> {
const elements = (params.elements || []).map(e => (e as ElementHandleDispatcher)._elementHandle); const elements = (params.elements || []).map(e => (e as ElementHandleDispatcher)._elementHandle);
return { values: await this._frame.selectOption(params.selector, elements, params.options || [], params) }; return { values: await this._frame.selectOption(params.selector, elements, params.options || [], params) };
} }
async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions): Promise<void> { async setInputFiles(params: channels.FrameSetInputFilesParams): Promise<void> {
await this._frame.setInputFiles(params.selector, params.files, params); await this._frame.setInputFiles(params.selector, params.files, params);
} }
async type(params: { selector: string, text: string } & { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }): Promise<void> { async type(params: channels.FrameTypeParams): Promise<void> {
await this._frame.type(params.selector, params.text, params); await this._frame.type(params.selector, params.text, params);
} }
async press(params: { selector: string, key: string } & { delay?: number | undefined } & types.TimeoutOptions & { noWaitAfter?: boolean }): Promise<void> { async press(params: channels.FramePressParams): Promise<void> {
await this._frame.press(params.selector, params.key, params); await this._frame.press(params.selector, params.key, params);
} }
async check(params: { selector: string } & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }): Promise<void> { async check(params: channels.FrameCheckParams): Promise<void> {
await this._frame.check(params.selector, params); await this._frame.check(params.selector, params);
} }
async uncheck(params: { selector: string } & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }): Promise<void> { async uncheck(params: channels.FrameUncheckParams): Promise<void> {
await this._frame.uncheck(params.selector, params); await this._frame.uncheck(params.selector, params);
} }
async waitForFunction(params: FrameWaitForFunctionParams): Promise<{ handle: JSHandleChannel }> { async waitForFunction(params: channels.FrameWaitForFunctionParams): Promise<channels.FrameWaitForFunctionResult> {
const options = { const options = {
...params, ...params,
polling: params.pollingInterval === undefined ? 'raf' as const : params.pollingInterval polling: params.pollingInterval === undefined ? 'raf' as const : params.pollingInterval
@ -180,7 +180,7 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
return { handle: createHandle(this._scope, await this._frame._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), options)) }; return { handle: createHandle(this._scope, await this._frame._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), options)) };
} }
async title(): Promise<{ value: string }> { async title(): Promise<channels.FrameTitleResult> {
return { value: await this._frame.title() }; return { value: await this._frame.title() };
} }
} }

View file

@ -15,12 +15,12 @@
*/ */
import * as js from '../../javascript'; import * as js from '../../javascript';
import { JSHandleChannel, JSHandleInitializer, SerializedArgument, SerializedValue } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { createHandle } from './elementHandlerDispatcher'; import { createHandle } from './elementHandlerDispatcher';
import { parseSerializedValue, serializeValue } from '../serializers'; import { parseSerializedValue, serializeValue } from '../serializers';
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitializer> implements JSHandleChannel { export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandleInitializer> implements channels.JSHandleChannel {
constructor(scope: DispatcherScope, jsHandle: js.JSHandle) { constructor(scope: DispatcherScope, jsHandle: js.JSHandle) {
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', { super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
@ -29,21 +29,21 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', { preview })); jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', { preview }));
} }
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evaluateExpression(params: channels.JSHandleEvaluateExpressionParams): Promise<channels.JSHandleEvaluateExpressionResult> {
return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg))) }; return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg))) };
} }
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: SerializedArgument}): Promise<{ handle: JSHandleChannel }> { async evaluateExpressionHandle(params: channels.JSHandleEvaluateExpressionHandleParams): Promise<channels.JSHandleEvaluateExpressionHandleResult> {
const jsHandle = await this._object._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg)); const jsHandle = await this._object._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg));
return { handle: createHandle(this._scope, jsHandle) }; return { handle: createHandle(this._scope, jsHandle) };
} }
async getProperty(params: { name: string }): Promise<{ handle: JSHandleChannel }> { async getProperty(params: channels.JSHandleGetPropertyParams): Promise<channels.JSHandleGetPropertyResult> {
const jsHandle = await this._object.getProperty(params.name); const jsHandle = await this._object.getProperty(params.name);
return { handle: createHandle(this._scope, jsHandle) }; return { handle: createHandle(this._scope, jsHandle) };
} }
async getPropertyList(): Promise<{ properties: { name: string, value: JSHandleChannel }[] }> { async getPropertyList(): Promise<channels.JSHandleGetPropertyListResult> {
const map = await this._object.getProperties(); const map = await this._object.getProperties();
const properties = []; const properties = [];
for (const [name, value] of map) for (const [name, value] of map)
@ -51,7 +51,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
return { properties }; return { properties };
} }
async jsonValue(): Promise<{ value: SerializedValue }> { async jsonValue(): Promise<channels.JSHandleJsonValueResult> {
return { value: serializeResult(await this._object.jsonValue()) }; return { value: serializeResult(await this._object.jsonValue()) };
} }
@ -62,13 +62,14 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
// Generic channel parser converts guids to JSHandleDispatchers, // Generic channel parser converts guids to JSHandleDispatchers,
// and this function takes care of coverting them into underlying JSHandles. // and this function takes care of coverting them into underlying JSHandles.
export function parseArgument(arg: SerializedArgument): any { export function parseArgument(arg: channels.SerializedArgument): any {
return parseSerializedValue(arg.value, arg.handles.map(a => (a as JSHandleDispatcher)._object)); return parseSerializedValue(arg.value, arg.handles.map(a => (a as JSHandleDispatcher)._object));
} }
export function parseValue(v: SerializedValue): any {
export function parseValue(v: channels.SerializedValue): any {
return parseSerializedValue(v, []); return parseSerializedValue(v, []);
} }
export function serializeResult(arg: any): SerializedValue { export function serializeResult(arg: any): channels.SerializedValue {
return serializeValue(arg, value => ({ fallThrough: value }), new Set()); return serializeValue(arg, value => ({ fallThrough: value }), new Set());
} }

View file

@ -15,12 +15,11 @@
*/ */
import { Request, Response, Route } from '../../network'; import { Request, Response, Route } from '../../network';
import { RequestChannel, ResponseChannel, RouteChannel, ResponseInitializer, RequestInitializer, RouteInitializer, Binary } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher'; import { Dispatcher, DispatcherScope, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
import { FrameDispatcher } from './frameDispatcher'; import { FrameDispatcher } from './frameDispatcher';
import * as types from '../../types';
export class RequestDispatcher extends Dispatcher<Request, RequestInitializer> implements RequestChannel { export class RequestDispatcher extends Dispatcher<Request, channels.RequestInitializer> implements channels.RequestChannel {
static from(scope: DispatcherScope, request: Request): RequestDispatcher { static from(scope: DispatcherScope, request: Request): RequestDispatcher {
const result = existingDispatcher<RequestDispatcher>(request); const result = existingDispatcher<RequestDispatcher>(request);
@ -45,12 +44,12 @@ export class RequestDispatcher extends Dispatcher<Request, RequestInitializer> i
}); });
} }
async response(): Promise<{ response?: ResponseChannel }> { async response(): Promise<channels.RequestResponseResult> {
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._object.response()) }; return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._object.response()) };
} }
} }
export class ResponseDispatcher extends Dispatcher<Response, ResponseInitializer> implements ResponseChannel { export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseInitializer> implements channels.ResponseChannel {
constructor(scope: DispatcherScope, response: Response) { constructor(scope: DispatcherScope, response: Response) {
super(scope, response, 'Response', { super(scope, response, 'Response', {
@ -63,16 +62,16 @@ export class ResponseDispatcher extends Dispatcher<Response, ResponseInitializer
}); });
} }
async finished(): Promise<{ error?: string }> { async finished(): Promise<channels.ResponseFinishedResult> {
return await this._object._finishedPromise; return await this._object._finishedPromise;
} }
async body(): Promise<{ binary: Binary }> { async body(): Promise<channels.ResponseBodyResult> {
return { binary: (await this._object.body()).toString('base64') }; return { binary: (await this._object.body()).toString('base64') };
} }
} }
export class RouteDispatcher extends Dispatcher<Route, RouteInitializer> implements RouteChannel { export class RouteDispatcher extends Dispatcher<Route, channels.RouteInitializer> implements channels.RouteChannel {
constructor(scope: DispatcherScope, route: Route) { constructor(scope: DispatcherScope, route: Route) {
super(scope, route, 'Route', { super(scope, route, 'Route', {
@ -81,7 +80,7 @@ export class RouteDispatcher extends Dispatcher<Route, RouteInitializer> impleme
}); });
} }
async continue(params: { method?: string, headers?: types.HeadersArray, postData?: string }): Promise<void> { async continue(params: channels.RouteContinueParams): Promise<void> {
await this._object.continue({ await this._object.continue({
method: params.method, method: params.method,
headers: params.headers, headers: params.headers,
@ -89,11 +88,11 @@ export class RouteDispatcher extends Dispatcher<Route, RouteInitializer> impleme
}); });
} }
async fulfill(params: types.NormalizedFulfillResponse): Promise<void> { async fulfill(params: channels.RouteFulfillParams): Promise<void> {
await this._object.fulfill(params); await this._object.fulfill(params);
} }
async abort(params: { errorCode?: string }): Promise<void> { async abort(params: channels.RouteAbortParams): Promise<void> {
await this._object.abort(params.errorCode || 'failed'); await this._object.abort(params.errorCode || 'failed');
} }
} }

View file

@ -19,8 +19,7 @@ import { Events } from '../../events';
import { Frame } from '../../frames'; import { Frame } from '../../frames';
import { Request } from '../../network'; import { Request } from '../../network';
import { Page, Worker } from '../../page'; import { Page, Worker } from '../../page';
import * as types from '../../types'; import * as channels from '../channels';
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary, SerializedArgument, PagePdfParams, SerializedError, PageAccessibilitySnapshotResult, SerializedValue, PageEmulateMediaParams } from '../channels';
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher'; import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
import { parseError, serializeError } from '../serializers'; import { parseError, serializeError } from '../serializers';
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher'; import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
@ -33,7 +32,7 @@ import { ElementHandleDispatcher, createHandle } from './elementHandlerDispatche
import { FileChooser } from '../../fileChooser'; import { FileChooser } from '../../fileChooser';
import { CRCoverage } from '../../chromium/crCoverage'; import { CRCoverage } from '../../chromium/crCoverage';
export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements PageChannel { export class PageDispatcher extends Dispatcher<Page, channels.PageInitializer> implements channels.PageChannel {
private _page: Page; private _page: Page;
constructor(scope: DispatcherScope, page: Page) { constructor(scope: DispatcherScope, page: Page) {
@ -70,19 +69,19 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
page.on(Events.Page.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this._scope, worker) })); page.on(Events.Page.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this._scope, worker) }));
} }
async setDefaultNavigationTimeoutNoReply(params: { timeout: number }) { async setDefaultNavigationTimeoutNoReply(params: channels.PageSetDefaultNavigationTimeoutNoReplyParams): Promise<void> {
this._page.setDefaultNavigationTimeout(params.timeout); this._page.setDefaultNavigationTimeout(params.timeout);
} }
async setDefaultTimeoutNoReply(params: { timeout: number }) { async setDefaultTimeoutNoReply(params: channels.PageSetDefaultTimeoutNoReplyParams): Promise<void> {
this._page.setDefaultTimeout(params.timeout); this._page.setDefaultTimeout(params.timeout);
} }
async opener(): Promise<{ page?: PageChannel }> { async opener(): Promise<channels.PageOpenerResult> {
return { page: lookupNullableDispatcher<PageDispatcher>(await this._page.opener()) }; return { page: lookupNullableDispatcher<PageDispatcher>(await this._page.opener()) };
} }
async exposeBinding(params: { name: string }): Promise<void> { async exposeBinding(params: channels.PageExposeBindingParams): Promise<void> {
await this._page.exposeBinding(params.name, (source, ...args) => { await this._page.exposeBinding(params.name, (source, ...args) => {
const binding = new BindingCallDispatcher(this._scope, params.name, source, args); const binding = new BindingCallDispatcher(this._scope, params.name, source, args);
this._dispatchEvent('bindingCall', { binding }); this._dispatchEvent('bindingCall', { binding });
@ -90,38 +89,38 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
}); });
} }
async setExtraHTTPHeaders(params: { headers: types.HeadersArray }): Promise<void> { async setExtraHTTPHeaders(params: channels.PageSetExtraHTTPHeadersParams): Promise<void> {
await this._page.setExtraHTTPHeaders(params.headers); await this._page.setExtraHTTPHeaders(params.headers);
} }
async reload(params: types.NavigateOptions): Promise<{ response?: ResponseChannel }> { async reload(params: channels.PageReloadParams): Promise<channels.PageReloadResult> {
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.reload(params)) }; return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.reload(params)) };
} }
async goBack(params: types.NavigateOptions): Promise<{ response?: ResponseChannel }> { async goBack(params: channels.PageGoBackParams): Promise<channels.PageGoBackResult> {
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.goBack(params)) }; return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.goBack(params)) };
} }
async goForward(params: types.NavigateOptions): Promise<{ response?: ResponseChannel }> { async goForward(params: channels.PageGoForwardParams): Promise<channels.PageGoForwardResult> {
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.goForward(params)) }; return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._page.goForward(params)) };
} }
async emulateMedia(params: PageEmulateMediaParams): Promise<void> { async emulateMedia(params: channels.PageEmulateMediaParams): Promise<void> {
await this._page.emulateMedia({ await this._page.emulateMedia({
media: params.media === 'null' ? null : params.media, media: params.media === 'null' ? null : params.media,
colorScheme: params.colorScheme === 'null' ? null : params.colorScheme, colorScheme: params.colorScheme === 'null' ? null : params.colorScheme,
}); });
} }
async setViewportSize(params: { viewportSize: types.Size }): Promise<void> { async setViewportSize(params: channels.PageSetViewportSizeParams): Promise<void> {
await this._page.setViewportSize(params.viewportSize); await this._page.setViewportSize(params.viewportSize);
} }
async addInitScript(params: { source: string }): Promise<void> { async addInitScript(params: channels.PageAddInitScriptParams): Promise<void> {
await this._page._addInitScriptExpression(params.source); await this._page._addInitScriptExpression(params.source);
} }
async setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise<void> { async setNetworkInterceptionEnabled(params: channels.PageSetNetworkInterceptionEnabledParams): Promise<void> {
if (!params.enabled) { if (!params.enabled) {
await this._page._setRequestInterceptor(undefined); await this._page._setRequestInterceptor(undefined);
return; return;
@ -131,55 +130,55 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
}); });
} }
async screenshot(params: types.ScreenshotOptions): Promise<{ binary: Binary }> { async screenshot(params: channels.PageScreenshotParams): Promise<channels.PageScreenshotResult> {
return { binary: (await this._page.screenshot(params)).toString('base64') }; return { binary: (await this._page.screenshot(params)).toString('base64') };
} }
async close(params: { runBeforeUnload?: boolean }): Promise<void> { async close(params: channels.PageCloseParams): Promise<void> {
await this._page.close(params); await this._page.close(params);
} }
async setFileChooserInterceptedNoReply(params: { intercepted: boolean }) { async setFileChooserInterceptedNoReply(params: channels.PageSetFileChooserInterceptedNoReplyParams): Promise<void> {
await this._page._setFileChooserIntercepted(params.intercepted); await this._page._setFileChooserIntercepted(params.intercepted);
} }
async keyboardDown(params: { key: string }): Promise<void> { async keyboardDown(params: channels.PageKeyboardDownParams): Promise<void> {
await this._page.keyboard.down(params.key); await this._page.keyboard.down(params.key);
} }
async keyboardUp(params: { key: string }): Promise<void> { async keyboardUp(params: channels.PageKeyboardUpParams): Promise<void> {
await this._page.keyboard.up(params.key); await this._page.keyboard.up(params.key);
} }
async keyboardInsertText(params: { text: string }): Promise<void> { async keyboardInsertText(params: channels.PageKeyboardInsertTextParams): Promise<void> {
await this._page.keyboard.insertText(params.text); await this._page.keyboard.insertText(params.text);
} }
async keyboardType(params: { text: string, delay?: number }): Promise<void> { async keyboardType(params: channels.PageKeyboardTypeParams): Promise<void> {
await this._page.keyboard.type(params.text, params); await this._page.keyboard.type(params.text, params);
} }
async keyboardPress(params: { key: string, delay?: number }): Promise<void> { async keyboardPress(params: channels.PageKeyboardPressParams): Promise<void> {
await this._page.keyboard.press(params.key, params); await this._page.keyboard.press(params.key, params);
} }
async mouseMove(params: { x: number, y: number, steps?: number }): Promise<void> { async mouseMove(params: channels.PageMouseMoveParams): Promise<void> {
await this._page.mouse.move(params.x, params.y, params); await this._page.mouse.move(params.x, params.y, params);
} }
async mouseDown(params: { button?: types.MouseButton, clickCount?: number }): Promise<void> { async mouseDown(params: channels.PageMouseDownParams): Promise<void> {
await this._page.mouse.down(params); await this._page.mouse.down(params);
} }
async mouseUp(params: { button?: types.MouseButton, clickCount?: number }): Promise<void> { async mouseUp(params: channels.PageMouseUpParams): Promise<void> {
await this._page.mouse.up(params); await this._page.mouse.up(params);
} }
async mouseClick(params: { x: number, y: number, delay?: number, button?: types.MouseButton, clickCount?: number }): Promise<void> { async mouseClick(params: channels.PageMouseClickParams): Promise<void> {
await this._page.mouse.click(params.x, params.y, params); await this._page.mouse.click(params.x, params.y, params);
} }
async accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise<PageAccessibilitySnapshotResult> { async accessibilitySnapshot(params: channels.PageAccessibilitySnapshotParams): Promise<channels.PageAccessibilitySnapshotResult> {
const rootAXNode = await this._page.accessibility.snapshot({ const rootAXNode = await this._page.accessibility.snapshot({
interestingOnly: params.interestingOnly, interestingOnly: params.interestingOnly,
root: params.root ? (params.root as ElementHandleDispatcher)._elementHandle : undefined root: params.root ? (params.root as ElementHandleDispatcher)._elementHandle : undefined
@ -187,7 +186,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
return { rootAXNode: rootAXNode || undefined }; return { rootAXNode: rootAXNode || undefined };
} }
async pdf(params: PagePdfParams): Promise<{ pdf: Binary }> { async pdf(params: channels.PagePdfParams): Promise<channels.PagePdfResult> {
if (!this._page.pdf) if (!this._page.pdf)
throw new Error('PDF generation is only supported for Headless Chromium'); throw new Error('PDF generation is only supported for Headless Chromium');
const buffer = await this._page.pdf(params); const buffer = await this._page.pdf(params);
@ -198,22 +197,22 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
await this._page.bringToFront(); await this._page.bringToFront();
} }
async crStartJSCoverage(params: types.JSCoverageOptions): Promise<void> { async crStartJSCoverage(params: channels.PageCrStartJSCoverageParams): Promise<void> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
await coverage.startJSCoverage(params); await coverage.startJSCoverage(params);
} }
async crStopJSCoverage(): Promise<{ entries: types.JSCoverageEntry[] }> { async crStopJSCoverage(): Promise<channels.PageCrStopJSCoverageResult> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopJSCoverage() }; return { entries: await coverage.stopJSCoverage() };
} }
async crStartCSSCoverage(params: types.CSSCoverageOptions): Promise<void> { async crStartCSSCoverage(params: channels.PageCrStartCSSCoverageParams): Promise<void> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
await coverage.startCSSCoverage(params); await coverage.startCSSCoverage(params);
} }
async crStopCSSCoverage(): Promise<{ entries: types.CSSCoverageEntry[] }> { async crStopCSSCoverage(): Promise<channels.PageCrStopCSSCoverageResult> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopCSSCoverage() }; return { entries: await coverage.stopCSSCoverage() };
} }
@ -228,7 +227,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
} }
export class WorkerDispatcher extends Dispatcher<Worker, WorkerInitializer> implements WorkerChannel { export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerInitializer> implements channels.WorkerChannel {
constructor(scope: DispatcherScope, worker: Worker) { constructor(scope: DispatcherScope, worker: Worker) {
super(scope, worker, 'Worker', { super(scope, worker, 'Worker', {
url: worker.url() url: worker.url()
@ -236,16 +235,16 @@ export class WorkerDispatcher extends Dispatcher<Worker, WorkerInitializer> impl
worker.on(Events.Worker.Close, () => this._dispatchEvent('close')); worker.on(Events.Worker.Close, () => this._dispatchEvent('close'));
} }
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ value: SerializedValue }> { async evaluateExpression(params: channels.WorkerEvaluateExpressionParams): Promise<channels.WorkerEvaluateExpressionResult> {
return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) }; return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) };
} }
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: SerializedArgument }): Promise<{ handle: JSHandleChannel }> { async evaluateExpressionHandle(params: channels.WorkerEvaluateExpressionHandleParams): Promise<channels.WorkerEvaluateExpressionHandleResult> {
return { handle: createHandle(this._scope, await this._object._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) }; return { handle: createHandle(this._scope, await this._object._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) };
} }
} }
export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer> implements BindingCallChannel { export class BindingCallDispatcher extends Dispatcher<{}, channels.BindingCallInitializer> implements channels.BindingCallChannel {
private _resolve: ((arg: any) => void) | undefined; private _resolve: ((arg: any) => void) | undefined;
private _reject: ((error: any) => void) | undefined; private _reject: ((error: any) => void) | undefined;
private _promise: Promise<any>; private _promise: Promise<any>;
@ -266,11 +265,11 @@ export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer
return this._promise; return this._promise;
} }
async resolve(params: { result: SerializedArgument }) { async resolve(params: channels.BindingCallResolveParams): Promise<void> {
this._resolve!(parseArgument(params.result)); this._resolve!(parseArgument(params.result));
} }
async reject(params: { error: SerializedError }) { async reject(params: channels.BindingCallRejectParams): Promise<void> {
this._reject!(parseError(params.error)); this._reject!(parseError(params.error));
} }
} }

View file

@ -15,7 +15,7 @@
*/ */
import { Playwright } from '../../server/playwright'; import { Playwright } from '../../server/playwright';
import { PlaywrightChannel, PlaywrightInitializer } from '../channels'; import * as channels from '../channels';
import { BrowserTypeDispatcher } from './browserTypeDispatcher'; import { BrowserTypeDispatcher } from './browserTypeDispatcher';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { SelectorsDispatcher } from './selectorsDispatcher'; import { SelectorsDispatcher } from './selectorsDispatcher';
@ -23,7 +23,7 @@ import { Electron } from '../../server/electron';
import { ElectronDispatcher } from './electronDispatcher'; import { ElectronDispatcher } from './electronDispatcher';
import { DeviceDescriptors } from '../../deviceDescriptors'; import { DeviceDescriptors } from '../../deviceDescriptors';
export class PlaywrightDispatcher extends Dispatcher<Playwright, PlaywrightInitializer> implements PlaywrightChannel { export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.PlaywrightInitializer> implements channels.PlaywrightChannel {
constructor(scope: DispatcherScope, playwright: Playwright) { constructor(scope: DispatcherScope, playwright: Playwright) {
const electron = (playwright as any).electron as (Electron | undefined); const electron = (playwright as any).electron as (Electron | undefined);
const deviceDescriptors = Object.entries(DeviceDescriptors) const deviceDescriptors = Object.entries(DeviceDescriptors)

View file

@ -15,21 +15,21 @@
*/ */
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import { SelectorsInitializer, SelectorsChannel } from '../channels'; import * as channels from '../channels';
import { Selectors } from '../../selectors'; import { Selectors } from '../../selectors';
import { ElementHandleDispatcher } from './elementHandlerDispatcher'; import { ElementHandleDispatcher } from './elementHandlerDispatcher';
import * as dom from '../../dom'; import * as dom from '../../dom';
export class SelectorsDispatcher extends Dispatcher<Selectors, SelectorsInitializer> implements SelectorsChannel { export class SelectorsDispatcher extends Dispatcher<Selectors, channels.SelectorsInitializer> implements channels.SelectorsChannel {
constructor(scope: DispatcherScope, selectors: Selectors) { constructor(scope: DispatcherScope, selectors: Selectors) {
super(scope, selectors, 'Selectors', {}); super(scope, selectors, 'Selectors', {});
} }
async register(params: { name: string, source: string, contentScript?: boolean }): Promise<void> { async register(params: channels.SelectorsRegisterParams): Promise<void> {
await this._object.register(params.name, params.source, params.contentScript); await this._object.register(params.name, params.source, params.contentScript);
} }
async createSelector(params: { name: string, handle: ElementHandleDispatcher }): Promise<{ value?: string }> { async createSelector(params: channels.SelectorsCreateSelectorParams): Promise<channels.SelectorsCreateSelectorResult> {
return { value: await this._object._createSelector(params.name, params.handle._object as dom.ElementHandle<Element>) }; return { value: await this._object._createSelector(params.name, (params.handle as ElementHandleDispatcher)._object as dom.ElementHandle<Element>) };
} }
} }

View file

@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
import { StreamChannel, StreamInitializer, Binary } from '../channels'; import * as channels from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher';
import * as stream from 'stream'; import * as stream from 'stream';
export class StreamDispatcher extends Dispatcher<stream.Readable, StreamInitializer> implements StreamChannel { export class StreamDispatcher extends Dispatcher<stream.Readable, channels.StreamInitializer> implements channels.StreamChannel {
constructor(scope: DispatcherScope, stream: stream.Readable) { constructor(scope: DispatcherScope, stream: stream.Readable) {
super(scope, stream, 'Stream', {}); super(scope, stream, 'Stream', {});
} }
async read(params: { size?: number }): Promise<{ binary: Binary }> { async read(params: channels.StreamReadParams): Promise<channels.StreamReadResult> {
const buffer = this._object.read(Math.min(this._object.readableLength, params.size || this._object.readableLength)); const buffer = this._object.read(Math.min(this._object.readableLength, params.size || this._object.readableLength));
return { binary: buffer ? buffer.toString('base64') : '' }; return { binary: buffer ? buffer.toString('base64') : '' };
} }