diff --git a/src/rpc/channels.ts b/src/rpc/channels.ts index 1dd1186920..5dbe4bdce1 100644 --- a/src/rpc/channels.ts +++ b/src/rpc/channels.ts @@ -36,16 +36,16 @@ export type PlaywrightInitializer = { export interface SelectorsChannel extends Channel { register(params: { name: string, source: string, options: { contentScript?: boolean } }): Promise; - createSelector(params: { name: string, handle: ElementHandleChannel }): Promise; + createSelector(params: { name: string, handle: ElementHandleChannel }): Promise<{ value?: string }>; } export type SelectorsInitializer = {}; export interface BrowserTypeChannel extends Channel { - connect(params: types.ConnectOptions): Promise; - launch(params: types.LaunchOptions): Promise; - launchServer(params: types.LaunchServerOptions): Promise; - launchPersistentContext(params: { userDataDir: string } & types.LaunchOptions & types.BrowserContextOptions): Promise; + connect(params: types.ConnectOptions): Promise<{ browser: BrowserChannel }>; + launch(params: types.LaunchOptions): Promise<{ browser: BrowserChannel }>; + launchServer(params: types.LaunchServerOptions): Promise<{ server: BrowserServerChannel }>; + launchPersistentContext(params: { userDataDir: string } & types.LaunchOptions & types.BrowserContextOptions): Promise<{ context: BrowserContextChannel }>; } export type BrowserTypeInitializer = { executablePath: string, @@ -69,19 +69,19 @@ export interface BrowserChannel extends Channel { on(event: 'close', callback: () => void): this; close(): Promise; - newContext(params: types.BrowserContextOptions): Promise; + newContext(params: types.BrowserContextOptions): Promise<{ context: BrowserContextChannel }>; - crNewBrowserCDPSession(): Promise; + crNewBrowserCDPSession(): Promise<{ session: CDPSessionChannel }>; crStartTracing(params: { page?: PageChannel, path?: string, screenshots?: boolean, categories?: string[] }): Promise; - crStopTracing(): Promise; + crStopTracing(): Promise<{ binary: Binary }>; } export type BrowserInitializer = {}; export interface BrowserContextChannel extends Channel { - on(event: 'bindingCall', callback: (params: BindingCallChannel) => void): this; + on(event: 'bindingCall', callback: (params: { binding: BindingCallChannel }) => void): this; on(event: 'close', callback: () => void): this; - on(event: 'page', callback: (params: PageChannel) => void): this; + on(event: 'page', callback: (params: { page: PageChannel }) => void): this; on(event: 'route', callback: (params: { route: RouteChannel, request: RequestChannel }) => void): this; addCookies(params: { cookies: types.SetNetworkCookieParam[] }): Promise; @@ -89,10 +89,10 @@ export interface BrowserContextChannel extends Channel { clearCookies(): Promise; clearPermissions(): Promise; close(): Promise; - cookies(params: { urls: string[] }): Promise; + cookies(params: { urls: string[] }): Promise<{ cookies: types.NetworkCookie[] }>; exposeBinding(params: { name: string }): Promise; grantPermissions(params: { permissions: string[], origin?: string }): Promise; - newPage(): Promise; + newPage(): Promise<{ page: PageChannel }>; setDefaultNavigationTimeoutNoReply(params: { timeout: number }): void; setDefaultTimeoutNoReply(params: { timeout: number }): void; setExtraHTTPHeaders(params: { headers: types.Headers }): Promise; @@ -101,34 +101,34 @@ export interface BrowserContextChannel extends Channel { setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise; setOffline(params: { offline: boolean }): Promise; - on(event: 'crBackgroundPage', callback: (params: PageChannel) => void): this; - on(event: 'crServiceWorker', callback: (params: WorkerChannel) => void): this; - crNewCDPSession(params: { page: PageChannel }): Promise; + on(event: 'crBackgroundPage', callback: (params: { page: PageChannel }) => void): this; + on(event: 'crServiceWorker', callback: (params: { worker: WorkerChannel }) => void): this; + crNewCDPSession(params: { page: PageChannel }): Promise<{ session: CDPSessionChannel }>; } export type BrowserContextInitializer = {}; export interface PageChannel extends Channel { - on(event: 'bindingCall', callback: (params: BindingCallChannel) => void): this; + on(event: 'bindingCall', callback: (params: { binding: BindingCallChannel }) => void): this; on(event: 'close', callback: () => void): this; - on(event: 'console', callback: (params: ConsoleMessageChannel) => void): this; + on(event: 'console', callback: (params: { message: ConsoleMessageChannel }) => void): this; on(event: 'crash', callback: () => void): this; - on(event: 'dialog', callback: (params: DialogChannel) => void): this; - on(event: 'download', callback: (params: DownloadChannel) => void): this; + on(event: 'dialog', callback: (params: { dialog: DialogChannel }) => void): this; + on(event: 'download', callback: (params: { download: DownloadChannel }) => void): this; on(event: 'domcontentloaded', callback: () => void): this; on(event: 'fileChooser', callback: (params: { element: ElementHandleChannel, isMultiple: boolean }) => void): this; - on(event: 'frameAttached', callback: (params: FrameChannel) => void): this; - on(event: 'frameDetached', callback: (params: FrameChannel) => void): this; + on(event: 'frameAttached', callback: (params: { frame: FrameChannel }) => void): this; + on(event: 'frameDetached', callback: (params: { frame: FrameChannel }) => void): this; on(event: 'frameNavigated', callback: (params: { frame: FrameChannel, url: string, name: string }) => void): this; on(event: 'load', callback: () => void): this; on(event: 'pageError', callback: (params: { error: types.Error }) => void): this; - on(event: 'popup', callback: (params: PageChannel) => void): this; - on(event: 'request', callback: (params: RequestChannel) => void): this; + on(event: 'popup', callback: (params: { page: PageChannel }) => void): this; + on(event: 'request', callback: (params: { request: RequestChannel }) => void): this; on(event: 'requestFailed', callback: (params: { request: RequestChannel, failureText: string | null }) => void): this; - on(event: 'requestFinished', callback: (params: RequestChannel) => void): this; - on(event: 'response', callback: (params: ResponseChannel) => void): this; + on(event: 'requestFinished', callback: (params: { request: RequestChannel }) => void): this; + on(event: 'response', callback: (params: { response: ResponseChannel }) => void): this; on(event: 'route', callback: (params: { route: RouteChannel, request: RequestChannel }) => void): this; - on(event: 'worker', callback: (params: WorkerChannel) => void): this; + on(event: 'worker', callback: (params: { worker: WorkerChannel }) => void): this; setDefaultNavigationTimeoutNoReply(params: { timeout: number }): void; setDefaultTimeoutNoReply(params: { timeout: number }): Promise; @@ -138,11 +138,11 @@ export interface PageChannel extends Channel { close(params: { runBeforeUnload?: boolean }): Promise; emulateMedia(params: { media?: 'screen' | 'print', colorScheme?: 'dark' | 'light' | 'no-preference' }): Promise; exposeBinding(params: { name: string }): Promise; - goBack(params: types.NavigateOptions): Promise; - goForward(params: types.NavigateOptions): Promise; - opener(): Promise; - reload(params: types.NavigateOptions): Promise; - screenshot(params: types.ScreenshotOptions): Promise; + goBack(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }>; + goForward(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }>; + opener(): Promise<{ page: PageChannel | null }>; + reload(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }>; + screenshot(params: types.ScreenshotOptions): Promise<{ binary: Binary }>; setExtraHTTPHeaders(params: { headers: types.Headers }): Promise; setNetworkInterceptionEnabled(params: { enabled: boolean }): Promise; setViewportSize(params: { viewportSize: types.Size }): Promise; @@ -158,13 +158,13 @@ export interface PageChannel extends Channel { mouseUp(params: { button?: types.MouseButton, clickCount?: number }): Promise; mouseClick(params: { x: number, y: number, delay?: number, button?: types.MouseButton, clickCount?: number }): Promise; - accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise; - pdf: (params: PDFOptions) => Promise; + accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise<{ rootAXNode: types.SerializedAXNode | null }>; + pdf: (params: PDFOptions) => Promise<{ pdf: Binary }>; crStartJSCoverage(params: types.JSCoverageOptions): Promise; - crStopJSCoverage(): Promise; + crStopJSCoverage(): Promise<{ entries: types.JSCoverageEntry[] }>; crStartCSSCoverage(params: types.CSSCoverageOptions): Promise; - crStopCSSCoverage(): Promise; + crStopCSSCoverage(): Promise<{ entries: types.CSSCoverageEntry[] }>; } export type PageInitializer = { @@ -178,38 +178,38 @@ export type PageAttribution = { isPage?: boolean }; export interface FrameChannel extends Channel { on(event: 'loadstate', callback: (params: { add?: types.LifecycleEvent, remove?: types.LifecycleEvent }) => void): this; - evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise; - evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise; - addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise; - addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise; + evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<{ value: any }>; + evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<{ value: any }>; + addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<{ element: ElementHandleChannel }>; + addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<{ element: ElementHandleChannel }>; check(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise; click(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & PageAttribution): Promise; - content(): Promise; + content(): Promise<{ value: string }>; dblclick(params: { selector: string, force?: boolean } & types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & PageAttribution): Promise; dispatchEvent(params: { selector: string, type: string, eventInit: any } & types.TimeoutOptions & PageAttribution): Promise; - evaluateExpression(params: { expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise; - evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise; + evaluateExpression(params: { expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<{ value: any }>; + evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<{ handle: JSHandleChannel }>; fill(params: { selector: string, value: string } & types.NavigatingActionWaitOptions & PageAttribution): Promise; focus(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise; - frameElement(): Promise; - getAttribute(params: { selector: string, name: string } & types.TimeoutOptions & PageAttribution): Promise; - goto(params: { url: string } & types.GotoOptions & PageAttribution): Promise; + frameElement(): Promise<{ element: ElementHandleChannel }>; + getAttribute(params: { selector: string, name: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string | null }>; + goto(params: { url: string } & types.GotoOptions & PageAttribution): Promise<{ response: ResponseChannel | null }>; hover(params: { selector: string, force?: boolean } & types.PointerActionOptions & types.TimeoutOptions & PageAttribution): Promise; - innerHTML(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise; - innerText(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise; + innerHTML(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string }>; + innerText(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string }>; press(params: { selector: string, key: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise; - querySelector(params: { selector: string} & PageAttribution): Promise; - querySelectorAll(params: { selector: string} & PageAttribution): Promise; - selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise; + querySelector(params: { selector: string} & PageAttribution): Promise<{ element: ElementHandleChannel | null }>; + querySelectorAll(params: { selector: string} & PageAttribution): Promise<{ elements: ElementHandleChannel[] }>; + selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<{ values: string[] }>; setContent(params: { html: string } & types.NavigateOptions & PageAttribution): Promise; setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise; - textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise; - title(): Promise; + textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string | null }>; + title(): Promise<{ value: string }>; type(params: { selector: string, text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise; uncheck(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise; - waitForFunction(params: { expression: string, isFunction: boolean, arg: any } & types.WaitForFunctionOptions & PageAttribution): Promise; - waitForNavigation(params: types.WaitForNavigationOptions & PageAttribution): Promise; - waitForSelector(params: { selector: string } & types.WaitForElementOptions & PageAttribution): Promise; + waitForFunction(params: { expression: string, isFunction: boolean, arg: any } & types.WaitForFunctionOptions & PageAttribution): Promise<{ handle: JSHandleChannel }>; + waitForNavigation(params: types.WaitForNavigationOptions & PageAttribution): Promise<{ response: ResponseChannel | null }>; + waitForSelector(params: { selector: string } & types.WaitForElementOptions & PageAttribution): Promise<{ element: ElementHandleChannel | null }>; } export type FrameInitializer = { url: string, @@ -220,8 +220,8 @@ export type FrameInitializer = { export interface WorkerChannel extends Channel { - evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise; - evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise; + evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }>; + evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ handle: JSHandleChannel }>; } export type WorkerInitializer = { url: string, @@ -229,14 +229,14 @@ export type WorkerInitializer = { export interface JSHandleChannel extends Channel { - on(event: 'previewUpdated', callback: (preview: string) => void): this; + on(event: 'previewUpdated', callback: (params: { preview: string }) => void): this; dispose(): Promise; - evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise; - evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise; - getPropertyList(): Promise<{ name: string, value: JSHandleChannel}[]>; - getProperty(params: { name: string }): Promise; - jsonValue(): Promise; + evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }>; + evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<{ handle: JSHandleChannel }>; + getPropertyList(): Promise<{ properties: { name: string, value: JSHandleChannel}[] }>; + getProperty(params: { name: string }): Promise<{ handle: JSHandleChannel }>; + jsonValue(): Promise<{ value: any }>; } export type JSHandleInitializer = { preview: string, @@ -244,37 +244,37 @@ export type JSHandleInitializer = { export interface ElementHandleChannel extends JSHandleChannel { - evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise; - evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise; - boundingBox(): Promise; + evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }>; + evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }>; + boundingBox(): Promise<{ value: types.Rect | null }>; check(params: { force?: boolean } & { noWaitAfter?: boolean } & types.TimeoutOptions): Promise; click(params: { force?: boolean, noWaitAfter?: boolean } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions): Promise; - contentFrame(): Promise; + contentFrame(): Promise<{ frame: FrameChannel | null }>; dblclick(params: { force?: boolean, noWaitAfter?: boolean } & types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions): Promise; dispatchEvent(params: { type: string, eventInit: any }): Promise; fill(params: { value: string } & types.NavigatingActionWaitOptions): Promise; focus(): Promise; - getAttribute(params: { name: string }): Promise; + getAttribute(params: { name: string }): Promise<{ value: string | null }>; hover(params: { force?: boolean } & types.PointerActionOptions & types.TimeoutOptions): Promise; - innerHTML(): Promise; - innerText(): Promise; - ownerFrame(): Promise; + innerHTML(): Promise<{ value: string }>; + innerText(): Promise<{ value: string }>; + ownerFrame(): Promise<{ frame: FrameChannel | null }>; press(params: { key: string, delay?: number } & types.TimeoutOptions & { noWaitAfter?: boolean }): Promise; - querySelector(params: { selector: string }): Promise; - querySelectorAll(params: { selector: string }): Promise; - screenshot(params: types.ElementScreenshotOptions): Promise; + querySelector(params: { selector: string }): Promise<{ element: ElementHandleChannel | null }>; + querySelectorAll(params: { selector: string }): Promise<{ elements: ElementHandleChannel[] }>; + screenshot(params: types.ElementScreenshotOptions): Promise<{ binary: Binary }>; scrollIntoViewIfNeeded(params: types.TimeoutOptions): Promise; - selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): string[] | Promise; + selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<{ values: string[] }>; selectText(params: types.TimeoutOptions): Promise; setInputFiles(params: { files: { name: string, mimeType: string, buffer: Binary }[] } & types.NavigatingActionWaitOptions): Promise; - textContent(): Promise; + textContent(): Promise<{ value: string | null }>; type(params: { text: string, delay?: number, noWaitAfter?: boolean } & types.TimeoutOptions): Promise; uncheck(params: { force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions): Promise; } export interface RequestChannel extends Channel { - response(): Promise; + response(): Promise<{ response: ResponseChannel | null }>; } export type RequestInitializer = { frame: FrameChannel, @@ -304,8 +304,8 @@ export type RouteInitializer = { export interface ResponseChannel extends Channel { - body(): Promise; - finished(): Promise; + body(): Promise<{ binary: Binary }>; + finished(): Promise<{ error: Error | null }>; } export type ResponseInitializer = { request: RequestChannel, @@ -349,9 +349,9 @@ export type DialogInitializer = { export interface DownloadChannel extends Channel { - path(): Promise; - failure(): Promise; - stream(): Promise; + path(): Promise<{ value: string | null }>; + failure(): Promise<{ error: string | null }>; + stream(): Promise<{ stream: StreamChannel | null }>; delete(): Promise; } export type DownloadInitializer = { @@ -361,7 +361,7 @@ export type DownloadInitializer = { export interface StreamChannel extends Channel { - read(params: { size?: number }): Promise; + read(params: { size?: number }): Promise<{ binary: Binary }>; } export type StreamInitializer = { } @@ -372,7 +372,7 @@ export interface CDPSessionChannel extends Channel { on(event: 'event', callback: (params: { method: string, params?: Object }) => void): this; on(event: 'disconnected', callback: () => void): this; - send(params: { method: string, params?: Object }): Promise; + send(params: { method: string, params?: Object }): Promise<{ result: Object }>; detach(): Promise; } export type CDPSessionInitializer = {}; @@ -403,18 +403,18 @@ export type ElectronLaunchOptions = { timeout?: number, }; export interface ElectronChannel extends Channel { - launch(params: { executablePath: string } & ElectronLaunchOptions): Promise; + launch(params: { executablePath: string } & ElectronLaunchOptions): Promise<{ electronApplication: ElectronApplicationChannel }>; } export type ElectronInitializer = {}; export interface ElectronApplicationChannel extends Channel { on(event: 'close', callback: () => void): this; - on(event: 'window', callback: (params: PageChannel) => void): this; + on(event: 'window', callback: (params: { page: PageChannel }) => void): this; - newBrowserWindow(params: { arg: any }): Promise; - evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise; - evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise; + newBrowserWindow(params: { arg: any }): Promise<{ page: PageChannel }>; + evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }>; + evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ handle: JSHandleChannel }>; close(): Promise; } export type ElectronApplicationInitializer = { diff --git a/src/rpc/client/accessibility.ts b/src/rpc/client/accessibility.ts index 9c33d8f0c0..b95c51b900 100644 --- a/src/rpc/client/accessibility.ts +++ b/src/rpc/client/accessibility.ts @@ -26,8 +26,9 @@ export class Accessibility { this._channel = channel; } - snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise { + async snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise { const root = options.root ? options.root._elementChannel : undefined; - return this._channel.accessibilitySnapshot({ interestingOnly: options.interestingOnly, root }); + const result = await this._channel.accessibilitySnapshot({ interestingOnly: options.interestingOnly, root }); + return result.rootAXNode; } } diff --git a/src/rpc/client/browser.ts b/src/rpc/client/browser.ts index 683a0c969c..5dedf0634d 100644 --- a/src/rpc/client/browser.ts +++ b/src/rpc/client/browser.ts @@ -53,7 +53,7 @@ export class Browser extends ChannelOwner { async newContext(options: types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; - const context = BrowserContext.from(await this._channel.newContext(options)); + const context = BrowserContext.from((await this._channel.newContext(options)).context); this._contexts.add(context); context._logger = logger || this._logger; return context; diff --git a/src/rpc/client/browserContext.ts b/src/rpc/client/browserContext.ts index 7e6a7443b6..198f056f64 100644 --- a/src/rpc/client/browserContext.ts +++ b/src/rpc/client/browserContext.ts @@ -53,9 +53,9 @@ export class BrowserContext extends ChannelOwner this._onBinding(BindingCall.from(bindingCall))); + this._channel.on('bindingCall', ({binding}) => this._onBinding(BindingCall.from(binding))); this._channel.on('close', () => this._onClose()); - this._channel.on('page', page => this._onPage(Page.from(page))); + this._channel.on('page', ({page}) => this._onPage(Page.from(page))); this._channel.on('route', ({ route, request }) => this._onRoute(network.Route.from(route), network.Request.from(request))); this._closedPromise = new Promise(f => this.once(Events.BrowserContext.Close, f)); } @@ -99,7 +99,7 @@ export class BrowserContext extends ChannelOwner { if (this._ownerPage) throw new Error('Please use browser.newContext()'); - return Page.from(await this._channel.newPage()); + return Page.from((await this._channel.newPage()).page); } async cookies(urls?: string | string[]): Promise { @@ -107,7 +107,7 @@ export class BrowserContext extends ChannelOwner { diff --git a/src/rpc/client/browserType.ts b/src/rpc/client/browserType.ts index cf0a83bb71..2752d50127 100644 --- a/src/rpc/client/browserType.ts +++ b/src/rpc/client/browserType.ts @@ -43,20 +43,21 @@ export class BrowserType extends ChannelOwner { const logger = options.logger; options = { ...options, logger: undefined }; - const browser = Browser.from(await this._channel.launch(options)); + const browser = Browser.from((await this._channel.launch(options)).browser); browser._logger = logger; return browser; } async launchServer(options: types.LaunchServerOptions & { logger?: LoggerSink } = {}): Promise { options = { ...options, logger: undefined }; - return BrowserServer.from(await this._channel.launchServer(options)); + return BrowserServer.from((await this._channel.launchServer(options)).server); } async launchPersistentContext(userDataDir: string, options: types.LaunchOptions & types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise { const logger = options.logger; options = { ...options, logger: undefined }; - const context = BrowserContext.from(await this._channel.launchPersistentContext({ userDataDir, ...options })); + const result = await this._channel.launchPersistentContext({ userDataDir, ...options }); + const context = BrowserContext.from(result.context); context._logger = logger; return context; } @@ -64,7 +65,7 @@ export class BrowserType extends ChannelOwner { const logger = options.logger; options = { ...options, logger: undefined }; - const browser = Browser.from(await this._channel.connect(options)); + const browser = Browser.from((await this._channel.connect(options)).browser); browser._logger = logger; return browser; } diff --git a/src/rpc/client/cdpSession.ts b/src/rpc/client/cdpSession.ts index 170f368a24..e8d1948d72 100644 --- a/src/rpc/client/cdpSession.ts +++ b/src/rpc/client/cdpSession.ts @@ -47,7 +47,7 @@ export class CDPSession extends ChannelOwner { const result = await this._channel.send({ method, params }); - return result as Protocol.CommandReturnValues[T]; + return result.result as Protocol.CommandReturnValues[T]; } async detach() { diff --git a/src/rpc/client/chromiumBrowser.ts b/src/rpc/client/chromiumBrowser.ts index ccc1821a69..4c68b86147 100644 --- a/src/rpc/client/chromiumBrowser.ts +++ b/src/rpc/client/chromiumBrowser.ts @@ -20,7 +20,7 @@ import { Browser } from './browser'; export class ChromiumBrowser extends Browser { async newBrowserCDPSession(): Promise { - return CDPSession.from(await this._channel.crNewBrowserCDPSession()); + return CDPSession.from((await this._channel.crNewBrowserCDPSession()).session); } async startTracing(page?: Page, options: { path?: string; screenshots?: boolean; categories?: string[]; } = {}) { @@ -28,6 +28,6 @@ export class ChromiumBrowser extends Browser { } async stopTracing(): Promise { - return Buffer.from(await this._channel.crStopTracing(), 'base64'); + return Buffer.from((await this._channel.crStopTracing()).binary, 'base64'); } } diff --git a/src/rpc/client/chromiumBrowserContext.ts b/src/rpc/client/chromiumBrowserContext.ts index 55c16a3d5d..0001f216ac 100644 --- a/src/rpc/client/chromiumBrowserContext.ts +++ b/src/rpc/client/chromiumBrowserContext.ts @@ -29,16 +29,16 @@ export class ChromiumBrowserContext extends BrowserContext { constructor(parent: ChannelOwner, type: string, guid: string, initializer: BrowserContextInitializer) { super(parent, type, guid, initializer, 'chromium'); - this._channel.on('crBackgroundPage', pageChannel => { - const page = Page.from(pageChannel); - this._backgroundPages.add(page); - this.emit(ChromiumEvents.CRBrowserContext.BackgroundPage, page); + this._channel.on('crBackgroundPage', ({ page }) => { + const backgroundPage = Page.from(page); + this._backgroundPages.add(backgroundPage); + this.emit(ChromiumEvents.CRBrowserContext.BackgroundPage, backgroundPage); }); - this._channel.on('crServiceWorker', serviceWorkerChannel => { - const worker = Worker.from(serviceWorkerChannel); - worker._context = this; - this._serviceWorkers.add(worker); - this.emit(ChromiumEvents.CRBrowserContext.ServiceWorker, worker); + this._channel.on('crServiceWorker', ({worker}) => { + const serviceWorker = Worker.from(worker); + serviceWorker._context = this; + this._serviceWorkers.add(serviceWorker); + this.emit(ChromiumEvents.CRBrowserContext.ServiceWorker, serviceWorker); }); } @@ -51,6 +51,7 @@ export class ChromiumBrowserContext extends BrowserContext { } async newCDPSession(page: Page): Promise { - return CDPSession.from(await this._channel.crNewCDPSession({ page: page._channel })); + const result = await this._channel.crNewCDPSession({ page: page._channel }); + return CDPSession.from(result.session); } } diff --git a/src/rpc/client/coverage.ts b/src/rpc/client/coverage.ts index 393acf45d2..58497a8237 100644 --- a/src/rpc/client/coverage.ts +++ b/src/rpc/client/coverage.ts @@ -29,7 +29,7 @@ export class Coverage { } async stopJSCoverage(): Promise { - return await this._channel.crStopJSCoverage(); + return (await this._channel.crStopJSCoverage()).entries; } async startCSSCoverage(options: types.CSSCoverageOptions = {}) { @@ -37,6 +37,6 @@ export class Coverage { } async stopCSSCoverage(): Promise { - return await this._channel.crStopCSSCoverage(); + return (await this._channel.crStopCSSCoverage()).entries; } } diff --git a/src/rpc/client/download.ts b/src/rpc/client/download.ts index 5247eae9b1..7e567b0f0c 100644 --- a/src/rpc/client/download.ts +++ b/src/rpc/client/download.ts @@ -37,18 +37,18 @@ export class Download extends ChannelOwner } async path(): Promise { - return this._channel.path(); + return (await this._channel.path()).value; } async failure(): Promise { - return this._channel.failure(); + return (await this._channel.failure()).error; } async createReadStream(): Promise { - const s = await this._channel.stream(); - if (!s) + const result = await this._channel.stream(); + if (!result.stream) return null; - const stream = Stream.from(s); + const stream = Stream.from(result.stream); return stream.stream(); } diff --git a/src/rpc/client/electron.ts b/src/rpc/client/electron.ts index 577d889ca8..0dd5879202 100644 --- a/src/rpc/client/electron.ts +++ b/src/rpc/client/electron.ts @@ -37,7 +37,7 @@ export class Electron extends ChannelOwner async launch(executablePath: string, options: ElectronLaunchOptions = {}): Promise { options = { ...options }; delete (options as any).logger; - return ElectronApplication.from(await this._channel.launch({ executablePath, ...options })); + return ElectronApplication.from((await this._channel.launch({ executablePath, ...options })).electronApplication); } } @@ -53,10 +53,10 @@ export class ElectronApplication extends ChannelOwner { - const page = Page.from(pageChannel); - this._windows.add(page); - this.emit(ElectronEvents.ElectronApplication.Window, page); + this._channel.on('window', ({page}) => { + const window = Page.from(page); + this._windows.add(window); + this.emit(ElectronEvents.ElectronApplication.Window, window); }); this._channel.on('close', () => { this.emit(ElectronEvents.ElectronApplication.Close); @@ -74,7 +74,8 @@ export class ElectronApplication extends ChannelOwner { - return Page.from(await this._channel.newBrowserWindow({ arg: serializeArgument(options) })); + const result = await this._channel.newBrowserWindow({ arg: serializeArgument(options) }); + return Page.from(result.page); } context(): BrowserContext { @@ -100,13 +101,14 @@ export class ElectronApplication extends ChannelOwner(pageFunction: FuncOn, arg: Arg): Promise; async evaluate(pageFunction: FuncOn, arg?: any): Promise; async evaluate(pageFunction: FuncOn, arg: Arg): Promise { - return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return parseResult(result.value); } async evaluateHandle(pageFunction: FuncOn, arg: Arg): Promise>; async evaluateHandle(pageFunction: FuncOn, arg?: any): Promise>; async evaluateHandle(pageFunction: FuncOn, arg: Arg): Promise> { - const handleChannel = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); - return JSHandle.from(handleChannel) as SmartHandle; + const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return JSHandle.from(result.handle) as SmartHandle; } } diff --git a/src/rpc/client/elementHandle.ts b/src/rpc/client/elementHandle.ts index 3d3a34a7d7..c9b8e9e821 100644 --- a/src/rpc/client/elementHandle.ts +++ b/src/rpc/client/elementHandle.ts @@ -43,27 +43,27 @@ export class ElementHandle extends JSHandle { } async ownerFrame(): Promise { - return Frame.fromNullable(await this._elementChannel.ownerFrame()); + return Frame.fromNullable((await this._elementChannel.ownerFrame()).frame); } async contentFrame(): Promise { - return Frame.fromNullable(await this._elementChannel.contentFrame()); + return Frame.fromNullable((await this._elementChannel.contentFrame()).frame); } async getAttribute(name: string): Promise { - return await this._elementChannel.getAttribute({ name }); + return (await this._elementChannel.getAttribute({ name })).value; } async textContent(): Promise { - return await this._elementChannel.textContent(); + return (await this._elementChannel.textContent()).value; } async innerText(): Promise { - return await this._elementChannel.innerText(); + return (await this._elementChannel.innerText()).value; } async innerHTML(): Promise { - return await this._elementChannel.innerHTML(); + return (await this._elementChannel.innerHTML()).value; } async dispatchEvent(type: string, eventInit: Object = {}) { @@ -87,7 +87,8 @@ export class ElementHandle extends JSHandle { } async selectOption(values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { - return await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options }); + const result = await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options }); + return result.values; } async fill(value: string, options: types.NavigatingActionWaitOptions = {}): Promise { @@ -123,31 +124,34 @@ export class ElementHandle extends JSHandle { } async boundingBox(): Promise { - return await this._elementChannel.boundingBox(); + return (await this._elementChannel.boundingBox()).value; } async screenshot(options: types.ElementScreenshotOptions = {}): Promise { - return Buffer.from(await this._elementChannel.screenshot(options), 'base64'); + return Buffer.from((await this._elementChannel.screenshot(options)).binary, 'base64'); } async $(selector: string): Promise | null> { - return ElementHandle.fromNullable(await this._elementChannel.querySelector({ selector })) as ElementHandle | null; + return ElementHandle.fromNullable((await this._elementChannel.querySelector({ selector })).element) as ElementHandle | null; } async $$(selector: string): Promise[]> { - return (await this._elementChannel.querySelectorAll({ selector })).map(h => ElementHandle.from(h) as ElementHandle); + const result = await this._elementChannel.querySelectorAll({ selector }); + return result.elements.map(h => ElementHandle.from(h) as ElementHandle); } async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { - return parseResult(await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + const result = await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return parseResult(result.value); } async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { - return parseResult(await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + const result = await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return parseResult(result.value); } } diff --git a/src/rpc/client/frame.ts b/src/rpc/client/frame.ts index 3e3453fb74..ca552e1469 100644 --- a/src/rpc/client/frame.ts +++ b/src/rpc/client/frame.ts @@ -78,11 +78,11 @@ export class Frame extends ChannelOwner { } async goto(url: string, options: GotoOptions = {}): Promise { - return network.Response.fromNullable(await this._channel.goto({ url, ...options, isPage: this._page!._isPageCall })); + return network.Response.fromNullable((await this._channel.goto({ url, ...options, isPage: this._page!._isPageCall })).response); } async waitForNavigation(options: types.WaitForNavigationOptions = {}): Promise { - return network.Response.fromNullable(await this._channel.waitForNavigation({ ...options, isPage: this._page!._isPageCall })); + return network.Response.fromNullable((await this._channel.waitForNavigation({ ...options, isPage: this._page!._isPageCall })).response); } async waitForLoadState(state: types.LifecycleEvent = 'load', options: types.TimeoutOptions = {}): Promise { @@ -101,29 +101,33 @@ export class Frame extends ChannelOwner { } async frameElement(): Promise { - return ElementHandle.from(await this._channel.frameElement()); + return ElementHandle.from((await this._channel.frameElement()).element); } async evaluateHandle(pageFunction: Func1, arg: Arg): Promise>; async evaluateHandle(pageFunction: Func1, arg?: any): Promise>; async evaluateHandle(pageFunction: Func1, arg: Arg): Promise> { assertMaxArguments(arguments.length, 2); - return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall })) as SmartHandle; + const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + return JSHandle.from(result.handle) as SmartHandle; } async evaluate(pageFunction: Func1, arg: Arg): Promise; async evaluate(pageFunction: Func1, arg?: any): Promise; async evaluate(pageFunction: Func1, arg: Arg): Promise { assertMaxArguments(arguments.length, 2); - return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall })); + const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + return parseResult(result.value); } async $(selector: string): Promise | null> { - return ElementHandle.fromNullable(await this._channel.querySelector({ selector, isPage: this._page!._isPageCall })) as ElementHandle | null; + const result = await this._channel.querySelector({ selector, isPage: this._page!._isPageCall }); + return ElementHandle.fromNullable(result.element) as ElementHandle | null; } async waitForSelector(selector: string, options: types.WaitForElementOptions = {}): Promise | null> { - return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, ...options, isPage: this._page!._isPageCall })) as ElementHandle | null; + const result = await this._channel.waitForSelector({ selector, ...options, isPage: this._page!._isPageCall }); + return ElementHandle.fromNullable(result.element) as ElementHandle | null; } async dispatchEvent(selector: string, type: string, eventInit?: any, options: types.TimeoutOptions = {}): Promise { @@ -134,23 +138,25 @@ export class Frame extends ChannelOwner { async $eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + const result = await this._channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + return parseResult(result.value); } async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg?: any): Promise; async $$eval(selector: string, pageFunction: FuncOn, arg: Arg): Promise { assertMaxArguments(arguments.length, 3); - return await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + const result = await this._channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), isPage: this._page!._isPageCall }); + return parseResult(result.value); } async $$(selector: string): Promise[]> { const result = await this._channel.querySelectorAll({ selector, isPage: this._page!._isPageCall }); - return result.map(c => ElementHandle.from(c) as ElementHandle); + return result.elements.map(e => ElementHandle.from(e) as ElementHandle); } async content(): Promise { - return await this._channel.content(); + return (await this._channel.content()).value; } async setContent(html: string, options: types.NavigateOptions = {}): Promise { @@ -183,14 +189,14 @@ export class Frame extends ChannelOwner { copy.content = (await fsReadFileAsync(copy.path)).toString(); copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, ''); } - return ElementHandle.from(await this._channel.addScriptTag({ ...copy, isPage: this._page!._isPageCall })); + return ElementHandle.from((await this._channel.addScriptTag({ ...copy, isPage: this._page!._isPageCall })).element); } async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise { const copy = { ...options }; if (copy.path) copy.content = (await fsReadFileAsync(copy.path)).toString(); - return ElementHandle.from(await this._channel.addStyleTag({ ...options, isPage: this._page!._isPageCall })); + return ElementHandle.from((await this._channel.addStyleTag({ ...options, isPage: this._page!._isPageCall })).element); } async click(selector: string, options: types.MouseClickOptions & types.PointerActionWaitOptions & types.NavigatingActionWaitOptions = {}) { @@ -210,19 +216,19 @@ export class Frame extends ChannelOwner { } async textContent(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.textContent({ selector, ...options, isPage: this._page!._isPageCall }); + return (await this._channel.textContent({ selector, ...options, isPage: this._page!._isPageCall })).value; } async innerText(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.innerText({ selector, ...options, isPage: this._page!._isPageCall }); + return (await this._channel.innerText({ selector, ...options, isPage: this._page!._isPageCall })).value; } async innerHTML(selector: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.innerHTML({ selector, ...options, isPage: this._page!._isPageCall }); + return (await this._channel.innerHTML({ selector, ...options, isPage: this._page!._isPageCall })).value; } async getAttribute(selector: string, name: string, options: types.TimeoutOptions = {}): Promise { - return await this._channel.getAttribute({ selector, name, ...options, isPage: this._page!._isPageCall }); + return (await this._channel.getAttribute({ selector, name, ...options, isPage: this._page!._isPageCall })).value; } async hover(selector: string, options: types.PointerActionOptions & types.PointerActionWaitOptions = {}) { @@ -230,7 +236,7 @@ export class Frame extends ChannelOwner { } async selectOption(selector: string, values: string | ElementHandle | types.SelectOption | string[] | ElementHandle[] | types.SelectOption[] | null, options: types.NavigatingActionWaitOptions = {}): Promise { - return await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall }); + return (await this._channel.selectOption({ selector, ...convertSelectOptionValues(values), ...options, isPage: this._page!._isPageCall })).values; } async setInputFiles(selector: string, files: string | types.FilePayload | string[] | types.FilePayload[], options: types.NavigatingActionWaitOptions = {}): Promise { @@ -260,11 +266,12 @@ export class Frame extends ChannelOwner { async waitForFunction(pageFunction: Func1, arg: Arg, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg?: any, options?: types.WaitForFunctionOptions): Promise>; async waitForFunction(pageFunction: Func1, arg: Arg, options: types.WaitForFunctionOptions = {}): Promise> { - return JSHandle.from(await this._channel.waitForFunction({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), ...options, isPage: this._page!._isPageCall })) as SmartHandle; + const result = await this._channel.waitForFunction({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg), ...options, isPage: this._page!._isPageCall }); + return JSHandle.from(result.handle) as SmartHandle; } async title(): Promise { - return await this._channel.title(); + return (await this._channel.title()).value; } } diff --git a/src/rpc/client/jsHandle.ts b/src/rpc/client/jsHandle.ts index 29e0c70f08..ee45d2741d 100644 --- a/src/rpc/client/jsHandle.ts +++ b/src/rpc/client/jsHandle.ts @@ -49,36 +49,37 @@ export class JSHandle extends ChannelOwner this._preview = preview); + this._channel.on('previewUpdated', ({preview}) => this._preview = preview); } async evaluate(pageFunction: FuncOn, arg: Arg): Promise; async evaluate(pageFunction: FuncOn, arg?: any): Promise; async evaluate(pageFunction: FuncOn, arg: Arg): Promise { - return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return parseResult(result.value); } async evaluateHandle(pageFunction: FuncOn, arg: Arg): Promise>; async evaluateHandle(pageFunction: FuncOn, arg?: any): Promise>; async evaluateHandle(pageFunction: FuncOn, arg: Arg): Promise> { - const handleChannel = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); - return JSHandle.from(handleChannel) as SmartHandle; + const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return JSHandle.from(result.handle) as SmartHandle; } async getProperty(name: string): Promise { - const handleChannel = await this._channel.getProperty({ name }); - return JSHandle.from(handleChannel); + const result = await this._channel.getProperty({ name }); + return JSHandle.from(result.handle); } async getProperties(): Promise> { const map = new Map(); - for (const { name, value } of await this._channel.getPropertyList()) + for (const { name, value } of (await this._channel.getPropertyList()).properties) map.set(name, JSHandle.from(value)); return map; } async jsonValue(): Promise { - return parseResult(await this._channel.jsonValue()); + return parseResult((await this._channel.jsonValue()).value); } asElement(): ElementHandle | null { diff --git a/src/rpc/client/network.ts b/src/rpc/client/network.ts index d1b47fa571..e08380cbab 100644 --- a/src/rpc/client/network.ts +++ b/src/rpc/client/network.ts @@ -104,7 +104,7 @@ export class Request extends ChannelOwner { } async response(): Promise { - return Response.fromNullable(await this._channel.response()); + return Response.fromNullable((await this._channel.response()).response); } frame(): Frame { @@ -195,11 +195,11 @@ export class Response extends ChannelOwner } async finished(): Promise { - return await this._channel.finished(); + return (await this._channel.finished()).error; } async body(): Promise { - return Buffer.from(await this._channel.body(), 'base64'); + return Buffer.from((await this._channel.body()).binary, 'base64'); } async text(): Promise { diff --git a/src/rpc/client/page.ts b/src/rpc/client/page.ts index 5d28f8e977..71abc106e4 100644 --- a/src/rpc/client/page.ts +++ b/src/rpc/client/page.ts @@ -88,26 +88,26 @@ export class Page extends ChannelOwner { this._viewportSize = initializer.viewportSize; this._closed = initializer.isClosed; - this._channel.on('bindingCall', bindingCall => this._onBinding(BindingCall.from(bindingCall))); + this._channel.on('bindingCall', ({ binding }) => this._onBinding(BindingCall.from(binding))); this._channel.on('close', () => this._onClose()); - this._channel.on('console', message => this.emit(Events.Page.Console, ConsoleMessage.from(message))); + this._channel.on('console', ({ message }) => this.emit(Events.Page.Console, ConsoleMessage.from(message))); this._channel.on('crash', () => this._onCrash()); - this._channel.on('dialog', dialog => this.emit(Events.Page.Dialog, Dialog.from(dialog))); + this._channel.on('dialog', ({ dialog }) => this.emit(Events.Page.Dialog, Dialog.from(dialog))); this._channel.on('domcontentloaded', () => this.emit(Events.Page.DOMContentLoaded)); - this._channel.on('download', download => this.emit(Events.Page.Download, Download.from(download))); + this._channel.on('download', ({ download }) => this.emit(Events.Page.Download, Download.from(download))); this._channel.on('fileChooser', ({ element, isMultiple }) => this.emit(Events.Page.FileChooser, new FileChooser(this, ElementHandle.from(element), isMultiple))); - this._channel.on('frameAttached', frame => this._onFrameAttached(Frame.from(frame))); - this._channel.on('frameDetached', frame => this._onFrameDetached(Frame.from(frame))); + this._channel.on('frameAttached', ({ frame }) => this._onFrameAttached(Frame.from(frame))); + this._channel.on('frameDetached', ({ frame }) => this._onFrameDetached(Frame.from(frame))); this._channel.on('frameNavigated', ({ frame, url, name }) => this._onFrameNavigated(Frame.from(frame), url, name)); this._channel.on('load', () => this.emit(Events.Page.Load)); this._channel.on('pageError', ({ error }) => this.emit(Events.Page.PageError, parseError(error))); - this._channel.on('popup', popup => this.emit(Events.Page.Popup, Page.from(popup))); - this._channel.on('request', request => this.emit(Events.Page.Request, Request.from(request))); + this._channel.on('popup', ({ page }) => this.emit(Events.Page.Popup, Page.from(page))); + this._channel.on('request', ({ request }) => this.emit(Events.Page.Request, Request.from(request))); this._channel.on('requestFailed', ({ request, failureText }) => this._onRequestFailed(Request.from(request), failureText)); - this._channel.on('requestFinished', request => this.emit(Events.Page.RequestFinished, Request.from(request))); - this._channel.on('response', response => this.emit(Events.Page.Response, Response.from(response))); + this._channel.on('requestFinished', ({ request }) => this.emit(Events.Page.RequestFinished, Request.from(request))); + this._channel.on('response', ({ response }) => this.emit(Events.Page.Response, Response.from(response))); this._channel.on('route', ({ route, request }) => this._onRoute(Route.from(route), Request.from(request))); - this._channel.on('worker', worker => this._onWorker(Worker.from(worker))); + this._channel.on('worker', ({ worker }) => this._onWorker(Worker.from(worker))); if (this._browserContext._browserName === 'chromium') { this.coverage = new Coverage(this._channel); @@ -182,7 +182,7 @@ export class Page extends ChannelOwner { } async opener(): Promise { - return Page.fromNullable(await this._channel.opener()); + return Page.fromNullable((await this._channel.opener()).page); } mainFrame(): Frame { @@ -302,7 +302,7 @@ export class Page extends ChannelOwner { } async reload(options: types.NavigateOptions = {}): Promise { - return Response.fromNullable(await this._channel.reload(options)); + return Response.fromNullable((await this._channel.reload(options)).response); } async waitForLoadState(state?: types.LifecycleEvent, options?: types.TimeoutOptions): Promise { @@ -346,11 +346,11 @@ export class Page extends ChannelOwner { } async goBack(options: types.NavigateOptions = {}): Promise { - return Response.fromNullable(await this._channel.goBack(options)); + return Response.fromNullable((await this._channel.goBack(options)).response); } async goForward(options: types.NavigateOptions = {}): Promise { - return Response.fromNullable(await this._channel.goForward(options)); + return Response.fromNullable((await this._channel.goForward(options)).response); } async emulateMedia(options: { media?: types.MediaType, colorScheme?: types.ColorScheme }) { @@ -391,7 +391,7 @@ export class Page extends ChannelOwner { } async screenshot(options: types.ScreenshotOptions = {}): Promise { - return Buffer.from(await this._channel.screenshot(options), 'base64'); + return Buffer.from((await this._channel.screenshot(options)).binary, 'base64'); } async title(): Promise { @@ -514,8 +514,8 @@ export class Page extends ChannelOwner { if (options.margin && typeof options.margin[index] === 'number') transportOptions.margin![index] = transportOptions.margin![index] + 'px'; } - const binary = await this._channel.pdf(transportOptions); - const buffer = Buffer.from(binary, 'base64'); + const result = await this._channel.pdf(transportOptions); + const buffer = Buffer.from(result.pdf, 'base64'); if (path) await fsWriteFileAsync(path, buffer); return buffer; diff --git a/src/rpc/client/selectors.ts b/src/rpc/client/selectors.ts index a1c45a2f66..87ede311e2 100644 --- a/src/rpc/client/selectors.ts +++ b/src/rpc/client/selectors.ts @@ -34,6 +34,6 @@ export class Selectors extends ChannelOwner): Promise { - return this._channel.createSelector({ name, handle: handle._elementChannel }); + return (await this._channel.createSelector({ name, handle: handle._elementChannel })).value; } } diff --git a/src/rpc/client/stream.ts b/src/rpc/client/stream.ts index b6148de7fd..738d52d712 100644 --- a/src/rpc/client/stream.ts +++ b/src/rpc/client/stream.ts @@ -41,9 +41,9 @@ class StreamImpl extends Readable { } async _read(size: number) { - const data = await this._channel.read({ size }); - if (data) - this.push(Buffer.from(data, 'base64')); + const result = await this._channel.read({ size }); + if (result.binary) + this.push(Buffer.from(result.binary, 'base64')); else this.push(null); } diff --git a/src/rpc/client/worker.ts b/src/rpc/client/worker.ts index be479889c6..cf5dccd6ee 100644 --- a/src/rpc/client/worker.ts +++ b/src/rpc/client/worker.ts @@ -50,13 +50,15 @@ export class Worker extends ChannelOwner { async evaluate(pageFunction: Func1, arg?: any): Promise; async evaluate(pageFunction: Func1, arg: Arg): Promise { assertMaxArguments(arguments.length, 2); - return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })); + const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return parseResult(result.value); } async evaluateHandle(pageFunction: Func1, arg: Arg): Promise>; async evaluateHandle(pageFunction: Func1, arg?: any): Promise>; async evaluateHandle(pageFunction: Func1, arg: Arg): Promise> { assertMaxArguments(arguments.length, 2); - return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })) as SmartHandle; + const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }); + return JSHandle.from(result.handle) as SmartHandle; } } diff --git a/src/rpc/server/browserContextDispatcher.ts b/src/rpc/server/browserContextDispatcher.ts index 49ee7c583a..5b269a5f0e 100644 --- a/src/rpc/server/browserContextDispatcher.ts +++ b/src/rpc/server/browserContextDispatcher.ts @@ -33,8 +33,8 @@ export class BrowserContextDispatcher extends Dispatcher this._dispatchEvent('page', new PageDispatcher(this._scope, page))); + this._dispatchEvent('page', { page: new PageDispatcher(this._scope, page) }); + context.on(Events.BrowserContext.Page, page => this._dispatchEvent('page', { page: new PageDispatcher(this._scope, page) })); context.on(Events.BrowserContext.Close, () => { this._dispatchEvent('close'); this._dispose(); @@ -42,11 +42,11 @@ export class BrowserContextDispatcher extends Dispatcher this._dispatchEvent('crBackgroundPage', new PageDispatcher(this._scope, page))); + this._dispatchEvent('crBackgroundPage', { page: new PageDispatcher(this._scope, page) }); + context.on(ChromiumEvents.CRBrowserContext.BackgroundPage, page => this._dispatchEvent('crBackgroundPage', { page: new PageDispatcher(this._scope, page) })); for (const serviceWorker of (context as CRBrowserContext).serviceWorkers()) this._dispatchEvent('crServiceWorker', new WorkerDispatcher(this._scope, serviceWorker)); - context.on(ChromiumEvents.CRBrowserContext.ServiceWorker, serviceWorker => this._dispatchEvent('crServiceWorker', new WorkerDispatcher(this._scope, serviceWorker))); + context.on(ChromiumEvents.CRBrowserContext.ServiceWorker, serviceWorker => this._dispatchEvent('crServiceWorker', { worker: new WorkerDispatcher(this._scope, serviceWorker) })); } } @@ -60,18 +60,18 @@ export class BrowserContextDispatcher extends Dispatcher { await this._context.exposeBinding(params.name, (source, ...args) => { - const bindingCall = new BindingCallDispatcher(this._scope, params.name, source, args); - this._dispatchEvent('bindingCall', bindingCall); - return bindingCall.promise(); + const binding = new BindingCallDispatcher(this._scope, params.name, source, args); + this._dispatchEvent('bindingCall', { binding }); + return binding.promise(); }); } - async newPage(): Promise { - return lookupDispatcher(await this._context.newPage()); + async newPage(): Promise<{ page: PageChannel }> { + return { page: lookupDispatcher(await this._context.newPage()) }; } - async cookies(params: { urls: string[] }): Promise { - return await this._context.cookies(params.urls); + async cookies(params: { urls: string[] }): Promise<{ cookies: types.NetworkCookie[] }> { + return { cookies: await this._context.cookies(params.urls) }; } async addCookies(params: { cookies: types.SetNetworkCookieParam[] }): Promise { @@ -124,8 +124,8 @@ export class BrowserContextDispatcher extends Dispatcher { + async crNewCDPSession(params: { page: PageDispatcher }): Promise<{ session: CDPSessionChannel }> { const crBrowserContext = this._object as CRBrowserContext; - return new CDPSessionDispatcher(this._scope, await crBrowserContext.newCDPSession(params.page._object)); + return { session: new CDPSessionDispatcher(this._scope, await crBrowserContext.newCDPSession(params.page._object)) }; } } diff --git a/src/rpc/server/browserDispatcher.ts b/src/rpc/server/browserDispatcher.ts index 7a5a6f9787..6729c67793 100644 --- a/src/rpc/server/browserDispatcher.ts +++ b/src/rpc/server/browserDispatcher.ts @@ -34,17 +34,17 @@ export class BrowserDispatcher extends Dispatcher i }); } - async newContext(params: types.BrowserContextOptions): Promise { - return new BrowserContextDispatcher(this._scope, await this._object.newContext(params) as BrowserContextBase); + async newContext(params: types.BrowserContextOptions): Promise<{ context: BrowserContextChannel }> { + return { context: new BrowserContextDispatcher(this._scope, await this._object.newContext(params) as BrowserContextBase) }; } async close(): Promise { await this._object.close(); } - async crNewBrowserCDPSession(): Promise { + async crNewBrowserCDPSession(): Promise<{ session: CDPSessionChannel }> { const crBrowser = this._object as CRBrowser; - return 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 { @@ -52,9 +52,9 @@ export class BrowserDispatcher extends Dispatcher i await crBrowser.startTracing(params.page ? params.page._object : undefined, params); } - async crStopTracing(): Promise { + async crStopTracing(): Promise<{ binary: Binary }> { const crBrowser = this._object as CRBrowser; const buffer = await crBrowser.stopTracing(); - return buffer.toString('base64'); + return { binary: buffer.toString('base64') }; } } diff --git a/src/rpc/server/browserTypeDispatcher.ts b/src/rpc/server/browserTypeDispatcher.ts index 51d25230ca..b9baca8e20 100644 --- a/src/rpc/server/browserTypeDispatcher.ts +++ b/src/rpc/server/browserTypeDispatcher.ts @@ -32,22 +32,22 @@ export class BrowserTypeDispatcher extends Dispatcher { + async launch(params: types.LaunchOptions): Promise<{ browser: BrowserChannel }> { const browser = await this._object.launch(params); - return new BrowserDispatcher(this._scope, browser as BrowserBase); + return { browser: new BrowserDispatcher(this._scope, browser as BrowserBase) }; } - async launchPersistentContext(params: { userDataDir: string } & types.LaunchOptions & types.BrowserContextOptions): Promise { + async launchPersistentContext(params: { userDataDir: string } & types.LaunchOptions & types.BrowserContextOptions): Promise<{ context: BrowserContextChannel }> { const browserContext = await this._object.launchPersistentContext(params.userDataDir, params); - return new BrowserContextDispatcher(this._scope, browserContext as BrowserContextBase); + return { context: new BrowserContextDispatcher(this._scope, browserContext as BrowserContextBase) }; } - async launchServer(params: types.LaunchServerOptions): Promise { - return new BrowserServerDispatcher(this._scope, await this._object.launchServer(params)); + async launchServer(params: types.LaunchServerOptions): Promise<{ server: BrowserServerChannel }> { + return { server: new BrowserServerDispatcher(this._scope, await this._object.launchServer(params)) }; } - async connect(params: types.ConnectOptions): Promise { + async connect(params: types.ConnectOptions): Promise<{ browser: BrowserChannel }> { const browser = await this._object.connect(params); - return new BrowserDispatcher(this._scope, browser as BrowserBase); + return { browser: new BrowserDispatcher(this._scope, browser as BrowserBase) }; } } diff --git a/src/rpc/server/cdpSessionDispatcher.ts b/src/rpc/server/cdpSessionDispatcher.ts index 973ea791c6..a7e1ad85d9 100644 --- a/src/rpc/server/cdpSessionDispatcher.ts +++ b/src/rpc/server/cdpSessionDispatcher.ts @@ -28,8 +28,8 @@ export class CDPSessionDispatcher extends Dispatcher { - return this._object.send(params.method as any, params.params); + async send(params: { method: string, params?: Object }): Promise<{ result: Object }> { + return { result: await this._object.send(params.method as any, params.params) }; } async detach(): Promise { diff --git a/src/rpc/server/downloadDispatcher.ts b/src/rpc/server/downloadDispatcher.ts index f6eee1ab6c..9fe59c976b 100644 --- a/src/rpc/server/downloadDispatcher.ts +++ b/src/rpc/server/downloadDispatcher.ts @@ -27,20 +27,20 @@ export class DownloadDispatcher extends Dispatcher { - return this._object.path(); + async path(): Promise<{ value: string | null }> { + return { value: await this._object.path() }; } - async stream(): Promise { + async stream(): Promise<{ stream: StreamChannel | null }> { const stream = await this._object.createReadStream(); if (!stream) - return null; + return { stream: null }; await new Promise(f => stream.on('readable', f)); - return new StreamDispatcher(this._scope, stream); + return { stream: new StreamDispatcher(this._scope, stream) }; } - async failure(): Promise { - return this._object.failure(); + async failure(): Promise<{ error: string | null }> { + return { error: await this._object.failure() }; } async delete(): Promise { diff --git a/src/rpc/server/electronDispatcher.ts b/src/rpc/server/electronDispatcher.ts index b176f21260..e72169f52b 100644 --- a/src/rpc/server/electronDispatcher.ts +++ b/src/rpc/server/electronDispatcher.ts @@ -29,9 +29,9 @@ export class ElectronDispatcher extends Dispatcher { + async launch(params: { executablePath: string } & ElectronLaunchOptions): Promise<{ electronApplication: ElectronApplicationChannel }> { const electronApplication = await this._object.launch(params.executablePath, params); - return new ElectronApplicationDispatcher(this._scope, electronApplication); + return { electronApplication: new ElectronApplicationDispatcher(this._scope, electronApplication) }; } } @@ -42,22 +42,25 @@ export class ElectronApplicationDispatcher extends Dispatcher this._dispatchEvent('close')); - electronApplication.on(ElectronEvents.ElectronApplication.Window, (page: Page) => this._dispatchEvent('window', lookupDispatcher(page))); + electronApplication.on(ElectronEvents.ElectronApplication.Window, (page: Page) => { + this._dispatchEvent('window', { page: lookupDispatcher(page) }); + }); } - async newBrowserWindow(params: { arg: any }): Promise { - return lookupDispatcher(await this._object.newBrowserWindow(parseArgument(params.arg))); + async newBrowserWindow(params: { arg: any }): Promise<{ page: PageChannel }> { + const page = await this._object.newBrowserWindow(parseArgument(params.arg)); + return { page: lookupDispatcher(page) }; } - async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise { + async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }> { const handle = this._object._nodeElectronHandle!; - return handle._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg)); + return { value: await handle._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg)) }; } - async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise { + async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<{ handle: JSHandleChannel }> { const handle = this._object._nodeElectronHandle!; const result = await handle._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg)); - return createHandle(this._scope, result); + return { handle: createHandle(this._scope, result) }; } async close(): Promise { diff --git a/src/rpc/server/elementHandlerDispatcher.ts b/src/rpc/server/elementHandlerDispatcher.ts index e06f4de11e..7e4454c394 100644 --- a/src/rpc/server/elementHandlerDispatcher.ts +++ b/src/rpc/server/elementHandlerDispatcher.ts @@ -17,7 +17,7 @@ import { ElementHandle } from '../../dom'; import * as js from '../../javascript'; import * as types from '../../types'; -import { ElementHandleChannel, FrameChannel } from '../channels'; +import { ElementHandleChannel, FrameChannel, Binary } from '../channels'; import { DispatcherScope, lookupNullableDispatcher } from './dispatcher'; import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher'; import { FrameDispatcher } from './frameDispatcher'; @@ -40,28 +40,28 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme this._elementHandle = elementHandle; } - async ownerFrame(): Promise { - return lookupNullableDispatcher(await this._elementHandle.ownerFrame()); + async ownerFrame(): Promise<{ frame: FrameChannel | null }> { + return { frame: lookupNullableDispatcher(await this._elementHandle.ownerFrame()) }; } - async contentFrame(): Promise { - return lookupNullableDispatcher(await this._elementHandle.contentFrame()); + async contentFrame(): Promise<{ frame: FrameChannel | null }> { + return { frame: lookupNullableDispatcher(await this._elementHandle.contentFrame()) }; } - async getAttribute(params: { name: string }): Promise { - return this._elementHandle.getAttribute(params.name); + async getAttribute(params: { name: string }): Promise<{ value: string | null }> { + return { value: await this._elementHandle.getAttribute(params.name) }; } - async textContent(): Promise { - return this._elementHandle.textContent(); + async textContent(): Promise<{ value: string | null }> { + return { value: await this._elementHandle.textContent() }; } - async innerText(): Promise { - return this._elementHandle.innerText(); + async innerText(): Promise<{ value: string }> { + return { value: await this._elementHandle.innerText() }; } - async innerHTML(): Promise { - return this._elementHandle.innerHTML(); + async innerHTML(): Promise<{ value: string }> { + return { value: await this._elementHandle.innerHTML() }; } async dispatchEvent(params: { type: string, eventInit: Object }) { @@ -84,8 +84,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme await this._elementHandle.dblclick(params); } - async selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise { - return this._elementHandle.selectOption(convertSelectOptionValues(params.elements, params.options), params); + async selectOption(params: { elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions): Promise<{ values: string[] }> { + return { values: await this._elementHandle.selectOption(convertSelectOptionValues(params.elements, params.options), params) }; } async fill(params: { value: string } & types.NavigatingActionWaitOptions) { @@ -120,30 +120,30 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme await this._elementHandle.uncheck(params); } - async boundingBox(): Promise { - return await this._elementHandle.boundingBox(); + async boundingBox(): Promise<{ value: types.Rect | null }> { + return { value: await this._elementHandle.boundingBox() }; } - async screenshot(params: types.ElementScreenshotOptions): Promise { - return (await this._elementHandle.screenshot(params)).toString('base64'); + async screenshot(params: types.ElementScreenshotOptions): Promise<{ binary: Binary }> { + return { binary: (await this._elementHandle.screenshot(params)).toString('base64') }; } - async querySelector(params: { selector: string }): Promise { + async querySelector(params: { selector: string }): Promise<{ element: ElementHandleChannel | null }> { const handle = await this._elementHandle.$(params.selector); - return handle ? new ElementHandleDispatcher(this._scope, handle) : null; + return { element: handle ? new ElementHandleDispatcher(this._scope, handle) : null }; } - async querySelectorAll(params: { selector: string }): Promise { + async querySelectorAll(params: { selector: string }): Promise<{ elements: ElementHandleChannel[] }> { const elements = await this._elementHandle.$$(params.selector); - return 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: any }): Promise { - return serializeResult(await this._elementHandle._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + async evalOnSelector(params: { selector: string, expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }> { + 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: any }): Promise { - return serializeResult(await this._elementHandle._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + async evalOnSelectorAll(params: { selector: string, expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }> { + return { value: serializeResult(await this._elementHandle._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; } } diff --git a/src/rpc/server/frameDispatcher.ts b/src/rpc/server/frameDispatcher.ts index ed9472de27..c4b6d93664 100644 --- a/src/rpc/server/frameDispatcher.ts +++ b/src/rpc/server/frameDispatcher.ts @@ -46,33 +46,33 @@ export class FrameDispatcher extends Dispatcher impleme }); } - async goto(params: { url: string } & types.GotoOptions & PageAttribution): Promise { + async goto(params: { url: string } & types.GotoOptions & PageAttribution): Promise<{ response: ResponseChannel | null }> { const target = params.isPage ? this._frame._page : this._frame; - return lookupNullableDispatcher(await target.goto(params.url, params)); + return { response: lookupNullableDispatcher(await target.goto(params.url, params)) }; } - async waitForNavigation(params: types.WaitForNavigationOptions & PageAttribution): Promise { + async waitForNavigation(params: types.WaitForNavigationOptions & PageAttribution): Promise<{ response: ResponseChannel | null }> { const target = params.isPage ? this._frame._page : this._frame; - return lookupNullableDispatcher(await target.waitForNavigation(params)); + return { response: lookupNullableDispatcher(await target.waitForNavigation(params)) }; } - async frameElement(): Promise { - return new ElementHandleDispatcher(this._scope, await this._frame.frameElement()); + async frameElement(): Promise<{ element: ElementHandleChannel }> { + return { element: new ElementHandleDispatcher(this._scope, await this._frame.frameElement()) }; } - async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise { + async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise<{ value: any }> { const target = params.isPage ? this._frame._page : this._frame; - return serializeResult(await target._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))); + return { value: serializeResult(await target._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) }; } - async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise { + async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise<{ handle: JSHandleChannel }> { const target = params.isPage ? this._frame._page : this._frame; - return createHandle(this._scope, await target._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))); + return { handle: createHandle(this._scope, await target._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) }; } - async waitForSelector(params: { selector: string } & types.WaitForElementOptions & PageAttribution): Promise { + async waitForSelector(params: { selector: string } & types.WaitForElementOptions & PageAttribution): Promise<{ element: ElementHandleChannel | null }> { const target = params.isPage ? this._frame._page : this._frame; - return ElementHandleDispatcher.createNullable(this._scope, await target.waitForSelector(params.selector, params)); + return { element: ElementHandleDispatcher.createNullable(this._scope, await target.waitForSelector(params.selector, params)) }; } async dispatchEvent(params: { selector: string, type: string, eventInit: any } & types.TimeoutOptions & PageAttribution): Promise { @@ -80,29 +80,29 @@ export class FrameDispatcher extends Dispatcher impleme return target.dispatchEvent(params.selector, params.type, parseArgument(params.eventInit), params); } - async evalOnSelector(params: { selector: string, expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise { + async evalOnSelector(params: { selector: string, expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise<{ value: any }> { const target = params.isPage ? this._frame._page : this._frame; - return serializeResult(await target._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + return { value: serializeResult(await target._$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; } - async evalOnSelectorAll(params: { selector: string, expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise { + async evalOnSelectorAll(params: { selector: string, expression: string, isFunction: boolean, arg: any } & PageAttribution): Promise<{ value: any }> { const target = params.isPage ? this._frame._page : this._frame; - return serializeResult(await target._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))); + return { value: serializeResult(await target._$$evalExpression(params.selector, params.expression, params.isFunction, parseArgument(params.arg))) }; } - async querySelector(params: { selector: string } & PageAttribution): Promise { + async querySelector(params: { selector: string } & PageAttribution): Promise<{ element: ElementHandleChannel | null }> { const target = params.isPage ? this._frame._page : this._frame; - return ElementHandleDispatcher.createNullable(this._scope, await target.$(params.selector)); + return { element: ElementHandleDispatcher.createNullable(this._scope, await target.$(params.selector)) }; } - async querySelectorAll(params: { selector: string } & PageAttribution): Promise { + async querySelectorAll(params: { selector: string } & PageAttribution): Promise<{ elements: ElementHandleChannel[] }> { const target = params.isPage ? this._frame._page : this._frame; const elements = await target.$$(params.selector); - return elements.map(e => new ElementHandleDispatcher(this._scope, e)); + return { elements: elements.map(e => new ElementHandleDispatcher(this._scope, e)) }; } - async content(): Promise { - return await this._frame.content(); + async content(): Promise<{ value: string }> { + return { value: await this._frame.content() }; } async setContent(params: { html: string } & types.NavigateOptions & PageAttribution): Promise { @@ -110,14 +110,14 @@ export class FrameDispatcher extends Dispatcher impleme await target.setContent(params.html, params); } - async addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise { + async addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<{ element: ElementHandleChannel }> { const target = params.isPage ? this._frame._page : this._frame; - return new ElementHandleDispatcher(this._scope, await target.addScriptTag(params)); + return { element: new ElementHandleDispatcher(this._scope, await target.addScriptTag(params)) }; } - async addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise { + async addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<{ element: ElementHandleChannel }> { const target = params.isPage ? this._frame._page : this._frame; - return new ElementHandleDispatcher(this._scope, await target.addStyleTag(params)); + return { element: new ElementHandleDispatcher(this._scope, await target.addStyleTag(params)) }; } async click(params: { selector: string } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean } & PageAttribution): Promise { @@ -140,24 +140,24 @@ export class FrameDispatcher extends Dispatcher impleme await target.focus(params.selector, params); } - async textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise { + async textContent(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string | null }> { const target = params.isPage ? this._frame._page : this._frame; - return await target.textContent(params.selector, params); + return { value: await target.textContent(params.selector, params) }; } - async innerText(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise { + async innerText(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string }> { const target = params.isPage ? this._frame._page : this._frame; - return await target.innerText(params.selector, params); + return { value: await target.innerText(params.selector, params) }; } - async innerHTML(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise { + async innerHTML(params: { selector: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string }> { const target = params.isPage ? this._frame._page : this._frame; - return await target.innerHTML(params.selector, params); + return { value: await target.innerHTML(params.selector, params) }; } - async getAttribute(params: { selector: string, name: string } & types.TimeoutOptions & PageAttribution): Promise { + async getAttribute(params: { selector: string, name: string } & types.TimeoutOptions & PageAttribution): Promise<{ value: string | null }> { const target = params.isPage ? this._frame._page : this._frame; - return await target.getAttribute(params.selector, params.name, params); + return { value: await target.getAttribute(params.selector, params.name, params) }; } async hover(params: { selector: string } & types.PointerActionOptions & types.TimeoutOptions & { force?: boolean } & PageAttribution): Promise { @@ -165,9 +165,9 @@ export class FrameDispatcher extends Dispatcher impleme await target.hover(params.selector, params); } - async selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise { + async selectOption(params: { selector: string, elements?: ElementHandleChannel[], options?: types.SelectOption[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise<{ values: string[] }> { const target = params.isPage ? this._frame._page : this._frame; - return target.selectOption(params.selector, convertSelectOptionValues(params.elements, params.options), params); + return { values: await target.selectOption(params.selector, convertSelectOptionValues(params.elements, params.options), params) }; } async setInputFiles(params: { selector: string, files: { name: string, mimeType: string, buffer: string }[] } & types.NavigatingActionWaitOptions & PageAttribution): Promise { @@ -195,12 +195,12 @@ export class FrameDispatcher extends Dispatcher impleme await target.uncheck(params.selector, params); } - async waitForFunction(params: { expression: string, isFunction: boolean, arg: any } & types.WaitForFunctionOptions & PageAttribution): Promise { + async waitForFunction(params: { expression: string, isFunction: boolean, arg: any } & types.WaitForFunctionOptions & PageAttribution): Promise<{ handle: JSHandleChannel }> { const target = params.isPage ? this._frame._page : this._frame; - return createHandle(this._scope, await target._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params)); + return { handle: createHandle(this._scope, await target._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params)) }; } - async title(): Promise { - return await this._frame.title(); + async title(): Promise<{ value: string }> { + return { value: await this._frame.title() }; } } diff --git a/src/rpc/server/jsHandleDispatcher.ts b/src/rpc/server/jsHandleDispatcher.ts index 0f2ed9f186..4737bc6a9a 100644 --- a/src/rpc/server/jsHandleDispatcher.ts +++ b/src/rpc/server/jsHandleDispatcher.ts @@ -26,33 +26,33 @@ export class JSHandleDispatcher extends Dispatcher this._dispatchEvent('previewUpdated', preview)); + jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', { preview })); } - async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise { - return this._object._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg)); + async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<{ value: any }> { + return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, true /* returnByValue */, parseArgument(params.arg))) }; } - async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise { + async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<{ handle: JSHandleChannel }> { const jsHandle = await this._object._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg)); - return createHandle(this._scope, jsHandle); + return { handle: createHandle(this._scope, jsHandle) }; } - async getProperty(params: { name: string }): Promise { + async getProperty(params: { name: string }): Promise<{ handle: JSHandleChannel }> { const jsHandle = await this._object.getProperty(params.name); - return createHandle(this._scope, jsHandle); + return { handle: createHandle(this._scope, jsHandle) }; } - async getPropertyList(): Promise<{ name: string, value: JSHandleChannel }[]> { + async getPropertyList(): Promise<{ properties: { name: string, value: JSHandleChannel }[] }> { const map = await this._object.getProperties(); - const result = []; + const properties = []; for (const [name, value] of map) - result.push({ name, value: new JSHandleDispatcher(this._scope, value) }); - return result; + properties.push({ name, value: new JSHandleDispatcher(this._scope, value) }); + return { properties }; } - async jsonValue(): Promise { - return serializeResult(await this._object.jsonValue()); + async jsonValue(): Promise<{ value: any }> { + return { value: serializeResult(await this._object.jsonValue()) }; } async dispose() { diff --git a/src/rpc/server/networkDispatchers.ts b/src/rpc/server/networkDispatchers.ts index af511100b4..1ad7bbfd66 100644 --- a/src/rpc/server/networkDispatchers.ts +++ b/src/rpc/server/networkDispatchers.ts @@ -44,8 +44,8 @@ export class RequestDispatcher extends Dispatcher i }); } - async response(): Promise { - return lookupNullableDispatcher(await this._object.response()); + async response(): Promise<{ response: ResponseChannel | null }> { + return { response: lookupNullableDispatcher(await this._object.response()) }; } } @@ -62,12 +62,12 @@ export class ResponseDispatcher extends Dispatcher { - return await this._object.finished(); + async finished(): Promise<{ error: Error | null }> { + return { error: await this._object.finished() }; } - async body(): Promise { - return (await this._object.body()).toString('base64'); + async body(): Promise<{ binary: Binary }> { + return { binary: (await this._object.body()).toString('base64') }; } } diff --git a/src/rpc/server/pageDispatcher.ts b/src/rpc/server/pageDispatcher.ts index 5daeec5915..130718a002 100644 --- a/src/rpc/server/pageDispatcher.ts +++ b/src/rpc/server/pageDispatcher.ts @@ -46,11 +46,11 @@ export class PageDispatcher extends Dispatcher implements }); this._page = page; page.on(Events.Page.Close, () => this._dispatchEvent('close')); - page.on(Events.Page.Console, message => this._dispatchEvent('console', new ConsoleMessageDispatcher(this._scope, message))); + page.on(Events.Page.Console, message => this._dispatchEvent('console', { message: new ConsoleMessageDispatcher(this._scope, message) })); page.on(Events.Page.Crash, () => this._dispatchEvent('crash')); page.on(Events.Page.DOMContentLoaded, () => this._dispatchEvent('domcontentloaded')); - page.on(Events.Page.Dialog, dialog => this._dispatchEvent('dialog', new DialogDispatcher(this._scope, dialog))); - page.on(Events.Page.Download, dialog => this._dispatchEvent('download', new DownloadDispatcher(this._scope, dialog))); + page.on(Events.Page.Dialog, dialog => this._dispatchEvent('dialog', { dialog: new DialogDispatcher(this._scope, dialog) })); + page.on(Events.Page.Download, dialog => this._dispatchEvent('download', { download: new DownloadDispatcher(this._scope, dialog) })); page.on(Events.Page.FileChooser, (fileChooser: FileChooser) => this._dispatchEvent('fileChooser', { element: new ElementHandleDispatcher(this._scope, fileChooser.element()), isMultiple: fileChooser.isMultiple() @@ -60,15 +60,15 @@ export class PageDispatcher extends Dispatcher implements page.on(Events.Page.FrameNavigated, frame => this._onFrameNavigated(frame)); page.on(Events.Page.Load, () => this._dispatchEvent('load')); page.on(Events.Page.PageError, error => this._dispatchEvent('pageError', { error: serializeError(error) })); - page.on(Events.Page.Popup, page => this._dispatchEvent('popup', lookupDispatcher(page))); - page.on(Events.Page.Request, request => this._dispatchEvent('request', RequestDispatcher.from(this._scope, request))); + page.on(Events.Page.Popup, page => this._dispatchEvent('popup', { page: lookupDispatcher(page) })); + page.on(Events.Page.Request, request => this._dispatchEvent('request', { request: RequestDispatcher.from(this._scope, request) })); page.on(Events.Page.RequestFailed, (request: Request) => this._dispatchEvent('requestFailed', { request: RequestDispatcher.from(this._scope, request), failureText: request._failureText })); - page.on(Events.Page.RequestFinished, request => this._dispatchEvent('requestFinished', RequestDispatcher.from(scope, request))); - page.on(Events.Page.Response, response => this._dispatchEvent('response', new ResponseDispatcher(this._scope, response))); - page.on(Events.Page.Worker, worker => this._dispatchEvent('worker', new WorkerDispatcher(this._scope, worker))); + page.on(Events.Page.RequestFinished, request => this._dispatchEvent('requestFinished', { request: RequestDispatcher.from(scope, request) })); + page.on(Events.Page.Response, response => this._dispatchEvent('response', { response: new ResponseDispatcher(this._scope, response) })); + page.on(Events.Page.Worker, worker => this._dispatchEvent('worker', { worker: new WorkerDispatcher(this._scope, worker) })); } async setDefaultNavigationTimeoutNoReply(params: { timeout: number }) { @@ -79,15 +79,15 @@ export class PageDispatcher extends Dispatcher implements this._page.setDefaultTimeout(params.timeout); } - async opener(): Promise { - return lookupNullableDispatcher(await this._page.opener()); + async opener(): Promise<{ page: PageChannel | null }> { + return { page: lookupNullableDispatcher(await this._page.opener()) }; } async exposeBinding(params: { name: string }): Promise { await this._page.exposeBinding(params.name, (source, ...args) => { - const bindingCall = new BindingCallDispatcher(this._scope, params.name, source, args); - this._dispatchEvent('bindingCall', bindingCall); - return bindingCall.promise(); + const binding = new BindingCallDispatcher(this._scope, params.name, source, args); + this._dispatchEvent('bindingCall', { binding }); + return binding.promise(); }); } @@ -95,16 +95,16 @@ export class PageDispatcher extends Dispatcher implements await this._page.setExtraHTTPHeaders(params.headers); } - async reload(params: types.NavigateOptions): Promise { - return lookupNullableDispatcher(await this._page.reload(params)); + async reload(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }> { + return { response: lookupNullableDispatcher(await this._page.reload(params)) }; } - async goBack(params: types.NavigateOptions): Promise { - return lookupNullableDispatcher(await this._page.goBack(params)); + async goBack(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }> { + return { response: lookupNullableDispatcher(await this._page.goBack(params)) }; } - async goForward(params: types.NavigateOptions): Promise { - return lookupNullableDispatcher(await this._page.goForward(params)); + async goForward(params: types.NavigateOptions): Promise<{ response: ResponseChannel | null }> { + return { response: lookupNullableDispatcher(await this._page.goForward(params)) }; } async emulateMedia(params: { media?: 'screen' | 'print', colorScheme?: 'dark' | 'light' | 'no-preference' }): Promise { @@ -129,8 +129,8 @@ export class PageDispatcher extends Dispatcher implements }); } - async screenshot(params: types.ScreenshotOptions): Promise { - return (await this._page.screenshot(params)).toString('base64'); + async screenshot(params: types.ScreenshotOptions): Promise<{ binary: Binary }> { + return { binary: (await this._page.screenshot(params)).toString('base64') }; } async close(params: { runBeforeUnload?: boolean }): Promise { @@ -180,18 +180,19 @@ export class PageDispatcher extends Dispatcher implements await this._page.mouse.click(params.x, params.y, params); } - async accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise { - return await this._page.accessibility.snapshot({ + async accessibilitySnapshot(params: { interestingOnly?: boolean, root?: ElementHandleChannel }): Promise<{ rootAXNode: types.SerializedAXNode | null }> { + const rootAXNode = await this._page.accessibility.snapshot({ interestingOnly: params.interestingOnly, root: params.root ? (params.root as ElementHandleDispatcher)._elementHandle : undefined }); + return { rootAXNode }; } - async pdf(params: PDFOptions): Promise { + async pdf(params: PDFOptions): Promise<{ pdf: Binary }> { if (!this._page.pdf) throw new Error('PDF generation is only supported for Headless Chromium'); - const binary = await this._page.pdf(params); - return binary.toString('base64'); + const buffer = await this._page.pdf(params); + return { pdf: buffer.toString('base64') }; } async crStartJSCoverage(params: types.JSCoverageOptions): Promise { @@ -199,9 +200,9 @@ export class PageDispatcher extends Dispatcher implements await coverage.startJSCoverage(params); } - async crStopJSCoverage(): Promise { + async crStopJSCoverage(): Promise<{ entries: types.JSCoverageEntry[] }> { const coverage = this._page.coverage as CRCoverage; - return await coverage.stopJSCoverage(); + return { entries: await coverage.stopJSCoverage() }; } async crStartCSSCoverage(params: types.CSSCoverageOptions): Promise { @@ -209,13 +210,13 @@ export class PageDispatcher extends Dispatcher implements await coverage.startCSSCoverage(params); } - async crStopCSSCoverage(): Promise { + async crStopCSSCoverage(): Promise<{ entries: types.CSSCoverageEntry[] }> { const coverage = this._page.coverage as CRCoverage; - return await coverage.stopCSSCoverage(); + return { entries: await coverage.stopCSSCoverage() }; } _onFrameAttached(frame: Frame) { - this._dispatchEvent('frameAttached', FrameDispatcher.from(this._scope, frame)); + this._dispatchEvent('frameAttached', { frame: FrameDispatcher.from(this._scope, frame) }); } _onFrameNavigated(frame: Frame) { @@ -223,7 +224,7 @@ export class PageDispatcher extends Dispatcher implements } _onFrameDetached(frame: Frame) { - this._dispatchEvent('frameDetached', lookupDispatcher(frame)); + this._dispatchEvent('frameDetached', { frame: lookupDispatcher(frame) }); } } @@ -236,12 +237,12 @@ export class WorkerDispatcher extends Dispatcher impl worker.on(Events.Worker.Close, () => this._dispatchEvent('close')); } - async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { - return serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))); + async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<{ value: any }> { + return { value: serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg))) }; } - async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise { - return createHandle(this._scope, await this._object._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))); + async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<{ handle: JSHandleChannel }> { + return { handle: createHandle(this._scope, await this._object._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg))) }; } } diff --git a/src/rpc/server/selectorsDispatcher.ts b/src/rpc/server/selectorsDispatcher.ts index 52dafd972d..1cae7b1803 100644 --- a/src/rpc/server/selectorsDispatcher.ts +++ b/src/rpc/server/selectorsDispatcher.ts @@ -29,7 +29,7 @@ export class SelectorsDispatcher extends Dispatcher { - return this._object._createSelector(params.name, params.handle._object as dom.ElementHandle); + async createSelector(params: { name: string, handle: ElementHandleDispatcher }): Promise<{ value?: string }> { + return { value: await this._object._createSelector(params.name, params.handle._object as dom.ElementHandle) }; } } diff --git a/src/rpc/server/streamDispatcher.ts b/src/rpc/server/streamDispatcher.ts index 011243f23d..c749f15d92 100644 --- a/src/rpc/server/streamDispatcher.ts +++ b/src/rpc/server/streamDispatcher.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { StreamChannel, StreamInitializer } from '../channels'; +import { StreamChannel, StreamInitializer, Binary } from '../channels'; import { Dispatcher, DispatcherScope } from './dispatcher'; import * as stream from 'stream'; @@ -23,8 +23,8 @@ export class StreamDispatcher extends Dispatcher { + async read(params: { size?: number }): Promise<{ binary: Binary }> { const buffer = this._object.read(Math.min(this._object.readableLength, params.size || this._object.readableLength)); - return buffer ? buffer.toString('base64') : ''; + return { binary: buffer ? buffer.toString('base64') : '' }; } } diff --git a/test/jshandle.spec.js b/test/jshandle.spec.js index b7e3b4d20c..0ab4a5e3a0 100644 --- a/test/jshandle.spec.js +++ b/test/jshandle.spec.js @@ -99,6 +99,23 @@ describe('Page.evaluateHandle', function() { }); }); +describe('JSHandle.evaluate', function() { + it('should work with function', async({page, server}) => { + const windowHandle = await page.evaluateHandle(() => { + window.foo = [1, 2]; + return window; + }); + expect(await windowHandle.evaluate(w => w.foo)).toEqual([1, 2]); + }); + it('should work with expression', async({page, server}) => { + const windowHandle = await page.evaluateHandle(() => { + window.foo = [1, 2]; + return window; + }); + expect(await windowHandle.evaluate('window.foo')).toEqual([1, 2]); + }); +}); + describe('JSHandle.getProperty', function() { it('should work', async({page, server}) => { const aHandle = await page.evaluateHandle(() => ({ diff --git a/test/queryselector.spec.js b/test/queryselector.spec.js index 23ce695d66..f3b040c1e6 100644 --- a/test/queryselector.spec.js +++ b/test/queryselector.spec.js @@ -173,6 +173,11 @@ describe('Page.$eval', function() { await page.setContent('
'); await inputPromise; }); + it('should return complex values', async({page, server}) => { + await page.setContent('
43543
'); + const idAttribute = await page.$eval('css=section', e => [{ id: e.id }]); + expect(idAttribute).toEqual([{ id: 'testAttribute' }]); + }); }); describe('Page.$$eval', function() { @@ -221,6 +226,11 @@ describe('Page.$$eval', function() { await page.setContent('
'); expect(await page.$$eval('*css=div >> span', els => els.length)).toBe(2); }); + it('should return complex values', async({page, server}) => { + await page.setContent('
hello
beautiful
world!
'); + const texts = await page.$$eval('css=div', divs => divs.map(div => div.textContent)); + expect(texts).toEqual(['hello', 'beautiful', 'world!']); + }); }); describe('Page.$', function() {