Update debug proxy to match Mono commit b91580bafa7208b4a52d66cfadce070551f1904a

This commit is contained in:
Steve Sanderson 2020-03-03 11:04:17 +00:00
parent 085f6e1585
commit fee14d8e13
2 changed files with 72 additions and 48 deletions

View File

@ -183,19 +183,36 @@ namespace WebAssembly.Net.Debugging {
public SourceId (string id) public SourceId (string id)
{ {
id = id.Substring (Scheme.Length); if (!TryParse (id, out assembly, out document))
var sp = id.Split ('_'); throw new ArgumentException ("invalid source identifier", nameof (id));
this.assembly = int.Parse (sp [0]);
this.document = int.Parse (sp [1]);
} }
public static bool TryParse (string id, out SourceId script) public static bool TryParse (string id, out SourceId source)
{ {
script = null; source = null;
if (!TryParse (id, out var assembly, out var document))
return false;
source = new SourceId (assembly, document);
return true;
}
static bool TryParse (string id, out int assembly, out int document)
{
assembly = document = 0;
if (id == null || !id.StartsWith (Scheme, StringComparison.Ordinal)) if (id == null || !id.StartsWith (Scheme, StringComparison.Ordinal))
return false; return false;
script = new SourceId (id); var sp = id.Substring (Scheme.Length).Split ('_');
if (sp.Length != 2)
return false;
if (!int.TryParse (sp [0], out assembly))
return false;
if (!int.TryParse (sp [1], out document))
return false;
return true; return true;
} }
@ -495,6 +512,7 @@ namespace WebAssembly.Net.Debugging {
public IEnumerable<MethodInfo> Methods => this.methods; public IEnumerable<MethodInfo> Methods => this.methods;
public byte[] EmbeddedSource => doc.EmbeddedSource; public byte[] EmbeddedSource => doc.EmbeddedSource;
public string DocUrl => doc.Url;
public (int startLine, int startColumn, int endLine, int endColumn) GetExtents () public (int startLine, int startColumn, int endLine, int endColumn) GetExtents ()
{ {
@ -681,7 +699,7 @@ namespace WebAssembly.Net.Debugging {
public SourceFile GetFileByUrlRegex (string urlRegex) public SourceFile GetFileByUrlRegex (string urlRegex)
{ {
var regex = new Regex (urlRegex); var regex = new Regex (urlRegex);
return AllSources ().FirstOrDefault (file => regex.IsMatch (file.Url.ToString())); return AllSources ().FirstOrDefault (file => regex.IsMatch (file.Url.ToString()) || regex.IsMatch (file.DocUrl));
} }
public SourceFile GetFileByUrl (string url) public SourceFile GetFileByUrl (string url)

View File

@ -155,6 +155,14 @@ namespace WebAssembly.Net.Debugging {
protected override async Task<bool> AcceptEvent (SessionId sessionId, string method, JObject args, CancellationToken token) protected override async Task<bool> AcceptEvent (SessionId sessionId, string method, JObject args, CancellationToken token)
{ {
switch (method) { switch (method) {
case "Runtime.consoleAPICalled": {
var type = args["type"]?.ToString ();
if (type == "debug") {
if (args["args"]?[0]?["value"]?.ToString () == MonoConstants.RUNTIME_IS_READY && args["args"]?[1]?["value"]?.ToString () == "fe00e07a-5519-4dfe-b35a-f867dbaf2e28")
await RuntimeReady (sessionId, token);
}
break;
}
case "Runtime.executionContextCreated": { case "Runtime.executionContextCreated": {
SendEvent (sessionId, method, args, token); SendEvent (sessionId, method, args, token);
var ctx = args? ["context"]; var ctx = args? ["context"];
@ -167,7 +175,6 @@ namespace WebAssembly.Net.Debugging {
} }
} }
return true; return true;
//break;
} }
case "Debugger.paused": { case "Debugger.paused": {
@ -177,10 +184,6 @@ namespace WebAssembly.Net.Debugging {
if (top_func == "mono_wasm_fire_bp" || top_func == "_mono_wasm_fire_bp") { if (top_func == "mono_wasm_fire_bp" || top_func == "_mono_wasm_fire_bp") {
return await OnBreakpointHit (sessionId, args, token); return await OnBreakpointHit (sessionId, args, token);
} }
if (top_func == MonoConstants.RUNTIME_IS_READY) {
await OnRuntimeReady (sessionId, token);
return true;
}
break; break;
} }
@ -221,22 +224,36 @@ namespace WebAssembly.Net.Debugging {
} }
case "Debugger.getPossibleBreakpoints": { case "Debugger.getPossibleBreakpoints": {
var resp = await SendCommand (id, method, args, token);
if (resp.IsOk && resp.Value["locations"].HasValues) {
SendResponse (id, resp, token);
return true;
}
var start = SourceLocation.Parse (args? ["start"] as JObject); var start = SourceLocation.Parse (args? ["start"] as JObject);
//FIXME support variant where restrictToFunction=true and end is omitted //FIXME support variant where restrictToFunction=true and end is omitted
var end = SourceLocation.Parse (args? ["end"] as JObject); var end = SourceLocation.Parse (args? ["end"] as JObject);
if (start != null && end != null) if (start != null && end != null && await GetPossibleBreakpoints (id, start, end, token))
return GetPossibleBreakpoints (id, start, end, token); return true;
break;
SendResponse (id, resp, token);
return true;
} }
case "Debugger.setBreakpointByUrl": { case "Debugger.setBreakpointByUrl": {
Log ("info", $"BP req {args}"); var resp = await SendCommand (id, method, args, token);
var bp_req = BreakpointRequest.Parse (args, GetContext (id).Store); if (resp.IsOk && resp.Value ["locations"].HasValues) {
if (bp_req != null) { SendResponse (id, resp, token);
await SetBreakPoint (id, bp_req, token);
return true; return true;
} }
break;
Log ("info", $"BP req {args}");
var bp_req = BreakpointRequest.Parse (args, GetContext (id).Store);
if (bp_req != null && await SetBreakpoint (id, bp_req, token))
return true;
SendResponse (id, resp, token);
return true;
} }
case "Debugger.removeBreakpoint": { case "Debugger.removeBreakpoint": {
@ -289,14 +306,6 @@ namespace WebAssembly.Net.Debugging {
return false; return false;
} }
async Task OnRuntimeReady (SessionId sessionId, CancellationToken token)
{
Log ("info", "Runtime ready");
await RuntimeReady (sessionId, token);
await SendCommand (sessionId, "Debugger.resume", new JObject (), token);
SendEvent (sessionId, "Mono.runtimeReady", new JObject (), token);
}
//static int frame_id=0; //static int frame_id=0;
async Task<bool> OnBreakpointHit (SessionId sessionId, JObject args, CancellationToken token) async Task<bool> OnBreakpointHit (SessionId sessionId, JObject args, CancellationToken token)
{ {
@ -428,14 +437,12 @@ namespace WebAssembly.Net.Debugging {
b.State = BreakpointState.Pending; b.State = BreakpointState.Pending;
} }
Log ("info", "checking if the runtime is ready"); Log ("debug", "checking if the runtime is ready");
var res = await SendMonoCommand (sessionId, MonoCommands.IsRuntimeReady (), token); var res = await SendMonoCommand (sessionId, MonoCommands.IsRuntimeReady (), token);
var is_ready = res.Value? ["result"]? ["value"]?.Value<bool> (); var is_ready = res.Value? ["result"]? ["value"]?.Value<bool> ();
//Log ("verbose", $"\t{is_ready}");
if (is_ready.HasValue && is_ready.Value == true) { if (is_ready.HasValue && is_ready.Value == true) {
Log ("info", "RUNTIME LOOK READY. GO TIME!");
await RuntimeReady (sessionId, token); await RuntimeReady (sessionId, token);
SendEvent (sessionId, "Mono.runtimeReady", new JObject (), token);
} }
} }
@ -452,6 +459,9 @@ namespace WebAssembly.Net.Debugging {
if (context.CallStack == null) if (context.CallStack == null)
return false; return false;
if (context.CallStack.Count <= 1 && kind == StepKind.Out)
return false;
var res = await SendMonoCommand (msg_id, MonoCommands.StartSingleStepping (kind), token); var res = await SendMonoCommand (msg_id, MonoCommands.StartSingleStepping (kind), token);
SendResponse (msg_id, Result.Ok (new JObject ()), token); SendResponse (msg_id, Result.Ok (new JObject ()), token);
@ -579,7 +589,7 @@ namespace WebAssembly.Net.Debugging {
} }
} }
async Task<Result> EnableBreakPoint (SessionId sessionId, Breakpoint bp, CancellationToken token) async Task<Result> EnableBreakpoint (SessionId sessionId, Breakpoint bp, CancellationToken token)
{ {
var asm_name = bp.Location.CliLocation.Method.Assembly.Name; var asm_name = bp.Location.CliLocation.Method.Assembly.Name;
var method_token = bp.Location.CliLocation.Method.Token; var method_token = bp.Location.CliLocation.Method.Token;
@ -643,7 +653,7 @@ namespace WebAssembly.Net.Debugging {
foreach (var bp in context.Breakpoints) { foreach (var bp in context.Breakpoints) {
if (bp.State != BreakpointState.Pending) if (bp.State != BreakpointState.Pending)
continue; continue;
var res = await EnableBreakPoint (sessionId, bp, token); var res = await EnableBreakpoint (sessionId, bp, token);
var ret_code = res.Value? ["result"]? ["value"]?.Value<int> (); var ret_code = res.Value? ["result"]? ["value"]?.Value<int> ();
//if we fail we just buble that to the IDE (and let it panic over it) //if we fail we just buble that to the IDE (and let it panic over it)
@ -653,6 +663,7 @@ namespace WebAssembly.Net.Debugging {
bp.State = BreakpointState.Disabled; bp.State = BreakpointState.Disabled;
} }
} }
SendEvent (sessionId, "Mono.runtimeReady", new JObject (), token);
} }
async Task<bool> RemoveBreakpoint(MessageId msg_id, JObject args, CancellationToken token) { async Task<bool> RemoveBreakpoint(MessageId msg_id, JObject args, CancellationToken token) {
@ -689,19 +700,14 @@ namespace WebAssembly.Net.Debugging {
return res; return res;
} }
async Task SetBreakPoint (MessageId msg_id, BreakpointRequest req, CancellationToken token) async Task<bool> SetBreakpoint (MessageId msg_id, BreakpointRequest req, CancellationToken token)
{ {
var context = GetContext (msg_id); var context = GetContext (msg_id);
var bp_loc = context.Store.FindBestBreakpoint (req); var bp_loc = context.Store.FindBestBreakpoint (req);
Log ("info", $"BP request for '{req}' runtime ready {context.RuntimeReady} location '{bp_loc}'"); Log ("info", $"BP request for '{req}' runtime ready {context.RuntimeReady} location '{bp_loc}'");
if (bp_loc == null) { if (bp_loc == null) {
Log ("verbose", $"Could not resolve breakpoint request: {req}"); Log ("verbose", $"Could not resolve breakpoint request: {req}");
SendResponse (msg_id, Result.Err(JObject.FromObject (new { return false;
code = (int)MonoErrorCodes.BpNotFound,
message = $"C# Breakpoint at {req} not found."
})), token);
return;
} }
Breakpoint bp = null; Breakpoint bp = null;
@ -710,13 +716,12 @@ namespace WebAssembly.Net.Debugging {
} else { } else {
bp = new Breakpoint (bp_loc, context.NextBreakpointId (), BreakpointState.Disabled); bp = new Breakpoint (bp_loc, context.NextBreakpointId (), BreakpointState.Disabled);
var res = await EnableBreakPoint (msg_id, bp, token); var res = await EnableBreakpoint (msg_id, bp, token);
var ret_code = res.Value? ["result"]? ["value"]?.Value<int> (); var ret_code = res.Value? ["result"]? ["value"]?.Value<int> ();
//if we fail we just buble that to the IDE (and let it panic over it) //if we fail we just buble that to the IDE (and let it panic over it)
if (!ret_code.HasValue) { if (!ret_code.HasValue) {
SendResponse (msg_id, res, token); return false;
return;
} }
} }
@ -730,11 +735,12 @@ namespace WebAssembly.Net.Debugging {
}; };
SendResponse (msg_id, Result.OkFromObject (ok), token); SendResponse (msg_id, Result.OkFromObject (ok), token);
return true;
} }
bool GetPossibleBreakpoints (MessageId msg_id, SourceLocation start, SourceLocation end, CancellationToken token) async Task<bool> GetPossibleBreakpoints (MessageId msg_id, SourceLocation start, SourceLocation end, CancellationToken token)
{ {
var bps = GetContext (msg_id).Store.FindPossibleBreakpoints (start, end); var bps = (await LoadStore (msg_id, token)).FindPossibleBreakpoints (start, end);
if (bps == null) if (bps == null)
return false; return false;
@ -752,7 +758,7 @@ namespace WebAssembly.Net.Debugging {
if (!SourceId.TryParse (script_id, out var id)) if (!SourceId.TryParse (script_id, out var id))
return false; return false;
var src_file = GetContext (msg_id).Store.GetFileById (id); var src_file = (await LoadStore (msg_id, token)).GetFileById (id);
var res = new StringWriter (); var res = new StringWriter ();
try { try {