diff --git a/src/libraries/sendtohelix-wasm.targets b/src/libraries/sendtohelix-wasm.targets index 168d97a6afc2be4d7e0b204f344f52461350d86c..cd01a18d1c9656d45903ba34d11d688d42aa306d 100644 --- a/src/libraries/sendtohelix-wasm.targets +++ b/src/libraries/sendtohelix-wasm.targets @@ -3,6 +3,7 @@ <_workItemTimeout Condition="'$(Scenario)' == 'BuildWasmApps' and '$(_workItemTimeout)' == ''">01:30:00 <_workItemTimeout Condition="'$(NeedsToBuildWasmAppsOnHelix)' == 'true'">01:00:00 <_workItemTimeout Condition="'$(Scenario)' == 'WasmDebuggerTests'">01:00:00 + <_workItemTimeout Condition="'$(Scenario)' == 'WasmDebuggerTests' and '$(BrowserHost)' == 'windows'">01:30:00 <_workItemTimeout Condition="'$(Scenario)' == 'WasmTestOnBrowser' and '$(BrowserHost)' == 'windows'">00:45:00 true diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 960157f8176c2b9b72b0358c4af181ece746d2d5..5c888238b7f24836647961c9d527bc0932a1d5ac 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -401,11 +401,12 @@ internal enum PauseOnExceptionsKind internal class ExecutionContext { - public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData) + public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData, PauseOnExceptionsKind pauseOnExceptions) { Id = id; AuxData = auxData; SdbAgent = sdbAgent; + PauseOnExceptions = pauseOnExceptions; } public string DebugId { get; set; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxExecutionContext.cs b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxExecutionContext.cs index 8f8561bb2a59edf8f7471dcb54d5e99d2b25400e..253b731677953726eb8348596bbadfb7748325ce 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxExecutionContext.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/Firefox/FirefoxExecutionContext.cs @@ -14,7 +14,7 @@ internal sealed class FirefoxExecutionContext : ExecutionContext public string? GlobalName { get; set; } public Result LastDebuggerAgentBufferReceived { get; set; } - public FirefoxExecutionContext(MonoSDBHelper sdbAgent, int id, string actorName) : base(sdbAgent, id, actorName) + public FirefoxExecutionContext(MonoSDBHelper sdbAgent, int id, string actorName) : base(sdbAgent, id, actorName, PauseOnExceptionsKind.Unset) { ActorName = actorName; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 4ddddec96cb8db0fe12127b335fddb70703d7bba..c83f07ddaaae48290a8a9ff4e0dd8a1b3c32b93b 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -21,14 +21,14 @@ internal class MonoProxy : DevToolsProxy private IList urlSymbolServerList; private HashSet sessions = new HashSet(); protected Dictionary contexts = new Dictionary(); - private const string sPauseOnUncaught = "pause_on_uncaught"; - private const string sPauseOnCaught = "pause_on_caught"; public static HttpClient HttpClient => new HttpClient(); // index of the runtime in a same JS page/process public int RuntimeId { get; private init; } public bool JustMyCode { get; private set; } + private PauseOnExceptionsKind _defaultPauseOnExceptions { get; set; } + protected readonly ProxyOptions _options; public MonoProxy(ILogger logger, IList urlSymbolServerList, int runtimeId = 0, string loggerId = "", ProxyOptions options = null) : base(logger, loggerId) @@ -36,6 +36,7 @@ public MonoProxy(ILogger logger, IList urlSymbolServerList, int runtimeI this.urlSymbolServerList = urlSymbolServerList ?? new List(); RuntimeId = runtimeId; _options = options; + _defaultPauseOnExceptions = PauseOnExceptionsKind.Unset; } internal ExecutionContext GetContext(SessionId sessionId) @@ -160,55 +161,18 @@ protected override async Task AcceptEvent(SessionId sessionId, JObject par bool? is_default = aux_data["isDefault"]?.Value(); if (is_default == true) { - await OnDefaultContext(sessionId, new ExecutionContext(new MonoSDBHelper (this, logger, sessionId), id, aux_data), token); + await OnDefaultContext(sessionId, new ExecutionContext(new MonoSDBHelper (this, logger, sessionId), id, aux_data, _defaultPauseOnExceptions), token); } } return true; } - case "Runtime.exceptionThrown": - { - // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) - return false; - - if (!context.IsRuntimeReady) - { - string exceptionError = args?["exceptionDetails"]?["exception"]?["value"]?.Value(); - if (exceptionError == sPauseOnUncaught || exceptionError == sPauseOnCaught) - return true; - } - break; - } - case "Debugger.paused": { // Don't process events from sessions we aren't tracking - if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + if (!contexts.ContainsKey(sessionId)) return false; - if (!context.IsRuntimeReady) - { - string reason = args?["reason"]?.Value(); - if (reason == "exception") - { - string exceptionError = args?["data"]?["value"]?.Value(); - if (exceptionError == sPauseOnUncaught) - { - await SendResume(sessionId, token); - if (context.PauseOnExceptions == PauseOnExceptionsKind.Unset) - context.PauseOnExceptions = PauseOnExceptionsKind.Uncaught; - return true; - } - if (exceptionError == sPauseOnCaught) - { - await SendResume(sessionId, token); - context.PauseOnExceptions = PauseOnExceptionsKind.All; - 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(); switch (top_func) { @@ -291,6 +255,13 @@ protected async Task IsRuntimeAlreadyReadyAlready(SessionId sessionId, Can Result res = await SendMonoCommand(sessionId, MonoCommands.IsRuntimeReady(RuntimeId), token); return res.Value?["result"]?["value"]?.Value() ?? false; } + private static PauseOnExceptionsKind GetPauseOnExceptionsStatusFromString(string state) + { + PauseOnExceptionsKind pauseOnException; + if (Enum.TryParse(state, true, out pauseOnException)) + return pauseOnException; + return PauseOnExceptionsKind.Unset; + } protected override async Task AcceptCommand(MessageId id, JObject parms, CancellationToken token) { @@ -302,7 +273,16 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C await AttachToTarget(id, token); if (!contexts.TryGetValue(id, out ExecutionContext context)) + { + if (method == "Debugger.setPauseOnExceptions") + { + string state = args["state"].Value(); + var pauseOnException = GetPauseOnExceptionsStatusFromString(state); + if (pauseOnException != PauseOnExceptionsKind.Unset) + _defaultPauseOnExceptions = pauseOnException; + } return false; + } switch (method) { @@ -513,13 +493,9 @@ protected override async Task AcceptCommand(MessageId id, JObject parms, C case "Debugger.setPauseOnExceptions": { string state = args["state"].Value(); - context.PauseOnExceptions = state switch - { - "all" => PauseOnExceptionsKind.All, - "uncaught" => PauseOnExceptionsKind.Uncaught, - "none" => PauseOnExceptionsKind.None, - _ => PauseOnExceptionsKind.Unset - }; + var pauseOnException = GetPauseOnExceptionsStatusFromString(state); + if (pauseOnException != PauseOnExceptionsKind.Unset) + context.PauseOnExceptions = pauseOnException; if (context.IsRuntimeReady) await context.SdbAgent.EnableExceptions(context.PauseOnExceptions, token); @@ -1784,23 +1760,10 @@ private async Task AttachToTarget(SessionId sessionId, CancellationToken token) // see https://github.com/mono/mono/issues/19549 for background if (sessions.Add(sessionId)) { - string checkUncaughtExceptions = string.Empty; - string checkCaughtExceptions = string.Empty; - - //we only need this check if it's a non-vs debugging - if (sessionId == SessionId.Null) - { - if (!contexts.TryGetValue(sessionId, out ExecutionContext context) || context.PauseOnExceptions == PauseOnExceptionsKind.Unset) - { - checkUncaughtExceptions = $"throw \"{sPauseOnUncaught}\";"; - 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; {checkCaughtExceptions} {checkUncaughtExceptions}" }), + JObject.FromObject(new { source = $"globalThis.dotnetDebugger = true; delete navigator.constructor.prototype.webdriver;" }), token); if (sessionId != SessionId.Null && !res.IsOk)