Skip to content

Commit

Permalink
[wasm][debugger] Showing "Frame not in module" after vscode-js-debug …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
thaystg authored Jun 19, 2023
1 parent 01f63e7 commit 5fe7b06
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public FirefoxMonoProxy(ILogger logger, string loggerId = null, ProxyOptions opt

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));
}
Expand Down Expand Up @@ -316,7 +316,7 @@ protected override async Task<bool> AcceptCommand(MessageId sessionId, JObject a
{
case "resume":
{
if (!contexts.TryGetValue(sessionId, out ExecutionContext context))
if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context))
return false;
context.PausedOnWasm = false;
if (context.CallStack == null)
Expand Down Expand Up @@ -380,7 +380,7 @@ protected override async Task<bool> AcceptCommand(MessageId sessionId, JObject a
}
case "setBreakpoint":
{
if (!contexts.TryGetValue(sessionId, out ExecutionContext context))
if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context))
return false;
var req = JObject.FromObject(new
{
Expand Down Expand Up @@ -420,7 +420,7 @@ protected override async Task<bool> AcceptCommand(MessageId sessionId, JObject a
}
case "removeBreakpoint":
{
if (!contexts.TryGetValue(sessionId, out ExecutionContext context))
if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context))
return false;
Result resp = await SendCommand(sessionId, "", args, token);

Expand Down
44 changes: 34 additions & 10 deletions src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal class MonoProxy : DevToolsProxy
internal string CachePathSymbolServer { get; private set; }
private readonly HashSet<SessionId> sessions = new HashSet<SessionId>();
private static readonly string[] s_executionContextIndependentCDPCommandNames = { "DotnetDebugger.setDebuggerProperty", "DotnetDebugger.runTests" };
protected Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext>();
protected Dictionary<SessionId, List<ExecutionContext>> contexts = new Dictionary<SessionId, List<ExecutionContext>>();

public static HttpClient HttpClient => new HttpClient();

Expand All @@ -45,24 +45,37 @@ public MonoProxy(ILogger logger, int runtimeId = 0, string loggerId = "", ProxyO

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));
}

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<ExecutionContext> contextList))
return false;
if (contextList.Count == 0)
return false;
executionContext = contextList.Last<ExecutionContext>();
return true;
}

internal virtual Task<Result> 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
{
Expand Down Expand Up @@ -151,6 +164,16 @@ protected override async Task<bool> AcceptEvent(SessionId sessionId, JObject par
}
return true;
}
case "Runtime.executionContextDestroyed":
{
int id = args["executionContextId"].Value<int>();
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":
{
Expand Down Expand Up @@ -188,7 +211,7 @@ protected async Task<bool> OnDebuggerPaused(SessionId sessionId, JObject args, C

if (args["asyncStackTraceId"] != null)
{
if (!contexts.TryGetValue(sessionId, out ExecutionContext context))
if (!TryGetCurrentExecutionContextValue(sessionId, out ExecutionContext context))
return false;
if (context.CopyDataFromParentContext())
{
Expand Down Expand Up @@ -254,7 +277,7 @@ protected async Task<bool> OnDebuggerPaused(SessionId sessionId, JObject args, C

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;
Expand All @@ -264,7 +287,8 @@ protected void CreateWorkerExecutionContext(SessionId workerSessionId, SessionId
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)
Expand All @@ -273,7 +297,7 @@ protected virtual async Task SendResume(SessionId id, CancellationToken token)
}
protected async Task<bool> 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);
Expand All @@ -298,7 +322,7 @@ protected override async Task<bool> AcceptCommand(MessageId id, JObject parms, C
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")
{
Expand Down

0 comments on commit 5fe7b06

Please sign in to comment.