Update ws-proxy code (#19826)

This commit is contained in:
Steve Sanderson 2020-03-13 11:34:09 +00:00 committed by GitHub
parent 9343d2bca0
commit f1b812e21e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 33 deletions

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
@ -11,12 +11,45 @@ using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace WebAssembly.Net.Debugging {
internal class SessionId {
public string sessionId;
internal struct SessionId {
public readonly string sessionId;
public SessionId (string sessionId)
{
this.sessionId = sessionId;
}
public override int GetHashCode ()
=> sessionId?.GetHashCode () ?? 0;
public override bool Equals (object obj)
=> (obj is SessionId) ? ((SessionId) obj).sessionId == sessionId : false;
public override string ToString ()
=> $"session-{sessionId}";
}
internal class MessageId : SessionId {
public int id;
internal struct MessageId {
public readonly string sessionId;
public readonly int id;
public MessageId (string sessionId, int id)
{
this.sessionId = sessionId;
this.id = id;
}
public static implicit operator SessionId (MessageId id)
=> new SessionId (id.sessionId);
public override string ToString ()
=> $"msg-{sessionId}:::{id}";
public override int GetHashCode ()
=> (sessionId?.GetHashCode () ?? 0) ^ id.GetHashCode ();
public override bool Equals (object obj)
=> (obj is MessageId) ? ((MessageId) obj).sessionId == sessionId && ((MessageId) obj).id == id : false;
}
internal struct Result {
@ -28,17 +61,17 @@ namespace WebAssembly.Net.Debugging {
Result (JObject result, JObject error)
{
if (result != null && error != null)
throw new ArgumentException ($"Both {nameof(result)} and {nameof(error)} arguments cannot be non-null.");
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;
}
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)
@ -120,12 +153,13 @@ namespace WebAssembly.Net.Debugging {
internal class DevToolsProxy {
TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool> ();
TaskCompletionSource<bool> client_initiated_close = new TaskCompletionSource<bool> ();
List<(MessageId, TaskCompletionSource<Result>)> pending_cmds = new List<(MessageId, TaskCompletionSource<Result>)> ();
Dictionary<MessageId, TaskCompletionSource<Result>> pending_cmds = new Dictionary<MessageId, TaskCompletionSource<Result>> ();
ClientWebSocket browser;
WebSocket ide;
int next_cmd_id;
List<Task> pending_ops = new List<Task> ();
List<DevToolsQueue> queues = new List<DevToolsQueue> ();
protected readonly ILogger logger;
public DevToolsProxy (ILoggerFactory loggerFactory)
@ -219,11 +253,11 @@ namespace WebAssembly.Net.Debugging {
{
//logger.LogTrace ("got id {0} res {1}", id, result);
// Fixme
var idx = pending_cmds.FindIndex (e => e.Item1.id == id.id && e.Item1.sessionId == id.sessionId);
var item = pending_cmds [idx];
pending_cmds.RemoveAt (idx);
item.Item2.SetResult (result);
if (pending_cmds.Remove (id, out var task)) {
task.SetResult (result);
return;
}
logger.LogError ("Cannot respond to command: {id} with result: {result} - command is not pending", id, result);
}
void ProcessBrowserMessage (string msg, CancellationToken token)
@ -232,9 +266,9 @@ namespace WebAssembly.Net.Debugging {
var res = JObject.Parse (msg);
if (res ["id"] == null)
pending_ops.Add (OnEvent (new SessionId { sessionId = res ["sessionId"]?.Value<string> () }, res ["method"].Value<string> (), res ["params"] as JObject, token));
pending_ops.Add (OnEvent (new SessionId (res ["sessionId"]?.Value<string> ()), res ["method"].Value<string> (), res ["params"] as JObject, token));
else
OnResponse (new MessageId { id = res ["id"].Value<int> (), sessionId = res ["sessionId"]?.Value<string> () }, Result.FromJson (res));
OnResponse (new MessageId (res ["sessionId"]?.Value<string> (), res ["id"].Value<int> ()), Result.FromJson (res));
}
void ProcessIdeMessage (string msg, CancellationToken token)
@ -242,7 +276,10 @@ namespace WebAssembly.Net.Debugging {
Log ("protocol", $"ide: {msg}");
if (!string.IsNullOrEmpty (msg)) {
var res = JObject.Parse (msg);
pending_ops.Add (OnCommand (new MessageId { id = res ["id"].Value<int> (), sessionId = res ["sessionId"]?.Value<string> () }, res ["method"].Value<string> (), res ["params"] as JObject, token));
pending_ops.Add (OnCommand (
new MessageId (res ["sessionId"]?.Value<string> (), res ["id"].Value<int> ()),
res ["method"].Value<string> (),
res ["params"] as JObject, token));
}
}
@ -263,9 +300,9 @@ namespace WebAssembly.Net.Debugging {
});
var tcs = new TaskCompletionSource<Result> ();
var msgId = new MessageId { id = id, sessionId = sessionId.sessionId };
var msgId = new MessageId (sessionId.sessionId, id);
//Log ("verbose", $"add cmd id {sessionId}-{id}");
pending_cmds.Add ((msgId , tcs));
pending_cmds[msgId] = tcs;
Send (this.browser, o, token);
return tcs.Task;

View File

@ -134,24 +134,22 @@ namespace WebAssembly.Net.Debugging {
}
internal class MonoProxy : DevToolsProxy {
Dictionary<string, ExecutionContext> contexts = new Dictionary<string, ExecutionContext> ();
Dictionary<SessionId, ExecutionContext> contexts = new Dictionary<SessionId, ExecutionContext> ();
public MonoProxy (ILoggerFactory loggerFactory) : base(loggerFactory) { }
ExecutionContext GetContext (SessionId sessionId)
{
var id = sessionId?.sessionId ?? "default";
if (contexts.TryGetValue (id, out var context))
if (contexts.TryGetValue (sessionId, out var context))
return context;
throw new ArgumentException ($"Invalid Session: \"{id}\"", nameof (sessionId));
throw new ArgumentException ($"Invalid Session: \"{sessionId}\"", nameof (sessionId));
}
bool UpdateContext (SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext)
{
var id = sessionId?.sessionId ?? "default";
var previous = contexts.TryGetValue (id, out previousExecutionContext);
contexts[id] = executionContext;
var previous = contexts.TryGetValue (sessionId, out previousExecutionContext);
contexts[sessionId] = executionContext;
return previous;
}
@ -494,6 +492,14 @@ namespace WebAssembly.Net.Debugging {
var res = await SendMonoCommand (msg_id, MonoCommands.StartSingleStepping (kind), token);
var ret_code = res.Value? ["result"]? ["value"]?.Value<int> ();
if (ret_code.HasValue && ret_code.Value == 0) {
context.CallStack = null;
await SendCommand (msg_id, "Debugger.stepOut", new JObject (), token);
return false;
}
SendResponse (msg_id, Result.Ok (new JObject ()), token);
context.CallStack = null;