diff --git a/src/mono/mono/component/mini-wasm-debugger.c b/src/mono/mono/component/mini-wasm-debugger.c index 77ceed873a245..5413e1acc7077 100644 --- a/src/mono/mono/component/mini-wasm-debugger.c +++ b/src/mono/mono/component/mini-wasm-debugger.c @@ -54,6 +54,8 @@ static gboolean has_pending_lazy_loaded_assemblies; #define THREAD_TO_INTERNAL(thread) (thread)->internal_thread +extern void mono_wasm_debugger_log (int level, char *message); + void wasm_debugger_log (int level, const gchar *format, ...) { va_list args; @@ -62,19 +64,7 @@ void wasm_debugger_log (int level, const gchar *format, ...) va_start (args, format); mesg = g_strdup_vprintf (format, args); va_end (args); - - EM_ASM ({ - var level = $0; - var message = Module.UTF8ToString ($1); - var namespace = "Debugger.Debug"; - - if (INTERNAL["logging"] && INTERNAL.logging["debugger"]) { - INTERNAL.logging.debugger (level, message); - return; - } - - console.debug("%s: %s", namespace, message); - }, level, mesg); + mono_wasm_debugger_log(level, mesg); g_free (mesg); } @@ -367,6 +357,8 @@ mono_wasm_set_is_debugger_attached (gboolean is_attached) } } +extern void mono_wasm_add_dbg_command_received(mono_bool res_ok, int id, void* buffer, int buffer_len); + EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, int command, guint8* data, unsigned int size, int valtype, char* newvalue) { @@ -374,9 +366,7 @@ mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, i buffer_init (&bufWithParms, 128); m_dbgprot_buffer_add_data (&bufWithParms, data, size); if (!write_value_to_buffer(&bufWithParms, valtype, newvalue)) { - EM_ASM ({ - INTERNAL.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); - }, 0, id, 0, 0); + mono_wasm_add_dbg_command_received(0, id, 0, 0); return TRUE; } mono_wasm_send_dbg_command(id, command_set, command, bufWithParms.buf, m_dbgprot_buffer_len(&bufWithParms)); @@ -402,10 +392,9 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, } else error = mono_process_dbg_packet (id, command_set, command, &no_reply, data, data + size, &buf); - EM_ASM ({ - INTERNAL.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); - }, error == MDBGPROT_ERR_NONE, id, buf.buf, buf.p-buf.buf); - + + mono_wasm_add_dbg_command_received(error == MDBGPROT_ERR_NONE, id, buf.buf, buf.p-buf.buf); + buffer_free (&buf); return TRUE; } @@ -413,9 +402,7 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, static gboolean receive_debugger_agent_message (void *data, int len) { - EM_ASM ({ - INTERNAL.mono_wasm_add_dbg_command_received (1, -1, $0, $1); - }, data, len); + mono_wasm_add_dbg_command_received(1, -1, data, len); mono_wasm_save_thread_context(); mono_wasm_fire_debugger_agent_message (); return FALSE; diff --git a/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs b/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs index c4de27f4ee9f6..f5dc5ecca471b 100644 --- a/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs +++ b/src/mono/wasm/debugger/BrowserDebugHost/Startup.cs @@ -151,6 +151,12 @@ async Task ConnectProxy(HttpContext context) } var endpoint = new Uri($"ws://{devToolsHost.Authority}{context.Request.Path}"); + int runtimeId = 0; + if (context.Request.Query.TryGetValue("RuntimeId", out StringValues runtimeIdValue) && + int.TryParse(runtimeIdValue.FirstOrDefault(), out int parsedId)) + { + runtimeId = parsedId; + } try { using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => @@ -159,7 +165,7 @@ async Task ConnectProxy(HttpContext context) ); context.Request.Query.TryGetValue("urlSymbolServer", out StringValues urlSymbolServerList); - var proxy = new DebuggerProxy(loggerFactory, urlSymbolServerList.ToList()); + var proxy = new DebuggerProxy(loggerFactory, urlSymbolServerList.ToList(), runtimeId); System.Net.WebSockets.WebSocket ideSocket = await context.WebSockets.AcceptWebSocketAsync(); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebuggerProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebuggerProxy.cs index 197f4dd6cea5d..4c030d98fe693 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebuggerProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebuggerProxy.cs @@ -17,9 +17,9 @@ public class DebuggerProxy { private readonly MonoProxy proxy; - public DebuggerProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList) + public DebuggerProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList, int runtimeId = 0) { - proxy = new MonoProxy(loggerFactory, urlSymbolServerList); + proxy = new MonoProxy(loggerFactory, urlSymbolServerList, runtimeId); } public Task Run(Uri browserUri, WebSocket ideSocket) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 3e7cfd87f010d..9795d345f8752 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -172,31 +172,31 @@ internal class MonoCommands public MonoCommands(string expression) => this.expression = expression; - public static MonoCommands GetDebuggerAgentBufferReceived() => new MonoCommands("INTERNAL.mono_wasm_get_dbg_command_info()"); + public static MonoCommands GetDebuggerAgentBufferReceived(int runtimeId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_get_dbg_command_info()"); - public static MonoCommands IsRuntimeReady() => new MonoCommands("INTERNAL.mono_wasm_runtime_is_ready"); + public static MonoCommands IsRuntimeReady(int runtimeId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_runtime_is_ready"); - public static MonoCommands GetLoadedFiles() => new MonoCommands("INTERNAL.mono_wasm_get_loaded_files()"); + public static MonoCommands GetLoadedFiles(int runtimeId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_get_loaded_files()"); - public static MonoCommands SendDebuggerAgentCommand(int id, int command_set, int command, string command_parameters) + public static MonoCommands SendDebuggerAgentCommand(int runtimeId, int id, int command_set, int command, string command_parameters) { - return new MonoCommands($"INTERNAL.mono_wasm_send_dbg_command ({id}, {command_set}, {command},'{command_parameters}')"); + return new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_send_dbg_command ({id}, {command_set}, {command},'{command_parameters}')"); } - public static MonoCommands SendDebuggerAgentCommandWithParms(int id, int command_set, int command, string command_parameters, int len, int type, string parm) + public static MonoCommands SendDebuggerAgentCommandWithParms(int runtimeId, int id, int command_set, int command, string command_parameters, int len, int type, string parm) { - return new MonoCommands($"INTERNAL.mono_wasm_send_dbg_command_with_parms ({id}, {command_set}, {command},'{command_parameters}', {len}, {type}, '{parm}')"); + return new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_send_dbg_command_with_parms ({id}, {command_set}, {command},'{command_parameters}', {len}, {type}, '{parm}')"); } - public static MonoCommands CallFunctionOn(JToken args) => new MonoCommands($"INTERNAL.mono_wasm_call_function_on ({args})"); + public static MonoCommands CallFunctionOn(int runtimeId, JToken args) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_call_function_on ({args})"); - public static MonoCommands GetDetails(int objectId, JToken args = null) => new MonoCommands($"INTERNAL.mono_wasm_get_details ({objectId}, {(args ?? "{ }")})"); + public static MonoCommands GetDetails(int runtimeId, int objectId, JToken args = null) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_get_details ({objectId}, {(args ?? "{ }")})"); - public static MonoCommands Resume() => new MonoCommands($"INTERNAL.mono_wasm_debugger_resume ()"); + public static MonoCommands Resume(int runtimeId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_debugger_resume ()"); - public static MonoCommands DetachDebugger() => new MonoCommands($"INTERNAL.mono_wasm_detach_debugger()"); + public static MonoCommands DetachDebugger(int runtimeId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_detach_debugger()"); - public static MonoCommands ReleaseObject(DotnetObjectId objectId) => new MonoCommands($"INTERNAL.mono_wasm_release_object('{objectId}')"); + public static MonoCommands ReleaseObject(int runtimeId, DotnetObjectId objectId) => new MonoCommands($"getDotnetRuntime({runtimeId}).INTERNAL.mono_wasm_release_object('{objectId}')"); } internal enum MonoErrorCodes diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 298c87646f05b..96977600f94e3 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -24,10 +24,13 @@ internal class MonoProxy : DevToolsProxy private Dictionary contexts = new Dictionary(); private const string sPauseOnUncaught = "pause_on_uncaught"; private const string sPauseOnCaught = "pause_on_caught"; + // index of the runtime in a same JS page/process + public int RuntimeId { get; private init; } - public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList) : base(loggerFactory) + public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList, int runtimeId = 0) : base(loggerFactory) { this.urlSymbolServerList = urlSymbolServerList ?? new List(); + RuntimeId = runtimeId; } internal ExecutionContext GetContext(SessionId sessionId) @@ -223,7 +226,7 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth case "Target.targetDestroyed": { - await SendMonoCommand(sessionId, MonoCommands.DetachDebugger(), token); + await SendMonoCommand(sessionId, MonoCommands.DetachDebugger(RuntimeId), token); break; } } @@ -236,7 +239,7 @@ private async Task IsRuntimeAlreadyReadyAlready(SessionId sessionId, Cance if (contexts.TryGetValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) return true; - Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(), token); + Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(RuntimeId), token); return res.Value?["result"]?["value"]?.Value() ?? false; } @@ -434,7 +437,7 @@ protected override async Task AcceptCommand(MessageId id, string method, J if (!(DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId) && objectId.Scheme == "cfo_res")) break; - await SendMonoCommand(id, MonoCommands.ReleaseObject(objectId), token); + await SendMonoCommand(id, MonoCommands.ReleaseObject(RuntimeId, objectId), token); SendResponse(id, Result.OkFromObject(new { }), token); return true; } @@ -558,7 +561,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation break; case "cfo_res": { - Result cfo_res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token); + Result cfo_res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(RuntimeId, args), token); cfo_res = Result.OkFromObject(new { result = cfo_res.Value?["result"]?["value"]}); SendResponse(id, cfo_res, token); return true; @@ -574,7 +577,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation default: return false; } - Result res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token); + Result res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(RuntimeId, args), token); if (res.IsErr) { SendResponse(id, res, token); @@ -652,7 +655,7 @@ internal async Task RuntimeGetPropertiesInternal(SessionId id, DotnetObj return new JArray{await context.SdbAgent.GetPointerContent(int.Parse(objectId.Value), token)}; case "cfo_res": { - Result res = await SendMonoCommand(id, MonoCommands.GetDetails(int.Parse(objectId.Value), args), token); + Result res = await SendMonoCommand(id, MonoCommands.GetDetails(RuntimeId, int.Parse(objectId.Value), args), token); string value_json_str = res.Value["result"]?["value"]?["__value_as_json_string__"]?.Value(); return value_json_str != null ? JArray.Parse(value_json_str) : null; } @@ -831,7 +834,7 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con } private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObject args, CancellationToken token) { - Result res = await SendMonoCommand(sessionId, MonoCommands.GetDebuggerAgentBufferReceived(), token); + Result res = await SendMonoCommand(sessionId, MonoCommands.GetDebuggerAgentBufferReceived(RuntimeId), token); if (res.IsErr) return false; @@ -966,11 +969,11 @@ private async Task OnDefaultContext(SessionId sessionId, ExecutionContext contex private async Task OnResume(MessageId msg_id, CancellationToken token) { - ExecutionContext ctx = GetContext(msg_id); - if (ctx.CallStack != null) + ExecutionContext context = GetContext(msg_id); + if (context.CallStack != null) { // Stopped on managed code - await SendMonoCommand(msg_id, MonoCommands.Resume(), token); + await SendMonoCommand(msg_id, MonoCommands.Resume(RuntimeId), token); } //discard managed frames @@ -1187,7 +1190,7 @@ internal async Task LoadStore(SessionId sessionId, CancellationToken if (loaded_files == null) { - Result loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(), token); + Result loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(RuntimeId), token); loaded_files = loaded.Value?["result"]?["value"]?.ToObject(); } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 4ad3f6a45cb71..e8ceee49cbb65 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -859,7 +859,7 @@ public async Task EnableReceiveRequests(EventKind eventKind, CancellationT } internal async Task SendDebuggerAgentCommand(T command, MonoBinaryWriter arguments, CancellationToken token) => - MonoBinaryReader.From (await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, arguments?.ToBase64().data ?? string.Empty), token)); + MonoBinaryReader.From (await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(proxy.RuntimeId, GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, arguments?.ToBase64().data ?? string.Empty), token)); internal CommandSet GetCommandSetForCommand(T command) => command switch { @@ -882,7 +882,7 @@ internal CommandSet GetCommandSetForCommand(T command) => }; internal async Task SendDebuggerAgentCommandWithParms(T command, (string data, int length) encoded, int type, string extraParm, CancellationToken token) => - MonoBinaryReader.From(await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, encoded.data, encoded.length, type, extraParm), token)); + MonoBinaryReader.From(await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(proxy.RuntimeId, GetId(), (int)GetCommandSetForCommand(command), (int)(object)command, encoded.data, encoded.length, type, extraParm), token)); public async Task CreateString(string value, CancellationToken token) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 0e7f79f7a2a7a..ea0d7c5569978 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -36,7 +36,7 @@ public async Task CreateJSBreakpoint() { // Test that js breakpoints get set correctly // 13 24 - // 13 33 + // 13 53 var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 24); Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); @@ -48,7 +48,7 @@ public async Task CreateJSBreakpoint() Assert.Equal(13, (int)loc["lineNumber"]); Assert.Equal(24, (int)loc["columnNumber"]); - var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33); + var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 53); Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); @@ -57,14 +57,14 @@ public async Task CreateJSBreakpoint() Assert.NotNull(loc2["scriptId"]); Assert.Equal(13, (int)loc2["lineNumber"]); - Assert.Equal(33, (int)loc2["columnNumber"]); + Assert.Equal(53, (int)loc2["columnNumber"]); } [Fact] public async Task CreateJS0Breakpoint() { // 13 24 - // 13 33 + // 13 53 var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 0); Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); @@ -74,9 +74,9 @@ public async Task CreateJS0Breakpoint() Assert.NotNull(loc["scriptId"]); Assert.Equal(13, (int)loc["lineNumber"]); - Assert.Equal(24, (int)loc["columnNumber"]); + Assert.Equal(4, (int)loc["columnNumber"]); - var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33); + var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 53); Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); @@ -85,7 +85,7 @@ public async Task CreateJS0Breakpoint() Assert.NotNull(loc2["scriptId"]); Assert.Equal(13, (int)loc2["lineNumber"]); - Assert.Equal(33, (int)loc2["columnNumber"]); + Assert.Equal(53, (int)loc2["columnNumber"]); } [Theory] diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs index 38742d8d36330..eacdda9f8b803 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs @@ -18,12 +18,12 @@ public async Task BadRaiseDebugEventsTest() { var bad_expressions = new[] { - "INTERNAL.mono_wasm_raise_debug_event('')", - "INTERNAL.mono_wasm_raise_debug_event(undefined)", - "INTERNAL.mono_wasm_raise_debug_event({})", + "getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event('')", + "getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event(undefined)", + "getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event({})", - "INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, '')", - "INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, 12)" + "getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, '')", + "getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, 12)" }; foreach (var expression in bad_expressions) @@ -58,7 +58,7 @@ public async Task RaiseDebugEventTraceTest(bool? trace) }); var trace_str = trace.HasValue ? $"trace: {trace.ToString().ToLower()}" : String.Empty; - var expression = $"INTERNAL.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; + var expression = $"getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); Assert.True(res.IsOk, $"Expected to pass for {expression}"); @@ -139,7 +139,7 @@ async Task AssemblyLoadedEventTest(string asm_name, string asm_path, string pdb_ pdb_base64 = Convert.ToBase64String(bytes); } - var expression = $@"INTERNAL.mono_wasm_raise_debug_event({{ + var expression = $@"getDotnetRuntime(0).INTERNAL.mono_wasm_raise_debug_event({{ eventName: 'AssemblyLoaded', assembly_name: '{asm_name}', assembly_b64: '{asm_base64}', diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index a1cce5ee2b8ca..a141d677744e3 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -6,14 +6,14 @@