From 5fe7b06e1c4881d4e89a4baf00f2cbd6f4ff5838 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Mon, 19 Jun 2023 07:28:05 -0300 Subject: [PATCH] [wasm][debugger] Showing "Frame not in module" after vscode-js-debug bump on VS (#87154) * We were sending the scriptId of a context that was already destroyed and vscode-js-debug extension started to consider this information that was ignored before. * addressing @radical comments --- .../Firefox/FirefoxMonoProxy.cs | 8 ++-- .../debugger/BrowserDebugProxy/MonoProxy.cs | 44 ++++++++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs index 25c7dc8a3a9..8c8605cf25f 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxMonoProxy.cs @@ -23,7 +23,7 @@ internal sealed class FirefoxMonoProxy : MonoProxy public FirefoxExecutionContext GetContextFixefox(SessionId sessionId) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return context as FirefoxExecutionContext; throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId)); } @@ -316,7 +316,7 @@ internal sealed class FirefoxMonoProxy : MonoProxy { case "resume": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; context.PausedOnWasm = false; if (context.CallStack == null) @@ -380,7 +380,7 @@ internal sealed class FirefoxMonoProxy : MonoProxy } case "setBreakpoint": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; var req = JObject.FromObject(new { @@ -420,7 +420,7 @@ internal sealed class FirefoxMonoProxy : MonoProxy } case "removeBreakpoint": { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; Result resp = await SendCommand(sessionId, "", args, token); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 11cc46f7978..ed2495c469c 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -24,7 +24,7 @@ namespace Microsoft.WebAssembly.Diagnostics internal string CachePathSymbolServer { get; private set; } private readonly HashSet sessions = new HashSet(); private static readonly string[] s_executionContextIndependentCDPCommandNames = { "DotnetDebugger.setDebuggerProperty", "DotnetDebugger.runTests" }; - protected Dictionary contexts = new Dictionary(); + protected Dictionary> contexts = new Dictionary>(); public static HttpClient HttpClient => new HttpClient(); @@ -45,7 +45,7 @@ namespace Microsoft.WebAssembly.Diagnostics internal ExecutionContext GetContext(SessionId sessionId) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return context; throw new ArgumentException($"Invalid Session: \"{sessionId}\"", nameof(sessionId)); @@ -53,16 +53,29 @@ namespace Microsoft.WebAssembly.Diagnostics private bool UpdateContext(SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext) { - bool previous = contexts.TryGetValue(sessionId, out previousExecutionContext); - contexts[sessionId] = executionContext; + bool previous = TryGetCurrentExecutionContextValue(sessionId, out previousExecutionContext); + if (!previous) + contexts[sessionId] = new(); + contexts[sessionId].Add(executionContext); return previous; } + internal bool TryGetCurrentExecutionContextValue(SessionId id, out ExecutionContext executionContext) + { + executionContext = null; + if (!contexts.TryGetValue(id, out List contextList)) + return false; + if (contextList.Count == 0) + return false; + executionContext = contextList.Last(); + return true; + } + internal virtual Task SendMonoCommand(SessionId id, MonoCommands cmd, CancellationToken token) => SendCommand(id, "Runtime.evaluate", JObject.FromObject(cmd), token); internal void SendLog(SessionId sessionId, string message, CancellationToken token, string type = "warning") { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return; /*var o = JObject.FromObject(new { @@ -151,6 +164,16 @@ namespace Microsoft.WebAssembly.Diagnostics } return true; } + case "Runtime.executionContextDestroyed": + { + int id = args["executionContextId"].Value(); + if (!contexts.TryGetValue(sessionId, out var contextList)) + return false; + contextList.RemoveAll(x => x.Id == id); + if (contextList.Count == 0) + contexts.Remove(sessionId); + return false; + } case "Debugger.paused": { @@ -188,7 +211,7 @@ namespace Microsoft.WebAssembly.Diagnostics if (args["asyncStackTraceId"] != null) { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context)) return false; if (context.CopyDataFromParentContext()) { @@ -254,7 +277,7 @@ namespace Microsoft.WebAssembly.Diagnostics protected void CreateWorkerExecutionContext(SessionId workerSessionId, SessionId originSessionId) { - if (!contexts.TryGetValue(originSessionId, out ExecutionContext context)) + if (!TryGetCurrentExecutionContextValue(originSessionId, out ExecutionContext context)) { logger.LogDebug($"Origin sessionId does not exist - {originSessionId}"); return; @@ -264,7 +287,8 @@ namespace Microsoft.WebAssembly.Diagnostics logger.LogDebug($"Worker sessionId already exists - {originSessionId}"); return; } - contexts[workerSessionId] = context.CreateChildAsyncExecutionContext(workerSessionId); + contexts[workerSessionId] = new(); + contexts[workerSessionId].Add(context.CreateChildAsyncExecutionContext(workerSessionId)); } protected virtual async Task SendResume(SessionId id, CancellationToken token) @@ -273,7 +297,7 @@ namespace Microsoft.WebAssembly.Diagnostics } protected async Task IsRuntimeAlreadyReadyAlready(SessionId sessionId, CancellationToken token) { - if (contexts.TryGetValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) + if (TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context) && context.IsRuntimeReady) return true; Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(RuntimeId), token); @@ -298,7 +322,7 @@ namespace Microsoft.WebAssembly.Diagnostics if (id == SessionId.Null) await AttachToTarget(id, token); - if (!contexts.TryGetValue(id, out ExecutionContext context) && !s_executionContextIndependentCDPCommandNames.Contains(method)) + if (!TryGetCurrentExecutionContextValue(id, out ExecutionContext context) && !s_executionContextIndependentCDPCommandNames.Contains(method)) { if (method == "Debugger.setPauseOnExceptions") {