diff --git a/src/client/channelOwner.ts b/src/client/channelOwner.ts index c943d22133..91e59deabf 100644 --- a/src/client/channelOwner.ts +++ b/src/client/channelOwner.ts @@ -20,6 +20,7 @@ import type { Connection } from './connection'; import type { Logger } from './types'; import { debugLogger } from '../utils/debugLogger'; import { rewriteErrorMessage } from '../utils/stackTrace'; +import { createScheme, Validator, ValidationError } from '../protocol/validator'; export abstract class ChannelOwner extends EventEmitter { private _connection: Connection; @@ -48,23 +49,14 @@ export abstract class ChannelOwner { - if (String(prop).startsWith('_')) - return obj[prop]; - if (prop === 'then') - return obj.then; - if (prop === 'emit') - return obj.emit; - if (prop === 'on') - return obj.on; - if (prop === 'once') - return obj.once; - if (prop === 'addEventListener') - return obj.addListener; - if (prop === 'removeEventListener') - return obj.removeListener; - if (prop === 'domain') // https://github.com/microsoft/playwright/issues/3848 - return obj.domain; - return (params: any) => this._connection.sendMessageToServer(this._type, guid, String(prop), params); + if (prop === 'debugScopeState') + return (params: any) => this._connection.sendMessageToServer(guid, prop, params); + if (typeof prop === 'string') { + const validator = scheme[paramsName(type, prop)]; + if (validator) + return (params: any) => this._connection.sendMessageToServer(guid, prop, validator(params, '')); + } + return obj[prop]; }, }); (this._channel as any)._object = this; @@ -121,3 +113,17 @@ function logApiCall(logger: Logger | undefined, message: string) { logger.log('api', 'info', message, [], { color: 'cyan' }); debugLogger.log('api', message); } + +function paramsName(type: string, method: string) { + return type + method[0].toUpperCase() + method.substring(1) + 'Params'; +} + +const tChannel = (name: string): Validator => { + return (arg: any, path: string) => { + if (arg._object instanceof ChannelOwner && (name === '*' || arg._object._type === name)) + return { guid: arg._object._guid }; + throw new ValidationError(`${path}: expected ${name}`); + }; +}; + +const scheme = createScheme(tChannel); diff --git a/src/client/connection.ts b/src/client/connection.ts index cc0e01dc64..3efc9bf7a7 100644 --- a/src/client/connection.ts +++ b/src/client/connection.ts @@ -35,7 +35,6 @@ import * as channels from '../protocol/channels'; import { ChromiumBrowser } from './chromiumBrowser'; import { ChromiumBrowserContext } from './chromiumBrowserContext'; import { Stream } from './stream'; -import { createScheme, Validator, ValidationError } from '../protocol/validator'; import { WebKitBrowser } from './webkitBrowser'; import { FirefoxBrowser } from './firefoxBrowser'; import { debugLogger } from '../utils/debugLogger'; @@ -70,13 +69,12 @@ export class Connection { return this._objects.get(guid)!; } - async sendMessageToServer(type: string, guid: string, method: string, params: any): Promise { + async sendMessageToServer(guid: string, method: string, params: any): Promise { const stackObject: any = {}; Error.captureStackTrace(stackObject); const stack = stackObject.stack.startsWith('Error') ? stackObject.stack.substring(5) : stackObject.stack; const id = ++this._lastId; - const validated = method === 'debugScopeState' ? params : validateParams(type, method, params); - const converted = { id, guid, method, params: validated }; + const converted = { id, guid, method, params }; // Do not include metadata in debug logs to avoid noise. debugLogger.log('channel:command', converted); this.onmessage({ ...converted, metadata: { stack } }); @@ -243,20 +241,3 @@ export class Connection { return result; } } - -const tChannel = (name: string): Validator => { - return (arg: any, path: string) => { - if (arg._object instanceof ChannelOwner && (name === '*' || arg._object._type === name)) - return { guid: arg._object._guid }; - throw new ValidationError(`${path}: expected ${name}`); - }; -}; - -const scheme = createScheme(tChannel); - -function validateParams(type: string, method: string, params: any): any { - const name = type + method[0].toUpperCase() + method.substring(1) + 'Params'; - if (!scheme[name]) - throw new ValidationError(`Unknown scheme for ${type}.${method}`); - return scheme[name](params, ''); -}