Skip to content

Commit 27f577f

Browse files
committed
feat(inspector): serve source maps to DevTools via Network.loadNetworkResource
Chrome DevTools no longer fetches external source maps itself when debugging remote targets: it issues Network.loadNetworkResource to the target and reads the result back through IO.read/IO.close. None of these embedder-side CDP domains are implemented by V8's inspector, so external source maps failed and apps had to fall back to bloated inline-source-map builds. - Handle Network.loadNetworkResource natively: resolve the URL back to a file on disk and reply with a stream handle (success:false + net::ERR_FILE_NOT_FOUND when missing). - Implement IO.read (1MB base64 chunks; eof only on a final empty read, since the frontend discards data accompanying eof) and IO.close. - Reply with a JSON-RPC error for unsupported schemes (e.g. https) so DevTools keeps its existing fallback of fetching from the host. - Rewrite sourceMapURL in outgoing Debugger.scriptParsed / Debugger.scriptFailedToParse events from relative/file:// URLs to a custom nsruntime:// scheme. DevTools hard-excludes file:, data: and devtools: URLs from loading through the target, so without the rewrite it would never send Network.loadNetworkResource and instead try (and fail) to read device files from the host machine. data: and http(s) URLs are left untouched, keeping inline source maps working. - Allow opting out via nativescript.config.ts: android.disableSourceMapURLRewrite (or the same key at the top level). - Serve these messages on the websocket read thread (new native handleMessageOnSocketThread), since the main-thread queue is unavailable exactly when DevTools needs source maps: the pause loop bypasses dispatchMessage and a busy isolate never drains the queue. The handler is V8-free and returns the response for Java to send on the receiving socket. - Make Debugger.pause interrupt busy JS via Isolate::RequestInterrupt, skipped while already paused in the nested loop to avoid a spurious re-pause after resume. - Vendor nlohmann/json v3.12.0 (third_party/json.hpp, header-only) for CDP message handling outside V8. Ports NativeScript/ios#385 and NativeScript/ios#378 to Android. Refs: nodejs/node#58077
1 parent d0afd1e commit 27f577f

5 files changed

Lines changed: 26119 additions & 1 deletion

File tree

test-app/app/src/main/java/com/tns/AndroidJsV8Inspector.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class AndroidJsV8Inspector {
3737

3838
protected native final void dispatchMessage(String message);
3939

40+
private native String handleMessageOnSocketThread(String message);
41+
4042
private Handler mainHandler;
4143

4244
private final Object debugBrkLock;
@@ -294,6 +296,22 @@ protected void onMessage(final NanoWSD.WebSocketFrame message) {
294296
Log.d("V8Inspector", "To dbg backend: " + message.getTextPayload() + " ThreadId:" + Thread.currentThread().getId());
295297
}
296298

299+
// Network.loadNetworkResource / IO.read / IO.close are served from
300+
// disk on this thread so source maps load even while the isolate is
301+
// paused at a breakpoint or busy running JS; Debugger.pause schedules
302+
// a V8 interrupt and still flows through the queue.
303+
String fastPathResponse = handleMessageOnSocketThread(message.getTextPayload());
304+
if (fastPathResponse != null) {
305+
try {
306+
send(fastPathResponse);
307+
} catch (IOException e) {
308+
if (com.tns.Runtime.isDebuggable()) {
309+
e.printStackTrace();
310+
}
311+
}
312+
return;
313+
}
314+
297315
inspectorMessages.offer(message.getTextPayload());
298316

299317
if (!AndroidJsV8Inspector.ReadyToProcessMessages.get()) {

0 commit comments

Comments
 (0)