diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index be7d729dd019e..8579898faf715 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -330,6 +330,7 @@ internal class MethodInfo internal LocalScopeHandleCollection localScopes; public bool IsStatic() => (methodDef.Attributes & MethodAttributes.Static) != 0; public int IsAsync { get; set; } + public bool IsHiddenFromDebugger { get; } public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, int token, SourceFile source, TypeInfo type, MetadataReader asmMetadataReader, MetadataReader pdbMetadataReader) { this.IsAsync = -1; @@ -363,6 +364,18 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, StartLocation = new SourceLocation(this, start); EndLocation = new SourceLocation(this, end); + + foreach (var cattr in methodDef.GetCustomAttributes()) + { + var ctorHandle = asmMetadataReader.GetCustomAttribute(cattr).Constructor; + if (ctorHandle.Kind == HandleKind.MemberReference) + { + var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; + var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); + if (name == "DebuggerHiddenAttribute") + this.IsHiddenFromDebugger = true; + } + } } localScopes = pdbMetadataReader.GetLocalScopes(methodDefHandle); } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 674824df71580..cb0a51ccd7804 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -1301,6 +1301,9 @@ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, Breakpoi { SourceLocation loc = sourceId.First(); req.Method = loc.CliLocation.Method; + if (req.Method.IsHiddenFromDebugger) + continue; + Breakpoint bp = await SetMonoBreakpoint(sessionId, req.Id, loc, req.Condition, token); // If we didn't successfully enable the breakpoint diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index dd807d0bfaf54..398df51a299dd 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -642,5 +642,21 @@ await EvaluateAndCheck( } ); } + + + [Fact] + public async Task DebuggerAttributeNoStopInDebuggerHidden() + { + var bp_hidden = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "HiddenMethod", 1); + 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);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_visible.Value["locations"][0]["lineNumber"].Value(), + bp_visible.Value["locations"][0]["columnNumber"].Value(), + "VisibleMethod" + ); + } } } 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 2338c9e65d624..4a029949d156d 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -807,3 +807,25 @@ public int Increment(int count) return count + 1; } } + +public class DebuggerAttribute +{ + static int currentCount = 0; + + [System.Diagnostics.DebuggerHidden] + public static void HiddenMethod() + { + currentCount++; + } + + public static void VisibleMethod() + { + currentCount++; + } + + public static void Run() + { + HiddenMethod(); + VisibleMethod(); + } +}