From 00cb4e370f8e769abb80cc42ef04e6f17377d9bf Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 26 Mar 2020 23:30:55 -0700 Subject: [PATCH] chore: move transport to object messages (#1567) --- src/chromium/crBrowser.ts | 2 +- src/chromium/crConnection.ts | 53 +++++++++++++++++----------------- src/firefox/ffBrowser.ts | 2 +- src/firefox/ffConnection.ts | 55 ++++++++++++++++++------------------ src/platform.ts | 13 +++++---- src/server/chromium.ts | 2 +- src/server/firefox.ts | 2 +- src/server/pipeTransport.ts | 12 ++++---- src/server/webkit.ts | 46 +++++++++++++++--------------- src/transport.ts | 26 +++++++++++------ src/webkit/wkBrowser.ts | 2 +- src/webkit/wkConnection.ts | 39 ++++++++++++------------- 12 files changed, 133 insertions(+), 121 deletions(-) diff --git a/src/chromium/crBrowser.ts b/src/chromium/crBrowser.ts index dca2340f3e70a..fe3fcdac9771a 100644 --- a/src/chromium/crBrowser.ts +++ b/src/chromium/crBrowser.ts @@ -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; } } diff --git a/src/chromium/crConnection.ts b/src/chromium/crConnection.ts index 43d1843031552..5a7e89024ba6f 100644 --- a/src/chromium/crConnection.ts +++ b/src/chromium/crConnection.ts @@ -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(); 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); } diff --git a/src/firefox/ffBrowser.ts b/src/firefox/ffBrowser.ts index 5cd1220df89c4..7adcf7cc734cc 100644 --- a/src/firefox/ffBrowser.ts +++ b/src/firefox/ffBrowser.ts @@ -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; } } diff --git a/src/firefox/ffConnection.ts b/src/firefox/ffConnection.ts index 006d33155c5ec..b571fa1d15304 100644 --- a/src/firefox/ffConnection.ts +++ b/src/firefox/ffConnection.ts @@ -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; private _transport: ConnectionTransport; readonly _sessions: Map; - _debugProtocol: (message: string) => void = platform.debug('pw:protocol'); + _debugProtocol: platform.DebuggerType = platform.debug('pw:protocol'); _closed: boolean; on: (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); } diff --git a/src/platform.ts b/src/platform.ts index 5f5253b2a9f7e..129f16e879c25 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -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(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() { diff --git a/src/server/chromium.ts b/src/server/chromium.ts index cc3c93dbfbaa7..f14ca75e88b73 100644 --- a/src/server/chromium.ts +++ b/src/server/chromium.ts @@ -115,7 +115,7 @@ export class Chromium implements BrowserType { // 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) diff --git a/src/server/firefox.ts b/src/server/firefox.ts index fc4883a8305b0..b19a956ed23dc 100644 --- a/src/server/firefox.ts +++ b/src/server/firefox.ts @@ -130,7 +130,7 @@ export class Firefox implements BrowserType { // 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) diff --git a/src/server/pipeTransport.ts b/src/server/pipeTransport.ts index b089a28fb308a..01c94bfa386e3 100644 --- a/src/server/pipeTransport.ts +++ b/src/server/pipeTransport.ts @@ -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); diff --git a/src/server/webkit.ts b/src/server/webkit.ts index 5dc8fa6c1507f..700e7741559c2 100644 --- a/src/server/webkit.ts +++ b/src/server/webkit.ts @@ -114,8 +114,7 @@ export class WebKit implements BrowserType { // 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(); 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); } } diff --git a/src/transport.ts b/src/transport.ts index 6b56b5c145679..eb4ee484da265 100644 --- a/src/transport.ts +++ b/src/transport.ts @@ -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; - 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); } diff --git a/src/webkit/wkBrowser.ts b/src/webkit/wkBrowser.ts index 121a85c04cf14..1a87760af1992 100644 --- a/src/webkit/wkBrowser.ts +++ b/src/webkit/wkBrowser.ts @@ -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; } } diff --git a/src/webkit/wkConnection.ts b/src/webkit/wkConnection.ts index 754e5d5d77448..6326171ed16e0 100644 --- a/src/webkit/wkConnection.ts +++ b/src/webkit/wkConnection.ts @@ -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); }