mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: make parent scope explicit (#16819)
This commit is contained in:
parent
de2eb304d0
commit
a07a4a25a2
@ -20,7 +20,7 @@ import fs from 'fs';
|
||||
import * as playwright from '../..';
|
||||
import type { BrowserType } from '../client/browserType';
|
||||
import type { LaunchServerOptions } from '../client/types';
|
||||
import { createPlaywright, DispatcherConnection, Root, PlaywrightDispatcher } from '../server';
|
||||
import { createPlaywright, DispatcherConnection, RootDispatcher, PlaywrightDispatcher } from '../server';
|
||||
import type { Playwright } from '../server';
|
||||
import { IpcTransport, PipeTransport } from '../protocol/transport';
|
||||
import { PlaywrightServer } from '../remote/playwrightServer';
|
||||
@ -38,7 +38,7 @@ export function printApiJson() {
|
||||
|
||||
export function runDriver() {
|
||||
const dispatcherConnection = new DispatcherConnection();
|
||||
new Root(dispatcherConnection, async (rootScope, { sdkLanguage }) => {
|
||||
new RootDispatcher(dispatcherConnection, async (rootScope, { sdkLanguage }) => {
|
||||
const playwright = createPlaywright(sdkLanguage);
|
||||
return new PlaywrightDispatcher(rootScope, playwright);
|
||||
});
|
||||
|
||||
@ -79,7 +79,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||
this._channel.on('bindingCall', ({ binding }) => this._onBinding(BindingCall.from(binding)));
|
||||
this._channel.on('close', () => this._onClose());
|
||||
this._channel.on('page', ({ page }) => this._onPage(Page.from(page)));
|
||||
this._channel.on('route', ({ route, request }) => this._onRoute(network.Route.from(route), network.Request.from(request)));
|
||||
this._channel.on('route', ({ route }) => this._onRoute(network.Route.from(route)));
|
||||
this._channel.on('backgroundPage', ({ page }) => {
|
||||
const backgroundPage = Page.from(page);
|
||||
this._backgroundPages.add(backgroundPage);
|
||||
@ -147,14 +147,14 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
||||
response._finishedPromise.resolve();
|
||||
}
|
||||
|
||||
async _onRoute(route: network.Route, request: network.Request) {
|
||||
async _onRoute(route: network.Route) {
|
||||
const routeHandlers = this._routes.slice();
|
||||
for (const routeHandler of routeHandlers) {
|
||||
if (!routeHandler.matches(request.url()))
|
||||
if (!routeHandler.matches(route.request().url()))
|
||||
continue;
|
||||
if (routeHandler.willExpire())
|
||||
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
||||
const handled = await routeHandler.handle(route, request);
|
||||
const handled = await routeHandler.handle(route);
|
||||
if (!this._routes.length)
|
||||
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
||||
if (handled)
|
||||
|
||||
@ -604,14 +604,14 @@ export class RouteHandler {
|
||||
return urlMatches(this._baseURL, requestURL, this.url);
|
||||
}
|
||||
|
||||
public async handle(route: Route, request: Request): Promise<boolean> {
|
||||
public async handle(route: Route): Promise<boolean> {
|
||||
++this.handledCount;
|
||||
const handledPromise = route._startHandling();
|
||||
// Extract handler into a variable to avoid [RouteHandler.handler] in the stack.
|
||||
const handler = this.handler;
|
||||
const [handled] = await Promise.all([
|
||||
handledPromise,
|
||||
handler(route, request),
|
||||
handler(route, route.request()),
|
||||
]);
|
||||
return handled;
|
||||
}
|
||||
|
||||
@ -47,7 +47,8 @@ import { Keyboard, Mouse, Touchscreen } from './input';
|
||||
import { assertMaxArguments, JSHandle, parseResult, serializeArgument } from './jsHandle';
|
||||
import type { FrameLocator, Locator, LocatorOptions } from './locator';
|
||||
import type { RouteHandlerCallback } from './network';
|
||||
import { Request, Response, Route, RouteHandler, validateHeaders, WebSocket } from './network';
|
||||
import { Response, Route, RouteHandler, validateHeaders, WebSocket } from './network';
|
||||
import type { Request } from './network';
|
||||
import type { FilePayload, Headers, LifecycleEvent, SelectOption, SelectOptionOptions, Size, URLMatch, WaitForEventOptions, WaitForFunctionOptions } from './types';
|
||||
import { Video } from './video';
|
||||
import { Waiter } from './waiter';
|
||||
@ -145,7 +146,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
this._channel.on('frameAttached', ({ frame }) => this._onFrameAttached(Frame.from(frame)));
|
||||
this._channel.on('frameDetached', ({ frame }) => this._onFrameDetached(Frame.from(frame)));
|
||||
this._channel.on('pageError', ({ error }) => this.emit(Events.Page.PageError, parseError(error)));
|
||||
this._channel.on('route', ({ route, request }) => this._onRoute(Route.from(route), Request.from(request)));
|
||||
this._channel.on('route', ({ route }) => this._onRoute(Route.from(route)));
|
||||
this._channel.on('video', ({ artifact }) => {
|
||||
const artifactObject = Artifact.from(artifact);
|
||||
this._forceVideo()._artifactReady(artifactObject);
|
||||
@ -177,20 +178,20 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
||||
this.emit(Events.Page.FrameDetached, frame);
|
||||
}
|
||||
|
||||
private async _onRoute(route: Route, request: Request) {
|
||||
private async _onRoute(route: Route) {
|
||||
const routeHandlers = this._routes.slice();
|
||||
for (const routeHandler of routeHandlers) {
|
||||
if (!routeHandler.matches(request.url()))
|
||||
if (!routeHandler.matches(route.request().url()))
|
||||
continue;
|
||||
if (routeHandler.willExpire())
|
||||
this._routes.splice(this._routes.indexOf(routeHandler), 1);
|
||||
const handled = await routeHandler.handle(route, request);
|
||||
const handled = await routeHandler.handle(route);
|
||||
if (!this._routes.length)
|
||||
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
|
||||
if (handled)
|
||||
return;
|
||||
}
|
||||
await this._browserContext._onRoute(route, request);
|
||||
await this._browserContext._onRoute(route);
|
||||
}
|
||||
|
||||
async _onBinding(bindingCall: BindingCall) {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import type { Playwright as PlaywrightAPI } from './client/playwright';
|
||||
import { createPlaywright, DispatcherConnection, Root, PlaywrightDispatcher } from './server';
|
||||
import { createPlaywright, DispatcherConnection, RootDispatcher, PlaywrightDispatcher } from './server';
|
||||
import { Connection } from './client/connection';
|
||||
import { BrowserServerLauncherImpl } from './browserServerImpl';
|
||||
|
||||
@ -29,7 +29,7 @@ export function createInProcessPlaywright(): PlaywrightAPI {
|
||||
dispatcherConnection.onmessage = message => clientConnection.dispatch(message);
|
||||
clientConnection.onmessage = message => dispatcherConnection.dispatch(message);
|
||||
|
||||
const rootScope = new Root(dispatcherConnection);
|
||||
const rootScope = new RootDispatcher(dispatcherConnection);
|
||||
|
||||
// Initialize Playwright channel.
|
||||
new PlaywrightDispatcher(rootScope, playwright);
|
||||
|
||||
@ -1258,7 +1258,6 @@ export type BrowserContextPageEvent = {
|
||||
};
|
||||
export type BrowserContextRouteEvent = {
|
||||
route: RouteChannel,
|
||||
request: RequestChannel,
|
||||
};
|
||||
export type BrowserContextVideoEvent = {
|
||||
artifact: ArtifactChannel,
|
||||
@ -1586,7 +1585,6 @@ export type PagePageErrorEvent = {
|
||||
};
|
||||
export type PageRouteEvent = {
|
||||
route: RouteChannel,
|
||||
request: RequestChannel,
|
||||
};
|
||||
export type PageVideoEvent = {
|
||||
artifact: ArtifactChannel,
|
||||
|
||||
@ -992,7 +992,6 @@ BrowserContext:
|
||||
route:
|
||||
parameters:
|
||||
route: Route
|
||||
request: Request
|
||||
|
||||
video:
|
||||
parameters:
|
||||
@ -1422,7 +1421,6 @@ Page:
|
||||
route:
|
||||
parameters:
|
||||
route: Route
|
||||
request: Request
|
||||
|
||||
video:
|
||||
parameters:
|
||||
|
||||
@ -656,7 +656,6 @@ scheme.BrowserContextPageEvent = tObject({
|
||||
});
|
||||
scheme.BrowserContextRouteEvent = tObject({
|
||||
route: tChannel(['Route']),
|
||||
request: tChannel(['Request']),
|
||||
});
|
||||
scheme.BrowserContextVideoEvent = tObject({
|
||||
artifact: tChannel(['Artifact']),
|
||||
@ -842,7 +841,6 @@ scheme.PagePageErrorEvent = tObject({
|
||||
});
|
||||
scheme.PageRouteEvent = tObject({
|
||||
route: tChannel(['Route']),
|
||||
request: tChannel(['Request']),
|
||||
});
|
||||
scheme.PageVideoEvent = tObject({
|
||||
artifact: tChannel(['Artifact']),
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import type { WebSocket } from '../utilsBundle';
|
||||
import type { Playwright, DispatcherScope } from '../server';
|
||||
import { createPlaywright, DispatcherConnection, Root, PlaywrightDispatcher } from '../server';
|
||||
import type { Playwright } from '../server';
|
||||
import { createPlaywright, DispatcherConnection, RootDispatcher, PlaywrightDispatcher } from '../server';
|
||||
import { Browser } from '../server/browser';
|
||||
import { serverSideCallMetadata } from '../server/instrumentation';
|
||||
import { gracefullyCloseAll } from '../utils/processLauncher';
|
||||
@ -45,7 +45,7 @@ export class PlaywrightConnection {
|
||||
private _disconnected = false;
|
||||
private _preLaunched: PreLaunched;
|
||||
private _options: Options;
|
||||
private _root: Root;
|
||||
private _root: RootDispatcher;
|
||||
|
||||
constructor(lock: Promise<void>, mode: Mode, ws: WebSocket, options: Options, preLaunched: PreLaunched, log: (m: string) => void, onClose: () => void) {
|
||||
this._ws = ws;
|
||||
@ -72,7 +72,7 @@ export class PlaywrightConnection {
|
||||
ws.on('close', () => this._onDisconnect());
|
||||
ws.on('error', error => this._onDisconnect(error));
|
||||
|
||||
this._root = new Root(this._dispatcherConnection, async scope => {
|
||||
this._root = new RootDispatcher(this._dispatcherConnection, async scope => {
|
||||
if (mode === 'reuse-browser')
|
||||
return await this._initReuseBrowsersMode(scope);
|
||||
if (mode === 'use-pre-launched-browser')
|
||||
@ -83,7 +83,7 @@ export class PlaywrightConnection {
|
||||
});
|
||||
}
|
||||
|
||||
private async _initPlaywrightConnectMode(scope: DispatcherScope) {
|
||||
private async _initPlaywrightConnectMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged playwright.connect mode`);
|
||||
const playwright = createPlaywright('javascript');
|
||||
// Close all launched browsers on disconnect.
|
||||
@ -93,7 +93,7 @@ export class PlaywrightConnection {
|
||||
return new PlaywrightDispatcher(scope, playwright, socksProxy);
|
||||
}
|
||||
|
||||
private async _initLaunchBrowserMode(scope: DispatcherScope) {
|
||||
private async _initLaunchBrowserMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged launch mode for "${this._options.browserName}"`);
|
||||
|
||||
const playwright = createPlaywright('javascript');
|
||||
@ -112,7 +112,7 @@ export class PlaywrightConnection {
|
||||
return new PlaywrightDispatcher(scope, playwright, socksProxy, browser);
|
||||
}
|
||||
|
||||
private async _initPreLaunchedBrowserMode(scope: DispatcherScope) {
|
||||
private async _initPreLaunchedBrowserMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged pre-launched mode`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
const browser = this._preLaunched.browser!;
|
||||
@ -130,7 +130,7 @@ export class PlaywrightConnection {
|
||||
return playwrightDispatcher;
|
||||
}
|
||||
|
||||
private async _initReuseBrowsersMode(scope: DispatcherScope) {
|
||||
private async _initReuseBrowsersMode(scope: RootDispatcher) {
|
||||
this._debugLog(`engaged reuse browsers mode for ${this._options.browserName}`);
|
||||
const playwright = this._preLaunched.playwright!;
|
||||
const requestedOptions = launchOptionsHash(this._options.launchOptions);
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher, existingDispatcher } from './dispatcher';
|
||||
import type { Android, SocketBackend } from '../android/android';
|
||||
import { AndroidDevice } from '../android/android';
|
||||
@ -22,9 +22,9 @@ import type * as channels from '../../protocol/channels';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
|
||||
export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidChannel> implements channels.AndroidChannel {
|
||||
export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidChannel, RootDispatcher, AndroidDispatcher> implements channels.AndroidChannel {
|
||||
_type_Android = true;
|
||||
constructor(scope: DispatcherScope, android: Android) {
|
||||
constructor(scope: RootDispatcher, android: Android) {
|
||||
super(scope, android, 'Android', {}, true);
|
||||
}
|
||||
|
||||
@ -40,16 +40,16 @@ export class AndroidDispatcher extends Dispatcher<Android, channels.AndroidChann
|
||||
}
|
||||
}
|
||||
|
||||
export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.AndroidDeviceChannel> implements channels.AndroidDeviceChannel {
|
||||
export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.AndroidDeviceChannel, AndroidDispatcher, AndroidDeviceDispatcher> implements channels.AndroidDeviceChannel {
|
||||
_type_EventTarget = true;
|
||||
_type_AndroidDevice = true;
|
||||
|
||||
static from(scope: DispatcherScope, device: AndroidDevice): AndroidDeviceDispatcher {
|
||||
static from(scope: AndroidDispatcher, device: AndroidDevice): AndroidDeviceDispatcher {
|
||||
const result = existingDispatcher<AndroidDeviceDispatcher>(device);
|
||||
return result || new AndroidDeviceDispatcher(scope, device);
|
||||
}
|
||||
|
||||
constructor(scope: DispatcherScope, device: AndroidDevice) {
|
||||
constructor(scope: AndroidDispatcher, device: AndroidDevice) {
|
||||
super(scope, device, 'AndroidDevice', {
|
||||
model: device.model,
|
||||
serial: device.serial,
|
||||
@ -174,10 +174,10 @@ export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.
|
||||
}
|
||||
}
|
||||
|
||||
export class AndroidSocketDispatcher extends Dispatcher<SocketBackend, channels.AndroidSocketChannel> implements channels.AndroidSocketChannel {
|
||||
export class AndroidSocketDispatcher extends Dispatcher<SocketBackend, channels.AndroidSocketChannel, AndroidDeviceDispatcher, AndroidSocketDispatcher> implements channels.AndroidSocketChannel {
|
||||
_type_AndroidSocket = true;
|
||||
|
||||
constructor(scope: DispatcherScope, socket: SocketBackend) {
|
||||
constructor(scope: AndroidDeviceDispatcher, socket: SocketBackend) {
|
||||
super(scope, socket, 'AndroidSocket', {}, true);
|
||||
this.addObjectListener('data', (data: Buffer) => this._dispatchEvent('data', { data }));
|
||||
this.addObjectListener('close', () => {
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { StreamDispatcher } from './streamDispatcher';
|
||||
import fs from 'fs';
|
||||
import { mkdirIfNeeded } from '../../utils/fileUtils';
|
||||
import type { Artifact } from '../artifact';
|
||||
|
||||
export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactChannel> implements channels.ArtifactChannel {
|
||||
export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactChannel, DispatcherScope> implements channels.ArtifactChannel {
|
||||
_type_Artifact = true;
|
||||
constructor(scope: DispatcherScope, artifact: Artifact) {
|
||||
super(scope, artifact, 'Artifact', {
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher, lookupDispatcher } from './dispatcher';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { PageDispatcher, BindingCallDispatcher, WorkerDispatcher } from './pageDispatcher';
|
||||
import type { FrameDispatcher } from './frameDispatcher';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
@ -34,15 +34,15 @@ import * as path from 'path';
|
||||
import { createGuid } from '../../utils';
|
||||
import { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel> implements channels.BrowserContextChannel {
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope, BrowserContextDispatcher> implements channels.BrowserContextChannel {
|
||||
_type_EventTarget = true;
|
||||
_type_BrowserContext = true;
|
||||
private _context: BrowserContext;
|
||||
|
||||
constructor(parentScope: DispatcherScope, context: BrowserContext) {
|
||||
// We will reparent these to the context below.
|
||||
const requestContext = APIRequestContextDispatcher.from(parentScope, context.fetchRequest);
|
||||
const tracing = TracingDispatcher.from(parentScope, context.tracing);
|
||||
const requestContext = APIRequestContextDispatcher.from(parentScope as BrowserContextDispatcher, context.fetchRequest);
|
||||
const tracing = TracingDispatcher.from(parentScope as BrowserContextDispatcher, context.tracing);
|
||||
|
||||
super(parentScope, context, 'BrowserContext', {
|
||||
isChromium: context._browser.options.isChromium,
|
||||
@ -70,8 +70,10 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
||||
}
|
||||
|
||||
for (const page of context.pages())
|
||||
this._dispatchEvent('page', { page: new PageDispatcher(this._scope, page) });
|
||||
this.addObjectListener(BrowserContext.Events.Page, page => this._dispatchEvent('page', { page: new PageDispatcher(this._scope, page) }));
|
||||
this._dispatchEvent('page', { page: PageDispatcher.from(this._scope, page) });
|
||||
this.addObjectListener(BrowserContext.Events.Page, page => {
|
||||
this._dispatchEvent('page', { page: PageDispatcher.from(this._scope, page) });
|
||||
});
|
||||
this.addObjectListener(BrowserContext.Events.Close, () => {
|
||||
this._dispatchEvent('close');
|
||||
this._dispose();
|
||||
@ -79,8 +81,8 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
||||
|
||||
if (context._browser.options.name === 'chromium') {
|
||||
for (const page of (context as CRBrowserContext).backgroundPages())
|
||||
this._dispatchEvent('backgroundPage', { page: new PageDispatcher(this._scope, page) });
|
||||
this.addObjectListener(CRBrowserContext.CREvents.BackgroundPage, page => this._dispatchEvent('backgroundPage', { page: new PageDispatcher(this._scope, page) }));
|
||||
this._dispatchEvent('backgroundPage', { page: PageDispatcher.from(this._scope, page) });
|
||||
this.addObjectListener(CRBrowserContext.CREvents.BackgroundPage, page => this._dispatchEvent('backgroundPage', { page: PageDispatcher.from(this._scope, page) }));
|
||||
for (const serviceWorker of (context as CRBrowserContext).serviceWorkers())
|
||||
this._dispatchEvent('serviceWorker', { worker: new WorkerDispatcher(this._scope, serviceWorker) });
|
||||
this.addObjectListener(CRBrowserContext.CREvents.ServiceWorker, serviceWorker => this._dispatchEvent('serviceWorker', { worker: new WorkerDispatcher(this._scope, serviceWorker) }));
|
||||
@ -128,7 +130,8 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
||||
|
||||
async exposeBinding(params: channels.BrowserContextExposeBindingParams): Promise<void> {
|
||||
await this._context.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
|
||||
const binding = new BindingCallDispatcher(this._scope, params.name, !!params.needsHandle, source, args);
|
||||
const pageDispatcher = PageDispatcher.from(this._scope, source.page);
|
||||
const binding = new BindingCallDispatcher(pageDispatcher, params.name, !!params.needsHandle, source, args);
|
||||
this._dispatchEvent('bindingCall', { binding });
|
||||
return binding.promise();
|
||||
});
|
||||
@ -184,7 +187,7 @@ export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channel
|
||||
return;
|
||||
}
|
||||
await this._context.setRequestInterceptor((route, request) => {
|
||||
this._dispatchEvent('route', { route: RouteDispatcher.from(this._scope, route), request: RequestDispatcher.from(this._scope, request) });
|
||||
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this._scope, request), route) });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ import type * as channels from '../../protocol/channels';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import { CDPSessionDispatcher } from './cdpSessionDispatcher';
|
||||
import { existingDispatcher } from './dispatcher';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { CRBrowser } from '../chromium/crBrowser';
|
||||
import type { PageDispatcher } from './pageDispatcher';
|
||||
@ -27,11 +27,12 @@ import type { CallMetadata } from '../instrumentation';
|
||||
import { serverSideCallMetadata } from '../instrumentation';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { Selectors } from '../selectors';
|
||||
import type { BrowserTypeDispatcher } from './browserTypeDispatcher';
|
||||
|
||||
export class BrowserDispatcher extends Dispatcher<Browser, channels.BrowserChannel> implements channels.BrowserChannel {
|
||||
export class BrowserDispatcher extends Dispatcher<Browser, channels.BrowserChannel, BrowserTypeDispatcher, BrowserDispatcher> implements channels.BrowserChannel {
|
||||
_type_Browser = true;
|
||||
|
||||
constructor(scope: DispatcherScope, browser: Browser) {
|
||||
constructor(scope: BrowserTypeDispatcher, browser: Browser) {
|
||||
super(scope, browser, 'Browser', { version: browser.version(), name: browser.options.name }, true);
|
||||
this.addObjectListener(Browser.Events.Disconnected, () => this._didClose());
|
||||
}
|
||||
@ -81,12 +82,12 @@ export class BrowserDispatcher extends Dispatcher<Browser, channels.BrowserChann
|
||||
}
|
||||
|
||||
// This class implements multiplexing browser dispatchers over a single Browser instance.
|
||||
export class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.BrowserChannel> implements channels.BrowserChannel {
|
||||
export class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.BrowserChannel, RootDispatcher, BrowserDispatcher> implements channels.BrowserChannel {
|
||||
_type_Browser = true;
|
||||
private _contexts = new Set<BrowserContext>();
|
||||
readonly selectors: Selectors;
|
||||
|
||||
constructor(scope: DispatcherScope, browser: Browser) {
|
||||
constructor(scope: RootDispatcher, browser: Browser) {
|
||||
super(scope, browser, 'Browser', { version: browser.version(), name: browser.options.name }, true);
|
||||
// When we have a remotely-connected browser, each client gets a fresh Selector instance,
|
||||
// so that two clients do not interfere between each other.
|
||||
@ -141,7 +142,7 @@ export class ConnectedBrowserDispatcher extends Dispatcher<Browser, channels.Bro
|
||||
}
|
||||
}
|
||||
|
||||
async function newContextForReuse(browser: Browser, scope: DispatcherScope, params: channels.BrowserNewContextForReuseParams, selectors: Selectors | null, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> {
|
||||
async function newContextForReuse(browser: Browser, scope: BrowserDispatcher, params: channels.BrowserNewContextForReuseParams, selectors: Selectors | null, metadata: CallMetadata): Promise<channels.BrowserNewContextForReuseResult> {
|
||||
const { context, needsReset } = await browser.newContextForReuse(params, metadata);
|
||||
if (needsReset) {
|
||||
const oldContextDispatcher = existingDispatcher<BrowserContextDispatcher>(context);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
import type { BrowserType } from '../browserType';
|
||||
import { BrowserDispatcher } from './browserDispatcher';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
@ -29,9 +29,9 @@ import { ProgressController } from '../progress';
|
||||
import { WebSocketTransport } from '../transport';
|
||||
import { findValidator, ValidationError, type ValidatorContext } from '../../protocol/validator';
|
||||
|
||||
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.BrowserTypeChannel> implements channels.BrowserTypeChannel {
|
||||
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.BrowserTypeChannel, RootDispatcher, BrowserTypeDispatcher> implements channels.BrowserTypeChannel {
|
||||
_type_BrowserType = true;
|
||||
constructor(scope: DispatcherScope, browserType: BrowserType) {
|
||||
constructor(scope: RootDispatcher, browserType: BrowserType) {
|
||||
super(scope, browserType, 'BrowserType', {
|
||||
executablePath: browserType.executablePath(),
|
||||
name: browserType.name()
|
||||
@ -53,7 +53,7 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.Brow
|
||||
const browserDispatcher = new BrowserDispatcher(this._scope, browser);
|
||||
return {
|
||||
browser: browserDispatcher,
|
||||
defaultContext: browser._defaultContext ? new BrowserContextDispatcher(browserDispatcher._scope, browser._defaultContext) : undefined,
|
||||
defaultContext: browser._defaultContext ? new BrowserContextDispatcher(browserDispatcher, browser._defaultContext) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -17,13 +17,14 @@
|
||||
import type { CRSession } from '../chromium/crConnection';
|
||||
import { CRSessionEvents } from '../chromium/crConnection';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { BrowserDispatcher } from './browserDispatcher';
|
||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
|
||||
export class CDPSessionDispatcher extends Dispatcher<CRSession, channels.CDPSessionChannel> implements channels.CDPSessionChannel {
|
||||
export class CDPSessionDispatcher extends Dispatcher<CRSession, channels.CDPSessionChannel, BrowserDispatcher | BrowserContextDispatcher, CDPSessionDispatcher> implements channels.CDPSessionChannel {
|
||||
_type_CDPSession = true;
|
||||
|
||||
constructor(scope: DispatcherScope, crSession: CRSession) {
|
||||
constructor(scope: BrowserDispatcher | BrowserContextDispatcher, crSession: CRSession) {
|
||||
super(scope, crSession, 'CDPSession', {}, true);
|
||||
crSession._eventListener = (method, params) => {
|
||||
this._dispatchEvent('event', { method, params });
|
||||
|
||||
@ -16,13 +16,14 @@
|
||||
|
||||
import type { ConsoleMessage } from '../console';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { PageDispatcher } from './pageDispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
|
||||
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, channels.ConsoleMessageChannel> implements channels.ConsoleMessageChannel {
|
||||
export class ConsoleMessageDispatcher extends Dispatcher<ConsoleMessage, channels.ConsoleMessageChannel, PageDispatcher> implements channels.ConsoleMessageChannel {
|
||||
_type_ConsoleMessage = true;
|
||||
constructor(scope: DispatcherScope, message: ConsoleMessage) {
|
||||
|
||||
constructor(scope: PageDispatcher, message: ConsoleMessage) {
|
||||
super(scope, message, 'ConsoleMessage', {
|
||||
type: message.type(),
|
||||
text: message.text(),
|
||||
|
||||
@ -16,12 +16,13 @@
|
||||
|
||||
import type { Dialog } from '../dialog';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { PageDispatcher } from './pageDispatcher';
|
||||
|
||||
export class DialogDispatcher extends Dispatcher<Dialog, channels.DialogChannel> implements channels.DialogChannel {
|
||||
export class DialogDispatcher extends Dispatcher<Dialog, channels.DialogChannel, PageDispatcher> implements channels.DialogChannel {
|
||||
_type_Dialog = true;
|
||||
constructor(scope: DispatcherScope, dialog: Dialog) {
|
||||
|
||||
constructor(scope: PageDispatcher, dialog: Dialog) {
|
||||
super(scope, dialog, 'Dialog', {
|
||||
type: dialog.type(),
|
||||
message: dialog.message(),
|
||||
|
||||
@ -44,28 +44,28 @@ export function lookupNullableDispatcher<DispatcherType>(object: any | null): Di
|
||||
return object ? lookupDispatcher(object) : undefined;
|
||||
}
|
||||
|
||||
export class Dispatcher<Type extends { guid: string }, ChannelType> extends EventEmitter implements channels.Channel {
|
||||
export class Dispatcher<Type extends { guid: string }, ChannelType, ParentScopeType extends DispatcherScope, ScopeType extends DispatcherScope = ParentScopeType> extends EventEmitter implements channels.Channel {
|
||||
private _connection: DispatcherConnection;
|
||||
private _isScope: boolean;
|
||||
// Parent is always "isScope".
|
||||
private _parent: Dispatcher<any, any> | undefined;
|
||||
private _parent: ParentScopeType | undefined;
|
||||
// Only "isScope" channel owners have registered dispatchers inside.
|
||||
private _dispatchers = new Map<string, Dispatcher<any, any>>();
|
||||
private _dispatchers = new Map<string, DispatcherScope>();
|
||||
protected _disposed = false;
|
||||
protected _eventListeners: RegisteredListener[] = [];
|
||||
|
||||
readonly _guid: string;
|
||||
readonly _type: string;
|
||||
readonly _scope: Dispatcher<any, any>;
|
||||
readonly _scope: ScopeType;
|
||||
_object: Type;
|
||||
|
||||
constructor(parent: Dispatcher<any, any> | DispatcherConnection, object: Type, type: string, initializer: channels.InitializerTraits<Type>, isScope?: boolean) {
|
||||
constructor(parent: ParentScopeType | DispatcherConnection, object: Type, type: string, initializer: channels.InitializerTraits<Type>, isScope?: boolean) {
|
||||
super();
|
||||
|
||||
this._connection = parent instanceof DispatcherConnection ? parent : parent._connection;
|
||||
this._isScope = !!isScope;
|
||||
this._parent = parent instanceof DispatcherConnection ? undefined : parent;
|
||||
this._scope = isScope ? this : this._parent!;
|
||||
this._scope = (isScope ? this : this._parent!) as any as ScopeType;
|
||||
|
||||
const guid = object.guid;
|
||||
assert(!this._connection._dispatchers.has(guid));
|
||||
@ -84,11 +84,15 @@ export class Dispatcher<Type extends { guid: string }, ChannelType> extends Even
|
||||
this._connection.sendCreate(this._parent, type, guid, initializer, this._parent._object);
|
||||
}
|
||||
|
||||
parentScope(): ParentScopeType | undefined {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
addObjectListener(eventName: (string | symbol), handler: (...args: any[]) => void) {
|
||||
this._eventListeners.push(eventsHelper.addEventListener(this._object as unknown as EventEmitter, eventName, handler));
|
||||
}
|
||||
|
||||
adopt(child: Dispatcher<any, any>) {
|
||||
adopt(child: DispatcherScope) {
|
||||
assert(this._isScope);
|
||||
const oldParent = child._parent!;
|
||||
oldParent._dispatchers.delete(child._guid);
|
||||
@ -140,11 +144,12 @@ export class Dispatcher<Type extends { guid: string }, ChannelType> extends Even
|
||||
}
|
||||
}
|
||||
|
||||
export type DispatcherScope = Dispatcher<any, any>;
|
||||
export class Root extends Dispatcher<{ guid: '' }, any> {
|
||||
export type DispatcherScope = Dispatcher<any, any, any>;
|
||||
|
||||
export class RootDispatcher extends Dispatcher<{ guid: '' }, any, any> {
|
||||
private _initialized = false;
|
||||
|
||||
constructor(connection: DispatcherConnection, private readonly createPlaywright?: (scope: DispatcherScope, options: channels.RootInitializeParams) => Promise<PlaywrightDispatcher>) {
|
||||
constructor(connection: DispatcherConnection, private readonly createPlaywright?: (scope: RootDispatcher, options: channels.RootInitializeParams) => Promise<PlaywrightDispatcher>) {
|
||||
super(connection, { guid: '' }, 'Root', {}, true);
|
||||
}
|
||||
|
||||
@ -159,7 +164,7 @@ export class Root extends Dispatcher<{ guid: '' }, any> {
|
||||
}
|
||||
|
||||
export class DispatcherConnection {
|
||||
readonly _dispatchers = new Map<string, Dispatcher<any, any>>();
|
||||
readonly _dispatchers = new Map<string, DispatcherScope>();
|
||||
onmessage = (message: object) => {};
|
||||
private _waitOperations = new Map<string, CallMetadata>();
|
||||
private _isLocal: boolean;
|
||||
@ -168,23 +173,23 @@ export class DispatcherConnection {
|
||||
this._isLocal = !!isLocal;
|
||||
}
|
||||
|
||||
sendEvent(dispatcher: Dispatcher<any, any>, event: string, params: any, sdkObject?: SdkObject) {
|
||||
sendEvent(dispatcher: DispatcherScope, event: string, params: any, sdkObject?: SdkObject) {
|
||||
const validator = findValidator(dispatcher._type, event, 'Event');
|
||||
params = validator(params, '', { tChannelImpl: this._tChannelImplToWire.bind(this), binary: this._isLocal ? 'buffer' : 'toBase64' });
|
||||
this._sendMessageToClient(dispatcher._guid, dispatcher._type, event, params, sdkObject);
|
||||
}
|
||||
|
||||
sendCreate(parent: Dispatcher<any, any>, type: string, guid: string, initializer: any, sdkObject?: SdkObject) {
|
||||
sendCreate(parent: DispatcherScope, type: string, guid: string, initializer: any, sdkObject?: SdkObject) {
|
||||
const validator = findValidator(type, '', 'Initializer');
|
||||
initializer = validator(initializer, '', { tChannelImpl: this._tChannelImplToWire.bind(this), binary: this._isLocal ? 'buffer' : 'toBase64' });
|
||||
this._sendMessageToClient(parent._guid, type, '__create__', { type, initializer, guid }, sdkObject);
|
||||
}
|
||||
|
||||
sendAdopt(parent: Dispatcher<any, any>, dispatcher: Dispatcher<any, any>) {
|
||||
sendAdopt(parent: DispatcherScope, dispatcher: DispatcherScope) {
|
||||
this._sendMessageToClient(parent._guid, dispatcher._type, '__adopt__', { guid: dispatcher._guid });
|
||||
}
|
||||
|
||||
sendDispose(dispatcher: Dispatcher<any, any>) {
|
||||
sendDispose(dispatcher: DispatcherScope) {
|
||||
this._sendMessageToClient(dispatcher._guid, dispatcher._type, '__dispose__', {});
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type { Electron } from '../electron/electron';
|
||||
import { ElectronApplication } from '../electron/electron';
|
||||
@ -24,9 +24,10 @@ import type { PageDispatcher } from './pageDispatcher';
|
||||
import { parseArgument, serializeResult } from './jsHandleDispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
|
||||
export class ElectronDispatcher extends Dispatcher<Electron, channels.ElectronChannel> implements channels.ElectronChannel {
|
||||
export class ElectronDispatcher extends Dispatcher<Electron, channels.ElectronChannel, RootDispatcher, ElectronDispatcher> implements channels.ElectronChannel {
|
||||
_type_Electron = true;
|
||||
constructor(scope: DispatcherScope, electron: Electron) {
|
||||
|
||||
constructor(scope: RootDispatcher, electron: Electron) {
|
||||
super(scope, electron, 'Electron', {}, true);
|
||||
}
|
||||
|
||||
@ -36,11 +37,11 @@ export class ElectronDispatcher extends Dispatcher<Electron, channels.ElectronCh
|
||||
}
|
||||
}
|
||||
|
||||
export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplication, channels.ElectronApplicationChannel> implements channels.ElectronApplicationChannel {
|
||||
export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplication, channels.ElectronApplicationChannel, ElectronDispatcher, ElectronApplicationDispatcher> implements channels.ElectronApplicationChannel {
|
||||
_type_EventTarget = true;
|
||||
_type_ElectronApplication = true;
|
||||
|
||||
constructor(scope: DispatcherScope, electronApplication: ElectronApplication) {
|
||||
constructor(scope: ElectronDispatcher, electronApplication: ElectronApplication) {
|
||||
super(scope, electronApplication, 'ElectronApplication', {
|
||||
context: new BrowserContextDispatcher(scope, electronApplication.context())
|
||||
}, true);
|
||||
|
||||
@ -18,37 +18,38 @@ import type { ElementHandle } from '../dom';
|
||||
import type { Frame } from '../frames';
|
||||
import type * as js from '../javascript';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { existingDispatcher, lookupNullableDispatcher } from './dispatcher';
|
||||
import { JSHandleDispatcher, serializeResult, parseArgument } from './jsHandleDispatcher';
|
||||
import type { JSHandleDispatcherParentScope } from './jsHandleDispatcher';
|
||||
import type { FrameDispatcher } from './frameDispatcher';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||
import { assert } from '../../utils';
|
||||
import path from 'path';
|
||||
|
||||
export class ElementHandleDispatcher extends JSHandleDispatcher implements channels.ElementHandleChannel {
|
||||
_type_ElementHandle = true;
|
||||
|
||||
readonly _elementHandle: ElementHandle;
|
||||
|
||||
static from(scope: DispatcherScope, handle: ElementHandle): ElementHandleDispatcher {
|
||||
static from(scope: JSHandleDispatcherParentScope, handle: ElementHandle): ElementHandleDispatcher {
|
||||
return existingDispatcher<ElementHandleDispatcher>(handle) || new ElementHandleDispatcher(scope, handle);
|
||||
}
|
||||
|
||||
static fromNullable(scope: DispatcherScope, handle: ElementHandle | null): ElementHandleDispatcher | undefined {
|
||||
static fromNullable(scope: JSHandleDispatcherParentScope, handle: ElementHandle | null): ElementHandleDispatcher | undefined {
|
||||
if (!handle)
|
||||
return undefined;
|
||||
return existingDispatcher<ElementHandleDispatcher>(handle) || new ElementHandleDispatcher(scope, handle);
|
||||
}
|
||||
|
||||
static fromJSHandle(scope: DispatcherScope, handle: js.JSHandle): JSHandleDispatcher {
|
||||
static fromJSHandle(scope: JSHandleDispatcherParentScope, handle: js.JSHandle): JSHandleDispatcher {
|
||||
const result = existingDispatcher<JSHandleDispatcher>(handle);
|
||||
if (result)
|
||||
return result;
|
||||
return handle.asElement() ? new ElementHandleDispatcher(scope, handle.asElement()!) : new JSHandleDispatcher(scope, handle);
|
||||
}
|
||||
|
||||
private constructor(scope: DispatcherScope, elementHandle: ElementHandle) {
|
||||
private constructor(scope: JSHandleDispatcherParentScope, elementHandle: ElementHandle) {
|
||||
super(scope, elementHandle);
|
||||
this._elementHandle = elementHandle;
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
import type { NavigationEvent } from '../frames';
|
||||
import { Frame } from '../frames';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher, lookupNullableDispatcher, existingDispatcher } from './dispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
import { parseArgument, serializeResult } from './jsHandleDispatcher';
|
||||
@ -27,29 +26,30 @@ import type { CallMetadata } from '../instrumentation';
|
||||
import type { WritableStreamDispatcher } from './writableStreamDispatcher';
|
||||
import { assert } from '../../utils';
|
||||
import path from 'path';
|
||||
import type { PageDispatcher } from './pageDispatcher';
|
||||
|
||||
export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> implements channels.FrameChannel {
|
||||
export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel, PageDispatcher> implements channels.FrameChannel {
|
||||
_type_Frame = true;
|
||||
private _frame: Frame;
|
||||
|
||||
static from(scope: DispatcherScope, frame: Frame): FrameDispatcher {
|
||||
static from(scope: PageDispatcher, frame: Frame): FrameDispatcher {
|
||||
const result = existingDispatcher<FrameDispatcher>(frame);
|
||||
return result || new FrameDispatcher(scope, frame);
|
||||
}
|
||||
|
||||
static fromNullable(scope: DispatcherScope, frame: Frame | null): FrameDispatcher | undefined {
|
||||
static fromNullable(scope: PageDispatcher, frame: Frame | null): FrameDispatcher | undefined {
|
||||
if (!frame)
|
||||
return;
|
||||
return FrameDispatcher.from(scope, frame);
|
||||
}
|
||||
|
||||
private constructor(scope: DispatcherScope, frame: Frame) {
|
||||
private constructor(scope: PageDispatcher, frame: Frame) {
|
||||
super(scope, frame, 'Frame', {
|
||||
url: frame.url(),
|
||||
name: frame.name(),
|
||||
parentFrame: FrameDispatcher.fromNullable(scope, frame.parentFrame()),
|
||||
loadStates: Array.from(frame._subtreeLifecycleEvents),
|
||||
});
|
||||
}, true);
|
||||
this._frame = frame;
|
||||
this.addObjectListener(Frame.Events.AddLifecycle, lifecycleEvent => {
|
||||
this._dispatchEvent('loadstate', { add: lifecycleEvent });
|
||||
@ -62,7 +62,7 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel> im
|
||||
return;
|
||||
const params = { url: event.url, name: event.name, error: event.error ? event.error.message : undefined };
|
||||
if (event.newDocument)
|
||||
(params as any).newDocument = { request: RequestDispatcher.fromNullable(this._scope, event.newDocument.request || null) };
|
||||
(params as any).newDocument = { request: RequestDispatcher.fromNullable(scope.parentScope()!, event.newDocument.request || null) };
|
||||
this._dispatchEvent('navigated', params);
|
||||
});
|
||||
}
|
||||
|
||||
@ -16,15 +16,18 @@
|
||||
|
||||
import type * as js from '../javascript';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
import { parseSerializedValue, serializeValue } from '../../protocol/serializers';
|
||||
import type { PageDispatcher, WorkerDispatcher } from './pageDispatcher';
|
||||
import type { ElectronApplicationDispatcher } from './electronDispatcher';
|
||||
|
||||
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandleChannel> implements channels.JSHandleChannel {
|
||||
export type JSHandleDispatcherParentScope = PageDispatcher | WorkerDispatcher | ElectronApplicationDispatcher;
|
||||
|
||||
export class JSHandleDispatcher extends Dispatcher<js.JSHandle, channels.JSHandleChannel, JSHandleDispatcherParentScope> implements channels.JSHandleChannel {
|
||||
_type_JSHandle = true;
|
||||
|
||||
protected constructor(scope: DispatcherScope, jsHandle: js.JSHandle) {
|
||||
protected constructor(scope: JSHandleDispatcherParentScope, jsHandle: js.JSHandle) {
|
||||
// Do not call this directly, use createHandle() instead.
|
||||
super(scope, jsHandle, jsHandle.asElement() ? 'ElementHandle' : 'JSHandle', {
|
||||
preview: jsHandle.toString(),
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { createGuid } from '../../utils';
|
||||
import { serializeError } from '../../protocol/serializers';
|
||||
import type { BrowserTypeDispatcher } from './browserTypeDispatcher';
|
||||
|
||||
export class JsonPipeDispatcher extends Dispatcher<{ guid: string }, channels.JsonPipeChannel> implements channels.JsonPipeChannel {
|
||||
export class JsonPipeDispatcher extends Dispatcher<{ guid: string }, channels.JsonPipeChannel, BrowserTypeDispatcher> implements channels.JsonPipeChannel {
|
||||
_type_JsonPipe = true;
|
||||
constructor(scope: DispatcherScope) {
|
||||
constructor(scope: BrowserTypeDispatcher) {
|
||||
super(scope, { guid: 'jsonPipe@' + createGuid() }, 'JsonPipe', {});
|
||||
}
|
||||
|
||||
|
||||
@ -20,18 +20,18 @@ import path from 'path';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { assert, createGuid } from '../../utils';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { yazl, yauzl } from '../../zipBundle';
|
||||
import { ZipFile } from '../../utils/zipFile';
|
||||
import type * as har from '../har/har';
|
||||
import type { HeadersArray } from '../types';
|
||||
|
||||
export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.LocalUtilsChannel> implements channels.LocalUtilsChannel {
|
||||
export class LocalUtilsDispatcher extends Dispatcher<{ guid: string }, channels.LocalUtilsChannel, RootDispatcher> implements channels.LocalUtilsChannel {
|
||||
_type_LocalUtils: boolean;
|
||||
private _harBakends = new Map<string, HarBackend>();
|
||||
|
||||
constructor(scope: DispatcherScope) {
|
||||
constructor(scope: RootDispatcher) {
|
||||
super(scope, { guid: 'localUtils@' + createGuid() }, 'LocalUtils', {});
|
||||
this._type_LocalUtils = true;
|
||||
}
|
||||
|
||||
@ -19,36 +19,39 @@ import type { APIRequestContext } from '../fetch';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
import type { Request, Response, Route } from '../network';
|
||||
import { WebSocket } from '../network';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher, existingDispatcher, lookupNullableDispatcher } from './dispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { WorkerDispatcher } from './pageDispatcher';
|
||||
import { TracingDispatcher } from './tracingDispatcher';
|
||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import type { PageDispatcher } from './pageDispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
|
||||
export class RequestDispatcher extends Dispatcher<Request, channels.RequestChannel> implements channels.RequestChannel {
|
||||
export class RequestDispatcher extends Dispatcher<Request, channels.RequestChannel, FrameDispatcher | WorkerDispatcher> implements channels.RequestChannel {
|
||||
_type_Request: boolean;
|
||||
|
||||
static from(scope: DispatcherScope, request: Request): RequestDispatcher {
|
||||
static from(scope: BrowserContextDispatcher, request: Request): RequestDispatcher {
|
||||
const result = existingDispatcher<RequestDispatcher>(request);
|
||||
return result || new RequestDispatcher(scope, request);
|
||||
}
|
||||
|
||||
static fromNullable(scope: DispatcherScope, request: Request | null): RequestDispatcher | undefined {
|
||||
static fromNullable(scope: BrowserContextDispatcher, request: Request | null): RequestDispatcher | undefined {
|
||||
return request ? RequestDispatcher.from(scope, request) : undefined;
|
||||
}
|
||||
|
||||
private constructor(scope: DispatcherScope, request: Request) {
|
||||
private constructor(contextScope: BrowserContextDispatcher, request: Request) {
|
||||
const postData = request.postDataBuffer();
|
||||
const scope = parentScopeForRequest(contextScope, request);
|
||||
super(scope, request, 'Request', {
|
||||
frame: FrameDispatcher.fromNullable(scope, request.frame()),
|
||||
serviceWorker: WorkerDispatcher.fromNullable(scope, request.serviceWorker()),
|
||||
frame: request.frame() ? scope : undefined,
|
||||
serviceWorker: request.serviceWorker() ? scope : undefined,
|
||||
url: request.url(),
|
||||
resourceType: request.resourceType(),
|
||||
method: request.method(),
|
||||
postData: postData === null ? undefined : postData,
|
||||
headers: request.headers(),
|
||||
isNavigationRequest: request.isNavigationRequest(),
|
||||
redirectedFrom: RequestDispatcher.fromNullable(scope, request.redirectedFrom()),
|
||||
redirectedFrom: RequestDispatcher.fromNullable(contextScope, request.redirectedFrom()),
|
||||
});
|
||||
this._type_Request = true;
|
||||
}
|
||||
@ -62,22 +65,23 @@ export class RequestDispatcher extends Dispatcher<Request, channels.RequestChann
|
||||
}
|
||||
}
|
||||
|
||||
export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseChannel> implements channels.ResponseChannel {
|
||||
export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseChannel, FrameDispatcher | WorkerDispatcher> implements channels.ResponseChannel {
|
||||
_type_Response = true;
|
||||
|
||||
static from(scope: DispatcherScope, response: Response): ResponseDispatcher {
|
||||
static from(scope: BrowserContextDispatcher, response: Response): ResponseDispatcher {
|
||||
const result = existingDispatcher<ResponseDispatcher>(response);
|
||||
return result || new ResponseDispatcher(scope, response);
|
||||
}
|
||||
|
||||
static fromNullable(scope: DispatcherScope, response: Response | null): ResponseDispatcher | undefined {
|
||||
static fromNullable(scope: BrowserContextDispatcher, response: Response | null): ResponseDispatcher | undefined {
|
||||
return response ? ResponseDispatcher.from(scope, response) : undefined;
|
||||
}
|
||||
|
||||
private constructor(scope: DispatcherScope, response: Response) {
|
||||
private constructor(contextScope: BrowserContextDispatcher, response: Response) {
|
||||
const scope = parentScopeForRequest(contextScope, response.request());
|
||||
super(scope, response, 'Response', {
|
||||
// TODO: responses in popups can point to non-reported requests.
|
||||
request: RequestDispatcher.from(scope, response.request()),
|
||||
request: RequestDispatcher.from(contextScope, response.request()),
|
||||
url: response.url(),
|
||||
status: response.status(),
|
||||
statusText: response.statusText(),
|
||||
@ -108,18 +112,18 @@ export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseCh
|
||||
}
|
||||
}
|
||||
|
||||
export class RouteDispatcher extends Dispatcher<Route, channels.RouteChannel> implements channels.RouteChannel {
|
||||
export class RouteDispatcher extends Dispatcher<Route, channels.RouteChannel, RequestDispatcher> implements channels.RouteChannel {
|
||||
_type_Route = true;
|
||||
|
||||
static from(scope: DispatcherScope, route: Route): RouteDispatcher {
|
||||
static from(scope: RequestDispatcher, route: Route): RouteDispatcher {
|
||||
const result = existingDispatcher<RouteDispatcher>(route);
|
||||
return result || new RouteDispatcher(scope, route);
|
||||
}
|
||||
|
||||
private constructor(scope: DispatcherScope, route: Route) {
|
||||
private constructor(scope: RequestDispatcher, route: Route) {
|
||||
super(scope, route, 'Route', {
|
||||
// Context route can point to a non-reported request.
|
||||
request: RequestDispatcher.from(scope, route.request())
|
||||
request: scope
|
||||
});
|
||||
}
|
||||
|
||||
@ -145,11 +149,11 @@ export class RouteDispatcher extends Dispatcher<Route, channels.RouteChannel> im
|
||||
}
|
||||
}
|
||||
|
||||
export class WebSocketDispatcher extends Dispatcher<WebSocket, channels.WebSocketChannel> implements channels.WebSocketChannel {
|
||||
export class WebSocketDispatcher extends Dispatcher<WebSocket, channels.WebSocketChannel, PageDispatcher> implements channels.WebSocketChannel {
|
||||
_type_EventTarget = true;
|
||||
_type_WebSocket = true;
|
||||
|
||||
constructor(scope: DispatcherScope, webSocket: WebSocket) {
|
||||
constructor(scope: PageDispatcher, webSocket: WebSocket) {
|
||||
super(scope, webSocket, 'WebSocket', {
|
||||
url: webSocket.url(),
|
||||
});
|
||||
@ -160,21 +164,21 @@ export class WebSocketDispatcher extends Dispatcher<WebSocket, channels.WebSocke
|
||||
}
|
||||
}
|
||||
|
||||
export class APIRequestContextDispatcher extends Dispatcher<APIRequestContext, channels.APIRequestContextChannel> implements channels.APIRequestContextChannel {
|
||||
export class APIRequestContextDispatcher extends Dispatcher<APIRequestContext, channels.APIRequestContextChannel, RootDispatcher | BrowserContextDispatcher, APIRequestContextDispatcher> implements channels.APIRequestContextChannel {
|
||||
_type_APIRequestContext = true;
|
||||
|
||||
static from(scope: DispatcherScope, request: APIRequestContext): APIRequestContextDispatcher {
|
||||
static from(scope: RootDispatcher | BrowserContextDispatcher, request: APIRequestContext): APIRequestContextDispatcher {
|
||||
const result = existingDispatcher<APIRequestContextDispatcher>(request);
|
||||
return result || new APIRequestContextDispatcher(scope, request);
|
||||
}
|
||||
|
||||
static fromNullable(scope: DispatcherScope, request: APIRequestContext | null): APIRequestContextDispatcher | undefined {
|
||||
static fromNullable(scope: RootDispatcher | BrowserContextDispatcher, request: APIRequestContext | null): APIRequestContextDispatcher | undefined {
|
||||
return request ? APIRequestContextDispatcher.from(scope, request) : undefined;
|
||||
}
|
||||
|
||||
private constructor(parentScope: DispatcherScope, request: APIRequestContext) {
|
||||
private constructor(parentScope: RootDispatcher | BrowserContextDispatcher, request: APIRequestContext) {
|
||||
// We will reparent these to the context below.
|
||||
const tracing = TracingDispatcher.from(parentScope, request.tracing());
|
||||
const tracing = TracingDispatcher.from(parentScope as any as APIRequestContextDispatcher, request.tracing());
|
||||
|
||||
super(parentScope, request, 'APIRequestContext', {
|
||||
tracing,
|
||||
@ -217,3 +221,11 @@ export class APIRequestContextDispatcher extends Dispatcher<APIRequestContext, c
|
||||
this._object.disposeResponse(params.fetchUid);
|
||||
}
|
||||
}
|
||||
|
||||
function parentScopeForRequest(scope: BrowserContextDispatcher, request: Request): FrameDispatcher | WorkerDispatcher {
|
||||
if (request.frame())
|
||||
return FrameDispatcher.from(scope as any as PageDispatcher, request.frame()!); // Context will swap for Page after reparent.
|
||||
if (request.serviceWorker())
|
||||
return WorkerDispatcher.fromNullable(scope, request.serviceWorker())!;
|
||||
throw new Error('Internal error: requests does not belong to a page or a worker');
|
||||
}
|
||||
|
||||
@ -18,14 +18,14 @@ import type { BrowserContext } from '../browserContext';
|
||||
import type { Frame } from '../frames';
|
||||
import { Page, Worker } from '../page';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher, existingDispatcher, lookupDispatcher, lookupNullableDispatcher } from './dispatcher';
|
||||
import { parseError, serializeError } from '../../protocol/serializers';
|
||||
import { ConsoleMessageDispatcher } from './consoleMessageDispatcher';
|
||||
import { DialogDispatcher } from './dialogDispatcher';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { RequestDispatcher } from './networkDispatchers';
|
||||
import type { ResponseDispatcher } from './networkDispatchers';
|
||||
import { RequestDispatcher, RouteDispatcher, WebSocketDispatcher } from './networkDispatchers';
|
||||
import { RouteDispatcher, WebSocketDispatcher } from './networkDispatchers';
|
||||
import { serializeResult, parseArgument } from './jsHandleDispatcher';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
import type { FileChooser } from '../fileChooser';
|
||||
@ -36,25 +36,30 @@ import type { Artifact } from '../artifact';
|
||||
import { ArtifactDispatcher } from './artifactDispatcher';
|
||||
import type { Download } from '../download';
|
||||
import { createGuid } from '../../utils';
|
||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
|
||||
export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> implements channels.PageChannel {
|
||||
export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, BrowserContextDispatcher, PageDispatcher> implements channels.PageChannel {
|
||||
_type_EventTarget = true;
|
||||
_type_Page = true;
|
||||
private _page: Page;
|
||||
|
||||
static fromNullable(parentScope: DispatcherScope, page: Page | undefined): PageDispatcher | undefined {
|
||||
static from(parentScope: BrowserContextDispatcher, page: Page): PageDispatcher {
|
||||
return PageDispatcher.fromNullable(parentScope, page)!;
|
||||
}
|
||||
|
||||
static fromNullable(parentScope: BrowserContextDispatcher, page: Page | undefined): PageDispatcher | undefined {
|
||||
if (!page)
|
||||
return undefined;
|
||||
const result = existingDispatcher<PageDispatcher>(page);
|
||||
return result || new PageDispatcher(parentScope, page);
|
||||
}
|
||||
|
||||
constructor(parentScope: DispatcherScope, page: Page) {
|
||||
private constructor(parentScope: BrowserContextDispatcher, page: Page) {
|
||||
// TODO: theoretically, there could be more than one frame already.
|
||||
// If we split pageCreated and pageReady, there should be no main frame during pageCreated.
|
||||
|
||||
// We will reparent it to the page below using adopt.
|
||||
const mainFrame = FrameDispatcher.from(parentScope, page.mainFrame());
|
||||
const mainFrame = FrameDispatcher.from(parentScope as any as PageDispatcher, page.mainFrame());
|
||||
|
||||
super(parentScope, page, 'Page', {
|
||||
mainFrame,
|
||||
@ -154,7 +159,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
|
||||
return;
|
||||
}
|
||||
await this._page.setClientRequestInterceptor((route, request) => {
|
||||
this._dispatchEvent('route', { route: RouteDispatcher.from(this._scope, route), request: RequestDispatcher.from(this._scope, request) });
|
||||
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this.parentScope()!, request), route) });
|
||||
});
|
||||
}
|
||||
|
||||
@ -291,19 +296,20 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
|
||||
}
|
||||
|
||||
|
||||
export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel> implements channels.WorkerChannel {
|
||||
static fromNullable(scope: DispatcherScope, worker: Worker | null): WorkerDispatcher | undefined {
|
||||
export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel, PageDispatcher | BrowserContextDispatcher, WorkerDispatcher> implements channels.WorkerChannel {
|
||||
_type_Worker = true;
|
||||
|
||||
static fromNullable(scope: PageDispatcher | BrowserContextDispatcher, worker: Worker | null): WorkerDispatcher | undefined {
|
||||
if (!worker)
|
||||
return undefined;
|
||||
const result = existingDispatcher<WorkerDispatcher>(worker);
|
||||
return result || new WorkerDispatcher(scope, worker);
|
||||
}
|
||||
|
||||
_type_Worker = true;
|
||||
constructor(scope: DispatcherScope, worker: Worker) {
|
||||
constructor(scope: PageDispatcher | BrowserContextDispatcher, worker: Worker) {
|
||||
super(scope, worker, 'Worker', {
|
||||
url: worker.url()
|
||||
});
|
||||
}, true);
|
||||
this.addObjectListener(Worker.Events.Close, () => this._dispatchEvent('close'));
|
||||
}
|
||||
|
||||
@ -316,13 +322,13 @@ export class WorkerDispatcher extends Dispatcher<Worker, channels.WorkerChannel>
|
||||
}
|
||||
}
|
||||
|
||||
export class BindingCallDispatcher extends Dispatcher<{ guid: string }, channels.BindingCallChannel> implements channels.BindingCallChannel {
|
||||
export class BindingCallDispatcher extends Dispatcher<{ guid: string }, channels.BindingCallChannel, PageDispatcher | BrowserContextDispatcher> implements channels.BindingCallChannel {
|
||||
_type_BindingCall = true;
|
||||
private _resolve: ((arg: any) => void) | undefined;
|
||||
private _reject: ((error: any) => void) | undefined;
|
||||
private _promise: Promise<any>;
|
||||
|
||||
constructor(scope: DispatcherScope, name: string, needsHandle: boolean, source: { context: BrowserContext, page: Page, frame: Frame }, args: any[]) {
|
||||
constructor(scope: PageDispatcher, name: string, needsHandle: boolean, source: { context: BrowserContext, page: Page, frame: Frame }, args: any[]) {
|
||||
super(scope, { guid: 'bindingCall@' + createGuid() }, 'BindingCall', {
|
||||
frame: lookupDispatcher<FrameDispatcher>(source.frame),
|
||||
name,
|
||||
|
||||
@ -23,7 +23,7 @@ import { SocksProxy } from '../../common/socksProxy';
|
||||
import type * as types from '../types';
|
||||
import { AndroidDispatcher } from './androidDispatcher';
|
||||
import { BrowserTypeDispatcher } from './browserTypeDispatcher';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { ElectronDispatcher } from './electronDispatcher';
|
||||
import { LocalUtilsDispatcher } from './localUtilsDispatcher';
|
||||
@ -32,11 +32,11 @@ import { SelectorsDispatcher } from './selectorsDispatcher';
|
||||
import { ConnectedBrowserDispatcher } from './browserDispatcher';
|
||||
import { createGuid } from '../../utils';
|
||||
|
||||
export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.PlaywrightChannel> implements channels.PlaywrightChannel {
|
||||
export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.PlaywrightChannel, RootDispatcher> implements channels.PlaywrightChannel {
|
||||
_type_Playwright;
|
||||
private _browserDispatcher: ConnectedBrowserDispatcher | undefined;
|
||||
|
||||
constructor(scope: DispatcherScope, playwright: Playwright, socksProxy?: SocksProxy, preLaunchedBrowser?: Browser) {
|
||||
constructor(scope: RootDispatcher, playwright: Playwright, socksProxy?: SocksProxy, preLaunchedBrowser?: Browser) {
|
||||
const descriptors = require('../deviceDescriptors') as types.Devices;
|
||||
const deviceDescriptors = Object.entries(descriptors)
|
||||
.map(([name, descriptor]) => ({ name, descriptor }));
|
||||
@ -72,11 +72,11 @@ export class PlaywrightDispatcher extends Dispatcher<Playwright, channels.Playwr
|
||||
}
|
||||
}
|
||||
|
||||
class SocksSupportDispatcher extends Dispatcher<{ guid: string }, channels.SocksSupportChannel> implements channels.SocksSupportChannel {
|
||||
class SocksSupportDispatcher extends Dispatcher<{ guid: string }, channels.SocksSupportChannel, RootDispatcher> implements channels.SocksSupportChannel {
|
||||
_type_SocksSupport: boolean;
|
||||
private _socksProxy: SocksProxy;
|
||||
|
||||
constructor(scope: DispatcherScope, socksProxy: SocksProxy) {
|
||||
constructor(scope: RootDispatcher, socksProxy: SocksProxy) {
|
||||
super(scope, { guid: 'socksSupport@' + createGuid() }, 'SocksSupport', {});
|
||||
this._type_SocksSupport = true;
|
||||
this._socksProxy = socksProxy;
|
||||
|
||||
@ -14,14 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { Selectors } from '../selectors';
|
||||
|
||||
export class SelectorsDispatcher extends Dispatcher<Selectors, channels.SelectorsChannel> implements channels.SelectorsChannel {
|
||||
export class SelectorsDispatcher extends Dispatcher<Selectors, channels.SelectorsChannel, RootDispatcher> implements channels.SelectorsChannel {
|
||||
_type_Selectors = true;
|
||||
constructor(scope: DispatcherScope, selectors: Selectors) {
|
||||
|
||||
constructor(scope: RootDispatcher, selectors: Selectors) {
|
||||
super(scope, selectors, 'Selectors', {});
|
||||
}
|
||||
|
||||
|
||||
@ -20,9 +20,10 @@ import { Dispatcher } from './dispatcher';
|
||||
import type * as stream from 'stream';
|
||||
import { createGuid } from '../../utils';
|
||||
|
||||
export class StreamDispatcher extends Dispatcher<{ guid: string, stream: stream.Readable }, channels.StreamChannel> implements channels.StreamChannel {
|
||||
export class StreamDispatcher extends Dispatcher<{ guid: string, stream: stream.Readable }, channels.StreamChannel, DispatcherScope> implements channels.StreamChannel {
|
||||
_type_Stream = true;
|
||||
private _ended: boolean = false;
|
||||
|
||||
constructor(scope: DispatcherScope, stream: stream.Readable) {
|
||||
super(scope, { guid: 'stream@' + createGuid(), stream }, 'Stream', {});
|
||||
// In Node v12.9.0+ we can use readableEnded.
|
||||
|
||||
@ -17,18 +17,19 @@
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { Tracing } from '../trace/recorder/tracing';
|
||||
import { ArtifactDispatcher } from './artifactDispatcher';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher, existingDispatcher } from './dispatcher';
|
||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
import type { APIRequestContextDispatcher } from './networkDispatchers';
|
||||
|
||||
export class TracingDispatcher extends Dispatcher<Tracing, channels.TracingChannel> implements channels.TracingChannel {
|
||||
export class TracingDispatcher extends Dispatcher<Tracing, channels.TracingChannel, BrowserContextDispatcher | APIRequestContextDispatcher> implements channels.TracingChannel {
|
||||
_type_Tracing = true;
|
||||
|
||||
static from(scope: DispatcherScope, tracing: Tracing): TracingDispatcher {
|
||||
static from(scope: BrowserContextDispatcher | APIRequestContextDispatcher, tracing: Tracing): TracingDispatcher {
|
||||
const result = existingDispatcher<TracingDispatcher>(tracing);
|
||||
return result || new TracingDispatcher(scope, tracing);
|
||||
}
|
||||
|
||||
constructor(scope: DispatcherScope, tracing: Tracing) {
|
||||
constructor(scope: BrowserContextDispatcher | APIRequestContextDispatcher, tracing: Tracing) {
|
||||
super(scope, tracing, 'Tracing', {}, true);
|
||||
}
|
||||
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import type * as fs from 'fs';
|
||||
import { createGuid } from '../../utils';
|
||||
import type { BrowserContextDispatcher } from './browserContextDispatcher';
|
||||
|
||||
export class WritableStreamDispatcher extends Dispatcher<{ guid: string, stream: fs.WriteStream }, channels.WritableStreamChannel> implements channels.WritableStreamChannel {
|
||||
export class WritableStreamDispatcher extends Dispatcher<{ guid: string, stream: fs.WriteStream }, channels.WritableStreamChannel, BrowserContextDispatcher> implements channels.WritableStreamChannel {
|
||||
_type_WritableStream = true;
|
||||
constructor(scope: DispatcherScope, stream: fs.WriteStream) {
|
||||
constructor(scope: BrowserContextDispatcher, stream: fs.WriteStream) {
|
||||
super(scope, { guid: 'writableStream@' + createGuid(), stream }, 'WritableStream', {});
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ export {
|
||||
installBrowsersForNpmInstall,
|
||||
writeDockerVersion } from './registry';
|
||||
|
||||
export { DispatcherConnection, Root } from './dispatchers/dispatcher';
|
||||
export { DispatcherConnection, RootDispatcher } from './dispatchers/dispatcher';
|
||||
export { PlaywrightDispatcher } from './dispatchers/playwrightDispatcher';
|
||||
export { createPlaywright } from './playwright';
|
||||
|
||||
|
||||
@ -53,14 +53,14 @@ it('should scope context handles', async ({ browserType, server, expectScopeStat
|
||||
{ _guid: 'selectors', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
// Firefox Beta 96 yields a console warning for the pages that
|
||||
// don't use `<!DOCTYPE HTML> tag.
|
||||
await page.goto(server.PREFIX + '/empty-standard-mode.html');
|
||||
await expectScopeState(browser, {
|
||||
expectScopeState(browser, {
|
||||
_guid: '',
|
||||
objects: [
|
||||
{ _guid: 'android', objects: [] },
|
||||
@ -70,11 +70,12 @@ it('should scope context handles', async ({ browserType, server, expectScopeStat
|
||||
{ _guid: 'browser', objects: [
|
||||
{ _guid: 'browser-context', objects: [
|
||||
{ _guid: 'page', objects: [
|
||||
{ _guid: 'frame', objects: [] },
|
||||
{ _guid: 'frame', objects: [
|
||||
{ _guid: 'request', objects: [] },
|
||||
{ _guid: 'response', objects: [] },
|
||||
] },
|
||||
] },
|
||||
{ _guid: 'request', objects: [] },
|
||||
{ _guid: 'request-context', objects: [] },
|
||||
{ _guid: 'response', objects: [] },
|
||||
{ _guid: 'tracing', objects: [] }
|
||||
] },
|
||||
] },
|
||||
@ -87,7 +88,7 @@ it('should scope context handles', async ({ browserType, server, expectScopeStat
|
||||
});
|
||||
|
||||
await context.close();
|
||||
await expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browser, GOLDEN_PRECONDITION);
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
@ -110,10 +111,10 @@ it('should scope CDPSession handles', async ({ browserType, browserName, expectS
|
||||
{ _guid: 'selectors', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
|
||||
const session = await browser.newBrowserCDPSession();
|
||||
await expectScopeState(browserType, {
|
||||
expectScopeState(browserType, {
|
||||
_guid: '',
|
||||
objects: [
|
||||
{ _guid: 'android', objects: [] },
|
||||
@ -132,7 +133,7 @@ it('should scope CDPSession handles', async ({ browserType, browserName, expectS
|
||||
});
|
||||
|
||||
await session.detach();
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
|
||||
await browser.close();
|
||||
});
|
||||
@ -151,11 +152,11 @@ it('should scope browser handles', async ({ browserType, expectScopeState }) =>
|
||||
{ _guid: 'selectors', objects: [] },
|
||||
]
|
||||
};
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
|
||||
const browser = await browserType.launch();
|
||||
await browser.newContext();
|
||||
await expectScopeState(browserType, {
|
||||
expectScopeState(browserType, {
|
||||
_guid: '',
|
||||
objects: [
|
||||
{ _guid: 'android', objects: [] },
|
||||
@ -180,7 +181,7 @@ it('should scope browser handles', async ({ browserType, expectScopeState }) =>
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
await expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
expectScopeState(browserType, GOLDEN_PRECONDITION);
|
||||
});
|
||||
|
||||
it('should work with the domain module', async ({ browserType, server, browserName }) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user