Fix evaluate expression of mutidimensional array. (#72964)
authorThays Grazia <thaystg@gmail.com>
Thu, 28 Jul 2022 13:17:22 +0000 (10:17 -0300)
committerGitHub <noreply@github.com>
Thu, 28 Jul 2022 13:17:22 +0000 (10:17 -0300)
src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs
src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs
src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs
src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs

index d79bf66..42a3d7f 100644 (file)
@@ -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;
                     }
index ec9477a..0974528 100644 (file)
@@ -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<string>();
                         if (!DotnetObjectId.TryParse(rootObject?["objectId"]?.Value<string>(), 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<string>() == 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
index 60fea60..9fdf6b3 100644 (file)
@@ -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<string>();
+
+               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) =>
index 27af815..34eee99 100644 (file)
@@ -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() { }