Update ws-proxy code (#19826)
This commit is contained in:
parent
9343d2bca0
commit
f1b812e21e
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
@ -11,12 +11,45 @@ using System.Collections.Generic;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace WebAssembly.Net.Debugging {
|
namespace WebAssembly.Net.Debugging {
|
||||||
internal class SessionId {
|
internal struct SessionId {
|
||||||
public string 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 {
|
internal struct MessageId {
|
||||||
public int id;
|
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 {
|
internal struct Result {
|
||||||
|
|
@ -28,17 +61,17 @@ namespace WebAssembly.Net.Debugging {
|
||||||
|
|
||||||
Result (JObject result, JObject error)
|
Result (JObject result, JObject error)
|
||||||
{
|
{
|
||||||
if (result != null && error != null)
|
if (result != null && error != null)
|
||||||
throw new ArgumentException ($"Both {nameof(result)} and {nameof(error)} arguments cannot be non-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;
|
bool resultHasError = String.Compare ((result? ["result"] as JObject)? ["subtype"]?. Value<string> (), "error") == 0;
|
||||||
if (result != null && resultHasError) {
|
if (result != null && resultHasError) {
|
||||||
this.Value = null;
|
this.Value = null;
|
||||||
this.Error = result;
|
this.Error = result;
|
||||||
} else {
|
} else {
|
||||||
this.Value = result;
|
this.Value = result;
|
||||||
this.Error = error;
|
this.Error = error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result FromJson (JObject obj)
|
public static Result FromJson (JObject obj)
|
||||||
|
|
@ -120,12 +153,13 @@ namespace WebAssembly.Net.Debugging {
|
||||||
internal class DevToolsProxy {
|
internal class DevToolsProxy {
|
||||||
TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool> ();
|
TaskCompletionSource<bool> side_exception = new TaskCompletionSource<bool> ();
|
||||||
TaskCompletionSource<bool> client_initiated_close = 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;
|
ClientWebSocket browser;
|
||||||
WebSocket ide;
|
WebSocket ide;
|
||||||
int next_cmd_id;
|
int next_cmd_id;
|
||||||
List<Task> pending_ops = new List<Task> ();
|
List<Task> pending_ops = new List<Task> ();
|
||||||
List<DevToolsQueue> queues = new List<DevToolsQueue> ();
|
List<DevToolsQueue> queues = new List<DevToolsQueue> ();
|
||||||
|
|
||||||
protected readonly ILogger logger;
|
protected readonly ILogger logger;
|
||||||
|
|
||||||
public DevToolsProxy (ILoggerFactory loggerFactory)
|
public DevToolsProxy (ILoggerFactory loggerFactory)
|
||||||
|
|
@ -219,11 +253,11 @@ namespace WebAssembly.Net.Debugging {
|
||||||
{
|
{
|
||||||
//logger.LogTrace ("got id {0} res {1}", id, result);
|
//logger.LogTrace ("got id {0} res {1}", id, result);
|
||||||
// Fixme
|
// Fixme
|
||||||
var idx = pending_cmds.FindIndex (e => e.Item1.id == id.id && e.Item1.sessionId == id.sessionId);
|
if (pending_cmds.Remove (id, out var task)) {
|
||||||
var item = pending_cmds [idx];
|
task.SetResult (result);
|
||||||
pending_cmds.RemoveAt (idx);
|
return;
|
||||||
|
}
|
||||||
item.Item2.SetResult (result);
|
logger.LogError ("Cannot respond to command: {id} with result: {result} - command is not pending", id, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessBrowserMessage (string msg, CancellationToken token)
|
void ProcessBrowserMessage (string msg, CancellationToken token)
|
||||||
|
|
@ -232,9 +266,9 @@ namespace WebAssembly.Net.Debugging {
|
||||||
var res = JObject.Parse (msg);
|
var res = JObject.Parse (msg);
|
||||||
|
|
||||||
if (res ["id"] == null)
|
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
|
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)
|
void ProcessIdeMessage (string msg, CancellationToken token)
|
||||||
|
|
@ -242,7 +276,10 @@ namespace WebAssembly.Net.Debugging {
|
||||||
Log ("protocol", $"ide: {msg}");
|
Log ("protocol", $"ide: {msg}");
|
||||||
if (!string.IsNullOrEmpty (msg)) {
|
if (!string.IsNullOrEmpty (msg)) {
|
||||||
var res = JObject.Parse (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 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}");
|
//Log ("verbose", $"add cmd id {sessionId}-{id}");
|
||||||
pending_cmds.Add ((msgId , tcs));
|
pending_cmds[msgId] = tcs;
|
||||||
|
|
||||||
Send (this.browser, o, token);
|
Send (this.browser, o, token);
|
||||||
return tcs.Task;
|
return tcs.Task;
|
||||||
|
|
|
||||||
|
|
@ -134,24 +134,22 @@ namespace WebAssembly.Net.Debugging {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class MonoProxy : DevToolsProxy {
|
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) { }
|
public MonoProxy (ILoggerFactory loggerFactory) : base(loggerFactory) { }
|
||||||
|
|
||||||
ExecutionContext GetContext (SessionId sessionId)
|
ExecutionContext GetContext (SessionId sessionId)
|
||||||
{
|
{
|
||||||
var id = sessionId?.sessionId ?? "default";
|
if (contexts.TryGetValue (sessionId, out var context))
|
||||||
if (contexts.TryGetValue (id, out var context))
|
|
||||||
return 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)
|
bool UpdateContext (SessionId sessionId, ExecutionContext executionContext, out ExecutionContext previousExecutionContext)
|
||||||
{
|
{
|
||||||
var id = sessionId?.sessionId ?? "default";
|
var previous = contexts.TryGetValue (sessionId, out previousExecutionContext);
|
||||||
var previous = contexts.TryGetValue (id, out previousExecutionContext);
|
contexts[sessionId] = executionContext;
|
||||||
contexts[id] = executionContext;
|
|
||||||
return previous;
|
return previous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -494,6 +492,14 @@ namespace WebAssembly.Net.Debugging {
|
||||||
|
|
||||||
var res = await SendMonoCommand (msg_id, MonoCommands.StartSingleStepping (kind), token);
|
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);
|
SendResponse (msg_id, Result.Ok (new JObject ()), token);
|
||||||
|
|
||||||
context.CallStack = null;
|
context.CallStack = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue