Skip to content

Commit db19b06

Browse files
Matt Blagdenfacebook-github-bot
Matt Blagden
authored andcommittedSep 30, 2022
Support loading source URLs in inspector-proxy
Summary: The path to a source file may be a bundler service URL, rather than a filesystem path. This change makes the inspector-proxy detect when the source path is a URL, and fetch the source over HTTP (so long as the URL is on localhost). This change also includes a bit of reorganizing: the message-intercepting code is now responsible for sending the response, as some interceptions generate a synchronous response, some generate an asynchronous response, and some generate no response at all. As with errors when loading a file, a failure to load is sent to the client. Reviewed By: robhogan Differential Revision: D39629274 fbshipit-source-id: a205a015bff68190448f28350d481304ad207556
1 parent 0b4cd33 commit db19b06

File tree

2 files changed

+56
-38
lines changed

2 files changed

+56
-38
lines changed
 

‎packages/metro-inspector-proxy/src/Device.js

+56-24
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import type {
1313
DebuggerRequest,
14-
DebuggerResponse,
1514
GetScriptSourceRequest,
1615
GetScriptSourceResponse,
1716
MessageFromDevice,
@@ -21,6 +20,7 @@ import type {
2120
} from './types';
2221

2322
import * as fs from 'fs';
23+
import * as http from 'http';
2424
import * as path from 'path';
2525
import WS from 'ws';
2626

@@ -177,14 +177,13 @@ class Device {
177177
socket.on('message', (message: string) => {
178178
debug('(Debugger) -> (Proxy) (Device): ' + message);
179179
const debuggerRequest = JSON.parse(message);
180-
const interceptedResponse = this._interceptMessageFromDebugger(
180+
const handled = this._interceptMessageFromDebugger(
181181
debuggerRequest,
182182
debuggerInfo,
183+
socket,
183184
);
184185

185-
if (interceptedResponse) {
186-
socket.send(JSON.stringify(interceptedResponse));
187-
} else {
186+
if (!handled) {
188187
this._sendMessageToDevice({
189188
event: 'wrappedEvent',
190189
payload: {
@@ -437,21 +436,21 @@ class Device {
437436
}
438437
}
439438

440-
// Allows to make changes in incoming messages from debugger.
439+
// Allows to make changes in incoming messages from debugger. Returns a boolean
440+
// indicating whether the message has been handled locally (i.e. does not need
441+
// to be forwarded to the target).
441442
_interceptMessageFromDebugger(
442443
req: DebuggerRequest,
443444
debuggerInfo: DebuggerInfo,
444-
): ?DebuggerResponse {
445-
let response = null;
445+
socket: typeof WS,
446+
): boolean {
446447
if (req.method === 'Debugger.setBreakpointByUrl') {
447448
this._processDebuggerSetBreakpointByUrl(req, debuggerInfo);
448449
} else if (req.method === 'Debugger.getScriptSource') {
449-
response = {
450-
id: req.id,
451-
result: this._processDebuggerGetScriptSource(req),
452-
};
450+
this._processDebuggerGetScriptSource(req, socket);
451+
return true;
453452
}
454-
return response;
453+
return false;
455454
}
456455

457456
_processDebuggerSetBreakpointByUrl(
@@ -488,26 +487,59 @@ class Device {
488487

489488
_processDebuggerGetScriptSource(
490489
req: GetScriptSourceRequest,
491-
): GetScriptSourceResponse {
490+
socket: typeof WS,
491+
) {
492492
let scriptSource = `Source for script with id '${req.params.scriptId}' was not found.`;
493493

494+
const sendResponse = () => {
495+
const result: GetScriptSourceResponse = {scriptSource};
496+
socket.send(JSON.stringify({id: req.id, result}));
497+
};
498+
494499
const pathToSource = this._scriptIdToSourcePathMapping.get(
495500
req.params.scriptId,
496501
);
497502
if (pathToSource) {
503+
let pathIsURL = false;
498504
try {
499-
scriptSource = fs.readFileSync(
500-
path.resolve(this._projectRoot, pathToSource),
501-
'utf8',
502-
);
503-
} catch (err) {
504-
scriptSource = err.message;
505+
pathIsURL = new URL(pathToSource).hostname == 'localhost';
506+
} catch {}
507+
508+
if (pathIsURL) {
509+
http
510+
.get(pathToSource, httpResponse => {
511+
const {statusCode} = httpResponse;
512+
if (statusCode == 200) {
513+
httpResponse.setEncoding('utf8');
514+
scriptSource = '';
515+
httpResponse.on('data', body => {
516+
scriptSource += body;
517+
});
518+
httpResponse.on('end', () => {
519+
sendResponse();
520+
});
521+
} else {
522+
scriptSource = `Fetching ${pathToSource} returned status ${statusCode}`;
523+
sendResponse();
524+
httpResponse.resume();
525+
}
526+
})
527+
.on('error', e => {
528+
scriptSource = `Fetching ${pathToSource} failed with error ${e.message}`;
529+
sendResponse();
530+
});
531+
} else {
532+
try {
533+
scriptSource = fs.readFileSync(
534+
path.resolve(this._projectRoot, pathToSource),
535+
'utf8',
536+
);
537+
} catch (err) {
538+
scriptSource = err.message;
539+
}
540+
sendResponse();
505541
}
506542
}
507-
508-
return {
509-
scriptSource,
510-
};
511543
}
512544

513545
_mapToDevicePageId(pageId: string): string {

‎packages/metro-inspector-proxy/src/types.js

-14
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,6 @@ export type SetBreakpointByUrlRequest = {
110110
},
111111
};
112112

113-
export type SetBreakpointByUrlResponse = {
114-
breakpointId: string,
115-
locations: {
116-
scriptId: string,
117-
lineNumber: number,
118-
columnNumber?: number,
119-
}[],
120-
};
121-
122113
export type GetScriptSourceRequest = {
123114
id: number,
124115
method: 'Debugger.getScriptSource',
@@ -138,8 +129,3 @@ export type GetScriptSourceResponse = {
138129
export type DebuggerRequest =
139130
| SetBreakpointByUrlRequest
140131
| GetScriptSourceRequest;
141-
142-
export type DebuggerResponse = {
143-
id: number,
144-
result: SetBreakpointByUrlResponse | GetScriptSourceResponse,
145-
};

0 commit comments

Comments
 (0)
Please sign in to comment.