mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore(rpc): explicitly create page dispatcher (#2799)
This commit is contained in:
parent
d484e04a08
commit
c15dc94f8e
@ -20,9 +20,6 @@ import * as types from '../types';
|
||||
export type Binary = string;
|
||||
|
||||
export interface Channel extends EventEmitter {
|
||||
_type: string;
|
||||
_guid: string;
|
||||
_object: any;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user