chore(rpc): strongly-type the initializer, remove __init__ phase (#2729)
This commit is contained in:
parent
18d6140d3e
commit
02f7501725
|
|
@ -28,12 +28,17 @@ export interface BrowserTypeChannel extends Channel {
|
|||
launch(params: { options?: types.LaunchOptions }): Promise<BrowserChannel>;
|
||||
launchPersistentContext(params: { userDataDir: string, options?: types.LaunchOptions & types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
||||
}
|
||||
export type BrowserTypeInitializer = {
|
||||
executablePath: string,
|
||||
name: string
|
||||
};
|
||||
|
||||
export interface BrowserChannel extends Channel {
|
||||
close(): Promise<void>;
|
||||
newContext(params: { options?: types.BrowserContextOptions }): Promise<BrowserContextChannel>;
|
||||
newPage(params: { options?: types.BrowserContextOptions }): Promise<PageChannel>;
|
||||
}
|
||||
export type BrowserInitializer = {};
|
||||
|
||||
export interface BrowserContextChannel extends Channel {
|
||||
addCookies(params: { cookies: types.SetNetworkCookieParam[] }): Promise<void>;
|
||||
|
|
@ -54,6 +59,7 @@ export interface BrowserContextChannel extends Channel {
|
|||
setOffline(params: { offline: boolean }): Promise<void>;
|
||||
waitForEvent(params: { event: string }): Promise<any>;
|
||||
}
|
||||
export type BrowserContextInitializer = {};
|
||||
|
||||
export interface PageChannel extends Channel {
|
||||
on(event: 'bindingCall', callback: (params: BindingCallChannel) => void): this;
|
||||
|
|
@ -101,6 +107,10 @@ export interface PageChannel extends Channel {
|
|||
// A11Y
|
||||
accessibilitySnapshot(params: { options: { interestingOnly?: boolean, root?: ElementHandleChannel } }): Promise<types.SerializedAXNode | null>;
|
||||
}
|
||||
export type PageInitializer = {
|
||||
mainFrame: FrameChannel,
|
||||
viewportSize: types.Size | null
|
||||
};
|
||||
|
||||
export interface FrameChannel extends Channel {
|
||||
$$eval(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
||||
|
|
@ -137,6 +147,11 @@ export interface FrameChannel extends Channel {
|
|||
waitForNavigation(params: { options: types.WaitForNavigationOptions }): Promise<ResponseChannel | null>;
|
||||
waitForSelector(params: { selector: string, options: types.WaitForElementOptions }): Promise<ElementHandleChannel | null>;
|
||||
}
|
||||
export type FrameInitializer = {
|
||||
url: string,
|
||||
name: string,
|
||||
parentFrame: FrameChannel | null
|
||||
};
|
||||
|
||||
export interface JSHandleChannel extends Channel {
|
||||
dispose(): Promise<void>;
|
||||
|
|
@ -145,6 +160,9 @@ export interface JSHandleChannel extends Channel {
|
|||
getPropertyList(): Promise<{ name: string, value: JSHandleChannel}[]>;
|
||||
jsonValue(): Promise<any>;
|
||||
}
|
||||
export type JSHandleInitializer = {
|
||||
preview: string,
|
||||
};
|
||||
|
||||
export interface ElementHandleChannel extends JSHandleChannel {
|
||||
$$eval(params: { selector: string; expression: string, isFunction: boolean, arg: any }): Promise<any>;
|
||||
|
|
@ -178,22 +196,53 @@ export interface ElementHandleChannel extends JSHandleChannel {
|
|||
export interface RequestChannel extends Channel {
|
||||
response(): Promise<ResponseChannel | null>;
|
||||
}
|
||||
export type RequestInitializer = {
|
||||
frame: FrameChannel,
|
||||
url: string,
|
||||
resourceType: string,
|
||||
method: string,
|
||||
postData: string | null,
|
||||
headers: types.Headers,
|
||||
isNavigationRequest: boolean,
|
||||
redirectedFrom: RequestChannel | null,
|
||||
};
|
||||
|
||||
export interface RouteChannel extends Channel {
|
||||
abort(params: { errorCode: string }): Promise<void>;
|
||||
continue(params: { overrides: { method?: string, headers?: types.Headers, postData?: string } }): Promise<void>;
|
||||
fulfill(params: { response: types.FulfillResponse & { path?: string } }): Promise<void>;
|
||||
}
|
||||
export type RouteInitializer = {
|
||||
request: RequestChannel,
|
||||
};
|
||||
|
||||
export interface ResponseChannel extends Channel {
|
||||
body(): Promise<Buffer>;
|
||||
finished(): Promise<Error | null>;
|
||||
}
|
||||
export type ResponseInitializer = {
|
||||
request: RequestChannel,
|
||||
url: string,
|
||||
status: number,
|
||||
statusText: string,
|
||||
headers: types.Headers,
|
||||
};
|
||||
|
||||
export interface ConsoleMessageChannel extends Channel {
|
||||
}
|
||||
export type ConsoleMessageInitializer = {
|
||||
type: string,
|
||||
text: string,
|
||||
args: JSHandleChannel[],
|
||||
location: types.ConsoleMessageLocation,
|
||||
};
|
||||
|
||||
export interface BindingCallChannel extends Channel {
|
||||
reject(params: { error: types.Error }): void;
|
||||
resolve(params: { result: any }): void;
|
||||
}
|
||||
export type BindingCallInitializer = {
|
||||
frame: FrameChannel,
|
||||
name: string,
|
||||
args: any[]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
*/
|
||||
|
||||
import * as types from '../../types';
|
||||
import { BrowserChannel } from '../channels';
|
||||
import { BrowserChannel, BrowserInitializer } from '../channels';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { Page } from './page';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Connection } from '../connection';
|
||||
|
||||
export class Browser extends ChannelOwner<BrowserChannel> {
|
||||
export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
|
||||
readonly _contexts = new Set<BrowserContext>();
|
||||
private _isConnected = true;
|
||||
|
||||
|
|
@ -34,12 +34,10 @@ export class Browser extends ChannelOwner<BrowserChannel> {
|
|||
return browser ? Browser.from(browser) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: BrowserChannel) {
|
||||
super(connection, channel);
|
||||
constructor(connection: Connection, channel: BrowserChannel, initializer: BrowserInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
_initialize() {}
|
||||
|
||||
async newContext(options?: types.BrowserContextOptions): Promise<BrowserContext> {
|
||||
const context = BrowserContext.from(await this._channel.newContext({ options }));
|
||||
this._contexts.add(context);
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ import * as frames from './frame';
|
|||
import { Page, BindingCall, waitForEvent } from './page';
|
||||
import * as types from '../../types';
|
||||
import * as network from './network';
|
||||
import { BrowserContextChannel } from '../channels';
|
||||
import { BrowserContextChannel, BrowserContextInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { helper } from '../../helper';
|
||||
import { Browser } from './browser';
|
||||
import { Connection } from '../connection';
|
||||
import { Events } from '../../events';
|
||||
|
||||
export class BrowserContext extends ChannelOwner<BrowserContextChannel> {
|
||||
export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserContextInitializer> {
|
||||
_pages = new Set<Page>();
|
||||
private _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
|
||||
_browser: Browser | undefined;
|
||||
|
|
@ -39,11 +40,16 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel> {
|
|||
return context ? BrowserContext.from(context) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: BrowserContextChannel) {
|
||||
super(connection, channel);
|
||||
constructor(connection: Connection, channel: BrowserContextChannel, initializer: BrowserContextInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
channel.on('page', page => this._onPage(Page.from(page)));
|
||||
}
|
||||
|
||||
_initialize() {}
|
||||
private _onPage(page: Page): void {
|
||||
page._browserContext = this;
|
||||
this._pages.add(page);
|
||||
this.emit(Events.BrowserContext.Page, page);
|
||||
}
|
||||
|
||||
_onRoute(route: network.Route, request: network.Request) {
|
||||
for (const {url, handler} of this._routes) {
|
||||
|
|
@ -56,7 +62,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel> {
|
|||
}
|
||||
|
||||
async _onBinding(bindingCall: BindingCall) {
|
||||
const func = this._bindings.get(bindingCall.name);
|
||||
const func = this._bindings.get(bindingCall._initializer.name);
|
||||
if (!func)
|
||||
return;
|
||||
bindingCall.call(func);
|
||||
|
|
@ -157,5 +163,6 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel> {
|
|||
async close(): Promise<void> {
|
||||
await this._channel.close();
|
||||
this._browser!._contexts.delete(this);
|
||||
this.emit(Events.BrowserContext.Close);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,31 +15,23 @@
|
|||
*/
|
||||
|
||||
import * as types from '../../types';
|
||||
import { BrowserTypeChannel } from '../channels';
|
||||
import { BrowserTypeChannel, BrowserTypeInitializer } from '../channels';
|
||||
import { Browser } from './browser';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Connection } from '../connection';
|
||||
|
||||
export class BrowserType extends ChannelOwner<BrowserTypeChannel> {
|
||||
private _executablePath: string = '';
|
||||
private _name: string = '';
|
||||
|
||||
constructor(connection: Connection, channel: BrowserTypeChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(payload: { executablePath: string, name: string }) {
|
||||
this._executablePath = payload.executablePath;
|
||||
this._name = payload.name;
|
||||
export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeInitializer> {
|
||||
constructor(connection: Connection, channel: BrowserTypeChannel, initializer: BrowserTypeInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
executablePath(): string {
|
||||
return this._executablePath;
|
||||
return this._initializer.executablePath;
|
||||
}
|
||||
|
||||
name(): string {
|
||||
return this._name;
|
||||
return this._initializer.name;
|
||||
}
|
||||
|
||||
async launch(options?: types.LaunchOptions): Promise<Browser> {
|
||||
|
|
|
|||
|
|
@ -18,17 +18,17 @@ import { EventEmitter } from 'events';
|
|||
import { Channel } from '../channels';
|
||||
import { Connection } from '../connection';
|
||||
|
||||
export abstract class ChannelOwner<T extends Channel> extends EventEmitter {
|
||||
export abstract class ChannelOwner<T extends Channel, Initializer> extends EventEmitter {
|
||||
readonly _channel: T;
|
||||
readonly _initializer: Initializer;
|
||||
readonly _connection: Connection;
|
||||
static clientSymbol = Symbol('client');
|
||||
|
||||
constructor(connection: Connection, channel: T) {
|
||||
constructor(connection: Connection, channel: T, initializer: Initializer) {
|
||||
super();
|
||||
this._connection = connection;
|
||||
this._channel = channel;
|
||||
this._initializer = initializer;
|
||||
(channel as any)[ChannelOwner.clientSymbol] = this;
|
||||
}
|
||||
|
||||
abstract _initialize(payload: any): void;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,45 +17,33 @@
|
|||
import * as util from 'util';
|
||||
import { ConsoleMessageLocation } from '../../types';
|
||||
import { JSHandle } from './jsHandle';
|
||||
import { ConsoleMessageChannel, JSHandleChannel } from '../channels';
|
||||
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Connection } from '../connection';
|
||||
|
||||
export class ConsoleMessage extends ChannelOwner<ConsoleMessageChannel> {
|
||||
private _type: string = '';
|
||||
private _text: string = '';
|
||||
private _args: JSHandle[] = [];
|
||||
private _location: ConsoleMessageLocation = {};
|
||||
|
||||
export class ConsoleMessage extends ChannelOwner<ConsoleMessageChannel, ConsoleMessageInitializer> {
|
||||
static from(request: ConsoleMessageChannel): ConsoleMessage {
|
||||
return request._object;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: ConsoleMessageChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(params: { type: string, text: string, args: JSHandleChannel[], location: ConsoleMessageLocation }) {
|
||||
this._type = params.type;
|
||||
this._text = params.text;
|
||||
this._args = params.args.map(JSHandle.from);
|
||||
this._location = params.location;
|
||||
constructor(connection: Connection, channel: ConsoleMessageChannel, initializer: ConsoleMessageInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
type(): string {
|
||||
return this._type;
|
||||
return this._initializer.type;
|
||||
}
|
||||
|
||||
text(): string {
|
||||
return this._text;
|
||||
return this._initializer.text;
|
||||
}
|
||||
|
||||
args(): JSHandle[] {
|
||||
return this._args;
|
||||
return this._initializer.args.map(JSHandle.from);
|
||||
}
|
||||
|
||||
location(): ConsoleMessageLocation {
|
||||
return this._location;
|
||||
return this._initializer.location;
|
||||
}
|
||||
|
||||
[util.inspect.custom]() {
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
import * as types from '../../types';
|
||||
import { ElementHandleChannel } from '../channels';
|
||||
import { ElementHandleChannel, JSHandleInitializer } from '../channels';
|
||||
import { Frame } from './frame';
|
||||
import { FuncOn, JSHandle, convertArg } from './jsHandle';
|
||||
import { Connection } from '../connection';
|
||||
|
|
@ -31,8 +31,8 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
|
|||
return handle ? ElementHandle.from(handle) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: ElementHandleChannel) {
|
||||
super(connection, channel);
|
||||
constructor(connection: Connection, channel: ElementHandleChannel, initializer: JSHandleInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
this._elementChannel = channel;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import { assertMaxArguments } from '../../helper';
|
||||
import * as types from '../../types';
|
||||
import { FrameChannel } from '../channels';
|
||||
import { FrameChannel, FrameInitializer } from '../channels';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { ElementHandle, convertSelectOptionValues } from './elementHandle';
|
||||
|
|
@ -33,12 +33,13 @@ export type GotoOptions = types.NavigateOptions & {
|
|||
|
||||
export type FunctionWithSource = (source: { context: BrowserContext, page: Page, frame: Frame }, ...args: any) => any;
|
||||
|
||||
export class Frame extends ChannelOwner<FrameChannel> {
|
||||
export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
|
||||
_parentFrame: Frame | null = null;
|
||||
_url = '';
|
||||
_name = '';
|
||||
private _detached = false;
|
||||
_childFrames = new Set<Frame>();
|
||||
_page: Page | undefined;
|
||||
|
||||
static from(frame: FrameChannel): Frame {
|
||||
return frame._object;
|
||||
|
|
@ -48,16 +49,13 @@ export class Frame extends ChannelOwner<FrameChannel> {
|
|||
return frame ? Frame.from(frame) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: FrameChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(params: { name: string, url: string, parentFrame: FrameChannel | null }) {
|
||||
this._parentFrame = params.parentFrame ? params.parentFrame._object : null;
|
||||
constructor(connection: Connection, channel: FrameChannel, initializer: FrameInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
this._parentFrame = Frame.fromNullable(initializer.parentFrame);
|
||||
if (this._parentFrame)
|
||||
this._parentFrame._childFrames.add(this);
|
||||
this._name = params.name;
|
||||
this._url = params.url;
|
||||
this._name = initializer.name;
|
||||
this._url = initializer.url;
|
||||
}
|
||||
|
||||
async goto(url: string, options: GotoOptions = {}): Promise<network.Response | null> {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JSHandleChannel } from '../channels';
|
||||
import { JSHandleChannel, JSHandleInitializer } from '../channels';
|
||||
import { ElementHandle } from './elementHandle';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Connection } from '../connection';
|
||||
|
|
@ -35,10 +35,7 @@ export type Func1<Arg, R> = string | ((arg: Unboxed<Arg>) => R | Promise<R>);
|
|||
export type FuncOn<On, Arg2, R> = string | ((on: On, arg2: Unboxed<Arg2>) => R | Promise<R>);
|
||||
export type SmartHandle<T> = T extends Node ? ElementHandle<T> : JSHandle<T>;
|
||||
|
||||
export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel> {
|
||||
protected _jsChannel: JSHandleChannel;
|
||||
private _preview: string | undefined;
|
||||
|
||||
export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleInitializer> {
|
||||
static from(handle: JSHandleChannel): JSHandle {
|
||||
return handle._object;
|
||||
}
|
||||
|
|
@ -47,25 +44,20 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel> {
|
|||
return handle ? JSHandle.from(handle) : null;
|
||||
}
|
||||
|
||||
constructor(conection: Connection, channel: JSHandleChannel) {
|
||||
super(conection, channel);
|
||||
this._jsChannel = channel;
|
||||
}
|
||||
|
||||
_initialize(params: { preview: string }) {
|
||||
this._preview = params.preview;
|
||||
constructor(conection: Connection, channel: JSHandleChannel, initializer: JSHandleInitializer) {
|
||||
super(conection, channel, initializer);
|
||||
}
|
||||
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R>;
|
||||
async evaluate<R>(pageFunction: FuncOn<T, void, R>, arg?: any): Promise<R>;
|
||||
async evaluate<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<R> {
|
||||
return await this._jsChannel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: convertArg(arg) });
|
||||
return await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: convertArg(arg) });
|
||||
}
|
||||
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R>(pageFunction: FuncOn<T, void, R>, arg?: any): Promise<SmartHandle<R>>;
|
||||
async evaluateHandle<R, Arg>(pageFunction: FuncOn<T, Arg, R>, arg: Arg): Promise<SmartHandle<R>> {
|
||||
const handleChannel = await this._jsChannel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: convertArg(arg) });
|
||||
const handleChannel = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: convertArg(arg) });
|
||||
return JSHandle.from(handleChannel) as SmartHandle<R>;
|
||||
}
|
||||
|
||||
|
|
@ -83,13 +75,13 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel> {
|
|||
|
||||
async getProperties(): Promise<Map<string, JSHandle>> {
|
||||
const map = new Map<string, JSHandle>();
|
||||
for (const { name, value } of await this._jsChannel.getPropertyList())
|
||||
for (const { name, value } of await this._channel.getPropertyList())
|
||||
map.set(name, JSHandle.from(value));
|
||||
return map;
|
||||
}
|
||||
|
||||
async jsonValue(): Promise<T> {
|
||||
return await this._jsChannel.jsonValue();
|
||||
return await this._channel.jsonValue();
|
||||
}
|
||||
|
||||
asElement(): ElementHandle | null {
|
||||
|
|
@ -97,11 +89,11 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel> {
|
|||
}
|
||||
|
||||
async dispose() {
|
||||
return await this._jsChannel.dispose();
|
||||
return await this._channel.dispose();
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return this._preview!;
|
||||
return this._initializer.preview;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { URLSearchParams } from 'url';
|
||||
import * as types from '../../types';
|
||||
import { RequestChannel, ResponseChannel, FrameChannel, RouteChannel } from '../channels';
|
||||
import { RequestChannel, ResponseChannel, RouteChannel, RequestInitializer, ResponseInitializer, RouteInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Frame } from './frame';
|
||||
import { Connection } from '../connection';
|
||||
|
|
@ -44,17 +44,10 @@ export type SetNetworkCookieParam = {
|
|||
sameSite?: 'Strict' | 'Lax' | 'None'
|
||||
};
|
||||
|
||||
export class Request extends ChannelOwner<RequestChannel> {
|
||||
export class Request extends ChannelOwner<RequestChannel, RequestInitializer> {
|
||||
private _redirectedFrom: Request | null = null;
|
||||
private _redirectedTo: Request | null = null;
|
||||
private _isNavigationRequest = false;
|
||||
_failureText: string | null = null;
|
||||
private _url: string = '';
|
||||
private _resourceType = '';
|
||||
private _method = '';
|
||||
private _postData: string | null = null;
|
||||
private _headers: types.Headers = {};
|
||||
private _frame: Frame | undefined;
|
||||
|
||||
static from(request: RequestChannel): Request {
|
||||
return request._object;
|
||||
|
|
@ -64,42 +57,31 @@ export class Request extends ChannelOwner<RequestChannel> {
|
|||
return request ? Request.from(request) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: RequestChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(payload: { frame: FrameChannel, redirectedFrom: RequestChannel | null, isNavigationRequest: boolean,
|
||||
url: string, resourceType: string, method: string, postData: string | null, headers: types.Headers }) {
|
||||
this._frame = payload.frame._object as Frame;
|
||||
this._isNavigationRequest = payload.isNavigationRequest;
|
||||
this._redirectedFrom = Request.fromNullable(payload.redirectedFrom);
|
||||
constructor(connection: Connection, channel: RequestChannel, initializer: RequestInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
this._redirectedFrom = Request.fromNullable(initializer.redirectedFrom);
|
||||
if (this._redirectedFrom)
|
||||
this._redirectedFrom._redirectedTo = this;
|
||||
this._url = payload.url;
|
||||
this._resourceType = payload.resourceType;
|
||||
this._method = payload.method;
|
||||
this._postData = payload.postData;
|
||||
this._headers = payload.headers;
|
||||
}
|
||||
|
||||
url(): string {
|
||||
return this._url;
|
||||
return this._initializer.url;
|
||||
}
|
||||
|
||||
resourceType(): string {
|
||||
return this._resourceType;
|
||||
return this._initializer.resourceType;
|
||||
}
|
||||
|
||||
method(): string {
|
||||
return this._method;
|
||||
return this._initializer.method;
|
||||
}
|
||||
|
||||
postData(): string | null {
|
||||
return this._postData;
|
||||
return this._initializer.postData;
|
||||
}
|
||||
|
||||
postDataJSON(): Object | null {
|
||||
if (!this._postData)
|
||||
if (!this._initializer.postData)
|
||||
return null;
|
||||
|
||||
const contentType = this.headers()['content-type'];
|
||||
|
|
@ -108,17 +90,17 @@ export class Request extends ChannelOwner<RequestChannel> {
|
|||
|
||||
if (contentType === 'application/x-www-form-urlencoded') {
|
||||
const entries: Record<string, string> = {};
|
||||
const parsed = new URLSearchParams(this._postData);
|
||||
const parsed = new URLSearchParams(this._initializer.postData);
|
||||
for (const [k, v] of parsed.entries())
|
||||
entries[k] = v;
|
||||
return entries;
|
||||
}
|
||||
|
||||
return JSON.parse(this._postData);
|
||||
return JSON.parse(this._initializer.postData);
|
||||
}
|
||||
|
||||
headers(): {[key: string]: string} {
|
||||
return { ...this._headers };
|
||||
return { ...this._initializer.headers };
|
||||
}
|
||||
|
||||
async response(): Promise<Response | null> {
|
||||
|
|
@ -126,11 +108,11 @@ export class Request extends ChannelOwner<RequestChannel> {
|
|||
}
|
||||
|
||||
frame(): Frame {
|
||||
return this._frame!;
|
||||
return Frame.from(this._initializer.frame);
|
||||
}
|
||||
|
||||
isNavigationRequest(): boolean {
|
||||
return this._isNavigationRequest;
|
||||
return this._initializer.isNavigationRequest;
|
||||
}
|
||||
|
||||
redirectedFrom(): Request | null {
|
||||
|
|
@ -150,23 +132,17 @@ export class Request extends ChannelOwner<RequestChannel> {
|
|||
}
|
||||
}
|
||||
|
||||
export class Route extends ChannelOwner<RouteChannel> {
|
||||
private _request: Request | undefined;
|
||||
|
||||
export class Route extends ChannelOwner<RouteChannel, RouteInitializer> {
|
||||
static from(route: RouteChannel): Route {
|
||||
return route._object;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: RouteChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(params: { request: RequestChannel }) {
|
||||
this._request = Request.from(params.request);
|
||||
constructor(connection: Connection, channel: RouteChannel, initializer: RouteInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
request(): Request {
|
||||
return this._request!;
|
||||
return Request.from(this._initializer.request);
|
||||
}
|
||||
|
||||
async abort(errorCode: string = 'failed') {
|
||||
|
|
@ -184,13 +160,7 @@ export class Route extends ChannelOwner<RouteChannel> {
|
|||
|
||||
export type RouteHandler = (route: Route, request: Request) => void;
|
||||
|
||||
export class Response extends ChannelOwner<ResponseChannel> {
|
||||
private _request: Request | undefined;
|
||||
private _status: number = 0;
|
||||
private _statusText: string = '';
|
||||
private _url: string = '';
|
||||
private _headers: types.Headers = {};
|
||||
|
||||
export class Response extends ChannelOwner<ResponseChannel, ResponseInitializer> {
|
||||
static from(response: ResponseChannel): Response {
|
||||
return response._object;
|
||||
}
|
||||
|
|
@ -199,36 +169,28 @@ export class Response extends ChannelOwner<ResponseChannel> {
|
|||
return response ? Response.from(response) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: ResponseChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(payload: { request: RequestChannel, url: string, status: number, statusText: string, headers: types.Headers }) {
|
||||
this._request = Request.from(payload.request);
|
||||
this._status = payload.status;
|
||||
this._statusText = payload.statusText;
|
||||
this._url = payload.url;
|
||||
this._headers = payload.headers;
|
||||
constructor(connection: Connection, channel: ResponseChannel, initializer: ResponseInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
url(): string {
|
||||
return this._url;
|
||||
return this._initializer.url;
|
||||
}
|
||||
|
||||
ok(): boolean {
|
||||
return this._status === 0 || (this._status >= 200 && this._status <= 299);
|
||||
return this._initializer.status === 0 || (this._initializer.status >= 200 && this._initializer.status <= 299);
|
||||
}
|
||||
|
||||
status(): number {
|
||||
return this._status;
|
||||
return this._initializer.status;
|
||||
}
|
||||
|
||||
statusText(): string {
|
||||
return this._statusText;
|
||||
return this._initializer.statusText;
|
||||
}
|
||||
|
||||
headers(): object {
|
||||
return { ...this._headers };
|
||||
return { ...this._initializer.headers };
|
||||
}
|
||||
|
||||
async finished(): Promise<Error | null> {
|
||||
|
|
@ -250,10 +212,10 @@ export class Response extends ChannelOwner<ResponseChannel> {
|
|||
}
|
||||
|
||||
request(): Request {
|
||||
return this._request!;
|
||||
return Request.from(this._initializer.request);
|
||||
}
|
||||
|
||||
frame(): Frame {
|
||||
return this._request!.frame();
|
||||
return Request.from(this._initializer.request).frame();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { EventEmitter } from 'events';
|
|||
import { Events } from '../../events';
|
||||
import { assert, assertMaxArguments, helper, Listener, serializeError, parseError } from '../../helper';
|
||||
import * as types from '../../types';
|
||||
import { BrowserContextChannel, FrameChannel, PageChannel, BindingCallChannel, Channel } from '../channels';
|
||||
import { PageChannel, BindingCallChannel, Channel, PageInitializer, BindingCallInitializer } from '../channels';
|
||||
import { BrowserContext } from './browserContext';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { ElementHandle } from './elementHandle';
|
||||
|
|
@ -29,17 +29,17 @@ import { Request, Response, RouteHandler, Route } from './network';
|
|||
import { Connection } from '../connection';
|
||||
import { Keyboard, Mouse } from './input';
|
||||
import { Accessibility } from './accessibility';
|
||||
import { ConsoleMessage } from './console';
|
||||
import { ConsoleMessage } from './consoleMessage';
|
||||
|
||||
export class Page extends ChannelOwner<PageChannel> {
|
||||
export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
|
||||
|
||||
private _browserContext: BrowserContext | undefined;
|
||||
private _mainFrame: Frame | undefined;
|
||||
_browserContext: BrowserContext | undefined;
|
||||
private _mainFrame: Frame;
|
||||
private _frames = new Set<Frame>();
|
||||
private _workers: Worker[] = [];
|
||||
private _closed = false;
|
||||
private _viewportSize: types.Size | null = null;
|
||||
private _viewportSize: types.Size | null;
|
||||
private _routes: { url: types.URLMatch, handler: RouteHandler }[] = [];
|
||||
|
||||
readonly accessibility: Accessibility;
|
||||
|
|
@ -55,18 +55,16 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
return page ? Page.from(page) : null;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: PageChannel) {
|
||||
super(connection, channel);
|
||||
constructor(connection: Connection, channel: PageChannel, initializer: PageInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
this.accessibility = new Accessibility(channel);
|
||||
this.keyboard = new Keyboard(channel);
|
||||
this.mouse = new Mouse(channel);
|
||||
}
|
||||
|
||||
_initialize(payload: { browserContext: BrowserContextChannel, mainFrame: FrameChannel, viewportSize: types.Size }) {
|
||||
this._browserContext = BrowserContext.from(payload.browserContext);
|
||||
this._mainFrame = Frame.from(payload.mainFrame);
|
||||
this._mainFrame = Frame.from(initializer.mainFrame);
|
||||
this._mainFrame._page = this;
|
||||
this._frames.add(this._mainFrame);
|
||||
this._viewportSize = payload.viewportSize;
|
||||
this._viewportSize = initializer.viewportSize;
|
||||
|
||||
this._channel.on('bindingCall', bindingCall => this._onBinding(BindingCall.from(bindingCall)));
|
||||
this._channel.on('close', () => this._onClose());
|
||||
|
|
@ -88,6 +86,7 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
}
|
||||
|
||||
private _onFrameAttached(frame: Frame) {
|
||||
frame._page = this;
|
||||
this._frames.add(frame);
|
||||
if (frame._parentFrame)
|
||||
frame._parentFrame._childFrames.add(frame);
|
||||
|
|
@ -118,7 +117,7 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
}
|
||||
|
||||
async _onBinding(bindingCall: BindingCall) {
|
||||
const func = this._bindings.get(bindingCall.name);
|
||||
const func = this._bindings.get(bindingCall._initializer.name);
|
||||
if (func)
|
||||
bindingCall.call(func);
|
||||
this._browserContext!._onBinding(bindingCall);
|
||||
|
|
@ -138,7 +137,7 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
}
|
||||
|
||||
mainFrame(): Frame {
|
||||
return this._mainFrame!;
|
||||
return this._mainFrame;
|
||||
}
|
||||
|
||||
frame(options: string | { name?: string, url?: types.URLMatch }): Frame | null {
|
||||
|
|
@ -165,48 +164,48 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
}
|
||||
|
||||
async $(selector: string): Promise<ElementHandle<Element> | null> {
|
||||
return await this._mainFrame!.$(selector);
|
||||
return await this._mainFrame.$(selector);
|
||||
}
|
||||
|
||||
async waitForSelector(selector: string, options?: types.WaitForElementOptions): Promise<ElementHandle<Element> | null> {
|
||||
return await this._mainFrame!.waitForSelector(selector, options);
|
||||
return await this._mainFrame.waitForSelector(selector, options);
|
||||
}
|
||||
|
||||
async dispatchEvent(selector: string, type: string, eventInit?: Object, options?: types.TimeoutOptions): Promise<void> {
|
||||
return await this._mainFrame!.dispatchEvent(selector, type, eventInit, options);
|
||||
return await this._mainFrame.dispatchEvent(selector, type, eventInit, options);
|
||||
}
|
||||
|
||||
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._mainFrame!.evaluateHandle(pageFunction, arg);
|
||||
return await this._mainFrame.evaluateHandle(pageFunction, arg);
|
||||
}
|
||||
|
||||
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
|
||||
async $eval<R>(selector: string, pageFunction: FuncOn<Element, void, R>, arg?: any): Promise<R>;
|
||||
async $eval<R, Arg>(selector: string, pageFunction: FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return await this._mainFrame!.$eval(selector, pageFunction, arg);
|
||||
return await this._mainFrame.$eval(selector, pageFunction, arg);
|
||||
}
|
||||
|
||||
async $$eval<R, Arg>(selector: string, pageFunction: FuncOn<Element[], Arg, R>, arg: Arg): Promise<R>;
|
||||
async $$eval<R>(selector: string, pageFunction: FuncOn<Element[], void, R>, arg?: any): Promise<R>;
|
||||
async $$eval<R, Arg>(selector: string, pageFunction: FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
|
||||
assertMaxArguments(arguments.length, 3);
|
||||
return await this._mainFrame!.$$eval(selector, pageFunction, arg);
|
||||
return await this._mainFrame.$$eval(selector, pageFunction, arg);
|
||||
}
|
||||
|
||||
async $$(selector: string): Promise<ElementHandle<Element>[]> {
|
||||
return await this._mainFrame!.$$(selector);
|
||||
return await this._mainFrame.$$(selector);
|
||||
}
|
||||
|
||||
async addScriptTag(options: { url?: string; path?: string; content?: string; type?: string; }): Promise<ElementHandle> {
|
||||
return await this._mainFrame!.addScriptTag(options);
|
||||
return await this._mainFrame.addScriptTag(options);
|
||||
}
|
||||
|
||||
async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise<ElementHandle> {
|
||||
return await this._mainFrame!.addStyleTag(options);
|
||||
return await this._mainFrame.addStyleTag(options);
|
||||
}
|
||||
|
||||
async exposeFunction(name: string, playwrightFunction: Function) {
|
||||
|
|
@ -247,11 +246,11 @@ export class Page extends ChannelOwner<PageChannel> {
|
|||
}
|
||||
|
||||
async waitForLoadState(state?: types.LifecycleEvent, options?: types.TimeoutOptions): Promise<void> {
|
||||
return this._mainFrame!.waitForLoadState(state, options);
|
||||
return this._mainFrame.waitForLoadState(state, options);
|
||||
}
|
||||
|
||||
async waitForNavigation(options?: types.WaitForNavigationOptions): Promise<Response | null> {
|
||||
return this._mainFrame!.waitForNavigation(options);
|
||||
return this._mainFrame.waitForNavigation(options);
|
||||
}
|
||||
|
||||
async waitForRequest(urlOrPredicate: string | RegExp | ((r: Request) => boolean), options: types.TimeoutOptions = {}): Promise<Request> {
|
||||
|
|
@ -455,31 +454,24 @@ export class Worker extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
export class BindingCall extends ChannelOwner<BindingCallChannel> {
|
||||
name: string = '';
|
||||
source: { context: BrowserContext, page: Page, frame: Frame } | undefined;
|
||||
args: any[] = [];
|
||||
export class BindingCall extends ChannelOwner<BindingCallChannel, BindingCallInitializer> {
|
||||
static from(channel: BindingCallChannel): BindingCall {
|
||||
return channel._object;
|
||||
}
|
||||
|
||||
constructor(connection: Connection, channel: BindingCallChannel) {
|
||||
super(connection, channel);
|
||||
}
|
||||
|
||||
_initialize(params: { name: string, context: BrowserContextChannel, page: PageChannel, frame: FrameChannel, args: any[] }) {
|
||||
this.name = params.name;
|
||||
this.source = {
|
||||
context: BrowserContext.from(params.context),
|
||||
page: Page.from(params.page),
|
||||
frame: Frame.from(params.frame)
|
||||
};
|
||||
this.args = params.args;
|
||||
constructor(connection: Connection, channel: BindingCallChannel, initializer: BindingCallInitializer) {
|
||||
super(connection, channel, initializer);
|
||||
}
|
||||
|
||||
async call(func: FunctionWithSource) {
|
||||
try {
|
||||
this._channel.resolve({ result: await func(this.source!, ...this.args) });
|
||||
const frame = Frame.from(this._initializer.frame);
|
||||
const source = {
|
||||
context: frame._page!._browserContext!,
|
||||
page: frame._page!,
|
||||
frame
|
||||
};
|
||||
this._channel.resolve({ result: await func(source, ...this._initializer.args) });
|
||||
} catch (e) {
|
||||
this._channel.reject({ error: serializeError(e) });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,62 +26,75 @@ import { Request, Response, Route } from './client/network';
|
|||
import { Page, BindingCall } from './client/page';
|
||||
import debug = require('debug');
|
||||
import { Channel } from './channels';
|
||||
import { ConsoleMessage } from './client/console';
|
||||
import { ConsoleMessage } from './client/consoleMessage';
|
||||
|
||||
export class Connection {
|
||||
private _channels = new Map<string, Channel>();
|
||||
private _waitingForObject = new Map<string, any>();
|
||||
sendMessageToServerTransport = (message: any): Promise<any> => Promise.resolve();
|
||||
|
||||
constructor() {}
|
||||
|
||||
createRemoteObject(type: string, guid: string): any {
|
||||
private _createRemoteObject(type: string, guid: string, initializer: any): any {
|
||||
const channel = this._createChannel(guid) as any;
|
||||
this._channels.set(guid, channel);
|
||||
let result: ChannelOwner<any>;
|
||||
let result: ChannelOwner<any, any>;
|
||||
initializer = this._replaceGuidsWithChannels(initializer);
|
||||
switch (type) {
|
||||
case 'browserType':
|
||||
result = new BrowserType(this, channel);
|
||||
result = new BrowserType(this, channel, initializer);
|
||||
break;
|
||||
case 'browser':
|
||||
result = new Browser(this, channel);
|
||||
result = new Browser(this, channel, initializer);
|
||||
break;
|
||||
case 'context':
|
||||
result = new BrowserContext(this, channel);
|
||||
result = new BrowserContext(this, channel, initializer);
|
||||
break;
|
||||
case 'page':
|
||||
result = new Page(this, channel);
|
||||
result = new Page(this, channel, initializer);
|
||||
break;
|
||||
case 'frame':
|
||||
result = new Frame(this, channel);
|
||||
result = new Frame(this, channel, initializer);
|
||||
break;
|
||||
case 'request':
|
||||
result = new Request(this, channel);
|
||||
result = new Request(this, channel, initializer);
|
||||
break;
|
||||
case 'response':
|
||||
result = new Response(this, channel);
|
||||
result = new Response(this, channel, initializer);
|
||||
break;
|
||||
case 'route':
|
||||
result = new Route(this, channel);
|
||||
result = new Route(this, channel, initializer);
|
||||
break;
|
||||
case 'bindingCall':
|
||||
result = new BindingCall(this, channel);
|
||||
result = new BindingCall(this, channel, initializer);
|
||||
break;
|
||||
case 'jsHandle':
|
||||
result = new JSHandle(this, channel);
|
||||
result = new JSHandle(this, channel, initializer);
|
||||
break;
|
||||
case 'elementHandle':
|
||||
result = new ElementHandle(this, channel);
|
||||
result = new ElementHandle(this, channel, initializer);
|
||||
break;
|
||||
case 'consoleMessage':
|
||||
result = new ConsoleMessage(this, channel);
|
||||
result = new ConsoleMessage(this, channel, initializer);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Missing type ' + type);
|
||||
}
|
||||
channel._object = result;
|
||||
const callback = this._waitingForObject.get(guid);
|
||||
if (callback) {
|
||||
callback(result);
|
||||
this._waitingForObject.delete(guid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
waitForObjectWithKnownName(guid: string): Promise<any> {
|
||||
if (this._channels.has(guid))
|
||||
return this._channels.get(guid)!._object;
|
||||
return new Promise(f => this._waitingForObject.set(guid, f));
|
||||
}
|
||||
|
||||
async sendMessageToServer(message: { guid: string, method: string, params: any }) {
|
||||
const converted = {...message, params: this._replaceChannelsWithGuids(message.params)};
|
||||
debug('pw:channel:command')(converted);
|
||||
|
|
@ -95,15 +108,11 @@ export class Connection {
|
|||
const { guid, method, params } = message;
|
||||
|
||||
if (method === '__create__') {
|
||||
this.createRemoteObject(params.type, guid);
|
||||
this._createRemoteObject(params.type, guid, params.initializer);
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = this._channels.get(guid)!;
|
||||
if (message.method === '__init__') {
|
||||
channel._object._initialize(this._replaceGuidsWithChannels(params));
|
||||
return;
|
||||
}
|
||||
channel.emit(method, this._replaceGuidsWithChannels(params));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ import { EventEmitter } from 'events';
|
|||
import { helper } from '../helper';
|
||||
import { Channel } from './channels';
|
||||
|
||||
export class Dispatcher extends EventEmitter implements Channel {
|
||||
export class Dispatcher<Initializer> extends EventEmitter implements Channel {
|
||||
readonly _guid: string;
|
||||
readonly _type: string;
|
||||
protected _scope: DispatcherScope;
|
||||
_object: any;
|
||||
|
||||
constructor(scope: DispatcherScope, object: any, type: string, guid = type + '@' + helper.guid()) {
|
||||
constructor(scope: DispatcherScope, object: any, type: string, initializer: Initializer, guid = type + '@' + helper.guid()) {
|
||||
super();
|
||||
this._type = type;
|
||||
this._guid = guid;
|
||||
|
|
@ -32,20 +32,16 @@ export class Dispatcher extends EventEmitter implements Channel {
|
|||
this._scope = scope;
|
||||
scope.dispatchers.set(this._guid, this);
|
||||
object[scope.dispatcherSymbol] = this;
|
||||
this._scope.sendMessageToClient(this._guid, '__create__', { type });
|
||||
this._scope.sendMessageToClient(this._guid, '__create__', { type, initializer });
|
||||
}
|
||||
|
||||
_initialize(payload: any) {
|
||||
this._scope.sendMessageToClient(this._guid, '__init__', payload);
|
||||
}
|
||||
|
||||
_dispatchEvent(method: string, params: Dispatcher | any = {}) {
|
||||
_dispatchEvent(method: string, params: Dispatcher<any> | any = {}) {
|
||||
this._scope.sendMessageToClient(this._guid, method, params);
|
||||
}
|
||||
}
|
||||
|
||||
export class DispatcherScope {
|
||||
readonly dispatchers = new Map<string, Dispatcher>();
|
||||
readonly dispatchers = new Map<string, Dispatcher<any>>();
|
||||
readonly dispatcherSymbol = Symbol('dispatcher');
|
||||
sendMessageToClientTransport = (message: any) => {};
|
||||
|
||||
|
|
|
|||
|
|
@ -17,14 +17,13 @@
|
|||
import * as types from '../../types';
|
||||
import { BrowserContextBase, BrowserContext } from '../../browserContext';
|
||||
import { Events } from '../../events';
|
||||
import { BrowserDispatcher } from './browserDispatcher';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { PageDispatcher, BindingCallDispatcher } from './pageDispatcher';
|
||||
import { PageChannel, BrowserContextChannel } from '../channels';
|
||||
import { PageChannel, BrowserContextChannel, BrowserContextInitializer } from '../channels';
|
||||
import { RouteDispatcher, RequestDispatcher } from './networkDispatchers';
|
||||
import { Page } from '../../page';
|
||||
|
||||
export class BrowserContextDispatcher extends Dispatcher implements BrowserContextChannel {
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContextInitializer> implements BrowserContextChannel {
|
||||
private _context: BrowserContextBase;
|
||||
|
||||
static from(scope: DispatcherScope, browserContext: BrowserContext): BrowserContextDispatcher {
|
||||
|
|
@ -34,10 +33,7 @@ export class BrowserContextDispatcher extends Dispatcher implements BrowserConte
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, context: BrowserContextBase) {
|
||||
super(scope, context, 'context');
|
||||
this._initialize({
|
||||
browser: BrowserDispatcher.from(scope, context._browserBase)
|
||||
});
|
||||
super(scope, context, 'context', {});
|
||||
this._context = context;
|
||||
context.on(Events.BrowserContext.Page, page => this._dispatchEvent('page', PageDispatcher.from(this._scope, page)));
|
||||
context.on(Events.BrowserContext.Close, () => {
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ import { BrowserBase } from '../../browser';
|
|||
import { BrowserContextBase } from '../../browserContext';
|
||||
import * as types from '../../types';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import { BrowserChannel, BrowserContextChannel, PageChannel } from '../channels';
|
||||
import { BrowserChannel, BrowserContextChannel, PageChannel, BrowserInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { PageDispatcher } from './pageDispatcher';
|
||||
|
||||
export class BrowserDispatcher extends Dispatcher implements BrowserChannel {
|
||||
export class BrowserDispatcher extends Dispatcher<BrowserInitializer> implements BrowserChannel {
|
||||
private _browser: BrowserBase;
|
||||
|
||||
static from(scope: DispatcherScope, browser: BrowserBase): BrowserDispatcher {
|
||||
|
|
@ -38,8 +38,7 @@ export class BrowserDispatcher extends Dispatcher implements BrowserChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, browser: BrowserBase) {
|
||||
super(scope, browser, 'browser');
|
||||
this._initialize({});
|
||||
super(scope, browser, 'browser', {});
|
||||
this._browser = browser;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@ import { BrowserBase } from '../../browser';
|
|||
import { BrowserTypeBase } from '../../server/browserType';
|
||||
import * as types from '../../types';
|
||||
import { BrowserDispatcher } from './browserDispatcher';
|
||||
import { BrowserChannel, BrowserTypeChannel, BrowserContextChannel } from '../channels';
|
||||
import { BrowserChannel, BrowserTypeChannel, BrowserContextChannel, BrowserTypeInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { BrowserContextBase } from '../../browserContext';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
|
||||
export class BrowserTypeDispatcher extends Dispatcher implements BrowserTypeChannel {
|
||||
export class BrowserTypeDispatcher extends Dispatcher<BrowserTypeInitializer> implements BrowserTypeChannel {
|
||||
private _browserType: BrowserTypeBase;
|
||||
|
||||
static from(scope: DispatcherScope, browserType: BrowserTypeBase): BrowserTypeDispatcher {
|
||||
|
|
@ -33,8 +33,10 @@ export class BrowserTypeDispatcher extends Dispatcher implements BrowserTypeChan
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, browserType: BrowserTypeBase) {
|
||||
super(scope, browserType, 'browserType', browserType.name());
|
||||
this._initialize({ executablePath: browserType.executablePath(), name: browserType.name() });
|
||||
super(scope, browserType, 'browserType', {
|
||||
executablePath: browserType.executablePath(),
|
||||
name: browserType.name()
|
||||
}, browserType.name());
|
||||
this._browserType = browserType;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
|
||||
import { ConsoleMessage } from '../../console';
|
||||
import { ConsoleMessageChannel } from '../channels';
|
||||
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
|
||||
export class ConsoleMessageDispatcher extends Dispatcher implements ConsoleMessageChannel {
|
||||
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessageInitializer> implements ConsoleMessageChannel {
|
||||
static from(scope: DispatcherScope, message: ConsoleMessage): ConsoleMessageDispatcher {
|
||||
if ((message as any)[scope.dispatcherSymbol])
|
||||
return (message as any)[scope.dispatcherSymbol];
|
||||
|
|
@ -27,11 +27,10 @@ export class ConsoleMessageDispatcher extends Dispatcher implements ConsoleMessa
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, message: ConsoleMessage) {
|
||||
super(scope, message, 'consoleMessage');
|
||||
this._initialize({
|
||||
super(scope, message, 'consoleMessage', {
|
||||
type: message.type(),
|
||||
text: message.text(),
|
||||
args: message.args().map(a => ElementHandleDispatcher.from(this._scope, a)),
|
||||
args: message.args().map(a => ElementHandleDispatcher.from(scope, a)),
|
||||
location: message.location(),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@ export class ElementHandleDispatcher extends JSHandleDispatcher implements Eleme
|
|||
|
||||
|
||||
constructor(scope: DispatcherScope, elementHandle: ElementHandle) {
|
||||
super(scope, elementHandle, true);
|
||||
super(scope, elementHandle);
|
||||
this._elementHandle = elementHandle;
|
||||
this._initialize({ preview: elementHandle.toString(), frame: FrameDispatcher.from(scope, elementHandle._context.frame) });
|
||||
this._elementHandle = elementHandle;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
|
||||
import { Frame } from '../../frames';
|
||||
import * as types from '../../types';
|
||||
import { ElementHandleChannel, FrameChannel, JSHandleChannel, ResponseChannel } from '../channels';
|
||||
import { ElementHandleChannel, FrameChannel, JSHandleChannel, ResponseChannel, FrameInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { ElementHandleDispatcher, convertSelectOptionValues } from './elementHandlerDispatcher';
|
||||
import { JSHandleDispatcher } from './jsHandleDispatcher';
|
||||
import { ResponseDispatcher } from './networkDispatchers';
|
||||
|
||||
export class FrameDispatcher extends Dispatcher implements FrameChannel {
|
||||
export class FrameDispatcher extends Dispatcher<FrameInitializer> implements FrameChannel {
|
||||
private _frame: Frame;
|
||||
|
||||
static from(scope: DispatcherScope, frame: Frame): FrameDispatcher {
|
||||
|
|
@ -38,14 +38,12 @@ export class FrameDispatcher extends Dispatcher implements FrameChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, frame: Frame) {
|
||||
super(scope, frame, 'frame');
|
||||
this._frame = frame;
|
||||
const parentFrame = frame.parentFrame();
|
||||
this._initialize({
|
||||
super(scope, frame, 'frame', {
|
||||
url: frame.url(),
|
||||
name: frame.name(),
|
||||
parentFrame: FrameDispatcher.fromNullable(this._scope, parentFrame)
|
||||
parentFrame: FrameDispatcher.fromNullable(scope, frame.parentFrame())
|
||||
});
|
||||
this._frame = frame;
|
||||
}
|
||||
|
||||
async goto(params: { url: string, options: types.GotoOptions }): Promise<ResponseChannel | null> {
|
||||
|
|
|
|||
|
|
@ -15,17 +15,17 @@
|
|||
*/
|
||||
|
||||
import * as js from '../../javascript';
|
||||
import { JSHandleChannel } from '../channels';
|
||||
import { JSHandleChannel, JSHandleInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { convertArg } from './frameDispatcher';
|
||||
|
||||
export class JSHandleDispatcher extends Dispatcher implements JSHandleChannel {
|
||||
export class JSHandleDispatcher extends Dispatcher<JSHandleInitializer> implements JSHandleChannel {
|
||||
readonly _jsHandle: js.JSHandle<any>;
|
||||
|
||||
constructor(scope: DispatcherScope, jsHandle: js.JSHandle, omitInit?: boolean) {
|
||||
super(scope, jsHandle, jsHandle.asElement() ? 'elementHandle' : 'jsHandle');
|
||||
if (!omitInit)
|
||||
this._initialize({ preview: jsHandle.toString() });
|
||||
constructor(scope: DispatcherScope, jsHandle: js.JSHandle) {
|
||||
super(scope, jsHandle, jsHandle.asElement() ? 'elementHandle' : 'jsHandle', {
|
||||
preview: jsHandle.toString(),
|
||||
});
|
||||
this._jsHandle = jsHandle;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
import { Request, Response, Route } from '../../network';
|
||||
import * as types from '../../types';
|
||||
import { RequestChannel, ResponseChannel, RouteChannel } from '../channels';
|
||||
import { RequestChannel, ResponseChannel, RouteChannel, ResponseInitializer, RequestInitializer, RouteInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
|
||||
export class RequestDispatcher extends Dispatcher implements RequestChannel {
|
||||
export class RequestDispatcher extends Dispatcher<RequestInitializer> implements RequestChannel {
|
||||
private _request: Request;
|
||||
|
||||
static from(scope: DispatcherScope, request: Request): RequestDispatcher {
|
||||
|
|
@ -34,18 +34,15 @@ export class RequestDispatcher extends Dispatcher implements RequestChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, request: Request) {
|
||||
super(scope, request, 'request');
|
||||
this._initialize({
|
||||
super(scope, request, 'request', {
|
||||
frame: FrameDispatcher.from(scope, request.frame()),
|
||||
url: request.url(),
|
||||
resourceType: request.resourceType(),
|
||||
method: request.method(),
|
||||
postData: request.postData(),
|
||||
headers: request.headers(),
|
||||
isNavigationRequest: request.isNavigationRequest(),
|
||||
failure: request.failure(),
|
||||
frame: FrameDispatcher.from(this._scope, request.frame()),
|
||||
redirectedFrom: RequestDispatcher.fromNullable(this._scope, request.redirectedFrom()),
|
||||
redirectedTo: RequestDispatcher.fromNullable(this._scope, request.redirectedTo()),
|
||||
redirectedFrom: RequestDispatcher.fromNullable(scope, request.redirectedFrom()),
|
||||
});
|
||||
this._request = request;
|
||||
}
|
||||
|
|
@ -55,7 +52,7 @@ export class RequestDispatcher extends Dispatcher implements RequestChannel {
|
|||
}
|
||||
}
|
||||
|
||||
export class ResponseDispatcher extends Dispatcher implements ResponseChannel {
|
||||
export class ResponseDispatcher extends Dispatcher<ResponseInitializer> implements ResponseChannel {
|
||||
private _response: Response;
|
||||
|
||||
static from(scope: DispatcherScope, response: Response): ResponseDispatcher {
|
||||
|
|
@ -69,12 +66,9 @@ export class ResponseDispatcher extends Dispatcher implements ResponseChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, response: Response) {
|
||||
super(scope, response, 'response');
|
||||
this._initialize({
|
||||
frame: FrameDispatcher.from(this._scope, response.frame()),
|
||||
request: RequestDispatcher.from(this._scope, response.request())!,
|
||||
super(scope, response, 'response', {
|
||||
request: RequestDispatcher.from(scope, response.request())!,
|
||||
url: response.url(),
|
||||
ok: response.ok(),
|
||||
status: response.status(),
|
||||
statusText: response.statusText(),
|
||||
headers: response.headers(),
|
||||
|
|
@ -91,7 +85,7 @@ export class ResponseDispatcher extends Dispatcher implements ResponseChannel {
|
|||
}
|
||||
}
|
||||
|
||||
export class RouteDispatcher extends Dispatcher implements RouteChannel {
|
||||
export class RouteDispatcher extends Dispatcher<RouteInitializer> implements RouteChannel {
|
||||
private _route: Route;
|
||||
|
||||
static from(scope: DispatcherScope, route: Route): RouteDispatcher {
|
||||
|
|
@ -105,8 +99,9 @@ export class RouteDispatcher extends Dispatcher implements RouteChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, route: Route) {
|
||||
super(scope, route, 'route');
|
||||
this._initialize({ request: RequestDispatcher.from(this._scope, route.request()) });
|
||||
super(scope, route, 'route', {
|
||||
request: RequestDispatcher.from(scope, route.request())
|
||||
});
|
||||
this._route = route;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,16 +19,15 @@ import { Request } from '../../network';
|
|||
import { Frame } from '../../frames';
|
||||
import { Page } from '../../page';
|
||||
import * as types from '../../types';
|
||||
import { ElementHandleChannel, PageChannel, ResponseChannel, BindingCallChannel } from '../channels';
|
||||
import { ElementHandleChannel, PageChannel, ResponseChannel, BindingCallChannel, PageInitializer, BindingCallInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from '../dispatcher';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { RequestDispatcher, ResponseDispatcher, RouteDispatcher } from './networkDispatchers';
|
||||
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
|
||||
import { BrowserContext } from '../../browserContext';
|
||||
import { serializeError, parseError } from '../../helper';
|
||||
|
||||
export class PageDispatcher extends Dispatcher implements PageChannel {
|
||||
export class PageDispatcher extends Dispatcher<PageInitializer> implements PageChannel {
|
||||
private _page: Page;
|
||||
|
||||
static from(scope: DispatcherScope, page: Page): PageDispatcher {
|
||||
|
|
@ -44,11 +43,9 @@ export class PageDispatcher extends Dispatcher implements PageChannel {
|
|||
}
|
||||
|
||||
constructor(scope: DispatcherScope, page: Page) {
|
||||
super(scope, page, 'page');
|
||||
this._initialize({
|
||||
browserContext: BrowserContextDispatcher.from(scope, page._browserContext),
|
||||
super(scope, page, 'page', {
|
||||
mainFrame: FrameDispatcher.from(scope, page.mainFrame()),
|
||||
frames: page.frames().map(f => FrameDispatcher.from(this._scope, f)),
|
||||
viewportSize: page.viewportSize()
|
||||
});
|
||||
this._page = page;
|
||||
page.on(Events.Page.Close, () => this._dispatchEvent('close'));
|
||||
|
|
@ -196,18 +193,15 @@ export class PageDispatcher extends Dispatcher implements PageChannel {
|
|||
}
|
||||
|
||||
|
||||
export class BindingCallDispatcher extends Dispatcher implements BindingCallChannel {
|
||||
export class BindingCallDispatcher extends Dispatcher<BindingCallInitializer> implements BindingCallChannel {
|
||||
private _resolve: ((arg: any) => void) | undefined;
|
||||
private _reject: ((error: any) => void) | undefined;
|
||||
private _promise: Promise<any>;
|
||||
|
||||
constructor(scope: DispatcherScope, name: string, source: { context: BrowserContext, page: Page, frame: Frame }, args: any[]) {
|
||||
super(scope, {}, 'bindingCall');
|
||||
this._initialize({
|
||||
name,
|
||||
context: BrowserContextDispatcher.from(scope, source.context),
|
||||
page: PageDispatcher.from(scope, source.page),
|
||||
super(scope, {}, 'bindingCall', {
|
||||
frame: FrameDispatcher.from(scope, source.frame),
|
||||
name,
|
||||
args
|
||||
});
|
||||
this._promise = new Promise((resolve, reject) => {
|
||||
|
|
|
|||
13
test/test.js
13
test/test.js
|
|
@ -113,16 +113,15 @@ function collect(browserNames) {
|
|||
|
||||
for (const browserName of browserNames) {
|
||||
const browserType = playwright[browserName];
|
||||
let overridenBrowserType = browserType;
|
||||
|
||||
// Channel substitute
|
||||
if (process.env.PWCHANNEL) {
|
||||
BrowserTypeDispatcher.from(dispatcherScope, browserType);
|
||||
overridenBrowserType = connection.createRemoteObject('browserType', browserType.name());
|
||||
}
|
||||
|
||||
const browserTypeEnvironment = new Environment('BrowserType');
|
||||
browserTypeEnvironment.beforeAll(async state => {
|
||||
// Channel substitute
|
||||
let overridenBrowserType = browserType;
|
||||
if (process.env.PWCHANNEL) {
|
||||
BrowserTypeDispatcher.from(dispatcherScope, browserType);
|
||||
overridenBrowserType = await connection.waitForObjectWithKnownName(browserType.name());
|
||||
}
|
||||
state.browserType = overridenBrowserType;
|
||||
});
|
||||
browserTypeEnvironment.afterAll(async state => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue