Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/sdks
diff options
context:
space:
mode:
authorAnkit Jain <radical@gmail.com>2020-02-24 21:49:45 +0300
committerGitHub <noreply@github.com>2020-02-24 21:49:45 +0300
commitace2e34aae952ce79f34080954313bdbe7259509 (patch)
tree4a1042212ebc17c1e93fedc8e544c3bb50855aa1 /sdks
parent1dffbd0200f4cbb62506a4228a79a3db5feeaa51 (diff)
parent90499671069c1c2f23ffbbd2026fd3a1313ac2c4 (diff)
Merge pull request #19003 from radical/improve-locals-access
[wasm][debugger] Improve accessing locals
Diffstat (limited to 'sdks')
-rw-r--r--sdks/wasm/DebuggerTestSuite/Support.cs8
-rw-r--r--sdks/wasm/DebuggerTestSuite/Tests.cs419
-rw-r--r--sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs13
-rw-r--r--sdks/wasm/debugger-driver.html14
-rw-r--r--sdks/wasm/debugger-test.cs44
5 files changed, 486 insertions, 12 deletions
diff --git a/sdks/wasm/DebuggerTestSuite/Support.cs b/sdks/wasm/DebuggerTestSuite/Support.cs
index 38b844fc289..a9ffeff99be 100644
--- a/sdks/wasm/DebuggerTestSuite/Support.cs
+++ b/sdks/wasm/DebuggerTestSuite/Support.cs
@@ -42,6 +42,12 @@ namespace DebuggerTests
eventListeners[evtName] = cb;
}
+ void FailAllWaitersWithException (JObject exception)
+ {
+ foreach (var tcs in notifications.Values)
+ tcs.SetException (new ArgumentException (exception.ToString ()));
+ }
+
async Task OnMessage(string method, JObject args, CancellationToken token)
{
//System.Console.WriteLine("OnMessage " + method + args);
@@ -58,6 +64,8 @@ namespace DebuggerTests
}
if (eventListeners.ContainsKey (method))
await eventListeners[method](args, token);
+ else if (String.Compare (method, "Runtime.exceptionThrown") == 0)
+ FailAllWaitersWithException (args);
}
public async Task Ready (Func<InspectorClient, CancellationToken, Task> cb = null, TimeSpan? span = null) {
diff --git a/sdks/wasm/DebuggerTestSuite/Tests.cs b/sdks/wasm/DebuggerTestSuite/Tests.cs
index 9f621caaac8..7e40997d4ae 100644
--- a/sdks/wasm/DebuggerTestSuite/Tests.cs
+++ b/sdks/wasm/DebuggerTestSuite/Tests.cs
@@ -31,6 +31,8 @@ namespace DebuggerTests
dbgUrl = arrStr[0] + "/" + arrStr[1] + "/" + arrStr[2] + "/" + arrStr[arrStr.Length - 1];
dicScriptsIdToUrl[script_id] = dbgUrl;
dicFileToUrl[dbgUrl] = args["url"]?.Value<string>();
+ } else if (!String.IsNullOrEmpty (url)) {
+ dicFileToUrl[new Uri (url).AbsolutePath] = url;
}
await Task.FromResult (0);
});
@@ -39,9 +41,12 @@ namespace DebuggerTests
void CheckLocation (string script_loc, int line, int column, Dictionary<string, string> scripts, JToken location)
{
- Assert.Equal (script_loc, scripts[location["scriptId"].Value<string>()]);
- Assert.Equal (line, location ["lineNumber"].Value<int> ());
- Assert.Equal (column, location ["columnNumber"].Value<int> ());
+ var loc_str = $"{ scripts[location["scriptId"].Value<string>()] }"
+ + $"#{ location ["lineNumber"].Value<int> () }"
+ + $"#{ location ["columnNumber"].Value<int> () }";
+
+ var expected_loc_str = $"{script_loc}#{line}#{column}";
+ Assert.Equal (expected_loc_str, loc_str);
}
[Fact]
@@ -160,6 +165,58 @@ namespace DebuggerTests
});
}
+ [Fact]
+ public async Task ExceptionThrownInJS () {
+ var insp = new Inspector ();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready ();
+ await insp.Ready (async (cli, token) => {
+ var eval_req = JObject.FromObject(new {
+ expression = "invoke_bad_js_test();"
+ });
+
+ var eval_res = await cli.SendCommand ("Runtime.evaluate", eval_req, token);
+ Assert.True (eval_res.IsErr);
+ Assert.Equal ("Uncaught", eval_res.Error ["exceptionDetails"]? ["text"]? .Value<string> ());
+ });
+ }
+
+ [Fact]
+ public async Task ExceptionThrownInJSOutOfBand () {
+ var insp = new Inspector ();
+
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready ();
+ await insp.Ready (async (cli, token) => {
+ var bp1_req = JObject.FromObject(new {
+ lineNumber = 27,
+ columnNumber = 2,
+ url = dicFileToUrl["/debugger-driver.html"],
+ });
+
+ var bp1_res = await cli.SendCommand ("Debugger.setBreakpointByUrl", bp1_req, token);
+ Assert.True (bp1_res.IsOk);
+
+ var eval_req = JObject.FromObject(new {
+ expression = "window.setTimeout(function() { invoke_bad_js_test(); }, 1);",
+ });
+
+ var eval_res = await cli.SendCommand ("Runtime.evaluate", eval_req, token);
+ // Response here will be the id for the timer from JS!
+ Assert.True (eval_res.IsOk);
+
+ var ex = await Assert.ThrowsAsync<ArgumentException> (async () => await insp.WaitFor("Runtime.exceptionThrown"));
+ var ex_json = JObject.Parse (ex.Message);
+ Assert.Equal (dicFileToUrl["/debugger-driver.html"], ex_json ["exceptionDetails"]? ["url"]? .Value<string> ());
+ });
+
+ }
+
void CheckNumber (JToken locals, string name, int value) {
foreach (var l in locals) {
if (name != l["name"]?.Value<string> ())
@@ -172,9 +229,23 @@ namespace DebuggerTests
Assert.True(false, $"Could not find variable '{name}'");
}
+ void CheckString (JToken locals, string name, string value) {
+ foreach (var l in locals) {
+ if (name != l["name"]?.Value<string> ())
+ continue;
+ var val = l["value"];
+ if (value == null) {
+ Assert.Equal ("object", val ["type"]?.Value<string> ());
+ Assert.Equal ("null", val["subtype"]?.Value<string> ());
+ } else {
+ Assert.Equal ("string", val ["type"]?.Value<string> ());
+ Assert.Equal (value, val["value"]?.Value <string> ());
+ }
+ return;
+ }
+ Assert.True(false, $"Could not find variable '{name}'");
+ }
void CheckObject (JToken locals, string name, string class_name, string subtype=null) {
- Console.WriteLine ($"** Locals: {locals.ToString ()}");
- Console.WriteLine ($"\tChecking {name}");
foreach (var l in locals) {
if (name != l["name"]?.Value<string> ())
continue;
@@ -189,8 +260,6 @@ namespace DebuggerTests
}
void CheckArray (JToken locals, string name, string class_name) {
- Console.WriteLine ($"** Locals: {locals.ToString ()}");
- Console.WriteLine ($"\tChecking {name}");
foreach (var l in locals) {
if (name != l["name"]?.Value<string> ())
continue;
@@ -501,6 +570,342 @@ namespace DebuggerTests
});
}
+ [Fact]
+ public async Task InspectLocalsInPreviousFramesDuringSteppingIn2 () {
+ var insp = new Inspector ();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready (async (cli, token) => {
+ var dep_cs_loc = "dotnet://Simple.Dependency.dll/dependency.cs";
+
+ var ctx = new DebugTestContext (cli, insp, token, scripts);
+ var bp1_req = JObject.FromObject(new {
+ lineNumber = 24,
+ columnNumber = 2,
+ url = dicFileToUrl[dep_cs_loc]
+ });
+
+ var bp1_res = await cli.SendCommand ("Debugger.setBreakpointByUrl", bp1_req, token);
+ Assert.True (bp1_res.IsOk);
+
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+
+ // Will stop in Complex.DoEvenMoreStuff
+ var wait_res = await EvaluateAndCheck (
+ "window.setTimeout(function() { invoke_use_complex (); }, 1);",
+ dep_cs_loc, 24, 2, "DoEvenMoreStuff", ctx,
+ locals_fn: (locals) => {
+ Assert.Equal (1, locals.Count());
+ CheckObject (locals, "this", "Simple.Complex");
+ }
+ );
+
+ // Check UseComplex frame
+ await CheckLocalsOnFrame (wait_res ["callFrames"][3], debugger_test_loc, 17, 2, "UseComplex", ctx,
+ test_fn: (locals_m1) => {
+ Assert.Equal (7, locals_m1.Count());
+
+ CheckNumber (locals_m1, "a", 10);
+ CheckNumber (locals_m1, "b", 20);
+ CheckObject (locals_m1, "complex", "Simple.Complex");
+ CheckNumber (locals_m1, "c", 30);
+ CheckNumber (locals_m1, "d", 50);
+ CheckNumber (locals_m1, "e", 60);
+ CheckNumber (locals_m1, "f", 0);
+ }
+ );
+
+ wait_res = await StepAndCheck (StepKind.Over, dep_cs_loc, 16, 2, "DoStuff", ctx, times: 2);
+ // Check UseComplex frame again
+ await CheckLocalsOnFrame (wait_res ["callFrames"][1], debugger_test_loc, 17, 2, "UseComplex", ctx,
+ test_fn: (locals_m1) => {
+ Assert.Equal (7, locals_m1.Count());
+
+ CheckNumber (locals_m1, "a", 10);
+ CheckNumber (locals_m1, "b", 20);
+ CheckObject (locals_m1, "complex", "Simple.Complex");
+ CheckNumber (locals_m1, "c", 30);
+ CheckNumber (locals_m1, "d", 50);
+ CheckNumber (locals_m1, "e", 60);
+ CheckNumber (locals_m1, "f", 0);
+ }
+ );
+ });
+ }
+
+ [Fact]
+ public async Task InspectLocalsInPreviousFramesDuringSteppingIn () {
+ var insp = new Inspector ();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready (async (cli, token) => {
+ var ctx = new DebugTestContext (cli, insp, token, scripts);
+ var bp1_req = JObject.FromObject(new {
+ lineNumber = 100,
+ columnNumber = 3,
+ url = dicFileToUrl["dotnet://debugger-test.dll/debugger-test.cs"],
+ });
+
+ var bp1_res = await cli.SendCommand ("Debugger.setBreakpointByUrl", bp1_req, token);
+ Assert.True (bp1_res.IsOk);
+
+ var debugger_test_loc = "dotnet://debugger-test.dll/debugger-test.cs";
+
+ // Will stop in InnerMethod
+ var wait_res = await EvaluateAndCheck (
+ "window.setTimeout(function() { invoke_outer_method(); }, 1);",
+ debugger_test_loc, 100, 3, "InnerMethod", ctx,
+ locals_fn: (locals) => {
+ Assert.Equal (4, locals.Count());
+ CheckNumber (locals, "i", 5);
+ CheckNumber (locals, "j", 24);
+ CheckString (locals, "foo_str", "foo");
+ CheckObject (locals, "this", "Math.NestedInMath");
+ }
+ );
+
+ // Check OuterMethod frame
+ await CheckLocalsOnFrame (wait_res ["callFrames"][1], debugger_test_loc, 76, 2, "OuterMethod", ctx,
+ test_fn: (locals_m1) => {
+ Assert.Equal (5, locals_m1.Count());
+ // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
+ // FIXME: Failing test CheckString (locals_m1, "text", "Hello");
+ CheckNumber (locals_m1, "new_i", 0);
+ CheckNumber (locals_m1, "k", 0);
+ CheckObject (locals_m1, "nim", "Math.NestedInMath");
+ }
+ );
+
+ // step back into OuterMethod
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 80, 2, "OuterMethod", ctx, times: 7,
+ locals_fn: (locals) => {
+ Assert.Equal (5, locals.Count());
+
+ // FIXME: Failing test CheckNumber (locals_m1, "i", 5);
+ CheckString (locals, "text", "Hello");
+ // FIXME: Failing test CheckNumber (locals, "new_i", 24);
+ CheckNumber (locals, "k", 19);
+ CheckObject (locals, "nim", "Math.NestedInMath");
+ }
+ );
+
+ //await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 81, 2, "OuterMethod", ctx, times: 2);
+
+ // step into InnerMethod2
+ await StepAndCheck (StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 85, 1, "InnerMethod2", ctx,
+ locals_fn: (locals) => {
+ // umm use JOBject instead of JToken?
+ Assert.Equal (3, locals.Count());
+
+ CheckString (locals, "s", "test string");
+ //out var: CheckNumber (locals, "k", 0);
+ CheckNumber (locals, "i", 24);
+ }
+ );
+
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 89, 1, "InnerMethod2", ctx, times: 4,
+ locals_fn: (locals) => {
+ // umm use JOBject instead of JToken?
+ Assert.Equal (3, locals.Count());
+
+ CheckString (locals, "s", "test string");
+ // FIXME: Failing test CheckNumber (locals, "k", 34);
+ CheckNumber (locals, "i", 24);
+ }
+ );
+
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 81, 2, "OuterMethod", ctx, times: 2,
+ locals_fn: (locals) => {
+ Assert.Equal (5, locals.Count());
+
+ CheckString (locals, "text", "Hello");
+ // FIXME: failing test CheckNumber (locals, "i", 5);
+ CheckNumber (locals, "new_i", 22);
+ CheckNumber (locals, "k", 34);
+ CheckObject (locals, "nim", "Math.NestedInMath");
+ }
+ );
+ });
+ }
+
+ [Fact]
+ public async Task InspectLocalsDuringSteppingIn () {
+ var insp = new Inspector ();
+ //Collect events
+ var scripts = SubscribeToScripts(insp);
+
+ await Ready();
+ await insp.Ready (async (cli, token) => {
+ var ctx = new DebugTestContext (cli, insp, token, scripts);
+ var bp1_req = JObject.FromObject(new {
+ lineNumber = 75,
+ columnNumber = 2,
+ url = dicFileToUrl["dotnet://debugger-test.dll/debugger-test.cs"],
+ });
+
+ var bp1_res = await cli.SendCommand ("Debugger.setBreakpointByUrl", bp1_req, token);
+ Assert.True (bp1_res.IsOk);
+
+ await EvaluateAndCheck ("window.setTimeout(function() { invoke_outer_method(); }, 1);",
+ "dotnet://debugger-test.dll/debugger-test.cs", 75, 2, "OuterMethod", ctx,
+ locals_fn: (locals) => {
+ Assert.Equal (5, locals.Count());
+
+ CheckObject (locals, "nim", "Math.NestedInMath");
+ CheckNumber (locals, "i", 0);
+ CheckNumber (locals, "k", 0);
+ CheckNumber (locals, "new_i", 0);
+ CheckString (locals, "text", null);
+ }
+ );
+
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 76, 2, "OuterMethod", ctx,
+ locals_fn: (locals) => {
+ Assert.Equal (5, locals.Count());
+
+ CheckObject (locals, "nim", "Math.NestedInMath");
+ // FIXME: Failing test CheckNumber (locals, "i", 5);
+ CheckNumber (locals, "k", 0);
+ CheckNumber (locals, "new_i", 0);
+ CheckString (locals, "text", "Hello");
+ }
+ );
+
+ // Step into InnerMethod
+ await StepAndCheck (StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 94, 2, "InnerMethod", ctx);
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 98, 3, "InnerMethod", ctx, times: 5,
+ locals_fn: (locals) => {
+ Assert.Equal (4, locals.Count());
+
+ CheckNumber (locals, "i", 5);
+ CheckNumber (locals, "j", 15);
+ CheckString (locals, "foo_str", "foo");
+ CheckObject (locals, "this", "Math.NestedInMath");
+ }
+ );
+
+ // Step back to OuterMethod
+ await StepAndCheck (StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 77, 2, "OuterMethod", ctx, times: 5,
+ locals_fn: (locals) => {
+ Assert.Equal (5, locals.Count());
+
+ CheckObject (locals, "nim", "Math.NestedInMath");
+ // FIXME: Failing test CheckNumber (locals, "i", 5);
+ CheckNumber (locals, "k", 0);
+ CheckNumber (locals, "new_i", 24);
+ CheckString (locals, "text", "Hello");
+ }
+ );
+ });
+ }
+
+ async Task<JObject> StepAndCheck (StepKind kind, string script_loc, int line, int column, string function_name, DebugTestContext ctx,
+ Func<JObject, Task> wait_for_event_fn = null, Action<JToken> locals_fn = null, int times=1)
+ {
+ for (int i = 0; i < times - 1; i ++) {
+ await SendCommandAndCheck (null, $"Debugger.step{kind.ToString ()}", ctx);
+ }
+
+ // Check for method/line etc only at the last step
+ return await SendCommandAndCheck (
+ null, $"Debugger.step{kind.ToString ()}", ctx,
+ wait_for_event_fn: async (pause_location) => {
+ await CheckLocalsOnFrame (pause_location ["callFrames"][0], script_loc, line, column, function_name, ctx);
+ if (wait_for_event_fn != null)
+ await wait_for_event_fn (pause_location);
+ },
+ locals_fn: locals_fn);
+ }
+
+ async Task<JObject> EvaluateAndCheck (string expression, string script_loc, int line, int column, string function_name, DebugTestContext ctx,
+ Func<JObject, Task> wait_for_event_fn = null, Action<JToken> locals_fn = null)
+ => await SendCommandAndCheck (
+ JObject.FromObject (new { expression = expression }),
+ "Runtime.evaluate", ctx,
+ wait_for_event_fn: async (pause_location) => {
+ await CheckLocalsOnFrame (pause_location ["callFrames"][0], script_loc, line, column, function_name, ctx);
+ if (wait_for_event_fn != null)
+ await wait_for_event_fn (pause_location);
+ },
+ locals_fn: locals_fn);
+
+ async Task<JObject> SendCommandAndCheck (JObject args, string method, DebugTestContext ctx, Func<JObject, Task> wait_for_event_fn = null,
+ Action<JToken> locals_fn = null, string waitForEvent = Inspector.PAUSE)
+ {
+ var res = await ctx.cli.SendCommand (method, args, ctx.token);
+ if (!res.IsOk) {
+ Console.WriteLine ($"Failed to run command {method} with args: {args?.ToString ()}\nresult: {res.Error.ToString ()}");
+ Assert.True (false, $"SendCommand for {method} failed with {res.Error.ToString ()}");
+ }
+
+ var wait_res = await ctx.insp.WaitFor(waitForEvent);
+
+ if (wait_for_event_fn != null)
+ await wait_for_event_fn (wait_res);
+
+ if (locals_fn != null)
+ await CheckLocalsOnFrame (wait_res ["callFrames"][0], ctx, locals_fn);
+
+ return wait_res;
+ }
+
+ async Task CheckLocalsOnFrame (JToken frame, string script_loc, int line, int column, string function_name, DebugTestContext ctx, Action<JToken> test_fn = null)
+ {
+ CheckLocation (script_loc, line, column, ctx.scripts, frame ["location"]);
+ Assert.Equal (function_name, frame ["functionName"].Value<string> ());
+
+ await CheckLocalsOnFrame (frame, ctx, test_fn);
+ }
+
+ async Task CheckLocalsOnFrame (JToken frame, DebugTestContext ctx, Action<JToken> test_fn = null)
+ {
+ var get_prop_req = JObject.FromObject (new {
+ objectId = frame["callFrameId"]
+ });
+
+ var frame_props = await ctx.cli.SendCommand ("Runtime.getProperties", get_prop_req, ctx.token);
+ if (!frame_props.IsOk)
+ Assert.True (false, $"Runtime.getProperties failed for {get_prop_req.ToString ()}");
+
+ if (test_fn == null)
+ return;
+
+ var locals = frame_props.Value ["result"];
+ try {
+ test_fn (locals);
+ } catch {
+ Console.WriteLine ($"Failed trying to check locals: {locals.ToString ()}");
+ throw;
+ }
+ }
+
//TODO add tests covering basic stepping behavior as step in/out/over
}
+
+ class DebugTestContext
+ {
+ public InspectorClient cli;
+ public Inspector insp;
+ public CancellationToken token;
+ public Dictionary<string, string> scripts;
+
+ public DebugTestContext (InspectorClient cli, Inspector insp, CancellationToken token, Dictionary<string, string> scripts)
+ {
+ this.cli = cli;
+ this.insp = insp;
+ this.token = token;
+ this.scripts = scripts;
+ }
+ }
+
+ enum StepKind
+ {
+ Into,
+ Over,
+ Out
+ }
}
diff --git a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs
index ace484cb372..e849dc18e07 100644
--- a/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs
+++ b/sdks/wasm/Mono.WebAssembly.DebuggerProxy/DevToolsProxy.cs
@@ -27,8 +27,17 @@ namespace WebAssembly.Net.Debugging {
Result (JObject result, JObject error)
{
- this.Value = result;
- this.Error = error;
+ if (result != null && error != null)
+ throw new ArgumentException ($"Both {nameof(result)} and {nameof(error)} arguments cannot be non-null.");
+
+ bool resultHasError = String.Compare ((result? ["result"] as JObject)? ["subtype"]?. Value<string> (), "error") == 0;
+ if (result != null && resultHasError) {
+ this.Value = null;
+ this.Error = result;
+ } else {
+ this.Value = result;
+ this.Error = error;
+ }
}
public static Result FromJson (JObject obj)
diff --git a/sdks/wasm/debugger-driver.html b/sdks/wasm/debugger-driver.html
index fc241ff1a2f..42934a154d5 100644
--- a/sdks/wasm/debugger-driver.html
+++ b/sdks/wasm/debugger-driver.html
@@ -7,20 +7,34 @@
var App = {
init: function () {
this.int_add = Module.mono_bind_static_method ("[debugger-test] Math:IntAdd");
+ this.use_complex = Module.mono_bind_static_method ("[debugger-test] Math:UseComplex");
this.delegates_test = Module.mono_bind_static_method ("[debugger-test] Math:DelegatesTest");
this.generic_types_test = Module.mono_bind_static_method ("[debugger-test] Math:GenericTypesTest");
+ this.outer_method = Module.mono_bind_static_method ("[debugger-test] Math:OuterMethod");
console.log ("ready");
},
};
function invoke_add () {
return App.int_add (10, 20);
}
+ function invoke_use_complex () {
+ return App.use_complex (10, 20);
+ }
function invoke_delegates_test () {
return App.delegates_test ();
}
function invoke_generic_types_test () {
return App.generic_types_test ();
}
+ function invoke_bad_js_test () {
+ console.log ("js: In invoke_bad_js_test");
+ App.non_existant ();
+ console.log ("js: After.. shouldn't reach here");
+ }
+ function invoke_outer_method () {
+ console.log('invoke_outer_method called');
+ return App.outer_method ();
+ }
</script>
<script type="text/javascript" src="mono-config.js"></script>
<script type="text/javascript" src="runtime.js"></script>
diff --git a/sdks/wasm/debugger-test.cs b/sdks/wasm/debugger-test.cs
index c5c150ef783..18fba8e5b97 100644
--- a/sdks/wasm/debugger-test.cs
+++ b/sdks/wasm/debugger-test.cs
@@ -9,10 +9,14 @@ public class Math { //Only append content to this class as the test suite depend
return e;
}
- public static int UseComplex () {
+ public static int UseComplex (int a, int b) {
var complex = new Simple.Complex (10, "xx");
- var res = complex.DoStuff ();
- return res;
+ int c = a + b;
+ int d = c + b;
+ int e = d + a;
+ int f = 0;
+ e += complex.DoStuff ();
+ return e;
}
delegate bool IsMathNull (Math m);
@@ -63,4 +67,38 @@ public class Math { //Only append content to this class as the test suite depend
}
static bool IsMathNullDelegateTarget (Math m) => m == null;
+
+ public static void OuterMethod ()
+ {
+ Console.WriteLine ($"OuterMethod called");
+ var nim = new Math.NestedInMath ();
+ var i = 5;
+ var text = "Hello";
+ var new_i = nim.InnerMethod (i);
+ Console.WriteLine ($"i: {i}");
+ Console.WriteLine ($"-- InnerMethod returned: {new_i}, nim: {nim}, text: {text}");
+ int k = 19;
+ new_i = InnerMethod2 ("test string", new_i, out k);
+ Console.WriteLine ($"-- InnerMethod2 returned: {new_i}, and k: {k}");
+ }
+
+ static int InnerMethod2 (string s, int i, out int k)
+ {
+ k = i + 10;
+ Console.WriteLine ($"s: {s}, i: {i}, k: {k}");
+ return i - 2;
+ }
+
+ class NestedInMath
+ {
+ public int InnerMethod (int i)
+ {
+ int j = i + 10;
+ string foo_str = "foo";
+ Console.WriteLine ($"i: {i} and j: {j}, foo_str: {foo_str}");
+ j += 9;
+ Console.WriteLine ($"i: {i} and j: {j}");
+ return j;
+ }
+ }
}