diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 3e7cfd87f010d3..b5baaab2f7e6aa 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -287,7 +287,7 @@ public ExecutionContext(MonoSDBHelper sdbAgent, int id, object auxData) public TaskCompletionSource ready; public bool IsRuntimeReady => ready != null && ready.Task.IsCompleted; - + public bool IsSkippingHiddenMethod { get; set; } public int ThreadId { get; set; } public int Id { get; set; } public object AuxData { get; set; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 8b1265d866d4d6..c258cf1eb9bd61 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -732,7 +732,7 @@ private async Task SendBreakpointsOfMethodUpdated(SessionId sessionId, Exe return true; } - private async Task SendCallStack(SessionId sessionId, ExecutionContext context, string reason, int thread_id, Breakpoint bp, JObject data, IEnumerable orig_callframes, CancellationToken token) + private async Task SendCallStack(SessionId sessionId, ExecutionContext context, string reason, int thread_id, Breakpoint bp, JObject data, IEnumerable orig_callframes, EventKind event_kind, CancellationToken token) { var callFrames = new List(); var frames = new List(); @@ -751,6 +751,26 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con DebugStore store = await LoadStore(sessionId, token); var method = await context.SdbAgent.GetMethodInfo(methodId, token); + if (context.IsSkippingHiddenMethod == true) + { + context.IsSkippingHiddenMethod = false; + if (event_kind != EventKind.UserBreak) + { + await context.SdbAgent.Step(context.ThreadId, StepKind.Over, token); + await SendCommand(sessionId, "Debugger.resume", new JObject(), token); + return true; + } + } + + if (j == 0 && method?.Info.IsHiddenFromDebugger == true) + { + if (event_kind == EventKind.Step) + context.IsSkippingHiddenMethod = true; + await context.SdbAgent.Step(context.ThreadId, StepKind.Out, token); + await SendCommand(sessionId, "Debugger.resume", new JObject(), token); + return true; + } + SourceLocation location = method?.Info.GetLocationByIl(il_pos); // When hitting a breakpoint on the "IncrementCount" method in the standard @@ -878,7 +898,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec objectId = $"dotnet:object:{object_id}" }); - var ret = await SendCallStack(sessionId, context, reason, thread_id, null, data, args?["callFrames"]?.Values(), token); + var ret = await SendCallStack(sessionId, context, reason, thread_id, null, data, args?["callFrames"]?.Values(), event_kind, token); return ret; } case EventKind.UserBreak: @@ -890,7 +910,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec int methodId = 0; if (event_kind != EventKind.UserBreak) methodId = retDebuggerCmdReader.ReadInt32(); - var ret = await SendCallStack(sessionId, context, reason, thread_id, bp, null, args?["callFrames"]?.Values(), token); + var ret = await SendCallStack(sessionId, context, reason, thread_id, bp, null, args?["callFrames"]?.Values(), event_kind, token); return ret; } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 4ad3f6a45cb71d..bce8bff42f6307 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -1147,7 +1147,7 @@ public async Task Step(int thread_id, StepKind kind, CancellationToken tok commandParamsWriter.Write(thread_id); commandParamsWriter.Write((int)StepSize.Line); commandParamsWriter.Write((int)kind); - commandParamsWriter.Write((int)(StepFilter.StaticCtor | StepFilter.DebuggerHidden)); //filter + commandParamsWriter.Write((int)(StepFilter.StaticCtor)); //filter using var retDebuggerCmdReader = await SendDebuggerAgentCommand(CmdEventRequest.Set, commandParamsWriter, token); if (retDebuggerCmdReader.HasError) return false; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 0e7f79f7a2a7ae..09f0f6b2e86670 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -651,12 +651,38 @@ public async Task DebuggerAttributeNoStopInDebuggerHidden() var bp_visible = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "VisibleMethod", 1); Assert.Empty(bp_hidden.Value["locations"]); await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:VisibleMethod'); }, 1);", + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:Run'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", bp_visible.Value["locations"][0]["lineNumber"].Value(), bp_visible.Value["locations"][0]["columnNumber"].Value(), "VisibleMethod" ); } + + [Fact] + public async Task DebuggerAttributeStopOnDebuggerHiddenCallWithDebuggerBreakCall() + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 0); + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunDebuggerBreak" + ); + var pause_location = await SendCommandAndCheck(null, "Debugger.resume", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value() + 1, + 8, + "RunDebuggerBreak"); + Assert.Equal(init_location["callFrames"][0]["functionName"], pause_location["callFrames"][0]["functionName"]); + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrame(id, "local_var", false); + await SendCommandAndCheck(null, "Debugger.resume", + "dotnet://debugger-test.dll/debugger-test.cs", + 835, + 8, + "VisibleMethodDebuggerBreak"); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs index e1a4a46fd83ea4..bec62b77f97545 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs @@ -948,5 +948,77 @@ await EvaluateAndCheck( pause_location = await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 806, 8, "Increment"); Assert.Equal(pause_location["callFrames"][0]["callFrameId"], "dotnet:scope:1"); } + + [Fact] + public async Task DebuggerAttributeIgnoreStepIntoDebuggerHidden() + { + var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "Run", 1); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:Run'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + pause_location.Value["locations"][0]["lineNumber"].Value(), + pause_location.Value["locations"][0]["columnNumber"].Value(), + "Run" + ); + var step_into = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); + + Assert.Equal( + step_into["callFrames"][0]["location"]["lineNumber"].Value(), + pause_location.Value["locations"][0]["lineNumber"].Value() + 1 + ); + + } + + [Fact] + public async Task DebuggerAttributeIgnoreStepIntoDebuggerHiddenWithDebuggerBreakCall() + { + var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 1); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + pause_location.Value["locations"][0]["lineNumber"].Value(), + pause_location.Value["locations"][0]["columnNumber"].Value(), + "RunDebuggerBreak" + ); + var step_into1 = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); + + Assert.Equal( + pause_location.Value["locations"][0]["lineNumber"].Value(), + step_into1["callFrames"][0]["location"]["lineNumber"].Value() + ); + + var step_into2 = await SendCommandAndCheck(null, $"Debugger.stepInto", null, -1, -1, null); + + Assert.Equal( + pause_location.Value["locations"][0]["lineNumber"].Value() + 1, + step_into2["callFrames"][0]["location"]["lineNumber"].Value() + ); + + } + + [Fact] + public async Task DebuggerAttributeIgnoreStepOverDebuggerHiddenWithDebuggerBreakCall() + { + var pause_location = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 1); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunDebuggerBreak'); 1});", + "dotnet://debugger-test.dll/debugger-test.cs", + pause_location.Value["locations"][0]["lineNumber"].Value(), + pause_location.Value["locations"][0]["columnNumber"].Value(), + "RunDebuggerBreak" + ); + var step_over1 = await SendCommandAndCheck(null, $"Debugger.stepOver", null, -1, -1, null); + Assert.Equal( + pause_location.Value["locations"][0]["lineNumber"].Value(), + step_over1["callFrames"][0]["location"]["lineNumber"].Value() + ); + + var step_over2 = await SendCommandAndCheck(null, $"Debugger.stepOver", null, -1, -1, null); + + Assert.Equal( + pause_location.Value["locations"][0]["lineNumber"].Value() + 1, + step_over2["callFrames"][0]["location"]["lineNumber"].Value() + ); + } } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 4a029949d156d0..813102bbbc047d 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -818,14 +818,34 @@ public static void HiddenMethod() currentCount++; } + [System.Diagnostics.DebuggerHidden] + public static void HiddenMethodDebuggerBreak() + { + var local_var = 12; + System.Diagnostics.Debugger.Break(); + currentCount++; + } + public static void VisibleMethod() { currentCount++; } + public static void VisibleMethodDebuggerBreak() + { + System.Diagnostics.Debugger.Break(); + currentCount++; + } + public static void Run() { HiddenMethod(); VisibleMethod(); } + + public static void RunDebuggerBreak() + { + HiddenMethodDebuggerBreak(); + VisibleMethodDebuggerBreak(); + } }