mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: move transport to object messages (#1567)
This commit is contained in:
parent
af7a16c360
commit
00cb4e370f
@ -243,7 +243,7 @@ export class CRBrowser extends platform.EventEmitter implements Browser {
|
||||
return this._clientRootSessionPromise;
|
||||
}
|
||||
|
||||
_setDebugFunction(debugFunction: (message: string) => void) {
|
||||
_setDebugFunction(debugFunction: platform.DebuggerType) {
|
||||
this._connection._debugProtocol = debugFunction;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
import { assert } from '../helper';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { ConnectionTransport, ProtocolMessage } from '../transport';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export const ConnectionEvents = {
|
||||
@ -34,7 +34,7 @@ export class CRConnection extends platform.EventEmitter {
|
||||
private readonly _sessions = new Map<string, CRSession>();
|
||||
readonly rootSession: CRSession;
|
||||
_closed = false;
|
||||
_debugProtocol: (message: string) => void;
|
||||
_debugProtocol: platform.DebuggerType;
|
||||
|
||||
constructor(transport: ConnectionTransport) {
|
||||
super();
|
||||
@ -55,37 +55,37 @@ export class CRConnection extends platform.EventEmitter {
|
||||
return this._sessions.get(sessionId) || null;
|
||||
}
|
||||
|
||||
_rawSend(sessionId: string, message: any): number {
|
||||
_rawSend(sessionId: string, message: ProtocolMessage): number {
|
||||
const id = ++this._lastId;
|
||||
message.id = id;
|
||||
if (sessionId)
|
||||
message.sessionId = sessionId;
|
||||
const data = JSON.stringify(message);
|
||||
this._debugProtocol('SEND ► ' + (rewriteInjectedScriptEvaluationLog(message) || data));
|
||||
this._transport.send(data);
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('SEND ► ' + rewriteInjectedScriptEvaluationLog(message));
|
||||
this._transport.send(message);
|
||||
return id;
|
||||
}
|
||||
|
||||
async _onMessage(message: string) {
|
||||
this._debugProtocol('◀ RECV ' + message);
|
||||
const object = JSON.parse(message);
|
||||
if (object.id === kBrowserCloseMessageId)
|
||||
async _onMessage(message: ProtocolMessage) {
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('◀ RECV ' + rewriteInjectedScriptEvaluationLog(message));
|
||||
if (message.id === kBrowserCloseMessageId)
|
||||
return;
|
||||
if (object.method === 'Target.attachedToTarget') {
|
||||
const sessionId = object.params.sessionId;
|
||||
const rootSessionId = object.sessionId || '';
|
||||
const session = new CRSession(this, rootSessionId, object.params.targetInfo.type, sessionId);
|
||||
if (message.method === 'Target.attachedToTarget') {
|
||||
const sessionId = message.params.sessionId;
|
||||
const rootSessionId = message.sessionId || '';
|
||||
const session = new CRSession(this, rootSessionId, message.params.targetInfo.type, sessionId);
|
||||
this._sessions.set(sessionId, session);
|
||||
} else if (object.method === 'Target.detachedFromTarget') {
|
||||
const session = this._sessions.get(object.params.sessionId);
|
||||
} else if (message.method === 'Target.detachedFromTarget') {
|
||||
const session = this._sessions.get(message.params.sessionId);
|
||||
if (session) {
|
||||
session._onClosed();
|
||||
this._sessions.delete(object.params.sessionId);
|
||||
this._sessions.delete(message.params.sessionId);
|
||||
}
|
||||
}
|
||||
const session = this._sessions.get(object.sessionId || '');
|
||||
const session = this._sessions.get(message.sessionId || '');
|
||||
if (session)
|
||||
session._onMessage(object);
|
||||
session._onMessage(message);
|
||||
}
|
||||
|
||||
_onClose() {
|
||||
@ -156,12 +156,12 @@ export class CRSession extends platform.EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
_onMessage(object: { id?: number; method: string; params: any; error: { message: string; data: any; }; result?: any; }) {
|
||||
_onMessage(object: ProtocolMessage) {
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id)!;
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object));
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
} else {
|
||||
@ -188,10 +188,10 @@ export class CRSession extends platform.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function createProtocolError(error: Error, method: string, object: { error: { message: string; data: any; }; }): Error {
|
||||
let message = `Protocol error (${method}): ${object.error.message}`;
|
||||
if ('data' in object.error)
|
||||
message += ` ${object.error.data}`;
|
||||
function createProtocolError(error: Error, method: string, protocolError: { message: string; data: any; }): Error {
|
||||
let message = `Protocol error (${method}): ${protocolError.message}`;
|
||||
if ('data' in protocolError)
|
||||
message += ` ${protocolError.data}`;
|
||||
return rewriteError(error, message);
|
||||
}
|
||||
|
||||
@ -200,9 +200,10 @@ function rewriteError(error: Error, message: string): Error {
|
||||
return error;
|
||||
}
|
||||
|
||||
function rewriteInjectedScriptEvaluationLog(message: any): string | undefined {
|
||||
function rewriteInjectedScriptEvaluationLog(message: ProtocolMessage): string {
|
||||
// Injected script is very long and clutters protocol logs.
|
||||
// To increase development velocity, we skip replace it with short description in the log.
|
||||
if (message.method === 'Runtime.evaluate' && message.params && message.params.expression && message.params.expression.includes('src/injected/injected.ts'))
|
||||
return `{"id":${message.id} [evaluate injected script]}`;
|
||||
return JSON.stringify(message);
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ export class FFBrowser extends platform.EventEmitter implements Browser {
|
||||
await disconnected;
|
||||
}
|
||||
|
||||
_setDebugFunction(debugFunction: (message: string) => void) {
|
||||
_setDebugFunction(debugFunction: platform.DebuggerType) {
|
||||
this._connection._debugProtocol = debugFunction;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
import {assert} from '../helper';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { ConnectionTransport, ProtocolMessage } from '../transport';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export const ConnectionEvents = {
|
||||
@ -33,7 +33,7 @@ export class FFConnection extends platform.EventEmitter {
|
||||
private _callbacks: Map<number, {resolve: Function, reject: Function, error: Error, method: string}>;
|
||||
private _transport: ConnectionTransport;
|
||||
readonly _sessions: Map<string, FFSession>;
|
||||
_debugProtocol: (message: string) => void = platform.debug('pw:protocol');
|
||||
_debugProtocol: platform.DebuggerType = platform.debug('pw:protocol');
|
||||
_closed: boolean;
|
||||
|
||||
on: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
@ -76,33 +76,33 @@ export class FFConnection extends platform.EventEmitter {
|
||||
return ++this._lastId;
|
||||
}
|
||||
|
||||
_rawSend(message: any) {
|
||||
const data = JSON.stringify(message);
|
||||
this._debugProtocol('SEND ► ' + (rewriteInjectedScriptEvaluationLog(message) || data));
|
||||
this._transport.send(data);
|
||||
_rawSend(message: ProtocolMessage) {
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('SEND ► ' + rewriteInjectedScriptEvaluationLog(message));
|
||||
this._transport.send(message);
|
||||
}
|
||||
|
||||
async _onMessage(message: string) {
|
||||
this._debugProtocol('◀ RECV ' + message);
|
||||
const object = JSON.parse(message);
|
||||
if (object.id === kBrowserCloseMessageId)
|
||||
async _onMessage(message: ProtocolMessage) {
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('◀ RECV ' + message);
|
||||
if (message.id === kBrowserCloseMessageId)
|
||||
return;
|
||||
if (object.sessionId) {
|
||||
const session = this._sessions.get(object.sessionId);
|
||||
if (message.sessionId) {
|
||||
const session = this._sessions.get(message.sessionId);
|
||||
if (session)
|
||||
session.dispatchMessage(object);
|
||||
} else if (object.id) {
|
||||
const callback = this._callbacks.get(object.id);
|
||||
session.dispatchMessage(message);
|
||||
} else if (message.id) {
|
||||
const callback = this._callbacks.get(message.id);
|
||||
// Callbacks could be all rejected if someone has called `.dispose()`.
|
||||
if (callback) {
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object));
|
||||
this._callbacks.delete(message.id);
|
||||
if (message.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, message.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
callback.resolve(message.result);
|
||||
}
|
||||
} else {
|
||||
Promise.resolve().then(() => this.emit(object.method, object.params));
|
||||
Promise.resolve().then(() => this.emit(message.method, message.params));
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,12 +176,12 @@ export class FFSession extends platform.EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
dispatchMessage(object: { id?: number; method: string; params: object; error: { message: string; data: any; }; result?: any; }) {
|
||||
dispatchMessage(object: ProtocolMessage) {
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id)!;
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object));
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
} else {
|
||||
@ -200,10 +200,10 @@ export class FFSession extends platform.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
function createProtocolError(error: Error, method: string, object: { error: { message: string; data: any; }; }): Error {
|
||||
let message = `Protocol error (${method}): ${object.error.message}`;
|
||||
if ('data' in object.error)
|
||||
message += ` ${object.error.data}`;
|
||||
function createProtocolError(error: Error, method: string, protocolError: { message: string; data: any; }): Error {
|
||||
let message = `Protocol error (${method}): ${protocolError.message}`;
|
||||
if ('data' in protocolError)
|
||||
message += ` ${protocolError.data}`;
|
||||
return rewriteError(error, message);
|
||||
}
|
||||
|
||||
@ -212,9 +212,10 @@ function rewriteError(error: Error, message: string): Error {
|
||||
return error;
|
||||
}
|
||||
|
||||
function rewriteInjectedScriptEvaluationLog(message: any): string | undefined {
|
||||
function rewriteInjectedScriptEvaluationLog(message: ProtocolMessage): string {
|
||||
// Injected script is very long and clutters protocol logs.
|
||||
// To increase development velocity, we skip replace it with short description in the log.
|
||||
if (message.method === 'Runtime.evaluate' && message.params && message.params.expression && message.params.expression.includes('src/injected/injected.ts'))
|
||||
return `{"id":${message.id} [evaluate injected script]}`;
|
||||
return JSON.stringify(message);
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ import * as NodeWebSocket from 'ws';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
import { assert, helper } from './helper';
|
||||
import { ConnectionTransport } from './transport';
|
||||
import { ConnectionTransport, ProtocolMessage } from './transport';
|
||||
|
||||
export const isNode = typeof process === 'object' && !!process && typeof process.versions === 'object' && !!process.versions && !!process.versions.node;
|
||||
|
||||
@ -112,7 +112,8 @@ export const EventEmitter: typeof nodeEvents.EventEmitter = isNode ? nodeEvents.
|
||||
) as any as typeof nodeEvents.EventEmitter;
|
||||
export type EventEmitterType = nodeEvents.EventEmitter;
|
||||
|
||||
type DebugType = typeof nodeDebug;
|
||||
export type DebuggerType = nodeDebug.IDebugger;
|
||||
export type DebugType = nodeDebug.IDebug;
|
||||
export const debug: DebugType = isNode ? nodeDebug : (
|
||||
function debug(namespace: string) {
|
||||
return () => {};
|
||||
@ -322,7 +323,7 @@ export async function connectToWebsocket<T>(url: string, onopen: (transport: Con
|
||||
class WebSocketTransport implements ConnectionTransport {
|
||||
_ws: WebSocket;
|
||||
|
||||
onmessage?: (message: string) => void;
|
||||
onmessage?: (message: ProtocolMessage) => void;
|
||||
onclose?: () => void;
|
||||
|
||||
constructor(url: string) {
|
||||
@ -339,7 +340,7 @@ class WebSocketTransport implements ConnectionTransport {
|
||||
this._ws.addEventListener('message', event => {
|
||||
messageWrap(() => {
|
||||
if (this.onmessage)
|
||||
this.onmessage.call(null, event.data);
|
||||
this.onmessage.call(null, JSON.parse(event.data));
|
||||
});
|
||||
});
|
||||
|
||||
@ -351,8 +352,8 @@ class WebSocketTransport implements ConnectionTransport {
|
||||
this._ws.addEventListener('error', () => {});
|
||||
}
|
||||
|
||||
send(message: string) {
|
||||
this._ws.send(message);
|
||||
send(message: ProtocolMessage) {
|
||||
this._ws.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
close() {
|
||||
|
||||
@ -115,7 +115,7 @@ export class Chromium implements BrowserType<CRBrowser> {
|
||||
// our connection ignores kBrowserCloseMessageId.
|
||||
const t = transport || await platform.connectToWebsocket(browserWSEndpoint!, async transport => transport);
|
||||
const message = { method: 'Browser.close', id: kBrowserCloseMessageId };
|
||||
await t.send(JSON.stringify(message));
|
||||
await t.send(message);
|
||||
},
|
||||
onkill: (exitCode, signal) => {
|
||||
if (browserServer)
|
||||
|
||||
@ -130,7 +130,7 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
// our connection ignores kBrowserCloseMessageId.
|
||||
const transport = await platform.connectToWebsocket(browserWSEndpoint, async transport => transport);
|
||||
const message = { method: 'Browser.close', params: {}, id: kBrowserCloseMessageId };
|
||||
await transport.send(JSON.stringify(message));
|
||||
await transport.send(message);
|
||||
},
|
||||
onkill: (exitCode, signal) => {
|
||||
if (browserServer)
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
import { debugError, helper, RegisteredListener } from '../helper';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { ConnectionTransport, ProtocolMessage } from '../transport';
|
||||
import { makeWaitForNextTask } from '../platform';
|
||||
|
||||
export class PipeTransport implements ConnectionTransport {
|
||||
@ -26,7 +26,7 @@ export class PipeTransport implements ConnectionTransport {
|
||||
private _waitForNextTask = makeWaitForNextTask();
|
||||
private readonly _closeCallback: () => void;
|
||||
|
||||
onmessage?: (message: string) => void;
|
||||
onmessage?: (message: ProtocolMessage) => void;
|
||||
onclose?: () => void;
|
||||
|
||||
constructor(pipeWrite: NodeJS.WritableStream, pipeRead: NodeJS.ReadableStream, closeCallback: () => void) {
|
||||
@ -46,8 +46,8 @@ export class PipeTransport implements ConnectionTransport {
|
||||
this.onclose = undefined;
|
||||
}
|
||||
|
||||
send(message: string) {
|
||||
this._pipeWrite!.write(message);
|
||||
send(message: ProtocolMessage) {
|
||||
this._pipeWrite!.write(JSON.stringify(message));
|
||||
this._pipeWrite!.write('\0');
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export class PipeTransport implements ConnectionTransport {
|
||||
const message = this._pendingMessage + buffer.toString(undefined, 0, end);
|
||||
this._waitForNextTask(() => {
|
||||
if (this.onmessage)
|
||||
this.onmessage.call(null, message);
|
||||
this.onmessage.call(null, JSON.parse(message));
|
||||
});
|
||||
|
||||
let start = end + 1;
|
||||
@ -73,7 +73,7 @@ export class PipeTransport implements ConnectionTransport {
|
||||
const message = buffer.toString(undefined, start, end);
|
||||
this._waitForNextTask(() => {
|
||||
if (this.onmessage)
|
||||
this.onmessage.call(null, message);
|
||||
this.onmessage.call(null, JSON.parse(message));
|
||||
});
|
||||
start = end + 1;
|
||||
end = buffer.indexOf('\0', start);
|
||||
|
||||
@ -114,8 +114,7 @@ export class WebKit implements BrowserType<WKBrowser> {
|
||||
// We try to gracefully close to prevent crash reporting and core dumps.
|
||||
// Note that it's fine to reuse the pipe transport, since
|
||||
// our connection ignores kBrowserCloseMessageId.
|
||||
const message = JSON.stringify({method: 'Playwright.close', params: {}, id: kBrowserCloseMessageId});
|
||||
transport.send(message);
|
||||
transport.send({method: 'Playwright.close', params: {}, id: kBrowserCloseMessageId});
|
||||
},
|
||||
onkill: (exitCode, signal) => {
|
||||
if (browserServer)
|
||||
@ -194,54 +193,53 @@ function wrapTransportWithWebSocket(transport: ConnectionTransport, port: number
|
||||
const sockets = new Set<ws>();
|
||||
|
||||
transport.onmessage = message => {
|
||||
const parsedMessage = JSON.parse(message);
|
||||
if ('id' in parsedMessage) {
|
||||
if (parsedMessage.id === -9999)
|
||||
if (typeof message.id === 'number') {
|
||||
if (message.id === -9999)
|
||||
return;
|
||||
// Process command response.
|
||||
const value = idMixer.take(parsedMessage.id);
|
||||
const value = idMixer.take(message.id);
|
||||
if (!value)
|
||||
return;
|
||||
const { id, socket } = value;
|
||||
|
||||
if (!socket || socket.readyState === ws.CLOSING) {
|
||||
if (pendingBrowserContextCreations.has(id)) {
|
||||
transport.send(JSON.stringify({
|
||||
transport.send({
|
||||
id: ++SequenceNumberMixer._lastSequenceNumber,
|
||||
method: 'Playwright.deleteContext',
|
||||
params: { browserContextId: parsedMessage.result.browserContextId }
|
||||
}));
|
||||
params: { browserContextId: message.result.browserContextId }
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (pendingBrowserContextCreations.has(parsedMessage.id)) {
|
||||
if (pendingBrowserContextCreations.has(message.id)) {
|
||||
// Browser.createContext response -> establish context attribution.
|
||||
browserContextIds.set(parsedMessage.result.browserContextId, socket);
|
||||
pendingBrowserContextCreations.delete(parsedMessage.id);
|
||||
browserContextIds.set(message.result.browserContextId, socket);
|
||||
pendingBrowserContextCreations.delete(message.id);
|
||||
}
|
||||
|
||||
const deletedContextId = pendingBrowserContextDeletions.get(parsedMessage.id);
|
||||
const deletedContextId = pendingBrowserContextDeletions.get(message.id);
|
||||
if (deletedContextId) {
|
||||
// Browser.deleteContext response -> remove context attribution.
|
||||
browserContextIds.delete(deletedContextId);
|
||||
pendingBrowserContextDeletions.delete(parsedMessage.id);
|
||||
pendingBrowserContextDeletions.delete(message.id);
|
||||
}
|
||||
|
||||
parsedMessage.id = id;
|
||||
socket.send(JSON.stringify(parsedMessage));
|
||||
message.id = id;
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
|
||||
// Process notification response.
|
||||
const { method, params, pageProxyId } = parsedMessage;
|
||||
const { method, params, pageProxyId } = message;
|
||||
if (pageProxyId) {
|
||||
const socket = pageProxyIds.get(pageProxyId);
|
||||
if (!socket || socket.readyState === ws.CLOSING) {
|
||||
// Drop unattributed messages on the floor.
|
||||
return;
|
||||
}
|
||||
socket.send(message);
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
if (method === 'Playwright.pageProxyCreated') {
|
||||
@ -251,20 +249,20 @@ function wrapTransportWithWebSocket(transport: ConnectionTransport, port: number
|
||||
return;
|
||||
}
|
||||
pageProxyIds.set(params.pageProxyInfo.pageProxyId, socket);
|
||||
socket.send(message);
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
if (method === 'Playwright.pageProxyDestroyed') {
|
||||
const socket = pageProxyIds.get(params.pageProxyId);
|
||||
pageProxyIds.delete(params.pageProxyId);
|
||||
if (socket && socket.readyState !== ws.CLOSING)
|
||||
socket.send(message);
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
if (method === 'Playwright.provisionalLoadFailed') {
|
||||
const socket = pageProxyIds.get(params.pageProxyId);
|
||||
if (socket && socket.readyState !== ws.CLOSING)
|
||||
socket.send(message);
|
||||
socket.send(JSON.stringify(message));
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -280,7 +278,7 @@ function wrapTransportWithWebSocket(transport: ConnectionTransport, port: number
|
||||
const parsedMessage = JSON.parse(Buffer.from(message).toString());
|
||||
const { id, method, params } = parsedMessage;
|
||||
const seqNum = idMixer.generate({ id, socket });
|
||||
transport.send(JSON.stringify({ ...parsedMessage, id: seqNum }));
|
||||
transport.send({ ...parsedMessage, id: seqNum });
|
||||
if (method === 'Playwright.createContext')
|
||||
pendingBrowserContextCreations.add(seqNum);
|
||||
if (method === 'Playwright.deleteContext')
|
||||
@ -294,11 +292,11 @@ function wrapTransportWithWebSocket(transport: ConnectionTransport, port: number
|
||||
}
|
||||
for (const [browserContextId, s] of browserContextIds) {
|
||||
if (s === socket) {
|
||||
transport.send(JSON.stringify({
|
||||
transport.send({
|
||||
id: ++SequenceNumberMixer._lastSequenceNumber,
|
||||
method: 'Playwright.deleteContext',
|
||||
params: { browserContextId }
|
||||
}));
|
||||
});
|
||||
browserContextIds.delete(browserContextId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,10 +15,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type ProtocolMessage = {
|
||||
id?: number;
|
||||
method: string;
|
||||
params?: any;
|
||||
sessionId?: string;
|
||||
error?: { message: string; data: any; };
|
||||
result?: any;
|
||||
pageProxyId?: string;
|
||||
};
|
||||
|
||||
export interface ConnectionTransport {
|
||||
send(s: string): void;
|
||||
send(s: ProtocolMessage): void;
|
||||
close(): void; // Note: calling close is expected to issue onclose at some point.
|
||||
onmessage?: (message: string) => void,
|
||||
onmessage?: (message: ProtocolMessage) => void,
|
||||
onclose?: () => void,
|
||||
}
|
||||
|
||||
@ -26,7 +36,7 @@ export class SlowMoTransport {
|
||||
private readonly _delay: number;
|
||||
private readonly _delegate: ConnectionTransport;
|
||||
|
||||
onmessage?: (message: string) => void;
|
||||
onmessage?: (message: ProtocolMessage) => void;
|
||||
onclose?: () => void;
|
||||
|
||||
static wrap(transport: ConnectionTransport, delay?: number): ConnectionTransport {
|
||||
@ -40,7 +50,7 @@ export class SlowMoTransport {
|
||||
this._delegate.onclose = this._onClose.bind(this);
|
||||
}
|
||||
|
||||
private _onmessage(message: string) {
|
||||
private _onmessage(message: ProtocolMessage) {
|
||||
if (this.onmessage)
|
||||
this.onmessage(message);
|
||||
}
|
||||
@ -52,7 +62,7 @@ export class SlowMoTransport {
|
||||
this._delegate.onclose = undefined;
|
||||
}
|
||||
|
||||
send(s: string) {
|
||||
send(s: ProtocolMessage) {
|
||||
setTimeout(() => {
|
||||
if (this._delegate.onmessage)
|
||||
this._delegate.send(s);
|
||||
@ -68,14 +78,14 @@ export class DeferWriteTransport implements ConnectionTransport {
|
||||
private _delegate: ConnectionTransport;
|
||||
private _readPromise: Promise<void>;
|
||||
|
||||
onmessage?: (message: string) => void;
|
||||
onmessage?: (message: ProtocolMessage) => void;
|
||||
onclose?: () => void;
|
||||
|
||||
constructor(transport: ConnectionTransport) {
|
||||
this._delegate = transport;
|
||||
let callback: () => void;
|
||||
this._readPromise = new Promise(f => callback = f);
|
||||
this._delegate.onmessage = s => {
|
||||
this._delegate.onmessage = (s: ProtocolMessage) => {
|
||||
callback();
|
||||
if (this.onmessage)
|
||||
this.onmessage(s);
|
||||
@ -86,7 +96,7 @@ export class DeferWriteTransport implements ConnectionTransport {
|
||||
};
|
||||
}
|
||||
|
||||
async send(s: string) {
|
||||
async send(s: ProtocolMessage) {
|
||||
await this._readPromise;
|
||||
this._delegate.send(s);
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ export class WKBrowser extends platform.EventEmitter implements Browser {
|
||||
await disconnected;
|
||||
}
|
||||
|
||||
_setDebugFunction(debugFunction: (message: string) => void) {
|
||||
_setDebugFunction(debugFunction: platform.DebuggerType) {
|
||||
this._connection._debugProtocol = debugFunction;
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
import { assert } from '../helper';
|
||||
import * as platform from '../platform';
|
||||
import { ConnectionTransport } from '../transport';
|
||||
import { ConnectionTransport, ProtocolMessage } from '../transport';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
// WKPlaywright uses this special id to issue Browser.close command which we
|
||||
@ -34,7 +34,7 @@ export class WKConnection {
|
||||
private readonly _onDisconnect: () => void;
|
||||
private _lastId = 0;
|
||||
private _closed = false;
|
||||
_debugProtocol: (message: string) => void = platform.debug('pw:protocol');
|
||||
_debugProtocol: platform.DebuggerType = platform.debug('pw:protocol');
|
||||
|
||||
readonly browserSession: WKSession;
|
||||
|
||||
@ -53,23 +53,23 @@ export class WKConnection {
|
||||
return ++this._lastId;
|
||||
}
|
||||
|
||||
rawSend(message: any) {
|
||||
const data = JSON.stringify(message);
|
||||
this._debugProtocol('SEND ► ' + (rewriteInjectedScriptEvaluationLog(message) || data));
|
||||
this._transport.send(data);
|
||||
rawSend(message: ProtocolMessage) {
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('SEND ► ' + rewriteInjectedScriptEvaluationLog(message));
|
||||
this._transport.send(message);
|
||||
}
|
||||
|
||||
private _dispatchMessage(message: string) {
|
||||
this._debugProtocol('◀ RECV ' + message);
|
||||
const object = JSON.parse(message);
|
||||
if (object.id === kBrowserCloseMessageId)
|
||||
private _dispatchMessage(message: ProtocolMessage) {
|
||||
if (this._debugProtocol.enabled)
|
||||
this._debugProtocol('◀ RECV ' + message);
|
||||
if (message.id === kBrowserCloseMessageId)
|
||||
return;
|
||||
if (object.pageProxyId) {
|
||||
const payload: PageProxyMessageReceivedPayload = { message: object, pageProxyId: object.pageProxyId };
|
||||
if (message.pageProxyId) {
|
||||
const payload: PageProxyMessageReceivedPayload = { message: message, pageProxyId: message.pageProxyId };
|
||||
this.browserSession.dispatchMessage({ method: kPageProxyMessageReceived, params: payload });
|
||||
return;
|
||||
}
|
||||
this.browserSession.dispatchMessage(object);
|
||||
this.browserSession.dispatchMessage(message);
|
||||
}
|
||||
|
||||
_onClose() {
|
||||
@ -151,7 +151,7 @@ export class WKSession extends platform.EventEmitter {
|
||||
const callback = this._callbacks.get(object.id)!;
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object));
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
} else if (object.id) {
|
||||
@ -163,10 +163,10 @@ export class WKSession extends platform.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
export function createProtocolError(error: Error, method: string, object: { error: { message: string; data: any; }; }): Error {
|
||||
let message = `Protocol error (${method}): ${object.error.message}`;
|
||||
if ('data' in object.error)
|
||||
message += ` ${JSON.stringify(object.error.data)}`;
|
||||
export function createProtocolError(error: Error, method: string, protocolError: { message: string; data: any; }): Error {
|
||||
let message = `Protocol error (${method}): ${protocolError.message}`;
|
||||
if ('data' in protocolError)
|
||||
message += ` ${JSON.stringify(protocolError.data)}`;
|
||||
return rewriteError(error, message);
|
||||
}
|
||||
|
||||
@ -179,9 +179,10 @@ export function isSwappedOutError(e: Error) {
|
||||
return e.message.includes('Target was swapped out.');
|
||||
}
|
||||
|
||||
function rewriteInjectedScriptEvaluationLog(message: any): string | undefined {
|
||||
function rewriteInjectedScriptEvaluationLog(message: any): string {
|
||||
// Injected script is very long and clutters protocol logs.
|
||||
// To increase development velocity, we skip replace it with short description in the log.
|
||||
if (message.params && message.params.message && message.params.message.includes('Runtime.evaluate') && message.params.message.includes('src/injected/injected.ts'))
|
||||
return `{"id":${message.id},"method":"${message.method}","params":{"message":[evaluate injected script],"targetId":"${message.params.targetId}"},"pageProxyId":${message.pageProxyId}}`;
|
||||
return JSON.stringify(message);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user