[wasm][debugger] Support "on frame evaluation" of functions returning char (#65842)
authorIlona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Wed, 2 Mar 2022 13:03:10 +0000 (14:03 +0100)
committerGitHub <noreply@github.com>
Wed, 2 Mar 2022 13:03:10 +0000 (14:03 +0100)
* Optional parameter fix.

* Working version of optional parameter support, requires refactoring.

* Refactored.

* Fixed failing tests.

* Add support to functions returning char, add test to an existing case.

* Simplified tests.

* Merged with optional params, uncommented char test

* Remove spaces.

* Applied @radical's suggestions.

* Removed indentation.

* Another indentation.

* Removed comment.

* Reverted type=char, as @radical suggested.

* Applied @radical's suggestions. No need for escaping + reverting original name.

src/mono/wasm/debugger/BrowserDebugProxy/EvaluateExpression.cs
src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs
src/mono/wasm/debugger/DebuggerTestSuite/AssignmentTests.cs
src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs
src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs
src/mono/wasm/debugger/DebuggerTestSuite/MiscTests.cs
src/mono/wasm/debugger/DebuggerTestSuite/PointerTests.cs
src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs

index 17d2603..54b175b 100644 (file)
@@ -231,6 +231,12 @@ namespace Microsoft.WebAssembly.Diagnostics
                         typeRet = "string";
                         break;
                     }
+                    case "symbol":
+                     {
+                         valueRet = $"'{value?.Value<char>()}'";
+                         typeRet = "char";
+                         break;
+                     }
                     case "number":
                         //casting to double and back to string would loose precision; so casting straight to string
                         valueRet = value?.Value<string>();
@@ -424,6 +430,8 @@ namespace Microsoft.WebAssembly.Diagnostics
                 return new { type = "object", subtype = "null", className = type?.ToString(), description = type?.ToString() };
             if (v is string s)
                 return new { type = "string", value = s, description = s };
+            if (v is char c)
+                return new { type = "symbol", value = c, description = $"{(int)c} '{c}'" };
             if (NumericTypes.Contains(v.GetType()))
                 return new { type = "number", value = v, description = Convert.ToDouble(v).ToString(CultureInfo.InvariantCulture) };
             if (v is JObject)
index ed46b03..be8a074 100644 (file)
@@ -1765,8 +1765,9 @@ namespace Microsoft.WebAssembly.Diagnostics
 
         public JObject CreateJObjectForChar(int value)
         {
-            var description = $"{value.ToString()} '{Convert.ToChar(value)}'";
-            return CreateJObject<string>(description, "symbol", description, true);
+            char charValue = Convert.ToChar(value);
+            var description = $"{value} '{charValue}'";
+            return CreateJObject<char>(charValue, "symbol", description, true);
         }
 
         public async Task<JObject> CreateJObjectForPtr(ElementType etype, MonoBinaryReader retDebuggerCmdReader, string name, CancellationToken token)
index 16c61e1..b4ce80d 100644 (file)
@@ -16,7 +16,7 @@ namespace DebuggerTests
             { "MONO_TYPE_OBJECT",      TObject("object", is_null: true),                        TObject("object") },
             { "MONO_TYPE_CLASS",       TObject("DebuggerTests.MONO_TYPE_CLASS", is_null: true), TObject("DebuggerTests.MONO_TYPE_CLASS") },
             { "MONO_TYPE_BOOLEAN",     TBool(default),                                          TBool(true) },
-            { "MONO_TYPE_CHAR",        TSymbol("0 '\u0000'"),                                   TSymbol("97 'a'") },
+            { "MONO_TYPE_CHAR",        TChar('\u0000'),                                         TChar('a') },
             { "MONO_TYPE_STRING",      TString(default),                                        TString("hello") },
             { "MONO_TYPE_ENUM",        TEnum("DebuggerTests.RGB", "Red"),                       TEnum("DebuggerTests.RGB", "Blue") },
             { "MONO_TYPE_ARRAY",       TObject("byte[]", is_null: true),                        TArray("byte[]", "byte[2]") },
index aa61555..a1b9dac 100644 (file)
@@ -323,10 +323,10 @@ namespace DebuggerTests
             await CheckValue(l["value"], TString(value), name);
         }
 
