Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use exact, read-only types for protocol data structures #41315

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 22 additions & 17 deletions packages/dev-middleware/src/inspector-proxy/Device.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default class Device {
_deviceSocket: WS;

// Stores last list of device's pages.
_pages: Array<Page>;
_pages: $ReadOnlyArray<Page>;

// Stores information about currently connected debugger (if any).
_debuggerConnection: ?DebuggerInfo = null;
Expand Down Expand Up @@ -152,7 +152,7 @@ export default class Device {
return this._app;
}

getPagesList(): Array<Page> {
getPagesList(): $ReadOnlyArray<Page> {
if (this._lastConnectedReactNativePage) {
const reactNativeReloadablePage = {
id: REACT_NATIVE_RELOADABLE_PAGE_ID,
Expand Down Expand Up @@ -216,18 +216,18 @@ export default class Device {
pageId: this._debuggerConnection?.pageId ?? null,
frontendUserAgent: metadata.userAgent,
});
const handled = this._interceptMessageFromDebugger(
const processedReq = this._interceptMessageFromDebugger(
debuggerRequest,
debuggerInfo,
socket,
);

if (!handled) {
if (processedReq) {
this._sendMessageToDevice({
event: 'wrappedEvent',
payload: {
pageId: this._mapToDevicePageId(pageId),
wrappedEvent: JSON.stringify(debuggerRequest),
wrappedEvent: JSON.stringify(processedReq),
},
});
}
Expand Down Expand Up @@ -545,46 +545,51 @@ export default class Device {
req: DebuggerRequest,
debuggerInfo: DebuggerInfo,
socket: WS,
): boolean {
): ?DebuggerRequest {
if (req.method === 'Debugger.setBreakpointByUrl') {
this._processDebuggerSetBreakpointByUrl(req, debuggerInfo);
return this._processDebuggerSetBreakpointByUrl(req, debuggerInfo);
} else if (req.method === 'Debugger.getScriptSource') {
this._processDebuggerGetScriptSource(req, socket);
return true;
return null;
}
return false;
return req;
}

_processDebuggerSetBreakpointByUrl(
req: SetBreakpointByUrlRequest,
debuggerInfo: DebuggerInfo,
) {
): SetBreakpointByUrlRequest {
// If we replaced Android emulator's address to localhost we need to change it back.
if (debuggerInfo.originalSourceURLAddress != null) {
if (req.params.url != null) {
req.params.url = req.params.url.replace(
const processedReq = {...req, params: {...req.params}};
if (processedReq.params.url != null) {
processedReq.params.url = processedReq.params.url.replace(
'localhost',
debuggerInfo.originalSourceURLAddress,
);

if (
req.params.url &&
req.params.url.startsWith(FILE_PREFIX) &&
processedReq.params.url &&
processedReq.params.url.startsWith(FILE_PREFIX) &&
debuggerInfo.prependedFilePrefix
) {
// Remove fake URL prefix if we modified URL in _processMessageFromDevice.
// $FlowFixMe[incompatible-use]
req.params.url = req.params.url.slice(FILE_PREFIX.length);
processedReq.params.url = processedReq.params.url.slice(
FILE_PREFIX.length,
);
}
}
if (req.params.urlRegex != null) {
req.params.urlRegex = req.params.urlRegex.replace(
if (processedReq.params.urlRegex != null) {
processedReq.params.urlRegex = processedReq.params.urlRegex.replace(
/localhost/g,
// $FlowFixMe[incompatible-call]
debuggerInfo.originalSourceURLAddress,
);
}
return processedReq;
}
return req;
}

_processDebuggerGetScriptSource(req: GetScriptSourceRequest, socket: WS) {
Expand Down
77 changes: 36 additions & 41 deletions packages/dev-middleware/src/inspector-proxy/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,49 +12,43 @@
// Page information received from the device. New page is created for
// each new instance of VM and can appear when user reloads React Native
// application.
export type Page = {
export type Page = $ReadOnly<{
id: string,
title: string,
vm: string,
app: string,
...
};
}>;

// Chrome Debugger Protocol message/event passed between device and debugger.
export type WrappedEvent = {
export type WrappedEvent = $ReadOnly<{
event: 'wrappedEvent',
payload: {
payload: $ReadOnly<{
pageId: string,
wrappedEvent: string,
...
},
...
};
}>,
}>;

// Request sent from Inspector Proxy to Device when new debugger is connected
// to particular page.
export type ConnectRequest = {
export type ConnectRequest = $ReadOnly<{
event: 'connect',
payload: {pageId: string, ...},
...
};
payload: $ReadOnly<{pageId: string}>,
}>;

// Request sent from Inspector Proxy to Device to notify that debugger is
// disconnected.
export type DisconnectRequest = {
export type DisconnectRequest = $ReadOnly<{
event: 'disconnect',
payload: {pageId: string, ...},
...
};
payload: $ReadOnly<{pageId: string}>,
}>;

// Request sent from Inspector Proxy to Device to get a list of pages.
export type GetPagesRequest = {event: 'getPages', ...};
export type GetPagesRequest = {event: 'getPages'};

// Response to GetPagesRequest containing a list of page infos.
export type GetPagesResponse = {
event: 'getPages',
payload: Array<Page>,
...
payload: $ReadOnlyArray<Page>,
};

// Union type for all possible messages sent from device to Inspector Proxy.
Expand All @@ -71,68 +65,69 @@ export type MessageToDevice =
| DisconnectRequest;

// Page description object that is sent in response to /json HTTP request from debugger.
export type PageDescription = {
export type PageDescription = $ReadOnly<{
id: string,
description: string,
title: string,
faviconUrl: string,
devtoolsFrontendUrl: string,
type: string,
webSocketDebuggerUrl: string,
deviceName: string,
vm: string,
// Metadata specific to React Native
reactNative: {
reactNative: $ReadOnly<{
logicalDeviceId: string,
},
...
};
export type JsonPagesListResponse = Array<PageDescription>;
}>,
}>;

export type JsonPagesListResponse = $ReadOnlyArray<PageDescription>;

// Response to /json/version HTTP request from the debugger specifying browser type and
// Chrome protocol version.
export type JsonVersionResponse = {
export type JsonVersionResponse = $ReadOnly<{
Browser: string,
'Protocol-Version': string,
...
};
}>;

/**
* Types were exported from https://github.com/ChromeDevTools/devtools-protocol/blob/master/types/protocol.d.ts
*/

export type SetBreakpointByUrlRequest = {
export type SetBreakpointByUrlRequest = $ReadOnly<{
id: number,
method: 'Debugger.setBreakpointByUrl',
params: {
params: $ReadOnly<{
lineNumber: number,
url?: string,
urlRegex?: string,
scriptHash?: string,
columnNumber?: number,
condition?: string,
},
};
}>,
}>;

export type GetScriptSourceRequest = {
export type GetScriptSourceRequest = $ReadOnly<{
id: number,
method: 'Debugger.getScriptSource',
params: {
scriptId: string,
},
};
}>;

export type GetScriptSourceResponse = {
export type GetScriptSourceResponse = $ReadOnly<{
scriptSource: string,
/**
* Wasm bytecode.
*/
bytecode?: string,
};
}>;

export type ErrorResponse = {
error: {
export type ErrorResponse = $ReadOnly<{
error: $ReadOnly<{
message: string,
},
};
}>,
}>;

export type DebuggerRequest =
| SetBreakpointByUrlRequest
Expand Down