[wasm][debugger] Correctly handle empty, and whitespace-only strings (#41424)
authorAnkit Jain <radical@gmail.com>
Mon, 31 Aug 2020 14:21:04 +0000 (10:21 -0400)
committerGitHub <noreply@github.com>
Mon, 31 Aug 2020 14:21:04 +0000 (09:21 -0500)
There are two cases being fixed here:

1. str=='', or str=' '
- We check `str_value == 0`, and for the above cases JS returns
true, due to type coercion.
- So, we show the result as a null string.

2. str==null
- debugger.c adds the value for this with `mono_wasm_add_typed_value ("string", NULL, 0)`
- the second argument is converted to a string with
  `Module.UTF8ToString(..)`, but when it's `0`/NULL, we get an
  empty string. And that becomes a null string, because of (1).

Fixing this by using `===` operator to avoid type coercion.

Fixes https://github.com/dotnet/runtime/issues/41276

src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs
src/mono/wasm/debugger/tests/debugger-test.cs
src/mono/wasm/runtime/library_mono.js

index 34dc5ef..61e9086 100644 (file)
@@ -359,6 +359,41 @@ namespace DebuggerTests
                 }
             );
 
+        [Fact]
+        public async Task InspectSimpleStringLocals() =>
+            await CheckInspectLocalsAtBreakpointSite(
+                "Math", "TestSimpleStrings", 13, "TestSimpleStrings",
+                "window.setTimeout(function() { invoke_static_method ('[debugger-test] Math:TestSimpleStrings')(); }, 1);",
+                wait_for_event_fn: async (pause_location) =>
+                {
+                    var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value<string>());
+
+                    var str_null = TString(null);
+                    var str_empty = TString(String.Empty);
+                    var str_spaces = TString(" ");
+                    var str_esc = TString("\\");
+
+                    await CheckProps(locals, new
+                    {
+                        str_null,
+                        str_empty,
+                        str_spaces,
+                        str_esc,
+
+                        strings = TArray("string[]", 4)
+                    }, "locals");
+
+                    var strings_arr = await GetObjectOnLocals(locals, "strings");
+                    await CheckProps(strings_arr, new[]
+                    {
+                        str_null,
+                        str_empty,
+                        str_spaces,
+                        str_esc
+                    }, "locals#strings");
+                }
+            );
+
         [Theory]
         [InlineData(false)]
         [InlineData(true)]
index 9b53cea..4fb58be 100644 (file)
@@ -302,6 +302,23 @@ public partial class Math
         public static GenericStruct<bool[]> DelegateTargetForSignatureTest(Math m, GenericStruct<GenericStruct<T[]>> gs) => new GenericStruct<bool[]>();
     }
 
+    public static void TestSimpleStrings()
+    {
+        string str_null = null;
+        string str_empty = String.Empty;
+        string str_spaces = " ";
+        string str_esc = "\\";
+
+        var strings = new[]
+        {
+            str_null,
+            str_empty,
+            str_spaces,
+            str_esc
+        };
+        Console.WriteLine ($"break here");
+    }
+
 }
 
 public class DebuggerTest
index eccc137..67ae4c1 100644 (file)
@@ -1609,7 +1609,7 @@ var MonoSupportLib = {
                },
 
                _mono_wasm_add_string_var: function(var_value) {
-                       if (var_value == 0) {
+                       if (var_value === 0) {
                                MONO.mono_wasm_add_null_var ("string");
                                return;
                        }
@@ -1692,7 +1692,7 @@ var MonoSupportLib = {
                                value: {
                                        type            : "object",
                                        className       : fixed_class_name,
-                                       description     : (toString == 0 ? fixed_class_name: Module.UTF8ToString (toString)),
+                                       description     : (toString === 0 ? fixed_class_name: Module.UTF8ToString (toString)),
                                        expanded        : true,
                                        isValueType     : true,
                                        __extra_vt_props: { klass: args.klass, value64: base64String },
@@ -1734,7 +1734,7 @@ var MonoSupportLib = {
                                value: {
                                        type: "object",
                                        className: fixed_class_name,
-                                       description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)),
+                                       description: (toString === 0 ? fixed_class_name : Module.UTF8ToString (toString)),
                                        isValueType: true
                                }
                        });
@@ -1745,6 +1745,8 @@ var MonoSupportLib = {
                        let type_str = type;
                        if (typeof type != 'string')
                                type_str = Module.UTF8ToString (type);
+
+                       if (str_value !== 0)
                                str_value = Module.UTF8ToString (str_value);
 
                        switch (type_str) {
@@ -1962,7 +1964,7 @@ var MonoSupportLib = {
                        value: {
                                type: "object",
                                className: fixed_class_name,
-                               description: (toString == 0 ? fixed_class_name : Module.UTF8ToString (toString)),
+                               description: (toString === 0 ? fixed_class_name : Module.UTF8ToString (toString)),
                                objectId: "dotnet:object:"+ objectId,
                        }
                });