chore(rpc): explicitly create page dispatcher (#2799)

This commit is contained in:
Pavel Feldman 2020-07-01 18:36:09 -07:00 committed by GitHub
parent d484e04a08
commit c15dc94f8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 36 additions and 60 deletions

View File

@ -20,9 +20,6 @@ import * as types from '../types';
export type Binary = string;
export interface Channel extends EventEmitter {
_type: string;
_guid: string;
_object: any;
}

View File

@ -29,7 +29,7 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
static from(browser: BrowserChannel): Browser {
return browser._object;
return (browser as any)._object;
}
static fromNullable(browser: BrowserChannel | null): Browser | null {

View File

@ -37,7 +37,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
_ownerPage: Page | undefined;
static from(context: BrowserContextChannel): BrowserContext {
return context._object;
return (context as any)._object;
}
static fromNullable(context: BrowserContextChannel | null): BrowserContext | null {

View File

@ -21,8 +21,8 @@ import { ChannelOwner } from './channelOwner';
import { Events } from '../../events';
export class BrowserServer extends ChannelOwner<BrowserServerChannel, BrowserServerInitializer> {
static from(request: BrowserServerChannel): BrowserServer {
return request._object;
static from(server: BrowserServerChannel): BrowserServer {
return (server as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: BrowserServerInitializer) {

View File

@ -22,9 +22,11 @@ export abstract class ChannelOwner<T extends Channel, Initializer> extends Event
readonly _channel: T;
readonly _initializer: Initializer;
readonly _scope: ConnectionScope;
readonly guid: string;
constructor(scope: ConnectionScope, guid: string, initializer: Initializer, isScope?: boolean) {
super();
this.guid = guid;
this._scope = isScope ? scope.createChild(guid) : scope;
const base = new EventEmitter();
this._channel = new Proxy(base, {
@ -46,8 +48,7 @@ export abstract class ChannelOwner<T extends Channel, Initializer> extends Event
return (params: any) => scope.sendMessageToServer({ guid, method: String(prop), params });
},
});
this._channel._object = this;
this._channel._guid = guid;
(this._channel as any)._object = this;
this._initializer = initializer;
}
}

View File

@ -99,11 +99,8 @@ export class Connection {
return payload;
if (Array.isArray(payload))
return payload.map(p => this._replaceChannelsWithGuids(p));
if (payload._guid)
return { guid: payload._guid };
// TODO: send base64
if (payload instanceof Buffer)
return payload;
if (payload._object instanceof ChannelOwner)
return { guid: payload._object.guid };
if (typeof payload === 'object') {
const result: any = {};
for (const key of Object.keys(payload))
@ -120,9 +117,6 @@ export class Connection {
return payload.map(p => this._replaceGuidsWithChannels(p));
if (payload.guid && this._objects.has(payload.guid))
return this._objects.get(payload.guid)!._channel;
// TODO: send base64
if (payload instanceof Buffer)
return payload;
if (typeof payload === 'object') {
const result: any = {};
for (const key of Object.keys(payload))

View File

@ -22,8 +22,8 @@ import { ChannelOwner } from './channelOwner';
import { ConnectionScope } from './connection';
export class ConsoleMessage extends ChannelOwner<ConsoleMessageChannel, ConsoleMessageInitializer> {
static from(request: ConsoleMessageChannel): ConsoleMessage {
return request._object;
static from(message: ConsoleMessageChannel): ConsoleMessage {
return (message as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: ConsoleMessageInitializer) {

View File

@ -19,8 +19,8 @@ import { ConnectionScope } from './connection';
import { ChannelOwner } from './channelOwner';
export class Dialog extends ChannelOwner<DialogChannel, DialogInitializer> {
static from(request: DialogChannel): Dialog {
return request._object;
static from(dialog: DialogChannel): Dialog {
return (dialog as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: DialogInitializer) {

View File

@ -21,8 +21,8 @@ import { ChannelOwner } from './channelOwner';
import { Readable } from 'stream';
export class Download extends ChannelOwner<DownloadChannel, DownloadInitializer> {
static from(request: DownloadChannel): Download {
return request._object;
static from(download: DownloadChannel): Download {
return (download as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: DownloadInitializer) {

View File

@ -24,7 +24,7 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> {
readonly _elementChannel: ElementHandleChannel;
static from(handle: ElementHandleChannel): ElementHandle {
return handle._object;
return (handle as any)._object;
}
static fromNullable(handle: ElementHandleChannel | null): ElementHandle | null {

View File

@ -43,7 +43,7 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
_page: Page | undefined;
static from(frame: FrameChannel): Frame {
return frame._object;
return (frame as any)._object;
}
static fromNullable(frame: FrameChannel | null): Frame | null {

View File

@ -40,7 +40,7 @@ export class JSHandle<T = any> extends ChannelOwner<JSHandleChannel, JSHandleIni
private _preview: string;
static from(handle: JSHandleChannel): JSHandle {
return handle._object;
return (handle as any)._object;
}
static fromNullable(handle: JSHandleChannel | null): JSHandle | null {
@ -110,7 +110,7 @@ export function serializeArgument(arg: any): any {
};
const value = serializeAsCallArgument(arg, value => {
if (value instanceof ChannelOwner)
return { h: pushHandle(value._channel._guid) };
return { h: pushHandle(value.guid) };
return { fallThrough: value };
});
return { value, guids };

View File

@ -51,7 +51,7 @@ export class Request extends ChannelOwner<RequestChannel, RequestInitializer> {
_failureText: string | null = null;
static from(request: RequestChannel): Request {
return request._object;
return (request as any)._object;
}
static fromNullable(request: RequestChannel | null): Request | null {
@ -135,7 +135,7 @@ export class Request extends ChannelOwner<RequestChannel, RequestInitializer> {
export class Route extends ChannelOwner<RouteChannel, RouteInitializer> {
static from(route: RouteChannel): Route {
return route._object;
return (route as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: RouteInitializer) {
@ -169,7 +169,7 @@ export type RouteHandler = (route: Route, request: Request) => void;
export class Response extends ChannelOwner<ResponseChannel, ResponseInitializer> {
static from(response: ResponseChannel): Response {
return response._object;
return (response as any)._object;
}
static fromNullable(response: ResponseChannel | null): Response | null {

View File

@ -21,7 +21,7 @@ import { Events } from '../../events';
import { assert, assertMaxArguments, helper, Listener } from '../../helper';
import { TimeoutSettings } from '../../timeoutSettings';
import * as types from '../../types';
import { BindingCallChannel, BindingCallInitializer, Channel, PageChannel, PageInitializer } from '../channels';
import { BindingCallChannel, BindingCallInitializer, PageChannel, PageInitializer } from '../channels';
import { ConnectionScope } from './connection';
import { parseError, serializeError } from '../serializers';
import { Accessibility } from './accessibility';
@ -60,7 +60,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
_isPageCall = false;
static from(page: PageChannel): Page {
return page._object;
return (page as any)._object;
}
static fromNullable(page: PageChannel | null): Page | null {
@ -502,7 +502,7 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
export class BindingCall extends ChannelOwner<BindingCallChannel, BindingCallInitializer> {
static from(channel: BindingCallChannel): BindingCall {
return channel._object;
return (channel as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: BindingCallInitializer) {
@ -537,11 +537,9 @@ export async function waitForEvent(emitter: EventEmitter, event: string, options
let callback: (a: any) => void;
const result = new Promise(f => callback = f);
const listener = helper.addEventListener(emitter, event, param => {
// TODO: do not detect channel by guid.
const object = param && param._guid ? (param as Channel)._object : param;
if (predicate && !predicate(object))
if (predicate && !predicate(param))
return;
callback(object);
callback(param);
helper.removeEventListeners([listener]);
});
if (timeout === 0)

View File

@ -26,7 +26,7 @@ export class Worker extends ChannelOwner<WorkerChannel, WorkerInitializer> {
_page: Page | undefined;
static from(worker: WorkerChannel): Worker {
return worker._object;
return (worker as any)._object;
}
constructor(scope: ConnectionScope, guid: string, initializer: WorkerInitializer) {

View File

@ -28,10 +28,10 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, Browser
constructor(scope: DispatcherScope, context: BrowserContextBase) {
super(scope, context, 'context', {
pages: context.pages().map(p => PageDispatcher.from(scope, p))
pages: context.pages().map(p => new PageDispatcher(scope, p))
}, true);
this._context = context;
context.on(Events.BrowserContext.Page, page => this._dispatchEvent('page', PageDispatcher.from(this._scope, page)));
context.on(Events.BrowserContext.Page, page => this._dispatchEvent('page', new PageDispatcher(this._scope, page)));
context.on(Events.BrowserContext.Close, () => {
this._dispatchEvent('close');
this._scope.dispose();

View File

@ -15,7 +15,7 @@
*/
import { EventEmitter } from 'events';
import { helper, debugAssert } from '../../helper';
import { helper, debugAssert, assert } from '../../helper';
import { Channel } from '../channels';
import { serializeError } from '../serializers';
@ -77,6 +77,7 @@ export class DispatcherScope {
}
bind(guid: string, arg: Dispatcher<any, any>) {
assert(!this._dispatchers.has(guid));
this._dispatchers.set(guid, arg);
this._connection._dispatchers.set(guid, arg);
}
@ -161,9 +162,6 @@ export class DispatcherConnection {
return { guid: payload._guid };
if (Array.isArray(payload))
return payload.map(p => this._replaceDispatchersWithGuids(p));
// TODO: send base64
if (payload instanceof Buffer)
return payload;
if (typeof payload === 'object') {
const result: any = {};
for (const key of Object.keys(payload))
@ -180,9 +178,6 @@ export class DispatcherConnection {
return payload.map(p => this._replaceGuidsWithDispatchers(p));
if (payload.guid && this._dispatchers.has(payload.guid))
return this._dispatchers.get(payload.guid);
// TODO: send base64
if (payload instanceof Buffer)
return payload;
if (typeof payload === 'object') {
const result: any = {};
for (const key of Object.keys(payload))

View File

@ -21,7 +21,7 @@ import { Request } from '../../network';
import { Page, Worker } from '../../page';
import * as types from '../../types';
import { BindingCallChannel, BindingCallInitializer, ElementHandleChannel, PageChannel, PageInitializer, ResponseChannel, WorkerInitializer, WorkerChannel, JSHandleChannel, Binary } from '../channels';
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
import { Dispatcher, DispatcherScope, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
import { parseError, serializeError } from '../serializers';
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
import { DialogDispatcher } from './dialogDispatcher';
@ -35,16 +35,7 @@ import { FileChooser } from '../../fileChooser';
export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements PageChannel {
private _page: Page;
static from(scope: DispatcherScope, page: Page): PageDispatcher {
const result = existingDispatcher<PageDispatcher>(page);
return result || new PageDispatcher(scope, page);
}
static fromNullable(scope: DispatcherScope, request: Page | null): PageDispatcher | null {
return request ? PageDispatcher.from(scope, request) : null;
}
private constructor(scope: DispatcherScope, page: Page) {
constructor(scope: DispatcherScope, page: Page) {
super(scope, page, 'page', {
mainFrame: FrameDispatcher.from(scope, page.mainFrame()),
viewportSize: page.viewportSize()
@ -65,7 +56,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
page.on(Events.Page.FrameNavigated, frame => this._onFrameNavigated(frame));
page.on(Events.Page.Load, () => this._dispatchEvent('load'));
page.on(Events.Page.PageError, error => this._dispatchEvent('pageError', { error: serializeError(error) }));
page.on(Events.Page.Popup, page => this._dispatchEvent('popup', PageDispatcher.from(this._scope, page)));
page.on(Events.Page.Popup, page => this._dispatchEvent('popup', lookupDispatcher<PageDispatcher>(page)));
page.on(Events.Page.Request, request => this._dispatchEvent('request', RequestDispatcher.from(this._scope, request)));
page.on(Events.Page.RequestFailed, (request: Request) => this._dispatchEvent('requestFailed', {
request: RequestDispatcher.from(this._scope, request),
@ -188,7 +179,7 @@ export class PageDispatcher extends Dispatcher<Page, PageInitializer> implements
async accessibilitySnapshot(params: { options: { interestingOnly?: boolean, root?: ElementHandleChannel } }): Promise<types.SerializedAXNode | null> {
return await this._page.accessibility.snapshot({
interestingOnly: params.options.interestingOnly,
root: params.options.root ? params.options.root._object : undefined
root: params.options.root ? (params.options.root as ElementHandleDispatcher)._elementHandle : undefined
});
}