From d641668d77332533a55c41019ab146f312d92ce4 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Thu, 28 Jul 2022 10:17:22 -0300 Subject: [PATCH] Fix evaluate expression of mutidimensional array. (#72964) --- .../BrowserDebugProxy/EvaluateExpression.cs | 2 +- .../BrowserDebugProxy/MemberReferenceResolver.cs | 34 +++++++---- .../DebuggerTestSuite/EvaluateOnCallFrameTests.cs | 65 ++++++++++++++++++++++ .../tests/debugger-test/debugger-evaluate-test.cs | 31 +++++++++++ 4 files changed, 121 insertions(+), 11 deletions(-) diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs index d79bf66..42a3d7f 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs @@ -144,7 +144,7 @@ namespace Microsoft.WebAssembly.Diagnostics { // Generate a random suffix string suffix = Guid.NewGuid().ToString().Substring(0, 5); - string prefix = eaStr.Trim().Replace(".", "_").Replace("[", "_").Replace("]", "_"); + string prefix = regexForReplaceVarName.Replace(eaStr, "_"); id_name = $"{prefix}_{suffix}"; elementAccessToParamName[eaStr] = id_name; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index ec9477a..0974528 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -362,6 +362,7 @@ namespace Microsoft.WebAssembly.Diagnostics { JObject rootObject = null; string elementAccessStrExpression = elementAccess.Expression.ToString(); + var multiDimensionalArray = false; rootObject = await Resolve(elementAccessStrExpression, token); if (rootObject == null) { @@ -370,7 +371,7 @@ namespace Microsoft.WebAssembly.Diagnostics } if (rootObject != null) { - string elementIdxStr; + string elementIdxStr = null; int elementIdx = 0; var elementAccessStr = elementAccess.ToString(); // x[1] or x[a] or x[a.b] @@ -378,14 +379,19 @@ namespace Microsoft.WebAssembly.Diagnostics { if (elementAccess.ArgumentList != null) { - foreach (var arg in elementAccess.ArgumentList.Arguments) + for (int i = 0 ; i < elementAccess.ArgumentList.Arguments.Count; i++) { + var arg = elementAccess.ArgumentList.Arguments[i]; + if (i != 0) + { + elementIdxStr += ", "; + multiDimensionalArray = true; + } // e.g. x[1] if (arg.Expression is LiteralExpressionSyntax) { var argParm = arg.Expression as LiteralExpressionSyntax; - elementIdxStr = argParm.ToString(); - int.TryParse(elementIdxStr, out elementIdx); + elementIdxStr += argParm.ToString(); } // e.g. x[a] or x[a.b] @@ -401,10 +407,8 @@ namespace Microsoft.WebAssembly.Diagnostics { indexObject = await Resolve(argParm.Identifier.Text, token); } - elementIdxStr = indexObject["value"].ToString(); - int.TryParse(elementIdxStr, out elementIdx); + elementIdxStr += indexObject["value"].ToString(); } - // FixMe: indexing with expressions, e.g. x[a + 1] } } @@ -413,9 +417,8 @@ namespace Microsoft.WebAssembly.Diagnostics else { elementIdxStr = indexObject["value"].ToString(); - int.TryParse(elementIdxStr, out elementIdx); } - if (elementIdx >= 0) + if (elementIdxStr != null) { var type = rootObject?["type"]?.Value(); if (!DotnetObjectId.TryParse(rootObject?["objectId"]?.Value(), out DotnetObjectId objectId)) @@ -425,8 +428,19 @@ namespace Microsoft.WebAssembly.Diagnostics { case "array": rootObject["value"] = await context.SdbAgent.GetArrayValues(objectId.Value, token); - return (JObject)rootObject["value"][elementIdx]["value"]; + if (!multiDimensionalArray) + { + int.TryParse(elementIdxStr, out elementIdx); + return (JObject)rootObject["value"][elementIdx]["value"]; + } + else + { + return (JObject)(((JArray)rootObject["value"]).FirstOrDefault(x => x["name"].Value() == elementIdxStr)["value"]); + } case "object": + if (multiDimensionalArray) + throw new InvalidOperationException($"Cannot apply indexing with [,] to an object of type '{type}'"); + int.TryParse(elementIdxStr, out elementIdx); if (type == "string") { // ToArray() does not exist on string diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 60fea60..9fdf6b3 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -664,6 +664,71 @@ namespace DebuggerTests [ConditionalFact(nameof(RunningOnChrome))] public async Task EvaluateIndexingMultidimensional() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests.EvaluateLocals", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithMultidimensionalIndexingTests:EvaluateLocals'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + await EvaluateOnCallFrameAndCheck(id, + ("j", TNumber(1)), + ("f.idx1", TNumber(1)), + ("f.numArray2D[0, 0]", TNumber(1)), + ("f.numArray2D[0, 1]", TNumber(2)), + ("f.numArray2D[1, 0]", TNumber(3)), + ("f.numArray2D[1 ,1]", TNumber(4)), + ("f.numArray3D[0, 0, 0]", TNumber(1)), + ("f.numArray3D[0 ,0 ,1]", TNumber(2)), + ("f.numArray3D[0 ,0, 2]", TNumber(3)), + ("f.numArray3D[1, 1, 0]", TNumber(10)), + ("f.numArray3D[1, 1, 1]", TNumber(11)), + ("f.numArray3D[1 , 1, 2]", TNumber(12)), + ("f.numArray2D[0,0]", TNumber(1)), + ("f.numArray2D[0,1]", TNumber(2)), + ("f.numArray2D[1,0]", TNumber(3)), + ("f.numArray2D[1,1]", TNumber(4)), + ("f.numArray3D[0,0,0]", TNumber(1)), + ("f.numArray3D[0,0,1]", TNumber(2)), + ("f.numArray3D[0,0,2]", TNumber(3)), + ("f.numArray3D[1,1,0]", TNumber(10)), + ("f.numArray3D[1,1,1]", TNumber(11)), + ("f.numArray3D[1,1,2]", TNumber(12)), + ("f.textArray2D[0,0]", TString("one")), + ("f.textArray2D[0,1]", TString("two")), + ("f.textArray2D[1,0]", TString("three")), + ("f.textArray2D[1,1]", TString("four")), + ("f.numArray2D[i,i]", TNumber(1)), + ("f.numArray2D[i,j]", TNumber(2)), + ("f.numArray2D[j,i]", TNumber(3)), + ("f.numArray2D[j,j]", TNumber(4)), + ("f.numArray3D[i,i,i]", TNumber(1)), + ("f.numArray3D[i,i,j]", TNumber(2)), + ("f.numArray3D[i,i,2]", TNumber(3)), + ("f.numArray3D[j,j,i]", TNumber(10)), + ("f.numArray3D[j,j,1]", TNumber(11)), + ("f.numArray3D[j,j,2]", TNumber(12)), + ("f.textArray2D[i,i]", TString("one")), + ("f.textArray2D[i,j]", TString("two")), + ("f.textArray2D[j,i]", TString("three")), + ("f.textArray2D[j,j]", TString("four")), + ("f.numArray2D[f.idx0,f.idx0]", TNumber(1)), + ("f.numArray2D[f.idx0,f.idx1]", TNumber(2)), + ("f.numArray2D[f.idx1,f.idx0]", TNumber(3)), + ("f.numArray2D[f.idx1,f.idx1]", TNumber(4)), + ("f.numArray3D[f.idx0,f.idx0,f.idx0]", TNumber(1)), + ("f.numArray3D[f.idx0,f.idx0,f.idx1]", TNumber(2)), + ("f.numArray3D[f.idx0,f.idx0,2]", TNumber(3)), + ("f.numArray3D[f.idx1,f.idx1,f.idx0]", TNumber(10)), + ("f.numArray3D[f.idx1,f.idx1,f.idx1]", TNumber(11)), + ("f.numArray3D[f.idx1,f.idx1,2]", TNumber(12)), + ("f.textArray2D[f.idx0,f.idx0]", TString("one")), + ("f.textArray2D[f.idx0,f.idx1]", TString("two")), + ("f.textArray2D[f.idx1,f.idx0]", TString("three")), + ("f.textArray2D[f.idx1,f.idx1]", TString("four"))); + }); + + [ConditionalFact(nameof(RunningOnChrome))] + public async Task EvaluateIndexingJagged() => await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.EvaluateLocalsWithIndexingTests", "EvaluateLocals", 5, "DebuggerTests.EvaluateLocalsWithIndexingTests.EvaluateLocals", "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateLocalsWithIndexingTests:EvaluateLocals'); })", wait_for_event_fn: async (pause_location) => diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index 27af815..34eee99 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -543,6 +543,37 @@ namespace DebuggerTests } } + public class EvaluateLocalsWithMultidimensionalIndexingTests + { + public class TestEvaluate + { + public int[,] numArray2D; + public string[,] textArray2D; + public int[,,] numArray3D; + public int idx0; + public int idx1; + + public void run() + { + numArray2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; + textArray2D = new string[3, 2] { { "one", "two" }, { "three", "four" }, + { "five", "six" } }; + numArray3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, + { { 7, 8, 9 }, { 10, 11, 12 } } }; + idx0 = 0; + idx1 = 1; + } + } + + public static void EvaluateLocals() + { + int i = 0; + int j = 1; + TestEvaluate f = new TestEvaluate(); + f.run(); + } + } + public struct SampleStructure { public SampleStructure() { } -- 2.7.4