mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Migrate to private member syntax (#42299)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42299 Changelog: [Internal] TSIA Reviewed By: hoxyq Differential Revision: D52798108 fbshipit-source-id: 9ba980b9fb439b1aeee3eb1b08535b95556d72bb
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8e70acc235
commit
7a69fe424d
@@ -20,15 +20,15 @@ import until from 'wait-for-expect';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
export class DebuggerAgent {
|
||||
_ws: ?WebSocket;
|
||||
_readyPromise: Promise<void>;
|
||||
#ws: ?WebSocket;
|
||||
#readyPromise: Promise<void>;
|
||||
|
||||
constructor(url: string, signal?: AbortSignal) {
|
||||
const ws = new WebSocket(url, {
|
||||
// The mock server uses a self-signed certificate.
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
this._ws = ws;
|
||||
this.#ws = ws;
|
||||
ws.on('message', data => {
|
||||
this.__handle(JSON.parse(data.toString()));
|
||||
});
|
||||
@@ -37,7 +37,7 @@ export class DebuggerAgent {
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
this._readyPromise = new Promise<void>((resolve, reject) => {
|
||||
this.#readyPromise = new Promise<void>((resolve, reject) => {
|
||||
ws.once('open', () => {
|
||||
resolve();
|
||||
});
|
||||
@@ -50,29 +50,29 @@ export class DebuggerAgent {
|
||||
__handle(message: JSONSerializable): void {}
|
||||
|
||||
send(message: JSONSerializable) {
|
||||
if (!this._ws) {
|
||||
if (!this.#ws) {
|
||||
return;
|
||||
}
|
||||
this._ws.send(JSON.stringify(message));
|
||||
this.#ws.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
ready(): Promise<void> {
|
||||
return this._readyPromise;
|
||||
return this.#readyPromise;
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this._ws) {
|
||||
if (!this.#ws) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this._ws.terminate();
|
||||
this.#ws.terminate();
|
||||
} catch {}
|
||||
this._ws = null;
|
||||
this.#ws = null;
|
||||
}
|
||||
|
||||
// $FlowIgnore[unsafe-getters-setters]
|
||||
get socket(): WebSocket {
|
||||
return nullthrows(this._ws);
|
||||
return nullthrows(this.#ws);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,15 +23,15 @@ import type {
|
||||
import WebSocket from 'ws';
|
||||
|
||||
export class DeviceAgent {
|
||||
_ws: ?WebSocket;
|
||||
_readyPromise: Promise<void>;
|
||||
#ws: ?WebSocket;
|
||||
#readyPromise: Promise<void>;
|
||||
|
||||
constructor(url: string, signal?: AbortSignal) {
|
||||
const ws = new WebSocket(url, {
|
||||
// The mock server uses a self-signed certificate.
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
this._ws = ws;
|
||||
this.#ws = ws;
|
||||
ws.on('message', data => {
|
||||
this.__handle(JSON.parse(data.toString()));
|
||||
});
|
||||
@@ -40,7 +40,7 @@ export class DeviceAgent {
|
||||
this.close();
|
||||
});
|
||||
}
|
||||
this._readyPromise = new Promise<void>((resolve, reject) => {
|
||||
this.#readyPromise = new Promise<void>((resolve, reject) => {
|
||||
ws.once('open', () => {
|
||||
resolve();
|
||||
});
|
||||
@@ -53,24 +53,24 @@ export class DeviceAgent {
|
||||
__handle(message: MessageToDevice): void {}
|
||||
|
||||
send(message: MessageFromDevice) {
|
||||
if (!this._ws) {
|
||||
if (!this.#ws) {
|
||||
return;
|
||||
}
|
||||
this._ws.send(JSON.stringify(message));
|
||||
this.#ws.send(JSON.stringify(message));
|
||||
}
|
||||
|
||||
ready(): Promise<void> {
|
||||
return this._readyPromise;
|
||||
return this.#readyPromise;
|
||||
}
|
||||
|
||||
close() {
|
||||
if (!this._ws) {
|
||||
if (!this.#ws) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this._ws.terminate();
|
||||
this.#ws.terminate();
|
||||
} catch {}
|
||||
this._ws = null;
|
||||
this.#ws = null;
|
||||
}
|
||||
|
||||
sendWrappedEvent(pageId: string, event: JSONSerializable) {
|
||||
@@ -110,7 +110,7 @@ export class DeviceMock extends DeviceAgent {
|
||||
break;
|
||||
case 'getPages':
|
||||
const result = this.getPages(message);
|
||||
this._sendPayloadIfNonNull('getPages', result);
|
||||
this.#sendPayloadIfNonNull('getPages', result);
|
||||
break;
|
||||
case 'wrappedEvent':
|
||||
this.wrappedEvent(message);
|
||||
@@ -125,7 +125,7 @@ export class DeviceMock extends DeviceAgent {
|
||||
}
|
||||
}
|
||||
|
||||
_sendPayloadIfNonNull<Event: MessageFromDevice['event']>(
|
||||
#sendPayloadIfNonNull<Event: MessageFromDevice['event']>(
|
||||
event: Event,
|
||||
maybePayload:
|
||||
| MessageFromDevice['payload']
|
||||
|
||||
@@ -34,7 +34,7 @@ const PAGES_POLLING_INTERVAL = 1000;
|
||||
// Android's stock emulator and other emulators such as genymotion use a standard localhost alias.
|
||||
const EMULATOR_LOCALHOST_ADDRESSES: Array<string> = ['10.0.2.2', '10.0.3.2'];
|
||||
|
||||
// Prefix for script URLs that are alphanumeric IDs. See comment in _processMessageFromDevice method for
|
||||
// Prefix for script URLs that are alphanumeric IDs. See comment in #processMessageFromDevice method for
|
||||
// more details.
|
||||
const FILE_PREFIX = 'file://';
|
||||
|
||||
@@ -57,43 +57,43 @@ const REACT_NATIVE_RELOADABLE_PAGE_ID = '-1';
|
||||
*/
|
||||
export default class Device {
|
||||
// ID of the device.
|
||||
_id: string;
|
||||
#id: string;
|
||||
|
||||
// Name of the device.
|
||||
_name: string;
|
||||
#name: string;
|
||||
|
||||
// Package name of the app.
|
||||
_app: string;
|
||||
#app: string;
|
||||
|
||||
// Stores socket connection between Inspector Proxy and device.
|
||||
_deviceSocket: WS;
|
||||
#deviceSocket: WS;
|
||||
|
||||
// Stores last list of device's pages.
|
||||
_pages: $ReadOnlyArray<Page>;
|
||||
#pages: $ReadOnlyArray<Page>;
|
||||
|
||||
// Stores information about currently connected debugger (if any).
|
||||
_debuggerConnection: ?DebuggerInfo = null;
|
||||
#debuggerConnection: ?DebuggerInfo = null;
|
||||
|
||||
// Last known Page ID of the React Native page.
|
||||
// This is used by debugger connections that don't have PageID specified
|
||||
// (and will interact with the latest React Native page).
|
||||
_lastConnectedReactNativePage: ?Page = null;
|
||||
#lastConnectedReactNativePage: ?Page = null;
|
||||
|
||||
// Whether we are in the middle of a reload in the REACT_NATIVE_RELOADABLE_PAGE.
|
||||
_isReloading: boolean = false;
|
||||
#isReloading: boolean = false;
|
||||
|
||||
// The previous "GetPages" message, for deduplication in debug logs.
|
||||
_lastGetPagesMessage: string = '';
|
||||
#lastGetPagesMessage: string = '';
|
||||
|
||||
// Mapping built from scriptParsed events and used to fetch file content in `Debugger.getScriptSource`.
|
||||
_scriptIdToSourcePathMapping: Map<string, string> = new Map();
|
||||
#scriptIdToSourcePathMapping: Map<string, string> = new Map();
|
||||
|
||||
// Root of the project used for relative to absolute source path conversion.
|
||||
_projectRoot: string;
|
||||
#projectRoot: string;
|
||||
|
||||
_deviceEventReporter: ?DeviceEventReporter;
|
||||
#deviceEventReporter: ?DeviceEventReporter;
|
||||
|
||||
_pagesPollingIntervalId: ReturnType<typeof setInterval>;
|
||||
#pagesPollingIntervalId: ReturnType<typeof setInterval>;
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -103,13 +103,13 @@ export default class Device {
|
||||
projectRoot: string,
|
||||
eventReporter: ?EventReporter,
|
||||
) {
|
||||
this._id = id;
|
||||
this._name = name;
|
||||
this._app = app;
|
||||
this._pages = [];
|
||||
this._deviceSocket = socket;
|
||||
this._projectRoot = projectRoot;
|
||||
this._deviceEventReporter = eventReporter
|
||||
this.#id = id;
|
||||
this.#name = name;
|
||||
this.#app = app;
|
||||
this.#pages = [];
|
||||
this.#deviceSocket = socket;
|
||||
this.#projectRoot = projectRoot;
|
||||
this.#deviceEventReporter = eventReporter
|
||||
? new DeviceEventReporter(eventReporter, {
|
||||
deviceId: id,
|
||||
deviceName: name,
|
||||
@@ -118,57 +118,57 @@ export default class Device {
|
||||
: null;
|
||||
|
||||
// $FlowFixMe[incompatible-call]
|
||||
this._deviceSocket.on('message', (message: string) => {
|
||||
this.#deviceSocket.on('message', (message: string) => {
|
||||
const parsedMessage = JSON.parse(message);
|
||||
if (parsedMessage.event === 'getPages') {
|
||||
// There's a 'getPages' message every second, so only show them if they change
|
||||
if (message !== this._lastGetPagesMessage) {
|
||||
if (message !== this.#lastGetPagesMessage) {
|
||||
debug(
|
||||
'(Debugger) (Proxy) <- (Device), getPages ping has changed: ' +
|
||||
message,
|
||||
);
|
||||
this._lastGetPagesMessage = message;
|
||||
this.#lastGetPagesMessage = message;
|
||||
}
|
||||
} else {
|
||||
debug('(Debugger) (Proxy) <- (Device): ' + message);
|
||||
}
|
||||
this._handleMessageFromDevice(parsedMessage);
|
||||
this.#handleMessageFromDevice(parsedMessage);
|
||||
});
|
||||
// Sends 'getPages' request to device every PAGES_POLLING_INTERVAL milliseconds.
|
||||
this._pagesPollingIntervalId = setInterval(
|
||||
() => this._sendMessageToDevice({event: 'getPages'}),
|
||||
this.#pagesPollingIntervalId = setInterval(
|
||||
() => this.#sendMessageToDevice({event: 'getPages'}),
|
||||
PAGES_POLLING_INTERVAL,
|
||||
);
|
||||
this._deviceSocket.on('close', () => {
|
||||
this._deviceEventReporter?.logDisconnection('device');
|
||||
this.#deviceSocket.on('close', () => {
|
||||
this.#deviceEventReporter?.logDisconnection('device');
|
||||
// Device disconnected - close debugger connection.
|
||||
if (this._debuggerConnection) {
|
||||
this._debuggerConnection.socket.close();
|
||||
this._debuggerConnection = null;
|
||||
if (this.#debuggerConnection) {
|
||||
this.#debuggerConnection.socket.close();
|
||||
this.#debuggerConnection = null;
|
||||
}
|
||||
clearInterval(this._pagesPollingIntervalId);
|
||||
clearInterval(this.#pagesPollingIntervalId);
|
||||
});
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this._name;
|
||||
return this.#name;
|
||||
}
|
||||
|
||||
getApp(): string {
|
||||
return this._app;
|
||||
return this.#app;
|
||||
}
|
||||
|
||||
getPagesList(): $ReadOnlyArray<Page> {
|
||||
if (this._lastConnectedReactNativePage) {
|
||||
if (this.#lastConnectedReactNativePage) {
|
||||
const reactNativeReloadablePage = {
|
||||
id: REACT_NATIVE_RELOADABLE_PAGE_ID,
|
||||
title: 'React Native Experimental (Improved Chrome Reloads)',
|
||||
vm: "don't use",
|
||||
app: this._app,
|
||||
app: this.#app,
|
||||
};
|
||||
return this._pages.concat(reactNativeReloadablePage);
|
||||
return this.#pages.concat(reactNativeReloadablePage);
|
||||
} else {
|
||||
return this._pages;
|
||||
return this.#pages;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,17 +184,17 @@ export default class Device {
|
||||
}>,
|
||||
) {
|
||||
// Clear any commands we were waiting on.
|
||||
this._deviceEventReporter?.logDisconnection('debugger');
|
||||
this.#deviceEventReporter?.logDisconnection('debugger');
|
||||
|
||||
this._deviceEventReporter?.logConnection('debugger', {
|
||||
this.#deviceEventReporter?.logConnection('debugger', {
|
||||
pageId,
|
||||
frontendUserAgent: metadata.userAgent,
|
||||
});
|
||||
|
||||
// Disconnect current debugger if we already have debugger connected.
|
||||
if (this._debuggerConnection) {
|
||||
this._debuggerConnection.socket.close();
|
||||
this._debuggerConnection = null;
|
||||
if (this.#debuggerConnection) {
|
||||
this.#debuggerConnection.socket.close();
|
||||
this.#debuggerConnection = null;
|
||||
}
|
||||
|
||||
const debuggerInfo = {
|
||||
@@ -203,14 +203,14 @@ export default class Device {
|
||||
pageId,
|
||||
userAgent: metadata.userAgent,
|
||||
};
|
||||
this._debuggerConnection = debuggerInfo;
|
||||
this.#debuggerConnection = debuggerInfo;
|
||||
|
||||
debug(`Got new debugger connection for page ${pageId} of ${this._name}`);
|
||||
debug(`Got new debugger connection for page ${pageId} of ${this.#name}`);
|
||||
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'connect',
|
||||
payload: {
|
||||
pageId: this._mapToDevicePageId(pageId),
|
||||
pageId: this.#mapToDevicePageId(pageId),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -218,36 +218,36 @@ export default class Device {
|
||||
socket.on('message', (message: string) => {
|
||||
debug('(Debugger) -> (Proxy) (Device): ' + message);
|
||||
const debuggerRequest = JSON.parse(message);
|
||||
this._deviceEventReporter?.logRequest(debuggerRequest, 'debugger', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
this.#deviceEventReporter?.logRequest(debuggerRequest, 'debugger', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: metadata.userAgent,
|
||||
});
|
||||
const processedReq = this._interceptMessageFromDebugger(
|
||||
const processedReq = this.#interceptMessageFromDebugger(
|
||||
debuggerRequest,
|
||||
debuggerInfo,
|
||||
socket,
|
||||
);
|
||||
|
||||
if (processedReq) {
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'wrappedEvent',
|
||||
payload: {
|
||||
pageId: this._mapToDevicePageId(pageId),
|
||||
pageId: this.#mapToDevicePageId(pageId),
|
||||
wrappedEvent: JSON.stringify(processedReq),
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
socket.on('close', () => {
|
||||
debug(`Debugger for page ${pageId} and ${this._name} disconnected.`);
|
||||
this._deviceEventReporter?.logDisconnection('debugger');
|
||||
this._sendMessageToDevice({
|
||||
debug(`Debugger for page ${pageId} and ${this.#name} disconnected.`);
|
||||
this.#deviceEventReporter?.logDisconnection('debugger');
|
||||
this.#sendMessageToDevice({
|
||||
event: 'disconnect',
|
||||
payload: {
|
||||
pageId: this._mapToDevicePageId(pageId),
|
||||
pageId: this.#mapToDevicePageId(pageId),
|
||||
},
|
||||
});
|
||||
this._debuggerConnection = null;
|
||||
this.#debuggerConnection = null;
|
||||
});
|
||||
|
||||
// $FlowFixMe[method-unbinding]
|
||||
@@ -270,19 +270,19 @@ export default class Device {
|
||||
*/
|
||||
handleDuplicateDeviceConnection(newDevice: Device) {
|
||||
if (
|
||||
this._app !== newDevice.getApp() ||
|
||||
this._name !== newDevice.getName()
|
||||
this.#app !== newDevice.getApp() ||
|
||||
this.#name !== newDevice.getName()
|
||||
) {
|
||||
this._deviceSocket.close();
|
||||
this._debuggerConnection?.socket.close();
|
||||
this.#deviceSocket.close();
|
||||
this.#debuggerConnection?.socket.close();
|
||||
}
|
||||
|
||||
const oldDebugger = this._debuggerConnection;
|
||||
this._debuggerConnection = null;
|
||||
const oldDebugger = this.#debuggerConnection;
|
||||
this.#debuggerConnection = null;
|
||||
|
||||
if (oldDebugger) {
|
||||
oldDebugger.socket.removeAllListeners();
|
||||
this._deviceSocket.close();
|
||||
this.#deviceSocket.close();
|
||||
newDevice.handleDebuggerConnection(
|
||||
oldDebugger.socket,
|
||||
oldDebugger.pageId,
|
||||
@@ -294,25 +294,25 @@ export default class Device {
|
||||
}
|
||||
|
||||
// Handles messages received from device:
|
||||
// 1. For getPages responses updates local _pages list.
|
||||
// 1. For getPages responses updates local #pages list.
|
||||
// 2. All other messages are forwarded to debugger as wrappedEvent.
|
||||
//
|
||||
// In the future more logic will be added to this method for modifying
|
||||
// some of the messages (like updating messages with source maps and file
|
||||
// locations).
|
||||
_handleMessageFromDevice(message: MessageFromDevice) {
|
||||
#handleMessageFromDevice(message: MessageFromDevice) {
|
||||
if (message.event === 'getPages') {
|
||||
this._pages = message.payload;
|
||||
this.#pages = message.payload;
|
||||
|
||||
// Check if device have new React Native page.
|
||||
// There is usually no more than 2-3 pages per device so this operation
|
||||
// is not expensive.
|
||||
// TODO(hypuk): It is better for VM to send update event when new page is
|
||||
// created instead of manually checking this on every getPages result.
|
||||
for (let i = 0; i < this._pages.length; ++i) {
|
||||
if (this._pages[i].title.indexOf('React') >= 0) {
|
||||
if (this._pages[i].id !== this._lastConnectedReactNativePage?.id) {
|
||||
this._newReactNativePage(this._pages[i]);
|
||||
for (let i = 0; i < this.#pages.length; ++i) {
|
||||
if (this.#pages[i].title.indexOf('React') >= 0) {
|
||||
if (this.#pages[i].id !== this.#lastConnectedReactNativePage?.id) {
|
||||
this.#newReactNativePage(this.#pages[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -321,27 +321,27 @@ export default class Device {
|
||||
// Device sends disconnect events only when page is reloaded or
|
||||
// if debugger socket was disconnected.
|
||||
const pageId = message.payload.pageId;
|
||||
const debuggerSocket = this._debuggerConnection
|
||||
? this._debuggerConnection.socket
|
||||
const debuggerSocket = this.#debuggerConnection
|
||||
? this.#debuggerConnection.socket
|
||||
: null;
|
||||
if (debuggerSocket && debuggerSocket.readyState === WS.OPEN) {
|
||||
if (
|
||||
this._debuggerConnection != null &&
|
||||
this._debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID
|
||||
this.#debuggerConnection != null &&
|
||||
this.#debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID
|
||||
) {
|
||||
debug(`Page ${pageId} is reloading.`);
|
||||
debuggerSocket.send(JSON.stringify({method: 'reload'}));
|
||||
}
|
||||
}
|
||||
} else if (message.event === 'wrappedEvent') {
|
||||
if (this._debuggerConnection == null) {
|
||||
if (this.#debuggerConnection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Is it possible that we received message for pageID that does not
|
||||
// correspond to current debugger connection?
|
||||
|
||||
const debuggerSocket = this._debuggerConnection.socket;
|
||||
const debuggerSocket = this.#debuggerConnection.socket;
|
||||
if (debuggerSocket == null || debuggerSocket.readyState !== WS.OPEN) {
|
||||
// TODO(hypuk): Send error back to device?
|
||||
return;
|
||||
@@ -349,18 +349,18 @@ export default class Device {
|
||||
|
||||
const parsedPayload = JSON.parse(message.payload.wrappedEvent);
|
||||
if ('id' in parsedPayload) {
|
||||
this._deviceEventReporter?.logResponse(parsedPayload, 'device', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this._debuggerConnection?.userAgent ?? null,
|
||||
this.#deviceEventReporter?.logResponse(parsedPayload, 'device', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
if (this._debuggerConnection) {
|
||||
if (this.#debuggerConnection) {
|
||||
// Wrapping just to make flow happy :)
|
||||
// $FlowFixMe[unused-promise]
|
||||
this._processMessageFromDevice(
|
||||
this.#processMessageFromDevice(
|
||||
parsedPayload,
|
||||
this._debuggerConnection,
|
||||
this.#debuggerConnection,
|
||||
).then(() => {
|
||||
const messageToSend = JSON.stringify(parsedPayload);
|
||||
debuggerSocket.send(messageToSend);
|
||||
@@ -370,31 +370,31 @@ export default class Device {
|
||||
}
|
||||
|
||||
// Sends single message to device.
|
||||
_sendMessageToDevice(message: MessageToDevice) {
|
||||
#sendMessageToDevice(message: MessageToDevice) {
|
||||
try {
|
||||
if (message.event !== 'getPages') {
|
||||
debug('(Debugger) (Proxy) -> (Device): ' + JSON.stringify(message));
|
||||
}
|
||||
this._deviceSocket.send(JSON.stringify(message));
|
||||
this.#deviceSocket.send(JSON.stringify(message));
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
// We received new React Native Page ID.
|
||||
_newReactNativePage(page: Page) {
|
||||
#newReactNativePage(page: Page) {
|
||||
debug(`React Native page updated to ${page.id}`);
|
||||
if (
|
||||
this._debuggerConnection == null ||
|
||||
this._debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID
|
||||
this.#debuggerConnection == null ||
|
||||
this.#debuggerConnection.pageId !== REACT_NATIVE_RELOADABLE_PAGE_ID
|
||||
) {
|
||||
// We can just remember new page ID without any further actions if no
|
||||
// debugger is currently attached or attached debugger is not
|
||||
// "Reloadable React Native" connection.
|
||||
this._lastConnectedReactNativePage = page;
|
||||
this.#lastConnectedReactNativePage = page;
|
||||
return;
|
||||
}
|
||||
const oldPageId = this._lastConnectedReactNativePage?.id;
|
||||
this._lastConnectedReactNativePage = page;
|
||||
this._isReloading = true;
|
||||
const oldPageId = this.#lastConnectedReactNativePage?.id;
|
||||
this.#lastConnectedReactNativePage = page;
|
||||
this.#isReloading = true;
|
||||
|
||||
// We already had a debugger connected to React Native page and a
|
||||
// new one appeared - in this case we need to emulate execution context
|
||||
@@ -402,7 +402,7 @@ export default class Device {
|
||||
// page.
|
||||
|
||||
if (oldPageId != null) {
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'disconnect',
|
||||
payload: {
|
||||
pageId: oldPageId,
|
||||
@@ -410,7 +410,7 @@ export default class Device {
|
||||
});
|
||||
}
|
||||
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'connect',
|
||||
payload: {
|
||||
pageId: page.id,
|
||||
@@ -423,14 +423,14 @@ export default class Device {
|
||||
];
|
||||
|
||||
for (const message of toSend) {
|
||||
this._deviceEventReporter?.logRequest(message, 'proxy', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this._debuggerConnection?.userAgent ?? null,
|
||||
this.#deviceEventReporter?.logRequest(message, 'proxy', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
|
||||
});
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'wrappedEvent',
|
||||
payload: {
|
||||
pageId: this._mapToDevicePageId(page.id),
|
||||
pageId: this.#mapToDevicePageId(page.id),
|
||||
wrappedEvent: JSON.stringify(message),
|
||||
},
|
||||
});
|
||||
@@ -438,7 +438,7 @@ export default class Device {
|
||||
}
|
||||
|
||||
// Allows to make changes in incoming message from device.
|
||||
async _processMessageFromDevice(
|
||||
async #processMessageFromDevice(
|
||||
payload: {method: string, params: {sourceMapURL: string, url: string}},
|
||||
debuggerInfo: DebuggerInfo,
|
||||
) {
|
||||
@@ -457,7 +457,7 @@ export default class Device {
|
||||
}
|
||||
}
|
||||
|
||||
const sourceMapURL = this._tryParseHTTPURL(params.sourceMapURL);
|
||||
const sourceMapURL = this.#tryParseHTTPURL(params.sourceMapURL);
|
||||
if (sourceMapURL) {
|
||||
// Some debug clients do not support fetching HTTP URLs. If the
|
||||
// message headed to the debug client identifies the source map with
|
||||
@@ -465,12 +465,12 @@ export default class Device {
|
||||
// Data URL (which is more widely supported) before passing the
|
||||
// message to the debug client.
|
||||
try {
|
||||
const sourceMap = await this._fetchText(sourceMapURL);
|
||||
const sourceMap = await this.#fetchText(sourceMapURL);
|
||||
payload.params.sourceMapURL =
|
||||
'data:application/json;charset=utf-8;base64,' +
|
||||
new Buffer(sourceMap).toString('base64');
|
||||
} catch (exception) {
|
||||
this._sendErrorToDebugger(
|
||||
this.#sendErrorToDebugger(
|
||||
`Failed to fetch source map ${params.sourceMapURL}: ${exception.message}`,
|
||||
);
|
||||
}
|
||||
@@ -496,14 +496,14 @@ export default class Device {
|
||||
|
||||
// $FlowFixMe[prop-missing]
|
||||
if (params.scriptId != null) {
|
||||
this._scriptIdToSourcePathMapping.set(params.scriptId, params.url);
|
||||
this.#scriptIdToSourcePathMapping.set(params.scriptId, params.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
payload.method === 'Runtime.executionContextCreated' &&
|
||||
this._isReloading
|
||||
this.#isReloading
|
||||
) {
|
||||
// The new context is ready. First notify Chrome that we've reloaded so
|
||||
// it'll resend its breakpoints. If we do this earlier, we may not be
|
||||
@@ -520,40 +520,40 @@ export default class Device {
|
||||
// This is not an issue in VSCode/Nuclide where the IDE knows to resume
|
||||
// at its convenience.
|
||||
const resumeMessage = {method: 'Debugger.resume', id: 0};
|
||||
this._deviceEventReporter?.logRequest(resumeMessage, 'proxy', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this._debuggerConnection?.userAgent ?? null,
|
||||
this.#deviceEventReporter?.logRequest(resumeMessage, 'proxy', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
|
||||
});
|
||||
this._sendMessageToDevice({
|
||||
this.#sendMessageToDevice({
|
||||
event: 'wrappedEvent',
|
||||
payload: {
|
||||
pageId: this._mapToDevicePageId(debuggerInfo.pageId),
|
||||
pageId: this.#mapToDevicePageId(debuggerInfo.pageId),
|
||||
wrappedEvent: JSON.stringify(resumeMessage),
|
||||
},
|
||||
});
|
||||
|
||||
this._isReloading = false;
|
||||
this.#isReloading = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Allows to make changes in incoming messages from debugger. Returns a boolean
|
||||
// indicating whether the message has been handled locally (i.e. does not need
|
||||
// to be forwarded to the target).
|
||||
_interceptMessageFromDebugger(
|
||||
#interceptMessageFromDebugger(
|
||||
req: DebuggerRequest,
|
||||
debuggerInfo: DebuggerInfo,
|
||||
socket: WS,
|
||||
): ?DebuggerRequest {
|
||||
if (req.method === 'Debugger.setBreakpointByUrl') {
|
||||
return this._processDebuggerSetBreakpointByUrl(req, debuggerInfo);
|
||||
return this.#processDebuggerSetBreakpointByUrl(req, debuggerInfo);
|
||||
} else if (req.method === 'Debugger.getScriptSource') {
|
||||
this._processDebuggerGetScriptSource(req, socket);
|
||||
this.#processDebuggerGetScriptSource(req, socket);
|
||||
return null;
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
_processDebuggerSetBreakpointByUrl(
|
||||
#processDebuggerSetBreakpointByUrl(
|
||||
req: SetBreakpointByUrlRequest,
|
||||
debuggerInfo: DebuggerInfo,
|
||||
): SetBreakpointByUrlRequest {
|
||||
@@ -571,7 +571,7 @@ export default class Device {
|
||||
processedReq.params.url.startsWith(FILE_PREFIX) &&
|
||||
debuggerInfo.prependedFilePrefix
|
||||
) {
|
||||
// Remove fake URL prefix if we modified URL in _processMessageFromDevice.
|
||||
// Remove fake URL prefix if we modified URL in #processMessageFromDevice.
|
||||
// $FlowFixMe[incompatible-use]
|
||||
processedReq.params.url = processedReq.params.url.slice(
|
||||
FILE_PREFIX.length,
|
||||
@@ -590,14 +590,14 @@ export default class Device {
|
||||
return req;
|
||||
}
|
||||
|
||||
_processDebuggerGetScriptSource(req: GetScriptSourceRequest, socket: WS) {
|
||||
#processDebuggerGetScriptSource(req: GetScriptSourceRequest, socket: WS) {
|
||||
const sendSuccessResponse = (scriptSource: string) => {
|
||||
const result: GetScriptSourceResponse = {scriptSource};
|
||||
const response = {id: req.id, result};
|
||||
socket.send(JSON.stringify(response));
|
||||
this._deviceEventReporter?.logResponse(response, 'proxy', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this._debuggerConnection?.userAgent ?? null,
|
||||
this.#deviceEventReporter?.logResponse(response, 'proxy', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
|
||||
});
|
||||
};
|
||||
const sendErrorResponse = (error: string) => {
|
||||
@@ -607,20 +607,20 @@ export default class Device {
|
||||
socket.send(JSON.stringify(response));
|
||||
|
||||
// Send to the console as well, so the user can see it
|
||||
this._sendErrorToDebugger(error);
|
||||
this._deviceEventReporter?.logResponse(response, 'proxy', {
|
||||
pageId: this._debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this._debuggerConnection?.userAgent ?? null,
|
||||
this.#sendErrorToDebugger(error);
|
||||
this.#deviceEventReporter?.logResponse(response, 'proxy', {
|
||||
pageId: this.#debuggerConnection?.pageId ?? null,
|
||||
frontendUserAgent: this.#debuggerConnection?.userAgent ?? null,
|
||||
});
|
||||
};
|
||||
|
||||
const pathToSource = this._scriptIdToSourcePathMapping.get(
|
||||
const pathToSource = this.#scriptIdToSourcePathMapping.get(
|
||||
req.params.scriptId,
|
||||
);
|
||||
if (pathToSource != null) {
|
||||
const httpURL = this._tryParseHTTPURL(pathToSource);
|
||||
const httpURL = this.#tryParseHTTPURL(pathToSource);
|
||||
if (httpURL) {
|
||||
this._fetchText(httpURL).then(
|
||||
this.#fetchText(httpURL).then(
|
||||
text => sendSuccessResponse(text),
|
||||
err =>
|
||||
sendErrorResponse(
|
||||
@@ -631,7 +631,7 @@ export default class Device {
|
||||
let file;
|
||||
try {
|
||||
file = fs.readFileSync(
|
||||
path.resolve(this._projectRoot, pathToSource),
|
||||
path.resolve(this.#projectRoot, pathToSource),
|
||||
'utf8',
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -646,18 +646,18 @@ export default class Device {
|
||||
}
|
||||
}
|
||||
|
||||
_mapToDevicePageId(pageId: string): string {
|
||||
#mapToDevicePageId(pageId: string): string {
|
||||
if (
|
||||
pageId === REACT_NATIVE_RELOADABLE_PAGE_ID &&
|
||||
this._lastConnectedReactNativePage != null
|
||||
this.#lastConnectedReactNativePage != null
|
||||
) {
|
||||
return this._lastConnectedReactNativePage.id;
|
||||
return this.#lastConnectedReactNativePage.id;
|
||||
} else {
|
||||
return pageId;
|
||||
}
|
||||
}
|
||||
|
||||
_tryParseHTTPURL(url: string): ?URL {
|
||||
#tryParseHTTPURL(url: string): ?URL {
|
||||
let parsedURL: ?URL;
|
||||
try {
|
||||
parsedURL = new URL(url);
|
||||
@@ -673,7 +673,7 @@ export default class Device {
|
||||
|
||||
// Fetch text, raising an exception if the text could not be fetched,
|
||||
// or is too large.
|
||||
async _fetchText(url: URL): Promise<string> {
|
||||
async #fetchText(url: URL): Promise<string> {
|
||||
if (!['localhost', '127.0.0.1'].includes(url.hostname)) {
|
||||
throw new Error('remote fetches not permitted');
|
||||
}
|
||||
@@ -692,8 +692,8 @@ export default class Device {
|
||||
return text;
|
||||
}
|
||||
|
||||
_sendErrorToDebugger(message: string) {
|
||||
const debuggerSocket = this._debuggerConnection?.socket;
|
||||
#sendErrorToDebugger(message: string) {
|
||||
const debuggerSocket = this.#debuggerConnection?.socket;
|
||||
if (debuggerSocket && debuggerSocket.readyState === WS.OPEN) {
|
||||
debuggerSocket.send(
|
||||
JSON.stringify({
|
||||
|
||||
@@ -31,9 +31,9 @@ type RequestMetadata = $ReadOnly<{
|
||||
}>;
|
||||
|
||||
class DeviceEventReporter {
|
||||
_eventReporter: EventReporter;
|
||||
#eventReporter: EventReporter;
|
||||
|
||||
_pendingCommands: TTLCache<number, PendingCommand> = new TTLCache({
|
||||
#pendingCommands: TTLCache<number, PendingCommand> = new TTLCache({
|
||||
ttl: 10000,
|
||||
dispose: (
|
||||
command: PendingCommand,
|
||||
@@ -44,15 +44,15 @@ class DeviceEventReporter {
|
||||
// TODO: Report clobbering ('set') using a dedicated error code
|
||||
return;
|
||||
}
|
||||
this._logExpiredCommand(command);
|
||||
this.#logExpiredCommand(command);
|
||||
},
|
||||
});
|
||||
|
||||
_metadata: DeviceMetadata;
|
||||
#metadata: DeviceMetadata;
|
||||
|
||||
constructor(eventReporter: EventReporter, metadata: DeviceMetadata) {
|
||||
this._eventReporter = eventReporter;
|
||||
this._metadata = metadata;
|
||||
this.#eventReporter = eventReporter;
|
||||
this.#metadata = metadata;
|
||||
}
|
||||
|
||||
logRequest(
|
||||
@@ -60,7 +60,7 @@ class DeviceEventReporter {
|
||||
origin: 'debugger' | 'proxy',
|
||||
metadata: RequestMetadata,
|
||||
): void {
|
||||
this._pendingCommands.set(req.id, {
|
||||
this.#pendingCommands.set(req.id, {
|
||||
method: req.method,
|
||||
requestOrigin: origin,
|
||||
requestTime: Date.now(),
|
||||
@@ -80,9 +80,9 @@ class DeviceEventReporter {
|
||||
frontendUserAgent: string | null,
|
||||
}>,
|
||||
): void {
|
||||
const pendingCommand = this._pendingCommands.get(res.id);
|
||||
const pendingCommand = this.#pendingCommands.get(res.id);
|
||||
if (!pendingCommand) {
|
||||
this._eventReporter.logEvent({
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
protocol: 'CDP',
|
||||
requestOrigin: null,
|
||||
@@ -91,22 +91,22 @@ class DeviceEventReporter {
|
||||
errorCode: 'UNMATCHED_REQUEST_ID',
|
||||
responseOrigin: 'proxy',
|
||||
timeSinceStart: null,
|
||||
appId: this._metadata.appId,
|
||||
deviceId: this._metadata.deviceId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
appId: this.#metadata.appId,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
pageId: metadata.pageId,
|
||||
frontendUserAgent: metadata.frontendUserAgent,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const timeSinceStart = Date.now() - pendingCommand.requestTime;
|
||||
this._pendingCommands.delete(res.id);
|
||||
this.#pendingCommands.delete(res.id);
|
||||
if (res.error) {
|
||||
let {message} = res.error;
|
||||
if ('data' in res.error) {
|
||||
message += ` (${String(res.error.data)})`;
|
||||
}
|
||||
this._eventReporter.logEvent({
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
requestOrigin: pendingCommand.requestOrigin,
|
||||
method: pendingCommand.method,
|
||||
@@ -116,15 +116,15 @@ class DeviceEventReporter {
|
||||
errorDetails: message,
|
||||
responseOrigin: origin,
|
||||
timeSinceStart,
|
||||
appId: this._metadata.appId,
|
||||
deviceId: this._metadata.deviceId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
appId: this.#metadata.appId,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
pageId: pendingCommand.metadata.pageId,
|
||||
frontendUserAgent: pendingCommand.metadata.frontendUserAgent,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this._eventReporter.logEvent({
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
protocol: 'CDP',
|
||||
requestOrigin: pendingCommand.requestOrigin,
|
||||
@@ -132,9 +132,9 @@ class DeviceEventReporter {
|
||||
status: 'success',
|
||||
responseOrigin: origin,
|
||||
timeSinceStart,
|
||||
appId: this._metadata.appId,
|
||||
deviceId: this._metadata.deviceId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
appId: this.#metadata.appId,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
pageId: pendingCommand.metadata.pageId,
|
||||
frontendUserAgent: pendingCommand.metadata.frontendUserAgent,
|
||||
});
|
||||
@@ -147,19 +147,19 @@ class DeviceEventReporter {
|
||||
frontendUserAgent: string | null,
|
||||
}>,
|
||||
) {
|
||||
this._eventReporter.logEvent({
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'connect_debugger_frontend',
|
||||
status: 'success',
|
||||
appId: this._metadata.appId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
deviceId: this._metadata.deviceId,
|
||||
appId: this.#metadata.appId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
pageId: metadata.pageId,
|
||||
frontendUserAgent: metadata.frontendUserAgent,
|
||||
});
|
||||
}
|
||||
|
||||
logDisconnection(disconnectedEntity: 'device' | 'debugger') {
|
||||
const eventReporter = this._eventReporter;
|
||||
const eventReporter = this.#eventReporter;
|
||||
if (!eventReporter) {
|
||||
return;
|
||||
}
|
||||
@@ -167,8 +167,8 @@ class DeviceEventReporter {
|
||||
disconnectedEntity === 'device'
|
||||
? 'DEVICE_DISCONNECTED'
|
||||
: 'DEBUGGER_DISCONNECTED';
|
||||
for (const pendingCommand of this._pendingCommands.values()) {
|
||||
this._eventReporter.logEvent({
|
||||
for (const pendingCommand of this.#pendingCommands.values()) {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
protocol: 'CDP',
|
||||
requestOrigin: pendingCommand.requestOrigin,
|
||||
@@ -177,18 +177,18 @@ class DeviceEventReporter {
|
||||
errorCode,
|
||||
responseOrigin: 'proxy',
|
||||
timeSinceStart: Date.now() - pendingCommand.requestTime,
|
||||
appId: this._metadata.appId,
|
||||
deviceId: this._metadata.deviceId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
appId: this.#metadata.appId,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
pageId: pendingCommand.metadata.pageId,
|
||||
frontendUserAgent: pendingCommand.metadata.frontendUserAgent,
|
||||
});
|
||||
}
|
||||
this._pendingCommands.clear();
|
||||
this.#pendingCommands.clear();
|
||||
}
|
||||
|
||||
_logExpiredCommand(pendingCommand: PendingCommand): void {
|
||||
this._eventReporter.logEvent({
|
||||
#logExpiredCommand(pendingCommand: PendingCommand): void {
|
||||
this.#eventReporter.logEvent({
|
||||
type: 'debugger_command',
|
||||
protocol: 'CDP',
|
||||
requestOrigin: pendingCommand.requestOrigin,
|
||||
@@ -197,9 +197,9 @@ class DeviceEventReporter {
|
||||
errorCode: 'TIMED_OUT',
|
||||
responseOrigin: 'proxy',
|
||||
timeSinceStart: Date.now() - pendingCommand.requestTime,
|
||||
appId: this._metadata.appId,
|
||||
deviceId: this._metadata.deviceId,
|
||||
deviceName: this._metadata.deviceName,
|
||||
appId: this.#metadata.appId,
|
||||
deviceId: this.#metadata.deviceId,
|
||||
deviceName: this.#metadata.deviceName,
|
||||
pageId: pendingCommand.metadata.pageId,
|
||||
frontendUserAgent: pendingCommand.metadata.frontendUserAgent,
|
||||
});
|
||||
|
||||
@@ -42,20 +42,20 @@ export interface InspectorProxyQueries {
|
||||
*/
|
||||
export default class InspectorProxy implements InspectorProxyQueries {
|
||||
// Root of the project used for relative to absolute source path conversion.
|
||||
_projectRoot: string;
|
||||
#projectRoot: string;
|
||||
|
||||
/** The base URL to the dev server from the developer machine. */
|
||||
_serverBaseUrl: string;
|
||||
#serverBaseUrl: string;
|
||||
|
||||
// Maps device ID to Device instance.
|
||||
_devices: Map<string, Device>;
|
||||
#devices: Map<string, Device>;
|
||||
|
||||
// Internal counter for device IDs -- just gets incremented for each new device.
|
||||
_deviceCounter: number = 0;
|
||||
#deviceCounter: number = 0;
|
||||
|
||||
_eventReporter: ?EventReporter;
|
||||
#eventReporter: ?EventReporter;
|
||||
|
||||
_experiments: Experiments;
|
||||
#experiments: Experiments;
|
||||
|
||||
constructor(
|
||||
projectRoot: string,
|
||||
@@ -63,22 +63,22 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
eventReporter: ?EventReporter,
|
||||
experiments: Experiments,
|
||||
) {
|
||||
this._projectRoot = projectRoot;
|
||||
this._serverBaseUrl = serverBaseUrl;
|
||||
this._devices = new Map();
|
||||
this._eventReporter = eventReporter;
|
||||
this._experiments = experiments;
|
||||
this.#projectRoot = projectRoot;
|
||||
this.#serverBaseUrl = serverBaseUrl;
|
||||
this.#devices = new Map();
|
||||
this.#eventReporter = eventReporter;
|
||||
this.#experiments = experiments;
|
||||
}
|
||||
|
||||
getPageDescriptions(): Array<PageDescription> {
|
||||
// Build list of pages from all devices.
|
||||
let result: Array<PageDescription> = [];
|
||||
Array.from(this._devices.entries()).forEach(([deviceId, device]) => {
|
||||
Array.from(this.#devices.entries()).forEach(([deviceId, device]) => {
|
||||
result = result.concat(
|
||||
device
|
||||
.getPagesList()
|
||||
.map((page: Page) =>
|
||||
this._buildPageDescription(deviceId, device, page),
|
||||
this.#buildPageDescription(deviceId, device, page),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -99,9 +99,9 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
pathname === PAGES_LIST_JSON_URL ||
|
||||
pathname === PAGES_LIST_JSON_URL_2
|
||||
) {
|
||||
this._sendJsonResponse(response, this.getPageDescriptions());
|
||||
this.#sendJsonResponse(response, this.getPageDescriptions());
|
||||
} else if (pathname === PAGES_LIST_JSON_VERSION_URL) {
|
||||
this._sendJsonResponse(response, {
|
||||
this.#sendJsonResponse(response, {
|
||||
Browser: 'Mobile JavaScript',
|
||||
'Protocol-Version': '1.1',
|
||||
});
|
||||
@@ -114,19 +114,19 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
[path: string]: WS.Server,
|
||||
} {
|
||||
return {
|
||||
[WS_DEVICE_URL]: this._createDeviceConnectionWSServer(),
|
||||
[WS_DEBUGGER_URL]: this._createDebuggerConnectionWSServer(),
|
||||
[WS_DEVICE_URL]: this.#createDeviceConnectionWSServer(),
|
||||
[WS_DEBUGGER_URL]: this.#createDebuggerConnectionWSServer(),
|
||||
};
|
||||
}
|
||||
|
||||
// Converts page information received from device into PageDescription object
|
||||
// that is sent to debugger.
|
||||
_buildPageDescription(
|
||||
#buildPageDescription(
|
||||
deviceId: string,
|
||||
device: Device,
|
||||
page: Page,
|
||||
): PageDescription {
|
||||
const {host, protocol} = new URL(this._serverBaseUrl);
|
||||
const {host, protocol} = new URL(this.#serverBaseUrl);
|
||||
const webSocketScheme = protocol === 'https:' ? 'wss' : 'ws';
|
||||
|
||||
const webSocketUrlWithoutProtocol = `${host}${WS_DEBUGGER_URL}?device=${deviceId}&page=${page.id}`;
|
||||
@@ -157,7 +157,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
|
||||
// Sends object as response to HTTP request.
|
||||
// Just serializes object using JSON and sets required headers.
|
||||
_sendJsonResponse(
|
||||
#sendJsonResponse(
|
||||
response: ServerResponse,
|
||||
object: JsonPagesListResponse | JsonVersionResponse,
|
||||
) {
|
||||
@@ -176,7 +176,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
// HTTP GET params.
|
||||
// For each new websocket connection we parse device and app names and create
|
||||
// new instance of Device class.
|
||||
_createDeviceConnectionWSServer(): ws$WebSocketServer {
|
||||
#createDeviceConnectionWSServer(): ws$WebSocketServer {
|
||||
const wss = new WS.Server({
|
||||
noServer: true,
|
||||
perMessageDeflate: true,
|
||||
@@ -187,35 +187,35 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
// $FlowFixMe[value-as-type]
|
||||
wss.on('connection', async (socket: WS, req) => {
|
||||
try {
|
||||
const fallbackDeviceId = String(this._deviceCounter++);
|
||||
const fallbackDeviceId = String(this.#deviceCounter++);
|
||||
|
||||
const query = url.parse(req.url || '', true).query || {};
|
||||
const deviceId = query.device || fallbackDeviceId;
|
||||
const deviceName = query.name || 'Unknown';
|
||||
const appName = query.app || 'Unknown';
|
||||
|
||||
const oldDevice = this._devices.get(deviceId);
|
||||
const oldDevice = this.#devices.get(deviceId);
|
||||
const newDevice = new Device(
|
||||
deviceId,
|
||||
deviceName,
|
||||
appName,
|
||||
socket,
|
||||
this._projectRoot,
|
||||
this._eventReporter,
|
||||
this.#projectRoot,
|
||||
this.#eventReporter,
|
||||
);
|
||||
|
||||
if (oldDevice) {
|
||||
oldDevice.handleDuplicateDeviceConnection(newDevice);
|
||||
}
|
||||
|
||||
this._devices.set(deviceId, newDevice);
|
||||
this.#devices.set(deviceId, newDevice);
|
||||
|
||||
debug(
|
||||
`Got new connection: name=${deviceName}, app=${appName}, device=${deviceId}`,
|
||||
);
|
||||
|
||||
socket.on('close', () => {
|
||||
this._devices.delete(deviceId);
|
||||
this.#devices.delete(deviceId);
|
||||
debug(`Device ${deviceName} disconnected.`);
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -231,7 +231,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
// in /json response.
|
||||
// When debugger connects we try to parse device and page IDs from the query and pass
|
||||
// websocket object to corresponding Device instance.
|
||||
_createDebuggerConnectionWSServer(): ws$WebSocketServer {
|
||||
#createDebuggerConnectionWSServer(): ws$WebSocketServer {
|
||||
const wss = new WS.Server({
|
||||
noServer: true,
|
||||
perMessageDeflate: false,
|
||||
@@ -250,7 +250,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
throw new Error('Incorrect URL - must provide device and page IDs');
|
||||
}
|
||||
|
||||
const device = this._devices.get(deviceId);
|
||||
const device = this.#devices.get(deviceId);
|
||||
if (device == null) {
|
||||
throw new Error('Unknown device with ID ' + deviceId);
|
||||
}
|
||||
@@ -261,7 +261,7 @@ export default class InspectorProxy implements InspectorProxyQueries {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
socket.close(INTERNAL_ERROR_CODE, e?.toString() ?? 'Unknown error');
|
||||
this._eventReporter?.logEvent({
|
||||
this.#eventReporter?.logEvent({
|
||||
type: 'connect_debugger_frontend',
|
||||
status: 'error',
|
||||
error: e,
|
||||
|
||||
Reference in New Issue
Block a user