Implementation:Microsoft Playwright ChannelOwner
| Knowledge Sources | |
|---|---|
| Domains | Browser Automation, Client-Server Architecture |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
Concrete tool for serving as the base class for all client-side Playwright objects that communicate with the server over protocol channels, provided by the Playwright library.
Description
ChannelOwner is the abstract base class for every client-side Playwright object (Page, BrowserContext, Frame, ElementHandle, etc.). It extends EventEmitter and manages the bidirectional communication channel between client and server. Key responsibilities include:
- Channel proxy creation: Creates a Proxy-based channel object that intercepts method calls, validates parameters through protocol validators, and routes them through the connection's
sendMessageToServer(). - Object tree management: Maintains a parent-child tree of
ChannelOwnerobjects via_objectsmap, with methods for adoption (_adopt) and disposal (_dispose). - Subscription management: Overrides
on,off,addListener,removeListener, andprependListenerto automatically send subscription updates to the server when listeners are added or removed. - API call wrapping: The
_wrapApiCall()method provides instrumentation, stack trace capture, logging, and error enrichment for all API calls. - Serialization: Custom
toJSON()for safe Jest/debugging output.
An ApiZone type tracks the current API call context including name, stack frames, internal flag, and error state.
Usage
ChannelOwner is not used directly by end users. It is the foundational base class that all Playwright client objects inherit from. Understanding it is essential for comprehending how the Playwright client-server protocol works.
Code Reference
Source Location
- Repository: Microsoft_Playwright
- File:
packages/playwright-core/src/client/channelOwner.ts
Signature
export abstract class ChannelOwner<T extends channels.Channel = channels.Channel> extends EventEmitter {
readonly _connection: Connection;
readonly _type: string;
readonly _guid: string;
readonly _channel: T;
readonly _initializer: channels.InitializerTraits<T>;
_logger: Logger | undefined;
readonly _instrumentation: ClientInstrumentation;
_wasCollected: boolean;
constructor(parent: ChannelOwner | Connection, type: string, guid: string, initializer: channels.InitializerTraits<T>);
_setEventToSubscriptionMapping(mapping: Map<string, string>): void;
on(event: string | symbol, listener: Listener): this;
addListener(event: string | symbol, listener: Listener): this;
prependListener(event: string | symbol, listener: Listener): this;
off(event: string | symbol, listener: Listener): this;
removeListener(event: string | symbol, listener: Listener): this;
_adopt(child: ChannelOwner<any>): void;
_dispose(reason: 'gc' | undefined): void;
_debugScopeState(): any;
async _wrapApiCall<R>(func: (apiZone: ApiZone) => Promise<R>, options?: { internal?: boolean; title?: string }): Promise<R>;
}
Import
import { ChannelOwner } from 'playwright-core/src/client/channelOwner';
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| parent | Connection | Yes | The parent object or connection instance |
| type | string |
Yes | The protocol type name (e.g., 'Page', 'Frame') |
| guid | string |
Yes | The unique identifier for this object in the protocol |
| initializer | channels.InitializerTraits<T> |
Yes | The initialization data from the server |
Outputs
| Name | Type | Description |
|---|---|---|
| _channel | T |
The Proxy-based channel for sending protocol messages to the server |
| _wrapApiCall() | Promise<R> |
Wraps function execution with instrumentation, logging, and error handling |
Usage Examples
// ChannelOwner is used as a base class, not directly:
export class Page extends ChannelOwner<channels.PageChannel> implements api.Page {
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.PageInitializer) {
super(parent, type, guid, initializer);
// Page-specific initialization...
}
async goto(url: string): Promise<Response | null> {
return await this._wrapApiCall(async () => {
const result = await this._channel.goto({ url });
return Response.fromNullable(result.response);
});
}
}