From 4438f333041660cf4973ee20b93f2111d5ad953c Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 30 Apr 2020 15:48:46 +0100 Subject: [PATCH] Update ws-proxy to match runtime in use (from Mono commit cc6d4bf6cfce33ae3b41f74ac14ac2cb770603d5) --- .../MonoDebugProxy/ws-proxy/DevToolsHelper.cs | 16 +++--- .../src/MonoDebugProxy/ws-proxy/MonoProxy.cs | 55 ++++++++++--------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/DevToolsHelper.cs b/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/DevToolsHelper.cs index 10712c4d2d..871c10de9b 100644 --- a/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/DevToolsHelper.cs +++ b/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/DevToolsHelper.cs @@ -187,14 +187,8 @@ namespace WebAssembly.Net.Debugging { public static MonoCommands ClearAllBreakpoints () => new MonoCommands ("MONO.mono_wasm_clear_all_breakpoints()"); - public static MonoCommands GetObjectProperties (DotnetObjectId objectId, bool expandValueTypes) - => new MonoCommands ($"MONO.mono_wasm_get_object_properties({int.Parse (objectId.Value)}, { (expandValueTypes ? "true" : "false") })"); - - public static MonoCommands GetArrayValues (int objectId) - => new MonoCommands ($"MONO.mono_wasm_get_array_values({objectId})"); - - public static MonoCommands GetArrayValueExpanded (int objectId, int idx) - => new MonoCommands ($"MONO.mono_wasm_get_array_value_expanded({objectId}, {idx})"); + public static MonoCommands GetDetails (DotnetObjectId objectId, JToken args = null) + => new MonoCommands ($"MONO.mono_wasm_get_details ('{objectId}', {(args ?? "{}")})"); public static MonoCommands GetScopeVariables (int scopeId, params int[] vars) => new MonoCommands ($"MONO.mono_wasm_get_variables({scopeId}, [ {string.Join (",", vars)} ])"); @@ -204,6 +198,12 @@ namespace WebAssembly.Net.Debugging { public static MonoCommands RemoveBreakpoint (int breakpointId) => new MonoCommands ($"MONO.mono_wasm_remove_breakpoint({breakpointId})"); + + public static MonoCommands ReleaseObject (DotnetObjectId objectId) + => new MonoCommands ($"MONO.mono_wasm_release_object('{objectId}')"); + + public static MonoCommands CallFunctionOn (JToken args) + => new MonoCommands ($"MONO.mono_wasm_call_function_on ({args.ToString ()})"); } internal enum MonoErrorCodes { diff --git a/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/MonoProxy.cs b/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/MonoProxy.cs index aa93301b7c..7f11df13d8 100644 --- a/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/MonoProxy.cs +++ b/src/Components/WebAssembly/DebugProxy/src/MonoDebugProxy/ws-proxy/MonoProxy.cs @@ -246,7 +246,7 @@ namespace WebAssembly.Net.Debugging { if (!(DotnetObjectId.TryParse (args ["objectId"], out var objectId) && objectId.Scheme == "cfo_res")) break; - await SendMonoCommand (id, new MonoCommands ($"MONO.mono_wasm_release_object('{objectId}')"), token); + await SendMonoCommand (id, MonoCommands.ReleaseObject (objectId), token); SendResponse (id, Result.OkFromObject (new{}), token); return true; } @@ -325,9 +325,8 @@ namespace WebAssembly.Net.Debugging { } var returnByValue = args ["returnByValue"]?.Value () ?? false; - var cmd = new MonoCommands ($"MONO.mono_wasm_call_function_on ({args.ToString ()}, {(returnByValue ? "true" : "false")})"); + var res = await SendMonoCommand (id, MonoCommands.CallFunctionOn (args), token); - var res = await SendMonoCommand (id, cmd, token); if (!returnByValue && DotnetObjectId.TryParse (res.Value?["result"]?["value"]?["objectId"], out var resultObjectId) && resultObjectId.Scheme == "cfo_res") @@ -349,7 +348,7 @@ namespace WebAssembly.Net.Debugging { if (objectId.Scheme == "scope") return await GetScopeProperties (id, int.Parse (objectId.Value), token); - var res = await SendMonoCommand (id, new MonoCommands ($"MONO.mono_wasm_get_details ('{objectId}', {args})"), token); + var res = await SendMonoCommand (id, MonoCommands.GetDetails (objectId, args), token); if (res.IsErr) return res; @@ -415,6 +414,9 @@ namespace WebAssembly.Net.Debugging { var method_token = mono_frame ["method_token"].Value (); var assembly_name = mono_frame ["assembly_name"].Value (); + // This can be different than `method.Name`, like in case of generic methods + var method_name = mono_frame ["method_name"]?.Value (); + var store = await LoadStore (sessionId, token); var asm = store.GetAssemblyByName (assembly_name); if (asm == null) { @@ -440,11 +442,11 @@ namespace WebAssembly.Net.Debugging { } Log ("info", $"frame il offset: {il_pos} method token: {method_token} assembly name: {assembly_name}"); - Log ("info", $"\tmethod {method.Name} location: {location}"); + Log ("info", $"\tmethod {method_name} location: {location}"); frames.Add (new Frame (method, location, frame_id-1)); callFrames.Add (new { - functionName = method.Name, + functionName = method_name, callFrameId = $"dotnet:scope:{frame_id-1}", functionLocation = method.StartLocation.AsLocation (), @@ -461,7 +463,7 @@ namespace WebAssembly.Net.Debugging { description = "Object", objectId = $"dotnet:scope:{frame_id-1}", }, - name = method.Name, + name = method_name, startLocation = method.StartLocation.AsLocation (), endLocation = method.EndLocation.AsLocation (), }} @@ -558,24 +560,20 @@ namespace WebAssembly.Net.Debugging { return obj; var scope = context.CallStack.FirstOrDefault (s => s.Id == scope_id); - var vars = scope.Method.GetLiveVarsAt (scope.Location.CliLocation.Offset); + var live_vars = scope.Method.GetLiveVarsAt (scope.Location.CliLocation.Offset); //get_this - int [] var_ids = { }; - var res = await SendMonoCommand (msg_id, MonoCommands.GetScopeVariables (scope.Id, var_ids), token); - var values = res.Value? ["result"]? ["value"]?.Values ().ToArray (); - thisValue = values.FirstOrDefault (v => v ["name"].Value () == "this"); + var res = await SendMonoCommand (msg_id, MonoCommands.GetScopeVariables (scope.Id, live_vars.Select (lv => lv.Index).ToArray ()), token); + + var scope_values = res.Value? ["result"]? ["value"]?.Values ()?.ToArray (); + thisValue = scope_values?.FirstOrDefault (v => v ["name"]?.Value () == "this"); if (!only_search_on_this) { - if (thisValue != null && expression == "this") { + if (thisValue != null && expression == "this") return thisValue; - } - //search in locals - var var_id = vars.SingleOrDefault (v => v.Name == expression); - if (var_id != null) { - res = await SendMonoCommand (msg_id, MonoCommands.GetScopeVariables (scope.Id, new int [] { var_id.Index }), token); - values = res.Value? ["result"]? ["value"]?.Values ().ToArray (); - return values [0]; - } + + var value = scope_values.SingleOrDefault (sv => sv ["name"]?.Value () == expression); + if (value != null) + return value; } //search in scope @@ -583,9 +581,9 @@ namespace WebAssembly.Net.Debugging { if (!DotnetObjectId.TryParse (thisValue ["value"] ["objectId"], out var objectId)) return null; - res = await SendMonoCommand (msg_id, MonoCommands.GetObjectProperties (objectId, expandValueTypes: false), token); - values = res.Value? ["result"]? ["value"]?.Values ().ToArray (); - var foundValue = values.FirstOrDefault (v => v ["name"].Value () == expression); + res = await SendMonoCommand (msg_id, MonoCommands.GetDetails (objectId), token); + scope_values = res.Value? ["result"]? ["value"]?.Values ().ToArray (); + var foundValue = scope_values.FirstOrDefault (v => v ["name"].Value () == expression); if (foundValue != null) { foundValue["fromThis"] = true; context.LocalsCache[foundValue ["name"].Value ()] = foundValue; @@ -605,7 +603,6 @@ namespace WebAssembly.Net.Debugging { var varValue = await TryGetVariableValue (msg_id, scope_id, expression, false, token); if (varValue != null) { - varValue ["value"] ["description"] = varValue ["value"] ["className"]; SendResponse (msg_id, Result.OkFromObject (new { result = varValue ["value"] }), token); @@ -650,11 +647,17 @@ namespace WebAssembly.Net.Debugging { var var_list = new List (); int i = 0; for (; i < vars.Length && i < values.Length; i ++) { + // For async methods, we get locals with names, unlike non-async methods + // and the order may not match the var_ids, so, use the names that they + // come with + if (values [i]["name"] != null) + continue; + ctx.LocalsCache[vars [i].Name] = values [i]; var_list.Add (new { name = vars [i].Name, value = values [i]["value"] }); } for (; i < values.Length; i ++) { - ctx.LocalsCache[values [i]["name"].ToString()] = values [i]["value"]; + ctx.LocalsCache[values [i]["name"].ToString()] = values [i]; var_list.Add (values [i]); }