-        internal async Task<JToken> CheckSymbol(JToken locals, string name, string value)
+        internal async Task<JToken> CheckSymbol(JToken locals, string name, char value)
         {
             var l = GetAndAssertObjectWithName(locals, name);
-            await CheckValue(l["value"], TSymbol(value), name);
+            await CheckValue(l["value"], TChar(value), name);
             return l;
         }
 
@@ -1171,6 +1171,8 @@ namespace DebuggerTests
         internal static JObject TBool(bool value) => JObject.FromObject(new { type = "boolean", value = @value, description = @value ? "true" : "false" });
 
         internal static JObject TSymbol(string value) => JObject.FromObject(new { type = "symbol", value = @value, description = @value });
+        
+        internal static JObject TChar(char value) => JObject.FromObject(new { type = "symbol", value = @value, description = $"{(int)value} '{@value}'" });
 
         /*
                For target names with generated method names like
index c24449c..3e3071a 100644 (file)
@@ -528,11 +528,12 @@ namespace DebuggerTests
                var id = pause_location["callFrames"][0]["callFrameId"].Value<string>();
 
                await EvaluateOnCallFrameAndCheck(id,
-                   ("this.CallMethod()", TNumber(1)),
-                   ("this.CallMethod()", TNumber(1)),
-                   ("this.ParmToTestObj.MyMethod()", TString("methodOK")),
-                   ("this.ParmToTestObj.ToString()", TString("DebuggerTests.EvaluateMethodTestsClass+ParmToTest")),
-                   ("this.objToTest.MyMethod()", TString("methodOK")));
+                    ("this.CallMethod()", TNumber(1)),
+                    ("this.CallMethod()", TNumber(1)),
+                    ("this.CallMethodReturningChar()", TChar('A')),
+                    ("this.ParmToTestObj.MyMethod()", TString("methodOK")),
+                    ("this.ParmToTestObj.ToString()", TString("DebuggerTests.EvaluateMethodTestsClass+ParmToTest")),
+                    ("this.objToTest.MyMethod()", TString("methodOK")));
            });
 
 
@@ -1069,9 +1070,10 @@ namespace DebuggerTests
                    ("test.GetInt64Nullable()", TNumber(1)),
                    ("test.GetUInt64Nullable()", TNumber(1)),
 
-                //    ("test.GetChar()", TString("T")), //fails, Evaluate of this datatype symbol not implemented yet (for non optional parameters either)
-                //    ("test.GetCharNullable()", TString("T")),
-                //    ("test.GetUnicodeChar()", TString("ą")),
+                   ("test.GetChar()", TChar('T')),
+                   ("test.GetCharNullable()", TChar('T')),
+                   ("test.GetUnicodeChar()", TChar('ą')),
+
                    ("test.GetString()", TString("1.23")),
                    ("test.GetUnicodeString()", TString("żółć")),
                    ("test.GetString(null)", TObject("string", is_null: true)),
index 1fe9adc..b4eb66e 100644 (file)
@@ -84,8 +84,8 @@ namespace DebuggerTests
                 "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:PrimitiveTypesTest'); }, 1);",
                 test_fn: async (locals) =>
                 {
-                    await CheckSymbol(locals, "c0", "8364 '€'");
-                    await CheckSymbol(locals, "c1", "65 'A'");
+                    await CheckSymbol(locals, "c0", '€');
+                    await CheckSymbol(locals, "c1", 'A');
                     await Task.CompletedTask;
                 }
             );
index 891eea7..e559c88 100644 (file)
@@ -40,7 +40,7 @@ namespace DebuggerTests
                    ipp = TPointer("int**"),
                    ipp_null = TPointer("int**"),
 
-                   cvalue0 = TSymbol("113 'q'"),
+                   cvalue0 = TChar('q'),
                    cp = TPointer("char*"),
 
                    vp = TPointer("void*"),
@@ -65,7 +65,7 @@ namespace DebuggerTests
 
                // *cp
                props = await GetObjectOnLocals(locals, "cp");
-               await CheckPointerValue(props, "*cp", TSymbol("113 'q'"));
+               await CheckPointerValue(props, "*cp", TChar('q'));
            });
 
         [Theory]
index 116728c..baa6bac 100644 (file)
@@ -366,6 +366,11 @@ namespace DebuggerTests
                 return a;
             }
 
+            public char CallMethodReturningChar()
+            {
+                return 'A';
+            }
+
             public int CallMethodWithParm(int parm)
             {
                 return a + parm;