chore(rpc): support workers, file chooser, browser server (#2766)
This commit is contained in:
parent
5bb018e0e5
commit
e29f7b9f58
|
|
@ -121,7 +121,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
|
||||||
|
|
||||||
async _initializePreview() {
|
async _initializePreview() {
|
||||||
const utility = await this._context.injectedScript();
|
const utility = await this._context.injectedScript();
|
||||||
this._preview = await utility.evaluate((injected, e) => 'JSHandle@' + injected.previewNode(e), this);
|
this._setPreview(await utility.evaluate((injected, e) => 'JSHandle@' + injected.previewNode(e), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
asElement(): ElementHandle<T> | null {
|
asElement(): ElementHandle<T> | null {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ export class JSHandle<T = any> {
|
||||||
readonly _value: any;
|
readonly _value: any;
|
||||||
private _objectType: string;
|
private _objectType: string;
|
||||||
protected _preview: string;
|
protected _preview: string;
|
||||||
|
private _previewCallback: ((preview: string) => void) | undefined;
|
||||||
|
|
||||||
constructor(context: ExecutionContext, type: string, objectId?: ObjectId, value?: any) {
|
constructor(context: ExecutionContext, type: string, objectId?: ObjectId, value?: any) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
|
|
@ -147,6 +148,16 @@ export class JSHandle<T = any> {
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return this._preview;
|
return this._preview;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setPreviewCallback(callback: (preview: string) => void) {
|
||||||
|
this._previewCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setPreview(preview: string) {
|
||||||
|
this._preview = preview;
|
||||||
|
if (this._previewCallback)
|
||||||
|
this._previewCallback(preview);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function evaluate(context: ExecutionContext, returnByValue: boolean, pageFunction: Function | string, ...args: any[]): Promise<any> {
|
export async function evaluate(context: ExecutionContext, returnByValue: boolean, pageFunction: Function | string, ...args: any[]): Promise<any> {
|
||||||
|
|
|
||||||
|
|
@ -646,12 +646,20 @@ export class Worker extends EventEmitter {
|
||||||
return js.evaluate(await this._executionContextPromise, true /* returnByValue */, pageFunction, arg);
|
return js.evaluate(await this._executionContextPromise, true /* returnByValue */, pageFunction, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _evaluateExpression(expression: string, isFunction: boolean, arg: any): Promise<any> {
|
||||||
|
return js.evaluateExpression(await this._executionContextPromise, true /* returnByValue */, expression, isFunction, arg);
|
||||||
|
}
|
||||||
|
|
||||||
async evaluateHandle<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<js.SmartHandle<R>>;
|
async evaluateHandle<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<js.SmartHandle<R>>;
|
||||||
async evaluateHandle<R>(pageFunction: js.Func1<void, R>, arg?: any): Promise<js.SmartHandle<R>>;
|
async evaluateHandle<R>(pageFunction: js.Func1<void, R>, arg?: any): Promise<js.SmartHandle<R>>;
|
||||||
async evaluateHandle<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<js.SmartHandle<R>> {
|
async evaluateHandle<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<js.SmartHandle<R>> {
|
||||||
assertMaxArguments(arguments.length, 2);
|
assertMaxArguments(arguments.length, 2);
|
||||||
return js.evaluate(await this._executionContextPromise, false /* returnByValue */, pageFunction, arg);
|
return js.evaluate(await this._executionContextPromise, false /* returnByValue */, pageFunction, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _evaluateExpressionHandle(expression: string, isFunction: boolean, arg: any): Promise<any> {
|
||||||
|
return js.evaluateExpression(await this._executionContextPromise, false /* returnByValue */, expression, isFunction, arg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PageBinding {
|
export class PageBinding {
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,11 @@ export interface Channel extends EventEmitter {
|
||||||
_object: any;
|
_object: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface BrowserTypeChannel extends Channel {
|
export interface BrowserTypeChannel extends Channel {
|
||||||
connect(params: { options: types.ConnectOptions }): Promise<BrowserChannel>;
|
connect(params: { options: types.ConnectOptions }): Promise<BrowserChannel>;
|
||||||
launch(params: { options?: types.LaunchOptions }): Promise<BrowserChannel>;
|
launch(params: { options?: types.LaunchOptions }): Promise<BrowserChannel>;
|
||||||
|
launchServer(params: { options?: types.LaunchServerOptions }): Promise<BrowserServerChannel>;
|
||||||
launchPersistentContext(params: { userDataDir: string, options?: types.LaunchOptions & types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
launchPersistentContext(params: { userDataDir: string, options?: types.LaunchOptions & types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
||||||
}
|
}
|
||||||
export type BrowserTypeInitializer = {
|
export type BrowserTypeInitializer = {
|
||||||
|
|
@ -36,7 +38,21 @@ export type BrowserTypeInitializer = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface BrowserServerChannel extends Channel {
|
||||||
|
on(event: 'close', callback: () => void): this;
|
||||||
|
|
||||||
|
close(): Promise<void>;
|
||||||
|
kill(): Promise<void>;
|
||||||
|
}
|
||||||
|
export type BrowserServerInitializer = {
|
||||||
|
wsEndpoint: string,
|
||||||
|
pid: number
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export interface BrowserChannel extends Channel {
|
export interface BrowserChannel extends Channel {
|
||||||
|
on(event: 'close', callback: () => void): this;
|
||||||
|
|
||||||
close(): Promise<void>;
|
close(): Promise<void>;
|
||||||
newContext(params: { options?: types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
newContext(params: { options?: types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
||||||
newPage(params: { options?: types.BrowserContextOptions }): Promise<PageChannel>;
|
newPage(params: { options?: types.BrowserContextOptions }): Promise<PageChannel>;
|
||||||
|
|
@ -46,7 +62,10 @@ export type BrowserInitializer = {};
|
||||||
|
|
||||||
export interface BrowserContextChannel extends Channel {
|
export interface BrowserContextChannel extends Channel {
|
||||||
on(event: 'bindingCall', callback: (params: BindingCallChannel) => void): this;
|
on(event: 'bindingCall', callback: (params: BindingCallChannel) => void): this;
|
||||||
|
on(event: 'close', callback: () => void): this;
|
||||||
on(event: 'page', callback: (params: PageChannel) => void): this;
|
on(event: 'page', callback: (params: PageChannel) => void): this;
|
||||||
|
on(event: 'route', callback: (params: { route: RouteChannel, request: RequestChannel }) => void): this;
|
||||||
|
|
||||||
addCookies(params: { cookies: types.SetNetworkCookieParam[] }): Promise<void>;
|
addCookies(params: { cookies: types.SetNetworkCookieParam[] }): Promise<void>;
|
||||||
addInitScript(params: { source: string }): Promise<void>;
|
addInitScript(params: { source: string }): Promise<void>;
|
||||||
clearCookies(): Promise<void>;
|
clearCookies(): Promise<void>;
|
||||||
|
|
@ -78,6 +97,7 @@ export interface PageChannel extends Channel {
|
||||||
on(event: 'dialog', callback: (params: DialogChannel) => void): this;
|
on(event: 'dialog', callback: (params: DialogChannel) => void): this;
|
||||||
on(event: 'download', callback: (params: DownloadChannel) => void): this;
|
on(event: 'download', callback: (params: DownloadChannel) => void): this;
|
||||||
on(event: 'domcontentloaded', callback: () => 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: 'frameAttached', callback: (params: FrameChannel) => void): this;
|
||||||
on(event: 'frameDetached', callback: (params: FrameChannel) => void): this;
|
on(event: 'frameDetached', callback: (params: FrameChannel) => void): this;
|
||||||
on(event: 'frameNavigated', callback: (params: { frame: FrameChannel, url: string, name: string }) => void): this;
|
on(event: 'frameNavigated', callback: (params: { frame: FrameChannel, url: string, name: string }) => void): this;
|
||||||
|
|
@ -90,6 +110,7 @@ export interface PageChannel extends Channel {
|
||||||
on(event: 'requestFinished', callback: (params: RequestChannel) => void): this;
|
on(event: 'requestFinished', callback: (params: RequestChannel) => void): this;
|
||||||
on(event: 'response', callback: (params: ResponseChannel) => void): this;
|
on(event: 'response', callback: (params: ResponseChannel) => void): this;
|
||||||
on(event: 'route', callback: (params: { route: RouteChannel, request: RequestChannel }) => void): this;
|
on(event: 'route', callback: (params: { route: RouteChannel, request: RequestChannel }) => void): this;
|
||||||
|
on(event: 'worker', callback: (params: WorkerChannel) => void): this;
|
||||||
|
|
||||||
setDefaultNavigationTimeoutNoReply(params: { timeout: number }): void;
|
setDefaultNavigationTimeoutNoReply(params: { timeout: number }): void;
|
||||||
setDefaultTimeoutNoReply(params: { timeout: number }): Promise<void>;
|
setDefaultTimeoutNoReply(params: { timeout: number }): Promise<void>;
|
||||||
|
|
@ -121,7 +142,9 @@ export interface PageChannel extends Channel {
|
||||||
|
|
||||||
// A11Y
|
// A11Y
|
||||||
accessibilitySnapshot(params: { options: { interestingOnly?: boolean, root?: ElementHandleChannel } }): Promise<types.SerializedAXNode | null>;
|
accessibilitySnapshot(params: { options: { interestingOnly?: boolean, root?: ElementHandleChannel } }): Promise<types.SerializedAXNode | null>;
|
||||||
|
pdf: (params: { options?: types.PDFOptions }) => Promise<Binary>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PageInitializer = {
|
export type PageInitializer = {
|
||||||
mainFrame: FrameChannel,
|
mainFrame: FrameChannel,
|
||||||
viewportSize: types.Size | null
|
viewportSize: types.Size | null
|
||||||
|
|
@ -137,7 +160,7 @@ export interface FrameChannel extends Channel {
|
||||||
click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise<void>;
|
click(params: { selector: string, options: types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & { force?: boolean } & { noWaitAfter?: boolean }, isPage?: boolean }): Promise<void>;
|
||||||
content(): Promise<string>;
|
content(): Promise<string>;
|
||||||
dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean}): Promise<void>;
|
dblclick(params: { selector: string, options: types.PointerActionOptions & types.MouseMultiClickOptions & types.TimeoutOptions & { force?: boolean }, isPage?: boolean}): Promise<void>;
|
||||||
dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions, isPage?: boolean }): Promise<void>;
|
dispatchEvent(params: { selector: string, type: string, eventInit: any, options: types.TimeoutOptions, isPage?: boolean }): Promise<void>;
|
||||||
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<any>;
|
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<any>;
|
||||||
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<JSHandleChannel>;
|
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<JSHandleChannel>;
|
||||||
fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise<void>;
|
fill(params: { selector: string, value: string, options: types.NavigatingActionWaitOptions, isPage?: boolean }): Promise<void>;
|
||||||
|
|
@ -170,7 +193,18 @@ export type FrameInitializer = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface WorkerChannel extends Channel {
|
||||||
|
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
||||||
|
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any }): Promise<JSHandleChannel>;
|
||||||
|
}
|
||||||
|
export type WorkerInitializer = {
|
||||||
|
url: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export interface JSHandleChannel extends Channel {
|
export interface JSHandleChannel extends Channel {
|
||||||
|
on(event: 'previewUpdated', callback: (preview: string) => void): this;
|
||||||
|
|
||||||
dispose(): Promise<void>;
|
dispose(): Promise<void>;
|
||||||
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
||||||
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<JSHandleChannel>;
|
evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<JSHandleChannel>;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import { BrowserContext } from './browserContext';
|
||||||
import { Page } from './page';
|
import { Page } from './page';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { Connection } from '../connection';
|
import { Connection } from '../connection';
|
||||||
|
import { Events } from '../../events';
|
||||||
|
|
||||||
export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
||||||
readonly _contexts = new Set<BrowserContext>();
|
readonly _contexts = new Set<BrowserContext>();
|
||||||
|
|
@ -36,6 +37,10 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
||||||
|
|
||||||
constructor(connection: Connection, channel: BrowserChannel, initializer: BrowserInitializer) {
|
constructor(connection: Connection, channel: BrowserChannel, initializer: BrowserInitializer) {
|
||||||
super(connection, channel, initializer);
|
super(connection, channel, initializer);
|
||||||
|
channel.on('close', () => {
|
||||||
|
this._isConnected = false;
|
||||||
|
this.emit(Events.Browser.Disconnected);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async newContext(options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
async newContext(options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,9 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||||
page._setBrowserContext(this);
|
page._setBrowserContext(this);
|
||||||
});
|
});
|
||||||
this._channel.on('bindingCall', bindingCall => this._onBinding(BindingCall.from(bindingCall)));
|
this._channel.on('bindingCall', bindingCall => this._onBinding(BindingCall.from(bindingCall)));
|
||||||
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onPage(page: Page): void {
|
private _onPage(page: Page): void {
|
||||||
|
|
@ -180,8 +182,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async close(): Promise<void> {
|
private async _onClose() {
|
||||||
await this._channel.close();
|
|
||||||
if (this._browser)
|
if (this._browser)
|
||||||
this._browser._contexts.delete(this);
|
this._browser._contexts.delete(this);
|
||||||
|
|
||||||
|
|
@ -193,4 +194,8 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
|
||||||
this._pendingWaitForEvents.clear();
|
this._pendingWaitForEvents.clear();
|
||||||
this.emit(Events.BrowserContext.Close);
|
this.emit(Events.BrowserContext.Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async close(): Promise<void> {
|
||||||
|
await this._channel.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
src/rpc/client/browserServer.ts
Normal file
50
src/rpc/client/browserServer.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ChildProcess } from 'child_process';
|
||||||
|
import { BrowserServerChannel, BrowserServerInitializer } from '../channels';
|
||||||
|
import { Connection } from '../connection';
|
||||||
|
import { ChannelOwner } from './channelOwner';
|
||||||
|
import { Events } from '../../events';
|
||||||
|
|
||||||
|
export class BrowserServer extends ChannelOwner<BrowserServerChannel, BrowserServerInitializer> {
|
||||||
|
static from(request: BrowserServerChannel): BrowserServer {
|
||||||
|
return request._object;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(connection: Connection, channel: BrowserServerChannel, initializer: BrowserServerInitializer) {
|
||||||
|
super(connection, channel, initializer);
|
||||||
|
channel.on('close', () => this.emit(Events.BrowserServer.Close));
|
||||||
|
}
|
||||||
|
|
||||||
|
process(): ChildProcess {
|
||||||
|
return { pid: this._initializer.pid } as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsEndpoint(): string {
|
||||||
|
return this._initializer.wsEndpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
async kill(): Promise<void> {
|
||||||
|
await this._channel.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
async close(): Promise<void> {
|
||||||
|
await this._channel.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
_checkLeaks() {}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ import { Browser } from './browser';
|
||||||
import { BrowserContext } from './browserContext';
|
import { BrowserContext } from './browserContext';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { Connection } from '../connection';
|
import { Connection } from '../connection';
|
||||||
|
import { BrowserServer } from './browserServer';
|
||||||
|
|
||||||
export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeInitializer> {
|
export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeInitializer> {
|
||||||
constructor(connection: Connection, channel: BrowserTypeChannel, initializer: BrowserTypeInitializer) {
|
constructor(connection: Connection, channel: BrowserTypeChannel, initializer: BrowserTypeInitializer) {
|
||||||
|
|
@ -39,6 +40,11 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
|
||||||
return Browser.from(await this._channel.launch({ options }));
|
return Browser.from(await this._channel.launch({ options }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async launchServer(options?: types.LaunchServerOptions): Promise<BrowserServer> {
|
||||||
|
delete (options as any).logger;
|
||||||
|
return BrowserServer.from(await this._channel.launchServer({ options }));
|
||||||
|
}
|
||||||
|
|
||||||
async launchPersistentContext(userDataDir: string, options: types.LaunchOptions & types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
async launchPersistentContext(userDataDir: string, options: types.LaunchOptions & types.BrowserContextOptions = {}): Promise<BrowserContext> {
|
||||||
delete (options as any).logger;
|
delete (options as any).logger;
|
||||||
return BrowserContext.from(await this._channel.launchPersistentContext({ userDataDir, options }));
|
return BrowserContext.from(await this._channel.launchPersistentContext({ userDataDir, options }));
|
||||||
|
|
|
||||||
47
src/rpc/client/fileChooser.ts
Normal file
47
src/rpc/client/fileChooser.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as types from '../../types';
|
||||||
|
import { ElementHandle } from './elementHandle';
|
||||||
|
import { Page } from './page';
|
||||||
|
|
||||||
|
export class FileChooser {
|
||||||
|
private _page: Page;
|
||||||
|
private _elementHandle: ElementHandle<Node>;
|
||||||
|
private _isMultiple: boolean;
|
||||||
|
|
||||||
|
constructor(page: Page, elementHandle: ElementHandle, isMultiple: boolean) {
|
||||||
|
this._page = page;
|
||||||
|
this._elementHandle = elementHandle;
|
||||||
|
this._isMultiple = isMultiple;
|
||||||
|
}
|
||||||
|
|
||||||
|
element(): ElementHandle {
|
||||||
|
return this._elementHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
isMultiple(): boolean {
|
||||||
|
return this._isMultiple;
|
||||||
|
}
|
||||||
|
|
||||||
|
page(): Page {
|
||||||
|
return this._page;
|
||||||
|
}
|
||||||
|
|
||||||
|
async setFiles(files: string | types.FilePayload | string[] | types.FilePayload[], options?: types.NavigatingActionWaitOptions) {
|
||||||
|
return this._elementHandle.setInputFiles(files, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -97,8 +97,8 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
|
||||||
return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, options, isPage: this._page!._isPageCall })) as ElementHandle<Element> | null;
|
return ElementHandle.fromNullable(await this._channel.waitForSelector({ selector, options, isPage: this._page!._isPageCall })) as ElementHandle<Element> | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispatchEvent(selector: string, type: string, eventInit?: Object, options: types.TimeoutOptions = {}): Promise<void> {
|
async dispatchEvent(selector: string, type: string, eventInit?: any, options: types.TimeoutOptions = {}): Promise<void> {
|
||||||
await this._channel.dispatchEvent({ selector, type, eventInit, options, isPage: this._page!._isPageCall });
|
await this._channel.dispatchEvent({ selector, type, eventInit: serializeArgument(eventInit), options, isPage: this._page!._isPageCall });
|
||||||
}
|
}
|
||||||
|
|
||||||
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
|
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ export type FuncOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R |
|
||||||
export type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
export type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||||
|
|
||||||
export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleInitializer> {
|
export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleInitializer> {
|
||||||
|
private _preview: string;
|
||||||
|
|
||||||
static from(handle: JSHandleChannel): JSHandle {
|
static from(handle: JSHandleChannel): JSHandle {
|
||||||
return handle._object;
|
return handle._object;
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +49,8 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleIni
|
||||||
|
|
||||||
constructor(conection: Connection, channel: JSHandleChannel, initializer: JSHandleInitializer) {
|
constructor(conection: Connection, channel: JSHandleChannel, initializer: JSHandleInitializer) {
|
||||||
super(conection, channel, initializer);
|
super(conection, channel, initializer);
|
||||||
|
this._preview = this._initializer.preview;
|
||||||
|
channel.on('previewUpdated', preview => this._preview = preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R>;
|
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R>;
|
||||||
|
|
@ -94,7 +98,7 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleIni
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return this._initializer.preview;
|
return this._preview;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,35 +16,37 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
|
import { TimeoutError } from '../../errors';
|
||||||
import { Events } from '../../events';
|
import { Events } from '../../events';
|
||||||
import { assert, assertMaxArguments, helper, Listener } from '../../helper';
|
import { assert, assertMaxArguments, helper, Listener } from '../../helper';
|
||||||
|
import { TimeoutSettings } from '../../timeoutSettings';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
import { PageChannel, BindingCallChannel, Channel, PageInitializer, BindingCallInitializer } from '../channels';
|
import { BindingCallChannel, BindingCallInitializer, Channel, PageChannel, PageInitializer } from '../channels';
|
||||||
|
import { Connection } from '../connection';
|
||||||
|
import { parseError, serializeError } from '../serializers';
|
||||||
|
import { Accessibility } from './accessibility';
|
||||||
import { BrowserContext } from './browserContext';
|
import { BrowserContext } from './browserContext';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { ElementHandle } from './elementHandle';
|
|
||||||
import { Frame, FunctionWithSource, GotoOptions } from './frame';
|
|
||||||
import { Func1, FuncOn, SmartHandle } from './jsHandle';
|
|
||||||
import { Request, Response, RouteHandler, Route } from './network';
|
|
||||||
import { Connection } from '../connection';
|
|
||||||
import { Keyboard, Mouse } from './input';
|
|
||||||
import { Accessibility } from './accessibility';
|
|
||||||
import { ConsoleMessage } from './consoleMessage';
|
import { ConsoleMessage } from './consoleMessage';
|
||||||
import { Dialog } from './dialog';
|
import { Dialog } from './dialog';
|
||||||
import { Download } from './download';
|
import { Download } from './download';
|
||||||
import { TimeoutError } from '../../errors';
|
import { ElementHandle } from './elementHandle';
|
||||||
import { TimeoutSettings } from '../../timeoutSettings';
|
import { Worker } from './worker';
|
||||||
import { parseError, serializeError } from '../serializers';
|
import { Frame, FunctionWithSource, GotoOptions } from './frame';
|
||||||
|
import { Keyboard, Mouse } from './input';
|
||||||
|
import { Func1, FuncOn, SmartHandle } from './jsHandle';
|
||||||
|
import { Request, Response, Route, RouteHandler } from './network';
|
||||||
|
import { FileChooser } from './fileChooser';
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
|
||||||
export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
|
|
||||||
|
|
||||||
private _browserContext: BrowserContext | undefined;
|
private _browserContext: BrowserContext | undefined;
|
||||||
_ownedContext: BrowserContext | undefined;
|
_ownedContext: BrowserContext | undefined;
|
||||||
|
|
||||||
private _mainFrame: Frame;
|
private _mainFrame: Frame;
|
||||||
private _frames = new Set<Frame>();
|
private _frames = new Set<Frame>();
|
||||||
private _workers: Worker[] = [];
|
_workers = new Set<Worker>();
|
||||||
private _closed = false;
|
private _closed = false;
|
||||||
private _viewportSize: types.Size | null;
|
private _viewportSize: types.Size | null;
|
||||||
private _routes: { url: types.URLMatch, handler: RouteHandler }[] = [];
|
private _routes: { url: types.URLMatch, handler: RouteHandler }[] = [];
|
||||||
|
|
@ -83,6 +85,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
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('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('frameAttached', frame => this._onFrameAttached(Frame.from(frame)));
|
||||||
this._channel.on('frameDetached', frame => this._onFrameDetached(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('frameNavigated', ({ frame, url, name }) => this._onFrameNavigated(Frame.from(frame), url, name));
|
||||||
|
|
@ -94,6 +97,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
this._channel.on('requestFinished', request => this.emit(Events.Page.RequestFinished, Request.from(request)));
|
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('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('route', ({ route, request }) => this._onRoute(Route.from(route), Request.from(request)));
|
||||||
|
this._channel.on('worker', worker => this._onWorker(Worker.from(worker)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_setBrowserContext(context: BrowserContext) {
|
_setBrowserContext(context: BrowserContext) {
|
||||||
|
|
@ -145,6 +149,12 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
this._browserContext!._onBinding(bindingCall);
|
this._browserContext!._onBinding(bindingCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onWorker(worker: Worker): void {
|
||||||
|
this._workers.add(worker);
|
||||||
|
worker._page = this;
|
||||||
|
this.emit(Events.Page.Worker, worker);
|
||||||
|
}
|
||||||
|
|
||||||
private _onClose() {
|
private _onClose() {
|
||||||
this._closed = true;
|
this._closed = true;
|
||||||
this._browserContext!._pages.delete(this);
|
this._browserContext!._pages.delete(this);
|
||||||
|
|
@ -221,7 +231,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
return this._attributeToPage(() => this._mainFrame.waitForSelector(selector, options));
|
return this._attributeToPage(() => this._mainFrame.waitForSelector(selector, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispatchEvent(selector: string, type: string, eventInit?: Object, options?: types.TimeoutOptions): Promise<void> {
|
async dispatchEvent(selector: string, type: string, eventInit?: any, options?: types.TimeoutOptions): Promise<void> {
|
||||||
return this._attributeToPage(() => this._mainFrame.dispatchEvent(selector, type, eventInit, options));
|
return this._attributeToPage(() => this._mainFrame.dispatchEvent(selector, type, eventInit, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,7 +475,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
workers(): Worker[] {
|
workers(): Worker[] {
|
||||||
return this._workers;
|
return [...this._workers];
|
||||||
}
|
}
|
||||||
|
|
||||||
on(event: string | symbol, listener: Listener): this {
|
on(event: string | symbol, listener: Listener): this {
|
||||||
|
|
@ -483,33 +493,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||||
this._channel.setFileChooserInterceptedNoReply({ intercepted: false });
|
this._channel.setFileChooserInterceptedNoReply({ intercepted: false });
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export class Worker extends EventEmitter {
|
async pdf(options?: types.PDFOptions): Promise<Buffer> {
|
||||||
private _url: string;
|
const binary = await this._channel.pdf({ options });
|
||||||
private _channel: any;
|
return Buffer.from(binary, 'base64');
|
||||||
|
|
||||||
constructor(url: string) {
|
|
||||||
super();
|
|
||||||
this._url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
url(): string {
|
|
||||||
return this._url;
|
|
||||||
}
|
|
||||||
|
|
||||||
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R>;
|
|
||||||
async evaluate<R>(pageFunction: Func1<void, R>, arg?: any): Promise<R>;
|
|
||||||
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R> {
|
|
||||||
assertMaxArguments(arguments.length, 2);
|
|
||||||
return await this._channel.evaluate({ pageFunction, arg });
|
|
||||||
}
|
|
||||||
|
|
||||||
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
|
||||||
async evaluateHandle<R>(pageFunction: Func1<void, R>, arg?: any): Promise<SmartHandle<R>>;
|
|
||||||
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
|
||||||
assertMaxArguments(arguments.length, 2);
|
|
||||||
return await this._channel.evaluateHandle({ pageFunction, arg });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
57
src/rpc/client/worker.ts
Normal file
57
src/rpc/client/worker.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Events } from '../../events';
|
||||||
|
import { assertMaxArguments } from '../../helper';
|
||||||
|
import { WorkerChannel, WorkerInitializer } from '../channels';
|
||||||
|
import { Connection } from '../connection';
|
||||||
|
import { ChannelOwner } from './channelOwner';
|
||||||
|
import { Func1, JSHandle, parseResult, serializeArgument, SmartHandle } from './jsHandle';
|
||||||
|
import { Page } from './page';
|
||||||
|
|
||||||
|
export class Worker extends ChannelOwner<WorkerChannel, WorkerInitializer> {
|
||||||
|
_page: Page | undefined;
|
||||||
|
|
||||||
|
static from(worker: WorkerChannel): Worker {
|
||||||
|
return worker._object;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(connection: Connection, channel: WorkerChannel, initializer: WorkerInitializer) {
|
||||||
|
super(connection, channel, initializer);
|
||||||
|
channel.on('close', () => {
|
||||||
|
this._page!._workers.delete(this);
|
||||||
|
this.emit(Events.Worker.Close, this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
url(): string {
|
||||||
|
return this._initializer.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R>;
|
||||||
|
async evaluate<R>(pageFunction: Func1<void, R>, arg?: any): Promise<R>;
|
||||||
|
async evaluate<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<R> {
|
||||||
|
assertMaxArguments(arguments.length, 2);
|
||||||
|
return parseResult(await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||||
|
async evaluateHandle<R>(pageFunction: Func1<void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||||
|
async evaluateHandle<R, Arg>(pageFunction: Func1<Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||||
|
assertMaxArguments(arguments.length, 2);
|
||||||
|
return JSHandle.from(await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) })) as SmartHandle<R>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,12 +24,14 @@ import { Frame } from './client/frame';
|
||||||
import { JSHandle } from './client/jsHandle';
|
import { JSHandle } from './client/jsHandle';
|
||||||
import { Request, Response, Route } from './client/network';
|
import { Request, Response, Route } from './client/network';
|
||||||
import { Page, BindingCall } from './client/page';
|
import { Page, BindingCall } from './client/page';
|
||||||
|
import { Worker } from './client/worker';
|
||||||
import debug = require('debug');
|
import debug = require('debug');
|
||||||
import { Channel } from './channels';
|
import { Channel } from './channels';
|
||||||
import { ConsoleMessage } from './client/consoleMessage';
|
import { ConsoleMessage } from './client/consoleMessage';
|
||||||
import { Dialog } from './client/dialog';
|
import { Dialog } from './client/dialog';
|
||||||
import { Download } from './client/download';
|
import { Download } from './client/download';
|
||||||
import { parseError } from './serializers';
|
import { parseError } from './serializers';
|
||||||
|
import { BrowserServer } from './client/browserServer';
|
||||||
|
|
||||||
export class Connection {
|
export class Connection {
|
||||||
private _channels = new Map<string, Channel>();
|
private _channels = new Map<string, Channel>();
|
||||||
|
|
@ -52,6 +54,9 @@ export class Connection {
|
||||||
case 'browser':
|
case 'browser':
|
||||||
result = new Browser(this, channel, initializer);
|
result = new Browser(this, channel, initializer);
|
||||||
break;
|
break;
|
||||||
|
case 'browserServer':
|
||||||
|
result = new BrowserServer(this, channel, initializer);
|
||||||
|
break;
|
||||||
case 'browserType':
|
case 'browserType':
|
||||||
result = new BrowserType(this, channel, initializer);
|
result = new BrowserType(this, channel, initializer);
|
||||||
break;
|
break;
|
||||||
|
|
@ -88,6 +93,9 @@ export class Connection {
|
||||||
case 'route':
|
case 'route':
|
||||||
result = new Route(this, channel, initializer);
|
result = new Route(this, channel, initializer);
|
||||||
break;
|
break;
|
||||||
|
case 'worker':
|
||||||
|
result = new Worker(this, channel, initializer);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('Missing type ' + type);
|
throw new Error('Missing type ' + type);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||||
import { BrowserChannel, BrowserContextChannel, PageChannel, BrowserInitializer } from '../channels';
|
import { BrowserChannel, BrowserContextChannel, PageChannel, BrowserInitializer } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { PageDispatcher } from './pageDispatcher';
|
import { PageDispatcher } from './pageDispatcher';
|
||||||
|
import { Events } from '../../events';
|
||||||
|
|
||||||
export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> implements BrowserChannel {
|
export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> implements BrowserChannel {
|
||||||
static from(scope: DispatcherScope, browser: BrowserBase): BrowserDispatcher {
|
static from(scope: DispatcherScope, browser: BrowserBase): BrowserDispatcher {
|
||||||
|
|
@ -37,6 +38,7 @@ export class BrowserDispatcher extends Dispatcher<Browser, BrowserInitializer> i
|
||||||
|
|
||||||
constructor(scope: DispatcherScope, browser: BrowserBase) {
|
constructor(scope: DispatcherScope, browser: BrowserBase) {
|
||||||
super(scope, browser, 'browser', {});
|
super(scope, browser, 'browser', {});
|
||||||
|
browser.on(Events.Browser.Disconnected, () => this._dispatchEvent('close'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async newContext(params: { options?: types.BrowserContextOptions }): Promise<BrowserContextChannel> {
|
async newContext(params: { options?: types.BrowserContextOptions }): Promise<BrowserContextChannel> {
|
||||||
|
|
|
||||||
44
src/rpc/server/browserServerDispatcher.ts
Normal file
44
src/rpc/server/browserServerDispatcher.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BrowserServer } from '../../server/browserServer';
|
||||||
|
import { BrowserServerChannel, BrowserServerInitializer } from '../channels';
|
||||||
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
|
import { Events } from '../../events';
|
||||||
|
|
||||||
|
export class BrowserServerDispatcher extends Dispatcher<BrowserServer, BrowserServerInitializer> implements BrowserServerChannel {
|
||||||
|
static from(scope: DispatcherScope, browserServer: BrowserServer): BrowserServerDispatcher {
|
||||||
|
if ((browserServer as any)[scope.dispatcherSymbol])
|
||||||
|
return (browserServer as any)[scope.dispatcherSymbol];
|
||||||
|
return new BrowserServerDispatcher(scope, browserServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(scope: DispatcherScope, browserServer: BrowserServer) {
|
||||||
|
super(scope, browserServer, 'browserServer', {
|
||||||
|
wsEndpoint: browserServer.wsEndpoint(),
|
||||||
|
pid: browserServer.process().pid
|
||||||
|
});
|
||||||
|
browserServer.on(Events.BrowserServer.Close, () => this._dispatchEvent('close'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async close(): Promise<void> {
|
||||||
|
await this._object.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
async kill(): Promise<void> {
|
||||||
|
await this._object.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,10 +18,11 @@ import { BrowserBase } from '../../browser';
|
||||||
import { BrowserTypeBase, BrowserType } from '../../server/browserType';
|
import { BrowserTypeBase, BrowserType } from '../../server/browserType';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
import { BrowserDispatcher } from './browserDispatcher';
|
import { BrowserDispatcher } from './browserDispatcher';
|
||||||
import { BrowserChannel, BrowserTypeChannel, BrowserContextChannel, BrowserTypeInitializer } from '../channels';
|
import { BrowserChannel, BrowserTypeChannel, BrowserContextChannel, BrowserTypeInitializer, BrowserServerChannel } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { BrowserContextBase } from '../../browserContext';
|
import { BrowserContextBase } from '../../browserContext';
|
||||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||||
|
import { BrowserServerDispatcher } from './browserServerDispatcher';
|
||||||
|
|
||||||
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeInitializer> implements BrowserTypeChannel {
|
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeInitializer> implements BrowserTypeChannel {
|
||||||
static from(scope: DispatcherScope, browserType: BrowserTypeBase): BrowserTypeDispatcher {
|
static from(scope: DispatcherScope, browserType: BrowserTypeBase): BrowserTypeDispatcher {
|
||||||
|
|
@ -47,6 +48,10 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeIn
|
||||||
return BrowserContextDispatcher.from(this._scope, browserContext as BrowserContextBase);
|
return BrowserContextDispatcher.from(this._scope, browserContext as BrowserContextBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async launchServer(params: { options?: types.LaunchServerOptions }): Promise<BrowserServerChannel> {
|
||||||
|
return BrowserServerDispatcher.from(this._scope, await this._object.launchServer(params.options));
|
||||||
|
}
|
||||||
|
|
||||||
async connect(params: { options: types.ConnectOptions }): Promise<BrowserChannel> {
|
async connect(params: { options: types.ConnectOptions }): Promise<BrowserChannel> {
|
||||||
const browser = await this._object.connect(params.options);
|
const browser = await this._object.connect(params.options);
|
||||||
return BrowserDispatcher.from(this._scope, browser as BrowserBase);
|
return BrowserDispatcher.from(this._scope, browser as BrowserBase);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import { ConsoleMessage } from '../../console';
|
import { ConsoleMessage } from '../../console';
|
||||||
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels';
|
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
import { fromHandle } from './elementHandlerDispatcher';
|
||||||
|
|
||||||
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, ConsoleMessageInitializer> implements ConsoleMessageChannel {
|
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, ConsoleMessageInitializer> implements ConsoleMessageChannel {
|
||||||
static from(scope: DispatcherScope, message: ConsoleMessage): ConsoleMessageDispatcher {
|
static from(scope: DispatcherScope, message: ConsoleMessage): ConsoleMessageDispatcher {
|
||||||
|
|
@ -30,7 +30,7 @@ export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, Console
|
||||||
super(scope, message, 'consoleMessage', {
|
super(scope, message, 'consoleMessage', {
|
||||||
type: message.type(),
|
type: message.type(),
|
||||||
text: message.text(),
|
text: message.text(),
|
||||||
args: message.args().map(a => ElementHandleDispatcher.from(scope, a)),
|
args: message.args().map(a => fromHandle(scope, a)),
|
||||||
location: message.location(),
|
location: message.location(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,21 +22,21 @@ import { DispatcherScope } from '../dispatcher';
|
||||||
import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher';
|
import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher';
|
||||||
import { FrameDispatcher } from './frameDispatcher';
|
import { FrameDispatcher } from './frameDispatcher';
|
||||||
|
|
||||||
|
export function fromHandle(scope: DispatcherScope, handle: js.JSHandle): JSHandleDispatcher {
|
||||||
|
if ((handle as any)[scope.dispatcherSymbol])
|
||||||
|
return (handle as any)[scope.dispatcherSymbol];
|
||||||
|
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()!) : new JSHandleDispatcher(scope, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fromNullableHandle(scope: DispatcherScope, handle: js.JSHandle | null): JSHandleDispatcher | null {
|
||||||
|
if (!handle)
|
||||||
|
return null;
|
||||||
|
return fromHandle(scope, handle);
|
||||||
|
}
|
||||||
|
|
||||||
export class ElementHandleDispatcher extends JSHandleDispatcher implements ElementHandleChannel {
|
export class ElementHandleDispatcher extends JSHandleDispatcher implements ElementHandleChannel {
|
||||||
readonly _elementHandle: ElementHandle;
|
readonly _elementHandle: ElementHandle;
|
||||||
|
|
||||||
static from(scope: DispatcherScope, handle: js.JSHandle): JSHandleDispatcher {
|
|
||||||
if ((handle as any)[scope.dispatcherSymbol])
|
|
||||||
return (handle as any)[scope.dispatcherSymbol];
|
|
||||||
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()!) : new JSHandleDispatcher(scope, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromNullable(scope: DispatcherScope, handle: js.JSHandle | null): JSHandleDispatcher | null {
|
|
||||||
if (!handle)
|
|
||||||
return null;
|
|
||||||
return ElementHandleDispatcher.from(scope, handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromElement(scope: DispatcherScope, handle: ElementHandle): ElementHandleDispatcher {
|
static fromElement(scope: DispatcherScope, handle: ElementHandle): ElementHandleDispatcher {
|
||||||
if ((handle as any)[scope.dispatcherSymbol])
|
if ((handle as any)[scope.dispatcherSymbol])
|
||||||
return (handle as any)[scope.dispatcherSymbol];
|
return (handle as any)[scope.dispatcherSymbol];
|
||||||
|
|
@ -125,7 +125,7 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
|
||||||
}
|
}
|
||||||
|
|
||||||
async press(params: { key: string, options: { delay?: number } & types.NavigatingActionWaitOptions }) {
|
async press(params: { key: string, options: { delay?: number } & types.NavigatingActionWaitOptions }) {
|
||||||
await this._elementHandle.type(params.key, params.options);
|
await this._elementHandle.press(params.key, params.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async check(params: { options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions }) {
|
async check(params: { options?: types.PointerActionWaitOptions & types.NavigatingActionWaitOptions }) {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { Frame } from '../../frames';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
import { ElementHandleChannel, FrameChannel, FrameInitializer, JSHandleChannel, ResponseChannel } from '../channels';
|
import { ElementHandleChannel, FrameChannel, FrameInitializer, JSHandleChannel, ResponseChannel } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { convertSelectOptionValues, ElementHandleDispatcher } from './elementHandlerDispatcher';
|
import { convertSelectOptionValues, ElementHandleDispatcher, fromHandle } from './elementHandlerDispatcher';
|
||||||
import { parseArgument, serializeResult } from './jsHandleDispatcher';
|
import { parseArgument, serializeResult } from './jsHandleDispatcher';
|
||||||
import { ResponseDispatcher } from './networkDispatchers';
|
import { ResponseDispatcher } from './networkDispatchers';
|
||||||
|
|
||||||
|
|
@ -72,7 +72,7 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
|
||||||
|
|
||||||
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<JSHandleChannel> {
|
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<JSHandleChannel> {
|
||||||
const target = params.isPage ? this._frame._page : this._frame;
|
const target = params.isPage ? this._frame._page : this._frame;
|
||||||
return ElementHandleDispatcher.fromElement(this._scope, await target._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg)));
|
return fromHandle(this._scope, await target._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async waitForSelector(params: { selector: string, options: types.WaitForElementOptions, isPage?: boolean }): Promise<ElementHandleChannel | null> {
|
async waitForSelector(params: { selector: string, options: types.WaitForElementOptions, isPage?: boolean }): Promise<ElementHandleChannel | null> {
|
||||||
|
|
@ -80,9 +80,9 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
|
||||||
return ElementHandleDispatcher.fromNullableElement(this._scope, await target.waitForSelector(params.selector, params.options));
|
return ElementHandleDispatcher.fromNullableElement(this._scope, await target.waitForSelector(params.selector, params.options));
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispatchEvent(params: { selector: string, type: string, eventInit: Object | undefined, options: types.TimeoutOptions, isPage?: boolean }): Promise<void> {
|
async dispatchEvent(params: { selector: string, type: string, eventInit: any, options: types.TimeoutOptions, isPage?: boolean }): Promise<void> {
|
||||||
const target = params.isPage ? this._frame._page : this._frame;
|
const target = params.isPage ? this._frame._page : this._frame;
|
||||||
return target.dispatchEvent(params.selector, params.type, params.eventInit, params.options);
|
return target.dispatchEvent(params.selector, params.type, parseArgument(params.eventInit), params.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async $eval(params: { selector: string, expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<any> {
|
async $eval(params: { selector: string, expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<any> {
|
||||||
|
|
@ -202,7 +202,7 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
|
||||||
|
|
||||||
async waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions, isPage?: boolean }): Promise<JSHandleChannel> {
|
async waitForFunction(params: { expression: string, isFunction: boolean, arg: any; options: types.WaitForFunctionOptions, isPage?: boolean }): Promise<JSHandleChannel> {
|
||||||
const target = params.isPage ? this._frame._page : this._frame;
|
const target = params.isPage ? this._frame._page : this._frame;
|
||||||
return ElementHandleDispatcher.from(this._scope, await target._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params.options));
|
return fromHandle(this._scope, await target._waitForFunctionExpression(params.expression, params.isFunction, parseArgument(params.arg), params.options));
|
||||||
}
|
}
|
||||||
|
|
||||||
async title(): Promise<string> {
|
async title(): Promise<string> {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
import * as js from '../../javascript';
|
import * as js from '../../javascript';
|
||||||
import { JSHandleChannel, JSHandleInitializer } from '../channels';
|
import { JSHandleChannel, JSHandleInitializer } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
|
||||||
import { parseEvaluationResultValue, serializeAsCallArgument } from '../../common/utilityScriptSerializers';
|
import { parseEvaluationResultValue, serializeAsCallArgument } from '../../common/utilityScriptSerializers';
|
||||||
|
import { fromHandle } from './elementHandlerDispatcher';
|
||||||
|
|
||||||
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitializer> implements JSHandleChannel {
|
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitializer> implements JSHandleChannel {
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
|
||||||
super(scope, jsHandle, jsHandle.asElement() ? 'elementHandle' : 'jsHandle', {
|
super(scope, jsHandle, jsHandle.asElement() ? 'elementHandle' : 'jsHandle', {
|
||||||
preview: jsHandle.toString(),
|
preview: jsHandle.toString(),
|
||||||
});
|
});
|
||||||
|
jsHandle._setPreviewCallback(preview => this._dispatchEvent('previewUpdated', preview));
|
||||||
}
|
}
|
||||||
|
|
||||||
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any> {
|
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any }): Promise<any> {
|
||||||
|
|
@ -34,7 +35,7 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
|
||||||
|
|
||||||
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<JSHandleChannel> {
|
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any}): Promise<JSHandleChannel> {
|
||||||
const jsHandle = await this._object._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg));
|
const jsHandle = await this._object._evaluateExpression(params.expression, params.isFunction, false /* returnByValue */, parseArgument(params.arg));
|
||||||
return ElementHandleDispatcher.from(this._scope, jsHandle);
|
return fromHandle(this._scope, jsHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPropertyList(): Promise<{ name: string, value: JSHandleChannel }[]> {
|
async getPropertyList(): Promise<{ name: string, value: JSHandleChannel }[]> {
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ import { BrowserContext } from '../../browserContext';
|
||||||
import { Events } from '../../events';
|
import { Events } from '../../events';
|
||||||
import { Frame } from '../../frames';
|
import { Frame } from '../../frames';
|
||||||
import { Request } from '../../network';
|
import { Request } from '../../network';
|
||||||
import { Page } from '../../page';
|
import { Page, Worker } from '../../page';
|
||||||
import * as types from '../../types';
|
import * as types from '../../types';
|
||||||
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel } from '../channels';
|
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary } from '../channels';
|
||||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||||
import { parseError, serializeError } from '../serializers';
|
import { parseError, serializeError } from '../serializers';
|
||||||
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
|
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
|
||||||
|
|
@ -28,6 +28,9 @@ import { DialogDispatcher } from './dialogDispatcher';
|
||||||
import { DownloadDispatcher } from './downloadDispatcher';
|
import { DownloadDispatcher } from './downloadDispatcher';
|
||||||
import { FrameDispatcher } from './frameDispatcher';
|
import { FrameDispatcher } from './frameDispatcher';
|
||||||
import { RequestDispatcher, ResponseDispatcher, RouteDispatcher } from './networkDispatchers';
|
import { RequestDispatcher, ResponseDispatcher, RouteDispatcher } from './networkDispatchers';
|
||||||
|
import { serializeResult, parseArgument } from './jsHandleDispatcher';
|
||||||
|
import { fromHandle, ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||||
|
import { FileChooser } from '../../fileChooser';
|
||||||
|
|
||||||
export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements PageChannel {
|
export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements PageChannel {
|
||||||
private _page: Page;
|
private _page: Page;
|
||||||
|
|
@ -56,6 +59,10 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
|
||||||
page.on(Events.Page.DOMContentLoaded, () => this._dispatchEvent('domcontentloaded'));
|
page.on(Events.Page.DOMContentLoaded, () => this._dispatchEvent('domcontentloaded'));
|
||||||
page.on(Events.Page.Dialog, dialog => this._dispatchEvent('dialog', DialogDispatcher.from(this._scope, dialog)));
|
page.on(Events.Page.Dialog, dialog => this._dispatchEvent('dialog', DialogDispatcher.from(this._scope, dialog)));
|
||||||
page.on(Events.Page.Download, dialog => this._dispatchEvent('download', DownloadDispatcher.from(this._scope, dialog)));
|
page.on(Events.Page.Download, dialog => this._dispatchEvent('download', DownloadDispatcher.from(this._scope, dialog)));
|
||||||
|
page.on(Events.Page.FileChooser, (fileChooser: FileChooser) => this._dispatchEvent('fileChooser', {
|
||||||
|
element: ElementHandleDispatcher.fromElement(this._scope, fileChooser.element()),
|
||||||
|
isMultiple: fileChooser.isMultiple()
|
||||||
|
}));
|
||||||
page.on(Events.Page.FrameAttached, frame => this._onFrameAttached(frame));
|
page.on(Events.Page.FrameAttached, frame => this._onFrameAttached(frame));
|
||||||
page.on(Events.Page.FrameDetached, frame => this._onFrameDetached(frame));
|
page.on(Events.Page.FrameDetached, frame => this._onFrameDetached(frame));
|
||||||
page.on(Events.Page.FrameNavigated, frame => this._onFrameNavigated(frame));
|
page.on(Events.Page.FrameNavigated, frame => this._onFrameNavigated(frame));
|
||||||
|
|
@ -69,6 +76,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
|
||||||
}));
|
}));
|
||||||
page.on(Events.Page.RequestFinished, request => this._dispatchEvent('requestFinished', RequestDispatcher.from(this._scope, request)));
|
page.on(Events.Page.RequestFinished, request => this._dispatchEvent('requestFinished', RequestDispatcher.from(this._scope, request)));
|
||||||
page.on(Events.Page.Response, response => this._dispatchEvent('response', ResponseDispatcher.from(this._scope, response)));
|
page.on(Events.Page.Response, response => this._dispatchEvent('response', ResponseDispatcher.from(this._scope, response)));
|
||||||
|
page.on(Events.Page.Worker, worker => this._dispatchEvent('worker', WorkerDispatcher.from(this._scope, worker)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async setDefaultNavigationTimeoutNoReply(params: { timeout: number }) {
|
async setDefaultNavigationTimeoutNoReply(params: { timeout: number }) {
|
||||||
|
|
@ -187,6 +195,13 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async pdf(params: { options?: types.PDFOptions }): Promise<Binary> {
|
||||||
|
if (!this._page.pdf)
|
||||||
|
throw new Error('PDF generation is only supported for Headless Chromium');
|
||||||
|
const binary = await this._page.pdf(params.options);
|
||||||
|
return binary.toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
_onFrameAttached(frame: Frame) {
|
_onFrameAttached(frame: Frame) {
|
||||||
this._dispatchEvent('frameAttached', FrameDispatcher.from(this._scope, frame));
|
this._dispatchEvent('frameAttached', FrameDispatcher.from(this._scope, frame));
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +216,29 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class WorkerDispatcher extends Dispatcher<Worker, WorkerInitializer> implements WorkerChannel {
|
||||||
|
static from(scope: DispatcherScope, worker: Worker): WorkerDispatcher {
|
||||||
|
if ((worker as any)[scope.dispatcherSymbol])
|
||||||
|
return (worker as any)[scope.dispatcherSymbol];
|
||||||
|
return new WorkerDispatcher(scope, worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(scope: DispatcherScope, worker: Worker) {
|
||||||
|
super(scope, worker, 'worker', {
|
||||||
|
url: worker.url()
|
||||||
|
});
|
||||||
|
worker.on(Events.Worker.Close, () => this._dispatchEvent('close'));
|
||||||
|
}
|
||||||
|
|
||||||
|
async evaluateExpression(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<any> {
|
||||||
|
return serializeResult(await this._object._evaluateExpression(params.expression, params.isFunction, parseArgument(params.arg)));
|
||||||
|
}
|
||||||
|
|
||||||
|
async evaluateExpressionHandle(params: { expression: string, isFunction: boolean, arg: any, isPage?: boolean }): Promise<JSHandleChannel> {
|
||||||
|
return fromHandle(this._scope, await this._object._evaluateExpressionHandle(params.expression, params.isFunction, parseArgument(params.arg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer> implements BindingCallChannel {
|
export class BindingCallDispatcher extends Dispatcher<{}, BindingCallInitializer> implements BindingCallChannel {
|
||||||
private _resolve: ((arg: any) => void) | undefined;
|
private _resolve: ((arg: any) => void) | undefined;
|
||||||
private _reject: ((error: any) => void) | undefined;
|
private _reject: ((error: any) => void) | undefined;
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {FFOX, CHROMIUM, WEBKIT} = require('../utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('../utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('ChromiumBrowserContext', function() {
|
describe.skip(CHANNEL)('ChromiumBrowserContext', function() {
|
||||||
it('should create a worker from a service worker', async({browser, page, server, context}) => {
|
it('should create a worker from a service worker', async({browser, page, server, context}) => {
|
||||||
const [worker] = await Promise.all([
|
const [worker] = await Promise.all([
|
||||||
context.waitForEvent('serviceworker'),
|
context.waitForEvent('serviceworker'),
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {FFOX, CHROMIUM, WEBKIT} = require('../utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('../utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('JSCoverage', function() {
|
describe.skip(CHANNEL)('JSCoverage', function() {
|
||||||
it('should work', async function({page, server}) {
|
it('should work', async function({page, server}) {
|
||||||
await page.coverage.startJSCoverage();
|
await page.coverage.startJSCoverage();
|
||||||
await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' });
|
await page.goto(server.PREFIX + '/jscoverage/simple.html', { waitUntil: 'load' });
|
||||||
|
|
@ -88,7 +88,7 @@ describe('JSCoverage', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('CSSCoverage', function() {
|
describe.skip(CHANNEL)('CSSCoverage', function() {
|
||||||
it('should work', async function({page, server}) {
|
it('should work', async function({page, server}) {
|
||||||
await page.coverage.startCSSCoverage();
|
await page.coverage.startCSSCoverage();
|
||||||
await page.goto(server.PREFIX + '/csscoverage/simple.html');
|
await page.goto(server.PREFIX + '/csscoverage/simple.html');
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const utils = require('../utils');
|
const utils = require('../utils');
|
||||||
const {makeUserDataDir, removeUserDataDir} = utils;
|
const {makeUserDataDir, removeUserDataDir} = utils;
|
||||||
const {FFOX, CHROMIUM, WEBKIT, WIN, USES_HOOKS} = utils.testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, WIN, CHANNEL} = utils.testOptions(browserType);
|
||||||
|
|
||||||
describe('launcher', function() {
|
describe.skip(CHANNEL)('launcher', function() {
|
||||||
it('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
it('should throw with remote-debugging-pipe argument', async({browserType, defaultBrowserOptions}) => {
|
||||||
const options = Object.assign({}, defaultBrowserOptions);
|
const options = Object.assign({}, defaultBrowserOptions);
|
||||||
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
options.args = ['--remote-debugging-pipe'].concat(options.args || []);
|
||||||
|
|
@ -32,7 +32,7 @@ describe('launcher', function() {
|
||||||
const browser = await browserType.launchServer(options);
|
const browser = await browserType.launchServer(options);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
it.skip(USES_HOOKS)('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
it('should open devtools when "devtools: true" option is given', async({browserType, defaultBrowserOptions}) => {
|
||||||
let devtoolsCallback;
|
let devtoolsCallback;
|
||||||
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
|
const devtoolsPromise = new Promise(f => devtoolsCallback = f);
|
||||||
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
|
const __testHookForDevTools = devtools => devtools.__testHookOnBinding = parsed => {
|
||||||
|
|
@ -49,7 +49,7 @@ describe('launcher', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('extensions', () => {
|
describe.skip(CHANNEL)('extensions', () => {
|
||||||
it('should return background pages', async({browserType, defaultBrowserOptions}) => {
|
it('should return background pages', async({browserType, defaultBrowserOptions}) => {
|
||||||
const userDataDir = await makeUserDataDir();
|
const userDataDir = await makeUserDataDir();
|
||||||
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
|
const extensionPath = path.join(__dirname, '..', 'assets', 'simple-extension');
|
||||||
|
|
@ -73,7 +73,7 @@ describe('extensions', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('BrowserContext', function() {
|
describe.skip(CHANNEL)('BrowserContext', function() {
|
||||||
it('should not create pages automatically', async ({browserType, defaultBrowserOptions}) => {
|
it('should not create pages automatically', async ({browserType, defaultBrowserOptions}) => {
|
||||||
const browser = await browserType.launch(defaultBrowserOptions);
|
const browser = await browserType.launch(defaultBrowserOptions);
|
||||||
const browserSession = await browser.newBrowserCDPSession();
|
const browserSession = await browser.newBrowserCDPSession();
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {FFOX, CHROMIUM, WEBKIT} = require('../utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('../utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('OOPIF', function() {
|
describe.skip(CHANNEL)('OOPIF', function() {
|
||||||
beforeAll(async function(state) {
|
beforeAll(async function(state) {
|
||||||
state.browser = await state.browserType.launch(Object.assign({}, state.defaultBrowserOptions, {
|
state.browser = await state.browserType.launch(Object.assign({}, state.defaultBrowserOptions, {
|
||||||
args: (state.defaultBrowserOptions.args || []).concat(['--site-per-process']),
|
args: (state.defaultBrowserOptions.args || []).concat(['--site-per-process']),
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {FFOX, CHROMIUM, WEBKIT} = require('../utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('../utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('ChromiumBrowserContext.createSession', function() {
|
describe.skip(CHANNEL)('ChromiumBrowserContext.createSession', function() {
|
||||||
it('should work', async function({page, browser, server}) {
|
it('should work', async function({page, browser, server}) {
|
||||||
const client = await page.context().newCDPSession(page);
|
const client = await page.context().newCDPSession(page);
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ describe('ChromiumBrowserContext.createSession', function() {
|
||||||
await context.close();
|
await context.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('ChromiumBrowser.newBrowserCDPSession', function() {
|
describe.skip(CHANNEL)('ChromiumBrowser.newBrowserCDPSession', function() {
|
||||||
it('should work', async function({page, browser, server}) {
|
it('should work', async function({page, browser, server}) {
|
||||||
const session = await browser.newBrowserCDPSession();
|
const session = await browser.newBrowserCDPSession();
|
||||||
const version = await session.send('Browser.getVersion');
|
const version = await session.send('Browser.getVersion');
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const {FFOX, CHROMIUM, WEBKIT, OUTPUT_DIR} = require('../utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, OUTPUT_DIR, CHANNEL} = require('../utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('Chromium.startTracing', function() {
|
describe.skip(CHANNEL)('Chromium.startTracing', function() {
|
||||||
beforeEach(async function(state) {
|
beforeEach(async function(state) {
|
||||||
state.outputFile = path.join(OUTPUT_DIR, `trace-${state.parallelIndex}.json`);
|
state.outputFile = path.join(OUTPUT_DIR, `trace-${state.parallelIndex}.json`);
|
||||||
state.browser = await state.browserType.launch(state.defaultBrowserOptions);
|
state.browser = await state.browserType.launch(state.defaultBrowserOptions);
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ describe('launchPersistentContext()', function() {
|
||||||
expect(error.message).toContain('can not specify page');
|
expect(error.message).toContain('can not specify page');
|
||||||
await removeUserDataDir(userDataDir);
|
await removeUserDataDir(userDataDir);
|
||||||
});
|
});
|
||||||
it('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, defaultBrowserOptions, server}) => {
|
it.skip(USES_HOOKS)('should have passed URL when launching with ignoreDefaultArgs: true', async ({browserType, defaultBrowserOptions, server}) => {
|
||||||
const userDataDir = await makeUserDataDir();
|
const userDataDir = await makeUserDataDir();
|
||||||
const args = browserType._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
|
const args = browserType._defaultArgs(defaultBrowserOptions, 'persistent', userDataDir, 0).filter(a => a !== 'about:blank');
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const {FFOX, CHROMIUM, WEBKIT} = require('./utils').testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, CHANNEL} = require('./utils').testOptions(browserType);
|
||||||
|
|
||||||
describe('Logger', function() {
|
describe.skip(CHANNEL)('Logger', function() {
|
||||||
it('should log', async({browserType, defaultBrowserOptions}) => {
|
it('should log', async({browserType, defaultBrowserOptions}) => {
|
||||||
const log = [];
|
const log = [];
|
||||||
const browser = await browserType.launch({...defaultBrowserOptions, logger: {
|
const browser = await browserType.launch({...defaultBrowserOptions, logger: {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const {FFOX, CHROMIUM, WEBKIT, MAC, WIN} = utils.testOptions(browserType);
|
const {FFOX, CHROMIUM, WEBKIT, MAC, WIN, CHANNEL} = utils.testOptions(browserType);
|
||||||
|
|
||||||
describe('Page.goto', function() {
|
describe('Page.goto', function() {
|
||||||
it('should work', async({page, server}) => {
|
it('should work', async({page, server}) => {
|
||||||
|
|
@ -541,7 +541,7 @@ describe('Page.goto', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Page.waitForNavigation', function() {
|
describe.skip(CHANNEL)('Page.waitForNavigation', function() {
|
||||||
it('should work', async({page, server}) => {
|
it('should work', async({page, server}) => {
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
const [response] = await Promise.all([
|
const [response] = await Promise.all([
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ const { Connection } = require('../lib/rpc/connection');
|
||||||
const { helper } = require('../lib/helper');
|
const { helper } = require('../lib/helper');
|
||||||
const { BrowserTypeDispatcher } = require('../lib/rpc/server/browserTypeDispatcher');
|
const { BrowserTypeDispatcher } = require('../lib/rpc/server/browserTypeDispatcher');
|
||||||
|
|
||||||
|
Error.stackTraceLimit = 15;
|
||||||
|
|
||||||
function getCLIArgument(argName) {
|
function getCLIArgument(argName) {
|
||||||
for (let i = 0; i < process.argv.length; ++i) {
|
for (let i = 0; i < process.argv.length; ++i) {
|
||||||
// Support `./test.js --foo bar
|
// Support `./test.js --foo bar
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,8 @@ const utils = module.exports = {
|
||||||
browserType,
|
browserType,
|
||||||
GOLDEN_DIR,
|
GOLDEN_DIR,
|
||||||
OUTPUT_DIR,
|
OUTPUT_DIR,
|
||||||
USES_HOOKS: !!process.env.PWCHANNEL
|
USES_HOOKS: !!process.env.PWCHANNEL,
|
||||||
|
CHANNEL: !!process.env.PWCHANNEL,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue