From b0882ddaf6ba577c9705bd38d9e157c4918531d1 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 10 Jan 2022 15:14:07 +0100 Subject: [PATCH 01/14] Hidden methods and step through methods behave the same way. --- src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 669f37c62c3e74..2107433255ed00 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -377,7 +377,7 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (name == "DebuggerHiddenAttribute") + if (name == "DebuggerHiddenAttribute" || name == "DebuggerStepThroughAttribute") { this.IsHiddenFromDebugger = true; break; From 49f9ec87715aea522d3b5a742ac79a5fe0f0cca8 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 11 Jan 2022 14:56:20 +0100 Subject: [PATCH 02/14] Perpared flow for setting JustMyCode in the future. --- .../debugger/BrowserDebugProxy/DebugStore.cs | 10 ++++++- .../debugger/BrowserDebugProxy/MonoProxy.cs | 26 ++++++++++++++++++- .../DebuggerTestSuite/BreakpointTests.cs | 6 +++++ .../DebuggerTestSuite/DebuggerTestBase.cs | 8 ++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 2107433255ed00..4433bfda8f1e90 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -377,7 +377,8 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (name == "DebuggerHiddenAttribute" || name == "DebuggerStepThroughAttribute") + if (name == "DebuggerHiddenAttribute" || + (assembly.IsJustMyCodeEnabled() && name == "DebuggerStepThroughAttribute")) { this.IsHiddenFromDebugger = true; break; @@ -583,6 +584,7 @@ internal class AssemblyInfo private static int next_id; private readonly int id; private readonly ILogger logger; + private readonly MonoProxy monoProxy; private Dictionary methods = new Dictionary(); private Dictionary sourceLinkMappings = new Dictionary(); private readonly List sources = new List(); @@ -601,6 +603,7 @@ internal class AssemblyInfo public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token) { + this.monoProxy = monoProxy; debugId = -1; this.id = Interlocked.Increment(ref next_id); using var asmStream = new MemoryStream(assembly); @@ -642,6 +645,11 @@ public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, Populate(); } + public bool IsJustMyCodeEnabled() + { + return monoProxy.JustMyCode; + } + public async Task GetDebugId(MonoSDBHelper sdbAgent, CancellationToken token) { if (debugId > 0) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 6866feaf54c542..c7ca267ca249f6 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -26,6 +26,7 @@ internal class MonoProxy : DevToolsProxy private const string sPauseOnCaught = "pause_on_caught"; // index of the runtime in a same JS page/process public int RuntimeId { get; private init; } + public bool JustMyCode { get; private set; } public MonoProxy(ILoggerFactory loggerFactory, IList urlSymbolServerList, int runtimeId = 0) : base(loggerFactory) { @@ -573,15 +574,38 @@ protected override async Task AcceptCommand(MessageId id, string method, J return true; } } + case "DotnetDebugger.justMyCode": + { + try + { + SetJustMyCode(id, args, token); + } + catch (Exception) + { + SendResponse(id, + Result.Exception(new ArgumentException( + $"DotnetDebugger.justMyCode got incorrect argument ({args})")), + token); + } + return true; + } } return false; } + private void SetJustMyCode(MessageId id, JObject args, CancellationToken token) + { + var isEnabled = args["enabled"]?.Value(); + if (isEnabled == null) + throw new ArgumentException(); + JustMyCode = isEnabled.Value; + SendResponse(id, Result.OkFromObject(new { justMyCodeEnabled = JustMyCode }), token); + } private async Task CallOnFunction(MessageId id, JObject args, CancellationToken token) { var context = GetContext(id); if (!DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId)) { - return false; + return true; } switch (objectId.Scheme) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index b80a8f429b4827..ea5aa0494f5e1b 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -707,5 +707,11 @@ await SendCommandAndCheck(null, "Debugger.resume", 8, "VisibleMethodDebuggerBreak"); } + + [Fact] + public async Task StepThroughAttribute() + { + await SetJustMyCode(true); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index d6fcc282f09cd6..4313c903bcaf2a 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -1237,6 +1237,14 @@ internal async Task LoadAssemblyAndTestHotReload(string asm_file, strin await cli.SendCommand("Runtime.evaluate", run_method, token); return await insp.WaitFor(Inspector.PAUSE); } + + internal async Task SetJustMyCode(bool enabled) + { + var req = JObject.FromObject(new { enabled = enabled }); + var res = await cli.SendCommand("DotnetDebugger.justMyCode", req, token); + Assert.True(res.IsOk); + Assert.Equal(res.Value["justMyCodeEnabled"], enabled); + } } class DotnetObjectId From 50e74fa57b1eef939238ae4cdf688efd8fb08778 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 12 Jan 2022 11:37:25 +0100 Subject: [PATCH 03/14] Tests for JustMyCode setting before debug launch. --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 2 +- .../DebuggerTestSuite/BreakpointTests.cs | 36 +++++++++++++++++-- .../debugger/DebuggerTestSuite/MiscTests.cs | 2 +- .../tests/debugger-test/debugger-test.cs | 11 ++++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index c7ca267ca249f6..cf8041d3e0c4d2 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -605,7 +605,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation { var context = GetContext(id); if (!DotnetObjectId.TryParse(args["objectId"], out DotnetObjectId objectId)) { - return true; + return false; } switch (objectId.Scheme) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index ea5aa0494f5e1b..95388ab26ddbd7 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -708,10 +708,40 @@ await SendCommandAndCheck(null, "Debugger.resume", "VisibleMethodDebuggerBreak"); } - [Fact] - public async Task StepThroughAttribute() + [Theory] + [InlineData(false)] + // [InlineData(true)] + public async Task StepThroughAttribute(bool justMyCodeEnabled) { - await SetJustMyCode(true); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); + var bp_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 0); + int line; + string function_name; + + //by default justMyCode:false -> stepInto works + if (justMyCodeEnabled) + { + // setting a value after loading the assembly does not have any effect on context call stack, so for true it does not work + // unless MonoProxy.JustMyCode is set to true before launching debugging. It should be changed to dynamic change support + await SetJustMyCode(true); + line = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; + function_name = "RunStepThrough"; + } + else + { + line = bp_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name = "NotStopOnJustMyCode"; + } + + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunStepThrough" + ); + + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 4, function_name); } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 22b8b165159885..d936c8437cad04 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -913,7 +913,7 @@ public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 860, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 871, 8, "CallToEvaluateLocal", wait_for_event_fn: async (pause_location) => { 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 3ed1f339bfb8ec..3709971fe786e2 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -848,6 +848,17 @@ public static void RunDebuggerBreak() HiddenMethodDebuggerBreak(); VisibleMethodDebuggerBreak(); } + + [System.Diagnostics.DebuggerStepThroughAttribute] + public static void NotStopOnJustMyCode() + { + currentCount++; + } + + public static void RunStepThrough() + { + NotStopOnJustMyCode(); + } } public class DebugTypeFull From c41add3be0326b9f150987c667019d7ea53a9036 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 12 Jan 2022 11:48:42 +0100 Subject: [PATCH 04/14] Transformed into dynamic JustMyCode change flow. --- .../debugger/BrowserDebugProxy/DebugStore.cs | 18 ++++++++---------- .../debugger/BrowserDebugProxy/MonoProxy.cs | 4 +++- .../DebuggerTestSuite/BreakpointTests.cs | 7 ++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 4433bfda8f1e90..1d8f7bbe94f7e7 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -333,6 +333,7 @@ internal class MethodInfo public bool IsStatic() => (methodDef.Attributes & MethodAttributes.Static) != 0; public int IsAsync { get; set; } public bool IsHiddenFromDebugger { get; } + public bool HasStepThroughAttribute { get; } public TypeInfo TypeInfo { get; } public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, int token, SourceFile source, TypeInfo type, MetadataReader asmMetadataReader, MetadataReader pdbMetadataReader) @@ -377,10 +378,14 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (name == "DebuggerHiddenAttribute" || - (assembly.IsJustMyCodeEnabled() && name == "DebuggerStepThroughAttribute")) + if (name == "DebuggerHiddenAttribute") { - this.IsHiddenFromDebugger = true; + IsHiddenFromDebugger = true; + break; + } + if (name == "DebuggerStepThroughAttribute") + { + HasStepThroughAttribute = true; break; } @@ -584,7 +589,6 @@ internal class AssemblyInfo private static int next_id; private readonly int id; private readonly ILogger logger; - private readonly MonoProxy monoProxy; private Dictionary methods = new Dictionary(); private Dictionary sourceLinkMappings = new Dictionary(); private readonly List sources = new List(); @@ -603,7 +607,6 @@ internal class AssemblyInfo public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token) { - this.monoProxy = monoProxy; debugId = -1; this.id = Interlocked.Increment(ref next_id); using var asmStream = new MemoryStream(assembly); @@ -645,11 +648,6 @@ public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, Populate(); } - public bool IsJustMyCodeEnabled() - { - return monoProxy.JustMyCode; - } - public async Task GetDebugId(MonoSDBHelper sdbAgent, CancellationToken token) { if (debugId > 0) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index cf8041d3e0c4d2..e0ac4e585243fe 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -848,7 +848,9 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con } } - if (j == 0 && method?.Info.IsHiddenFromDebugger == true) + if (j == 0 && + (method?.Info.IsHiddenFromDebugger == true || + (method?.Info.HasStepThroughAttribute == true && JustMyCode))) { if (event_kind == EventKind.Step) context.IsSkippingHiddenMethod = true; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 95388ab26ddbd7..518bf7c34da87f 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -710,7 +710,7 @@ await SendCommandAndCheck(null, "Debugger.resume", [Theory] [InlineData(false)] - // [InlineData(true)] + [InlineData(true)] public async Task StepThroughAttribute(bool justMyCodeEnabled) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); @@ -721,8 +721,6 @@ public async Task StepThroughAttribute(bool justMyCodeEnabled) //by default justMyCode:false -> stepInto works if (justMyCodeEnabled) { - // setting a value after loading the assembly does not have any effect on context call stack, so for true it does not work - // unless MonoProxy.JustMyCode is set to true before launching debugging. It should be changed to dynamic change support await SetJustMyCode(true); line = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; function_name = "RunStepThrough"; @@ -739,8 +737,7 @@ public async Task StepThroughAttribute(bool justMyCodeEnabled) bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), "RunStepThrough" - ); - + ); await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 4, function_name); } } From 750947d65d4a2eacb7a72c06431030754cd7f066 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 13 Jan 2022 16:36:24 +0100 Subject: [PATCH 05/14] JustMyCode disabled, first 3 cases solved. --- .../BrowserDebugProxy/DevToolsHelper.cs | 2 + .../debugger/BrowserDebugProxy/MonoProxy.cs | 32 ++++++- .../DebuggerTestSuite/BreakpointTests.cs | 88 +++++++++++++++++-- .../tests/debugger-test/debugger-test.cs | 2 + 4 files changed, 115 insertions(+), 9 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index e948c6abe0ebf7..8847bdd5abbde7 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -311,6 +311,8 @@ 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 bool IsSteppingThroughMethod { get; set; } + public bool IsResumedAfterBp { 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 e0ac4e585243fe..d3b6348e4b8603 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -848,9 +848,18 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con } } - if (j == 0 && - (method?.Info.IsHiddenFromDebugger == true || - (method?.Info.HasStepThroughAttribute == true && JustMyCode))) + if (context.IsSteppingThroughMethod == true) + { + context.IsSteppingThroughMethod = false; + if (event_kind != EventKind.UserBreak && event_kind != EventKind.Breakpoint) + { + 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; @@ -859,6 +868,23 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con return true; } + if (j == 0 && method?.Info.HasStepThroughAttribute == true) + { + if (event_kind == EventKind.Step) + { + if (context.IsResumedAfterBp) + context.IsResumedAfterBp = false; + else + context.IsSteppingThroughMethod = true; + + await context.SdbAgent.Step(context.ThreadId, StepKind.Out, token); + await SendCommand(sessionId, "Debugger.resume", new JObject(), token); + return true; + } + if (event_kind == EventKind.Breakpoint) + context.IsResumedAfterBp = true; + } + SourceLocation location = method?.Info.GetLocationByIl(il_pos); // When hitting a breakpoint on the "IncrementCount" method in the standard diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 518bf7c34da87f..f7a7c7f1a68e63 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -710,15 +710,12 @@ await SendCommandAndCheck(null, "Debugger.resume", [Theory] [InlineData(false)] - [InlineData(true)] - public async Task StepThroughAttribute(bool justMyCodeEnabled) + public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); - var bp_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 0); int line; string function_name; - //by default justMyCode:false -> stepInto works if (justMyCodeEnabled) { await SetJustMyCode(true); @@ -727,8 +724,8 @@ public async Task StepThroughAttribute(bool justMyCodeEnabled) } else { - line = bp_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name = "NotStopOnJustMyCode"; + line = 862; + function_name = "RunStepThrough"; } var init_location = await EvaluateAndCheck( @@ -740,5 +737,84 @@ public async Task StepThroughAttribute(bool justMyCodeEnabled) ); await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 4, function_name); } + + [Theory] + [InlineData(false)] + public async Task StepThroughAttributeStepInWithBp(bool justMyCodeEnabled) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); + var bp2_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 3); + int line1, line2, line3; + string function_name1, function_name2, function_name3; + + if (justMyCodeEnabled) + { + await SetJustMyCode(true); + line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; + function_name1 = "RunStepThrough"; + line2 = 0; + function_name2 = ""; + line3 = 0; + function_name3 = ""; + } + else + { + line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name1 = "NotStopOnJustMyCode"; + line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name2 = "NotStopOnJustMyCode"; + line3 = 861; + function_name3 = "RunStepThrough"; + } + + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunStepThrough" + ); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, function_name2); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line3, 8, function_name3); + } + + [Theory] + [InlineData(false)] + public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); + int line1, line2; + string function_name1, function_name2; + + if (justMyCodeEnabled) + { + await SetJustMyCode(true); + line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; + function_name1 = "RunStepThrough"; + line2 = 0; + function_name2 = ""; + } + else + { + line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name1 = "NotStopOnJustMyCode"; + line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name2 = "RunStepThrough"; + } + + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunStepThrough" + ); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 4, function_name2); + } } } 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 3709971fe786e2..3dfa3a1e7a8765 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -852,7 +852,9 @@ public static void RunDebuggerBreak() [System.Diagnostics.DebuggerStepThroughAttribute] public static void NotStopOnJustMyCode() { + var a = 0; currentCount++; + var b = 1; } public static void RunStepThrough() From 4ba2114badeb8b1e40f13b22463efa55e1b7b65b Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 14 Jan 2022 10:10:11 +0100 Subject: [PATCH 06/14] Finished behavior for JMC disabled (with 1 difference). --- .../DebuggerTestSuite/BreakpointTests.cs | 45 +++++++++++++++++-- .../tests/debugger-test/debugger-test.cs | 7 +++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index f7a7c7f1a68e63..fc68976d30bb94 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -724,7 +724,7 @@ public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) } else { - line = 862; + line = 868; function_name = "RunStepThrough"; } @@ -735,7 +735,7 @@ public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) bp_init.Value["locations"][0]["columnNumber"].Value(), "RunStepThrough" ); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 4, function_name); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 8, function_name); } [Theory] @@ -764,7 +764,7 @@ public async Task StepThroughAttributeStepInWithBp(bool justMyCodeEnabled) function_name1 = "NotStopOnJustMyCode"; line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); function_name2 = "NotStopOnJustMyCode"; - line3 = 861; + line3 = 867; function_name3 = "RunStepThrough"; } @@ -814,7 +814,44 @@ public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) "RunStepThrough" ); await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); - await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 4, function_name2); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, function_name2); + } + + [Theory] + [InlineData(false, "Debugger.resume")] + [InlineData(false, "Debugger.stepInto")] + public async Task StepThroughAttributeWithUserBp(bool justMyCodeEnabled, string debuggingFunction) + { + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 3); + int line1, line2; + string function_name1, function_name2; + + if (justMyCodeEnabled) + { + await SetJustMyCode(true); + line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; + function_name1 = "RunStepThrough"; + line2 = 0; + function_name2 = ""; + } + else + { + line1 = 862; + function_name1 = "NotStopOnJustMyCodeUserBp"; + line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name2 = "RunStepThrough"; + } + + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunStepThrough" + ); + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, 4, function_name2); } } } 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 3dfa3a1e7a8765..93d006fe8efaa8 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -857,9 +857,16 @@ public static void NotStopOnJustMyCode() var b = 1; } + [System.Diagnostics.DebuggerStepThroughAttribute] + public static void NotStopOnJustMyCodeUserBp() + { + System.Diagnostics.Debugger.Break(); + } + public static void RunStepThrough() { NotStopOnJustMyCode(); + NotStopOnJustMyCodeUserBp(); } } From ea4d61295af2de443ffb6ddeee0bcbf048cdb376 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 14 Jan 2022 11:13:39 +0100 Subject: [PATCH 07/14] JMC enabled: stepIn np bp + stepIn bp + resume bp. --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 3 +- .../DebuggerTestSuite/BreakpointTests.cs | 98 +++++++------------ 2 files changed, 39 insertions(+), 62 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index d3b6348e4b8603..a754f3f1dd2aef 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -870,7 +870,8 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con if (j == 0 && method?.Info.HasStepThroughAttribute == true) { - if (event_kind == EventKind.Step) + if (event_kind == EventKind.Step || + (event_kind == EventKind.Breakpoint && JustMyCode)) { if (context.IsResumedAfterBp) context.IsResumedAfterBp = false; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index fc68976d30bb94..1543a3b0dbc533 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -710,23 +710,12 @@ await SendCommandAndCheck(null, "Debugger.resume", [Theory] [InlineData(false)] + [InlineData(true)] public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); - int line; - string function_name; - if (justMyCodeEnabled) - { - await SetJustMyCode(true); - line = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; - function_name = "RunStepThrough"; - } - else - { - line = 868; - function_name = "RunStepThrough"; - } + await SetJustMyCode(true); var init_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", @@ -734,40 +723,19 @@ public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), "RunStepThrough" - ); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 8, function_name); + ); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", 868, 8, "RunStepThrough"); } [Theory] [InlineData(false)] + [InlineData(true)] public async Task StepThroughAttributeStepInWithBp(bool justMyCodeEnabled) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); var bp2_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 3); - int line1, line2, line3; - string function_name1, function_name2, function_name3; - - if (justMyCodeEnabled) - { - await SetJustMyCode(true); - line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; - function_name1 = "RunStepThrough"; - line2 = 0; - function_name2 = ""; - line3 = 0; - function_name3 = ""; - } - else - { - line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name1 = "NotStopOnJustMyCode"; - line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name2 = "NotStopOnJustMyCode"; - line3 = 867; - function_name3 = "RunStepThrough"; - } - + var init_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", @@ -775,37 +743,34 @@ public async Task StepThroughAttributeStepInWithBp(bool justMyCodeEnabled) bp_init.Value["locations"][0]["columnNumber"].Value(), "RunStepThrough" ); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, function_name2); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line3, 8, function_name3); + + if (justMyCodeEnabled) + { + await SetJustMyCode(true); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", 868, 8, "RunStepThrough"); + } + else + { + var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var line3 = 867; + var step_throgh_fun = "NotStopOnJustMyCode"; + var outer_fun = "RunStepThrough"; + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, step_throgh_fun); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, step_throgh_fun); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line3, 8, outer_fun); + } } [Theory] [InlineData(false)] + [InlineData(true)] public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); - int line1, line2; - string function_name1, function_name2; - - if (justMyCodeEnabled) - { - await SetJustMyCode(true); - line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; - function_name1 = "RunStepThrough"; - line2 = 0; - function_name2 = ""; - } - else - { - line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name1 = "NotStopOnJustMyCode"; - line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name2 = "RunStepThrough"; - } - + var init_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", @@ -813,7 +778,18 @@ public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) bp_init.Value["locations"][0]["columnNumber"].Value(), "RunStepThrough" ); - await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + + if (justMyCodeEnabled) + await SetJustMyCode(true); + else + { + var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var function_name1 = "NotStopOnJustMyCode"; + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + } + + var line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var function_name2 = "RunStepThrough"; await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, function_name2); } From ce438f7e9f5b4a90ac784fea387609e57dd66fa2 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 14 Jan 2022 12:25:30 +0100 Subject: [PATCH 08/14] Functional version (with minor deviations from expected behavior). --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 5 ++-- .../DebuggerTestSuite/BreakpointTests.cs | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index a754f3f1dd2aef..f9c11a5d59c39d 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -871,11 +871,12 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con if (j == 0 && method?.Info.HasStepThroughAttribute == true) { if (event_kind == EventKind.Step || - (event_kind == EventKind.Breakpoint && JustMyCode)) + (event_kind == EventKind.Breakpoint && JustMyCode) || + (event_kind == EventKind.UserBreak && JustMyCode)) { if (context.IsResumedAfterBp) context.IsResumedAfterBp = false; - else + else if (event_kind != EventKind.UserBreak) context.IsSteppingThroughMethod = true; await context.SdbAgent.Step(context.ThreadId, StepKind.Out, token); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 1543a3b0dbc533..19bd210737b981 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -796,20 +796,31 @@ public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) [Theory] [InlineData(false, "Debugger.resume")] [InlineData(false, "Debugger.stepInto")] + [InlineData(true, "Debugger.stepInto")] + [InlineData(true, "Debugger.resume")] public async Task StepThroughAttributeWithUserBp(bool justMyCodeEnabled, string debuggingFunction) { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 3); + + var init_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunStepThrough" + ); + int line1, line2; string function_name1, function_name2; if (justMyCodeEnabled) { await SetJustMyCode(true); - line1 = bp_init.Value["locations"][0]["lineNumber"].Value() + 1; + line1 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value() - 1; function_name1 = "RunStepThrough"; - line2 = 0; - function_name2 = ""; + line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name2 = "RunStepThrough"; } else { @@ -818,14 +829,6 @@ public async Task StepThroughAttributeWithUserBp(bool justMyCodeEnabled, string line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); function_name2 = "RunStepThrough"; } - - var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", - bp_init.Value["locations"][0]["lineNumber"].Value(), - bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunStepThrough" - ); await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, 4, function_name2); } From 1dd4988d178fd5ac9c0b46a48d00603527e1b2c6 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 14 Jan 2022 13:10:11 +0100 Subject: [PATCH 09/14] Refactoring. --- .../debugger/BrowserDebugProxy/MonoProxy.cs | 69 ++++++++++--------- .../DebuggerTestSuite/BreakpointTests.cs | 4 +- .../debugger/DebuggerTestSuite/MiscTests.cs | 2 +- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index f9c11a5d59c39d..785a5310b92f71 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -837,51 +837,41 @@ 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; - } - } + var shouldReturn = await SkipMethod( + isSkippable: context.IsSkippingHiddenMethod, + shouldBeSkipped: event_kind != EventKind.UserBreak, + StepKind.Over); + context.IsSkippingHiddenMethod = false; + if (shouldReturn) + return true; + + shouldReturn = await SkipMethod( + isSkippable: context.IsSteppingThroughMethod, + shouldBeSkipped: event_kind != EventKind.UserBreak && event_kind != EventKind.Breakpoint, + StepKind.Over); + context.IsSteppingThroughMethod = false; + if (shouldReturn) + return true; - if (context.IsSteppingThroughMethod == true) + if (j == 0 && (method?.Info.HasStepThroughAttribute == true || method?.Info.IsHiddenFromDebugger == true)) { - context.IsSteppingThroughMethod = false; - if (event_kind != EventKind.UserBreak && event_kind != EventKind.Breakpoint) + if (method.Info.IsHiddenFromDebugger) { - await context.SdbAgent.Step(context.ThreadId, StepKind.Over, token); - await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - return true; + if (event_kind == EventKind.Step) + context.IsSkippingHiddenMethod = true; + if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) + 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; - } - - if (j == 0 && method?.Info.HasStepThroughAttribute == true) - { if (event_kind == EventKind.Step || - (event_kind == EventKind.Breakpoint && JustMyCode) || - (event_kind == EventKind.UserBreak && JustMyCode)) + (JustMyCode && (event_kind == EventKind.Breakpoint || event_kind == EventKind.UserBreak))) { if (context.IsResumedAfterBp) context.IsResumedAfterBp = false; else if (event_kind != EventKind.UserBreak) context.IsSteppingThroughMethod = true; - - await context.SdbAgent.Step(context.ThreadId, StepKind.Out, token); - await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - return true; + if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) + return true; } if (event_kind == EventKind.Breakpoint) context.IsResumedAfterBp = true; @@ -964,6 +954,17 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con SendEvent(sessionId, "Debugger.paused", o, token); return true; + + async Task SkipMethod(bool isSkippable, bool shouldBeSkipped, StepKind stepKind) + { + if (isSkippable && shouldBeSkipped) + { + await context.SdbAgent.Step(context.ThreadId, stepKind, token); + await SendCommand(sessionId, "Debugger.resume", new JObject(), token); + return true; + } + return false; + } } private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObject args, CancellationToken token) { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 19bd210737b981..49222fa24a5586 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -668,7 +668,7 @@ await EvaluateAndCheck( [Fact] - public async Task DebuggerAttributeNoStopInDebuggerHidden() + public async Task DebuggerHiddenNoStopOnBp() { var bp_hidden = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "HiddenMethod", 1); var bp_visible = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "VisibleMethod", 1); @@ -683,7 +683,7 @@ await EvaluateAndCheck( } [Fact] - public async Task DebuggerAttributeStopOnDebuggerHiddenCallWithDebuggerBreakCall() + public async Task DebuggerHiddenStopOnUserBp() { var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunDebuggerBreak", 0); var init_location = await EvaluateAndCheck( diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index d936c8437cad04..ba1da1728ae15e 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -913,7 +913,7 @@ public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 871, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 880, 8, "CallToEvaluateLocal", wait_for_event_fn: async (pause_location) => { From 442c2de099b8c0aea8bcfeb2c2feebf5ecaa3ef8 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 17 Jan 2022 11:01:18 +0100 Subject: [PATCH 10/14] All tests for NonUserCode work. --- .../debugger/BrowserDebugProxy/DebugStore.cs | 33 +++-- .../debugger/BrowserDebugProxy/MonoProxy.cs | 9 +- .../DebuggerTestSuite/BreakpointTests.cs | 134 ++++++++++-------- .../tests/debugger-test/debugger-test.cs | 28 +++- 4 files changed, 131 insertions(+), 73 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index e37f75191c5110..3c74bf450911e9 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -332,8 +332,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 bool HasStepThroughAttribute { get; } + public DebuggerAttributesInfo DebuggerAttrInfo { get; set; } public TypeInfo TypeInfo { get; } public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, int token, SourceFile source, TypeInfo type, MetadataReader asmMetadataReader, MetadataReader pdbMetadataReader) @@ -371,6 +370,7 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, StartLocation = new SourceLocation(this, start); EndLocation = new SourceLocation(this, end); + DebuggerAttrInfo = new DebuggerAttributesInfo(); foreach (var cattr in methodDef.GetCustomAttributes()) { var ctorHandle = asmMetadataReader.GetCustomAttribute(cattr).Constructor; @@ -378,16 +378,24 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - if (name == "DebuggerHiddenAttribute") + var stopSearch = true; + switch (name) { - IsHiddenFromDebugger = true; - break; + case "DebuggerHiddenAttribute": + DebuggerAttrInfo.HasDebuggerHidden = true; + break; + case "DebuggerStepThroughAttribute": + DebuggerAttrInfo.HasStepThrough = true; + break; + case "DebuggerNonUserCodeAttribute": + DebuggerAttrInfo.HasNonUserCode = true; + break; + default: + stopSearch = false; + break; } - if (name == "DebuggerStepThroughAttribute") - { - HasStepThroughAttribute = true; + if (stopSearch) break; - } } } @@ -478,6 +486,13 @@ public VarInfo[] GetLiveVarsAt(int offset) } public override string ToString() => "MethodInfo(" + Name + ")"; + + public class DebuggerAttributesInfo + { + public bool HasDebuggerHidden { get; internal set; } + public bool HasStepThrough { get; internal set; } + public bool HasNonUserCode { get; internal set; } + } } internal class TypeInfo diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 33d1dc4c59d985..5fff1c5a7f1fcc 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -853,9 +853,12 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con if (shouldReturn) return true; - if (j == 0 && (method?.Info.HasStepThroughAttribute == true || method?.Info.IsHiddenFromDebugger == true)) + if (j == 0 && + (method?.Info.DebuggerAttrInfo.HasStepThrough == true || + method?.Info.DebuggerAttrInfo.HasDebuggerHidden == true || + (method?.Info.DebuggerAttrInfo.HasNonUserCode == true && JustMyCode))) { - if (method.Info.IsHiddenFromDebugger) + if (method.Info.DebuggerAttrInfo.HasDebuggerHidden) { if (event_kind == EventKind.Step) context.IsSkippingHiddenMethod = true; @@ -1443,7 +1446,7 @@ private async Task SetBreakpoint(SessionId sessionId, DebugStore store, Breakpoi { SourceLocation loc = sourceId.First(); req.Method = loc.IlLocation.Method; - if (req.Method.IsHiddenFromDebugger) + if (req.Method.DebuggerAttrInfo.HasDebuggerHidden) continue; Breakpoint bp = await SetMonoBreakpoint(sessionId, req.Id, loc, req.Condition, token); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 01f526e8c78db1..1252bb4135f32b 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -709,128 +709,148 @@ await SendCommandAndCheck(null, "Debugger.resume", } [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task StepThroughAttributeStepInNoBp(bool justMyCodeEnabled) + [InlineData(false, "RunStepThrough")] + [InlineData(true, "RunStepThrough")] + [InlineData(true, "RunNonUserCode")] + [InlineData(false, "RunNonUserCode")] + public async Task StepThroughOrNonUserCodeAttributeStepInNoBp(bool justMyCodeEnabled, string evalFunName) { - var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); if (justMyCodeEnabled) await SetJustMyCode(true); var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", "dotnet://debugger-test.dll/debugger-test.cs", bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunStepThrough" + evalFunName ); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", 868, 8, "RunStepThrough"); + var (funcName, line, col) = (evalFunName, 868, 8); + if (evalFunName == "RunNonUserCode") + (funcName, line, col) = justMyCodeEnabled ? (evalFunName, 888, 8) : ("NonUserCodeBp", 873, 4); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, col, funcName); } [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task StepThroughAttributeStepInWithBp(bool justMyCodeEnabled) + [InlineData(false, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunNonUserCode", "NonUserCodeBp")] + [InlineData(false, "RunNonUserCode", "NonUserCodeBp")] + public async Task StepThroughOrNonUserCodeAttributeStepInWithBp(bool justMyCodeEnabled, string evalFunName, string decoratedFunName) { - var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); - var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); - var bp2_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 3); - + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", "dotnet://debugger-test.dll/debugger-test.cs", bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunStepThrough" + evalFunName ); if (justMyCodeEnabled) { await SetJustMyCode(true); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", 868, 8, "RunStepThrough"); + var line = (evalFunName == "RunNonUserCode") ? 888 : 868; + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line, 8, evalFunName); } else { - var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - var line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - var line3 = 867; - var step_throgh_fun = "NotStopOnJustMyCode"; - var outer_fun = "RunStepThrough"; - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, step_throgh_fun); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, step_throgh_fun); - await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line3, 8, outer_fun); + var (finalFunName, line3, col) = (decoratedFunName, 873, 4); + if (evalFunName == "RunStepThrough") + { + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 1); + var bp2_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 3); + (finalFunName, line3, col) = (evalFunName, 867, 8); + var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var line2 = bp2_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line1, col, decoratedFunName); + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line2, col, decoratedFunName); + } + await SendCommandAndCheck(null, "Debugger.stepInto", "dotnet://debugger-test.dll/debugger-test.cs", line3, col, finalFunName); } } [Theory] - [InlineData(false)] - [InlineData(true)] - public async Task StepThroughAttributeResumeWithBp(bool justMyCodeEnabled) + [InlineData(false, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunStepThrough", "StepThrougBp")] + [InlineData(true, "RunNonUserCode", "NonUserCodeBp")] + [InlineData(false, "RunNonUserCode", "NonUserCodeBp")] + public async Task StepThroughOrNonUserCodeAttributeResumeWithBp(bool justMyCodeEnabled, string evalFunName, string decoratedFunName) { - var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 1); - var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "NotStopOnJustMyCode", 1); - var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); - + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 1); var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", "dotnet://debugger-test.dll/debugger-test.cs", bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunStepThrough" + evalFunName ); if (justMyCodeEnabled) await SetJustMyCode(true); else { + var bp1_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", decoratedFunName, 1); var line1 = bp1_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - var function_name1 = "NotStopOnJustMyCode"; - await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, decoratedFunName); } - + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); var line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - var function_name2 = "RunStepThrough"; - await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, function_name2); + await SendCommandAndCheck(null, "Debugger.resume", "dotnet://debugger-test.dll/debugger-test.cs", line2, 8, evalFunName); } [Theory] - [InlineData(false, "Debugger.resume")] - [InlineData(false, "Debugger.stepInto")] - [InlineData(true, "Debugger.stepInto")] - [InlineData(true, "Debugger.resume")] - public async Task StepThroughAttributeWithUserBp(bool justMyCodeEnabled, string debuggingFunction) + [InlineData(false, "Debugger.resume", "RunStepThrough", "StepThrougUserBp")] + [InlineData(false, "Debugger.stepInto", "RunStepThrough", "StepThrougUserBp")] + [InlineData(true, "Debugger.stepInto", "RunStepThrough", null)] + [InlineData(true, "Debugger.resume", "RunStepThrough", null)] + [InlineData(true, "Debugger.stepInto", "RunNonUserCode", null)] + [InlineData(true, "Debugger.resume", "RunNonUserCode", null)] + [InlineData(false, "Debugger.stepInto", "RunNonUserCode", "NonUserCodeUserBp")] + [InlineData(false, "Debugger.resume", "RunNonUserCode", "NonUserCodeUserBp")] + public async Task StepThroughOrNonUserCodAttributeWithUserBp(bool justMyCodeEnabled, string debuggingFunction, string evalFunName, string decoratedFunName) { - var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 2); - var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunStepThrough", 3); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 2); + var bp_outside_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", evalFunName, 3); var init_location = await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerAttribute:RunStepThrough'); }, 1);", + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:{evalFunName}'); }}, 1);", "dotnet://debugger-test.dll/debugger-test.cs", bp_init.Value["locations"][0]["lineNumber"].Value(), bp_init.Value["locations"][0]["columnNumber"].Value(), - "RunStepThrough" + evalFunName ); - int line1, line2; + int line1, line2; + var (col1, col2) = (8, 4); string function_name1, function_name2; if (justMyCodeEnabled) { await SetJustMyCode(true); line1 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value() - 1; - function_name1 = "RunStepThrough"; line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name2 = "RunStepThrough"; + function_name1 = function_name2 = evalFunName; } else { - line1 = 862; - function_name1 = "NotStopOnJustMyCodeUserBp"; - line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); - function_name2 = "RunStepThrough"; + if (debuggingFunction == "Debugger.stepInto" && evalFunName == "RunNonUserCode") + { + (line1, col1) = (881, 4); + (line2, col2) = (882, 8); + function_name1 = function_name2 = decoratedFunName; + } + else + { + line1 = evalFunName == "RunNonUserCode" ? 882 : 862; + function_name1 = decoratedFunName; + line2 = bp_outside_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + function_name2 = evalFunName; + } } - await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line1, 8, function_name1); - await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, 4, function_name2); + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line1, col1, function_name1); + await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, col2, function_name2); } [Fact] 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 49c811faaa317f..52c88229823959 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -850,7 +850,7 @@ public static void RunDebuggerBreak() } [System.Diagnostics.DebuggerStepThroughAttribute] - public static void NotStopOnJustMyCode() + public static void StepThrougBp() { var a = 0; currentCount++; @@ -858,15 +858,35 @@ public static void NotStopOnJustMyCode() } [System.Diagnostics.DebuggerStepThroughAttribute] - public static void NotStopOnJustMyCodeUserBp() + public static void StepThrougUserBp() { System.Diagnostics.Debugger.Break(); } public static void RunStepThrough() { - NotStopOnJustMyCode(); - NotStopOnJustMyCodeUserBp(); + StepThrougBp(); + StepThrougUserBp(); + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeBp() + { + var a = 0; + currentCount++; + var b = 1; + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + public static void RunNonUserCode() + { + NonUserCodeBp(); + NonUserCodeUserBp(); } } From a3d42d3fe90db2ded0e155b5c1f0e11951f8c0c0 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 18 Jan 2022 09:20:39 +0100 Subject: [PATCH 11/14] Fix line number after adding code above. --- src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 9bb227f43f4092..8752e8a2407571 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -913,7 +913,7 @@ public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 880, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 900, 8, "CallToEvaluateLocal", wait_for_event_fn: async (pause_location) => { From 91e26a8a4ccc548c87e5ac5d6bf63196353fc71c Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 18 Jan 2022 16:16:17 +0100 Subject: [PATCH 12/14] Stepper boundary with tests. --- .../debugger/BrowserDebugProxy/DebugStore.cs | 5 +++ .../debugger/BrowserDebugProxy/MonoProxy.cs | 28 ++++++++------- .../DebuggerTestSuite/BreakpointTests.cs | 35 +++++++++++++++++++ .../debugger/DebuggerTestSuite/MiscTests.cs | 2 +- .../tests/debugger-test/debugger-test.cs | 26 +++++++++++++- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index 3c74bf450911e9..b89dba932521fb 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -379,6 +379,7 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); var stopSearch = true; + //WHAT ABOUT MULTIPLE DECORATORS? switch (name) { case "DebuggerHiddenAttribute": @@ -390,6 +391,9 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, case "DebuggerNonUserCodeAttribute": DebuggerAttrInfo.HasNonUserCode = true; break; + case "DebuggerStepperBoundaryAttribute": + DebuggerAttrInfo.HasStepperBoundary = true; + break; default: stopSearch = false; break; @@ -492,6 +496,7 @@ public class DebuggerAttributesInfo public bool HasDebuggerHidden { get; internal set; } public bool HasStepThrough { get; internal set; } public bool HasNonUserCode { get; internal set; } + public bool HasStepperBoundary { get; internal set; } } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 5fff1c5a7f1fcc..36d6289bf241c8 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -856,28 +856,32 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con if (j == 0 && (method?.Info.DebuggerAttrInfo.HasStepThrough == true || method?.Info.DebuggerAttrInfo.HasDebuggerHidden == true || + method?.Info.DebuggerAttrInfo.HasStepperBoundary == true || (method?.Info.DebuggerAttrInfo.HasNonUserCode == true && JustMyCode))) { - if (method.Info.DebuggerAttrInfo.HasDebuggerHidden) + if (method.Info.DebuggerAttrInfo.HasDebuggerHidden || + (method.Info.DebuggerAttrInfo.HasStepperBoundary && event_kind == EventKind.Step)) { if (event_kind == EventKind.Step) context.IsSkippingHiddenMethod = true; if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) return true; } - - if (event_kind == EventKind.Step || - (JustMyCode && (event_kind == EventKind.Breakpoint || event_kind == EventKind.UserBreak))) + if (!method.Info.DebuggerAttrInfo.HasStepperBoundary) { - if (context.IsResumedAfterBp) - context.IsResumedAfterBp = false; - else if (event_kind != EventKind.UserBreak) - context.IsSteppingThroughMethod = true; - if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) - return true; + if (event_kind == EventKind.Step || + (JustMyCode && (event_kind == EventKind.Breakpoint || event_kind == EventKind.UserBreak))) + { + if (context.IsResumedAfterBp) + context.IsResumedAfterBp = false; + else if (event_kind != EventKind.UserBreak) + context.IsSteppingThroughMethod = true; + if (await SkipMethod(isSkippable: true, shouldBeSkipped: true, StepKind.Out)) + return true; + } + if (event_kind == EventKind.Breakpoint) + context.IsResumedAfterBp = true; } - if (event_kind == EventKind.Breakpoint) - context.IsResumedAfterBp = true; } SourceLocation location = method?.Info.GetLocationByIl(il_pos); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 1252bb4135f32b..b8c58a27f1e5fb 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -853,6 +853,41 @@ public async Task StepThroughOrNonUserCodAttributeWithUserBp(bool justMyCodeEnab await SendCommandAndCheck(null, debuggingFunction, "dotnet://debugger-test.dll/debugger-test.cs", line2, col2, function_name2); } + [Theory] + [InlineData("Debugger.stepInto", 1, 2, false)] + [InlineData("Debugger.stepInto", 1, 2, true)] + [InlineData("Debugger.resume", 1, 2, true)] + [InlineData("Debugger.stepInto", 2, 3, false)] + [InlineData("Debugger.resume", 2, 3, false)] + public async Task StepperBoundary(string debuggingAction, int lineBpInit, int lineBpFinal, bool hasBpInDecoratedFun) + { + // behavior of StepperBoundary is the same for JMC enabled and disabled + // but the effect of NonUserCode escape is better visible for JMC: enabled + await SetJustMyCode(true); + var bp_init = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunNoBoundary", lineBpInit); + var init_location = await EvaluateAndCheck( + $"window.setTimeout(function() {{ invoke_static_method('[debugger-test] DebuggerAttribute:RunNoBoundary'); }}, {lineBpInit});", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_init.Value["locations"][0]["lineNumber"].Value(), + bp_init.Value["locations"][0]["columnNumber"].Value(), + "RunNoBoundary" + ); + var bp_final = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "RunNoBoundary", lineBpFinal); + if (hasBpInDecoratedFun) + { + var bp_decorated_fun = await SetBreakpointInMethod("debugger-test.dll", "DebuggerAttribute", "BoundaryBp", 2); + var line_decorated_fun = bp_decorated_fun.Value["locations"][0]["lineNumber"].Value(); + var col_decorated_fun = bp_decorated_fun.Value["locations"][0]["columnNumber"].Value(); + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", line_decorated_fun, col_decorated_fun, "BoundaryBp"); + } + if (lineBpInit == 2) + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", 900, 8, "BoundaryUserBp"); + + var line = bp_final.Value["locations"][0]["lineNumber"].Value(); + var col = bp_final.Value["locations"][0]["columnNumber"].Value(); + await SendCommandAndCheck(null, debuggingAction, "dotnet://debugger-test.dll/debugger-test.cs", line, col, "RunNoBoundary"); + } + [Fact] public async Task CreateGoodBreakpointAndHitGoToWasmPageWithoutAssetsComeBackAndHitAgain() { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs index 9bb227f43f4092..76f79a663f6e98 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs @@ -913,7 +913,7 @@ public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", - "dotnet://debugger-test.dll/debugger-test.cs", 880, 8, + "dotnet://debugger-test.dll/debugger-test.cs", 924, 8, "CallToEvaluateLocal", wait_for_event_fn: async (pause_location) => { 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 52c88229823959..3ecd2869fa2106 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -870,7 +870,7 @@ public static void RunStepThrough() } [System.Diagnostics.DebuggerNonUserCode] - public static void NonUserCodeBp() + public static void NonUserCodeBp(Action boundaryTestFun=null) { var a = 0; currentCount++; @@ -888,6 +888,30 @@ public static void RunNonUserCode() NonUserCodeBp(); NonUserCodeUserBp(); } + + [System.Diagnostics.DebuggerStepperBoundary] + public static void BoundaryBp() + { + var a = 5; + } + + [System.Diagnostics.DebuggerStepperBoundary] + public static void BoundaryUserBp() + { + System.Diagnostics.Debugger.Break(); + } + + [System.Diagnostics.DebuggerNonUserCode] + public static void NonUserCodeForBoundaryEscape(Action boundaryTestFun) + { + boundaryTestFun(); + } + + public static void RunNoBoundary() + { + NonUserCodeForBoundaryEscape(DebuggerAttribute.BoundaryBp); + NonUserCodeForBoundaryEscape(DebuggerAttribute.BoundaryUserBp); + } } public class DebugTypeFull From b95e9f705ba1270fd06879f7ff8f5577a338c59a Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 19 Jan 2022 09:01:00 +0100 Subject: [PATCH 13/14] Save information about multiple decorators. --- src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index b89dba932521fb..88ad41efc21722 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -378,8 +378,6 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, { var container = asmMetadataReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent; var name = asmMetadataReader.GetString(asmMetadataReader.GetTypeReference((TypeReferenceHandle)container).Name); - var stopSearch = true; - //WHAT ABOUT MULTIPLE DECORATORS? switch (name) { case "DebuggerHiddenAttribute": @@ -394,12 +392,7 @@ public MethodInfo(AssemblyInfo assembly, MethodDefinitionHandle methodDefHandle, case "DebuggerStepperBoundaryAttribute": DebuggerAttrInfo.HasStepperBoundary = true; break; - default: - stopSearch = false; - break; } - if (stopSearch) - break; } } From 189c1b45aac60bde6809f21bb3f3a7283d568e0a Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 19 Jan 2022 09:06:08 +0100 Subject: [PATCH 14/14] Fix error in merge. --- .../wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index b33a31e4bade2f..5fff1c5a7f1fcc 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -589,21 +589,6 @@ protected override async Task AcceptCommand(MessageId id, string method, J } return true; } - case "DotnetDebugger.justMyCode": - { - try - { - SetJustMyCode(id, args, token); - } - catch (Exception) - { - SendResponse(id, - Result.Exception(new ArgumentException( - $"DotnetDebugger.justMyCode got incorrect argument ({args})")), - token); - } - return true; - } } return false;