-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wasm][debugger] Detect initial status of pause on exceptions. #54040
Changes from 2 commits
68080fd
de352a1
232322e
cb1bc7f
6e4f0dd
ae2a17c
8a27dff
5900616
67b266f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ internal class MonoProxy : DevToolsProxy | |
private static HttpClient client = new HttpClient(); | ||
private HashSet<SessionId> sessions = new HashSet<SessionId>(); | ||
private Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext>(); | ||
private const string sPauseOnUncaught = "pause_on_uncaught"; | ||
private const string sPauseOnCaught = "pause_on_caught"; | ||
|
||
public MonoProxy(ILoggerFactory loggerFactory, IList<string> urlSymbolServerList) : base(loggerFactory) | ||
{ | ||
|
@@ -120,8 +122,40 @@ protected override async Task<bool> AcceptEvent(SessionId sessionId, string meth | |
return true; | ||
} | ||
|
||
case "Runtime.exceptionThrown": | ||
{ | ||
if (!GetContext(sessionId).IsRuntimeReady) | ||
{ | ||
string exceptionError = args?["exceptionDetails"]?["exception"]?["value"]?.Value<string>(); | ||
if (exceptionError == sPauseOnUncaught) | ||
{ | ||
GetContext(sessionId).PauseOnUncaught = true; | ||
return true; | ||
} | ||
if (exceptionError == sPauseOnCaught) | ||
{ | ||
GetContext(sessionId).PauseOnCaught = true; | ||
return true; | ||
} | ||
} | ||
break; | ||
} | ||
|
||
case "Debugger.paused": | ||
{ | ||
if (!GetContext(sessionId).IsRuntimeReady) | ||
{ | ||
string reason = args?["reason"]?.Value<string>(); | ||
if (reason == "exception") | ||
{ | ||
string exceptionError = args?["data"]?["value"]?.Value<string>(); | ||
if (exceptionError == sPauseOnUncaught || exceptionError == sPauseOnCaught) | ||
{ | ||
await SendCommand(sessionId, "Debugger.resume", new JObject(), token); | ||
return true; | ||
} | ||
} | ||
} | ||
//TODO figure out how to stich out more frames and, in particular what happens when real wasm is on the stack | ||
string top_func = args?["callFrames"]?[0]?["functionName"]?.Value<string>(); | ||
switch (top_func) { | ||
|
@@ -1078,6 +1112,11 @@ private async Task<DebugStore> RuntimeReady(SessionId sessionId, CancellationTok | |
Log("verbose", $"Failed to clear breakpoints due to {clear_result}"); | ||
} | ||
|
||
if (context.PauseOnCaught && context.PauseOnUncaught) | ||
await SendMonoCommand(sessionId, MonoCommands.SetPauseOnExceptions("all"), token); | ||
else if (context.PauseOnUncaught) | ||
await SendMonoCommand(sessionId, MonoCommands.SetPauseOnExceptions("uncaught"), token); | ||
|
||
DebugStore store = await LoadStore(sessionId, token); | ||
|
||
context.ready.SetResult(store); | ||
|
@@ -1214,10 +1253,12 @@ private async Task AttachToTarget(SessionId sessionId, CancellationToken token) | |
// see https://github.com/mono/mono/issues/19549 for background | ||
if (sessions.Add(sessionId)) | ||
{ | ||
string checkUncaughtExceptions = $"throw \"{sPauseOnUncaught}\";"; | ||
string checkCaughtExceptions = $"try {{throw \"{sPauseOnCaught}\";}} catch {{}}"; | ||
await SendMonoCommand(sessionId, new MonoCommands("globalThis.dotnetDebugger = true"), token); | ||
Result res = await SendCommand(sessionId, | ||
"Page.addScriptToEvaluateOnNewDocument", | ||
JObject.FromObject(new { source = "globalThis.dotnetDebugger = true; delete navigator.constructor.prototype.webdriver" }), | ||
JObject.FromObject(new { source = $"globalThis.dotnetDebugger = true; delete navigator.constructor.prototype.webdriver; {checkUncaughtExceptions} {checkCaughtExceptions}" }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doing it here is only going to work on new documents, would we be out of sync in the attach case still? does it work if you add it to the SendMonoCommand part above? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested two cases: The page is already loaded and then I connect debugger, it passes here and I can get the information that is expected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does not work if I add it to SendMonoCommand because it uses Runtime.Evaluate and Runtime.Evaluate does not call Debugger.Pause when an exception is threw. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand the flow here.
Also, it would be very useful to express that in tests too, but that might not be straight forward, so it can be in a follow up PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we attach to an already loaded page it will only pass on Runtime.exceptionThrown and this would print a message on console if I don't return true. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh no, I tested again, when the page is already loaded and we attach the debugger we receive the "Debugger.setPauseOnExceptions" with the correct information. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
By "pass on foo", do you mean that Question for scenario #1:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed somethings in the PR. For scenario #2: We don't need the current setting from the app, the current setting should always be correct, because during the use of the debugger we receive the |
||
token); | ||
|
||
if (sessionId != SessionId.Null && !res.IsOk) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might need to remove this check if you were trying the on attach version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attach is the case when the page is already loaded and then we connect the debugger? I tested it and it's working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only tested debugging on Chrome, I didn't test with VS or VSCode.