1
- using System ;
1
+ using System ;
2
2
using System . Linq ;
3
3
using System . Threading . Tasks ;
4
4
using Newtonsoft . Json . Linq ;
11
11
using Microsoft . Extensions . Logging ;
12
12
13
13
namespace WebAssembly . Net . Debugging {
14
- internal class SessionId {
15
- public string sessionId ;
14
+ internal struct SessionId {
15
+ public readonly string sessionId ;
16
+
17
+ public SessionId ( string sessionId )
18
+ {
19
+ this . sessionId = sessionId ;
20
+ }
21
+
22
+ public override int GetHashCode ( )
23
+ => sessionId ? . GetHashCode ( ) ?? 0 ;
24
+
25
+ public override bool Equals ( object obj )
26
+ => ( obj is SessionId ) ? ( ( SessionId ) obj ) . sessionId == sessionId : false ;
27
+
28
+ public override string ToString ( )
29
+ => $ "session-{ sessionId } ";
16
30
}
17
31
18
- internal class MessageId : SessionId {
19
- public int id ;
32
+ internal struct MessageId {
33
+ public readonly string sessionId ;
34
+ public readonly int id ;
35
+
36
+ public MessageId ( string sessionId , int id )
37
+ {
38
+ this . sessionId = sessionId ;
39
+ this . id = id ;
40
+ }
41
+
42
+ public static implicit operator SessionId ( MessageId id )
43
+ => new SessionId ( id . sessionId ) ;
44
+
45
+ public override string ToString ( )
46
+ => $ "msg-{ sessionId } :::{ id } ";
47
+
48
+ public override int GetHashCode ( )
49
+ => ( sessionId ? . GetHashCode ( ) ?? 0 ) ^ id . GetHashCode ( ) ;
50
+
51
+ public override bool Equals ( object obj )
52
+ => ( obj is MessageId ) ? ( ( MessageId ) obj ) . sessionId == sessionId && ( ( MessageId ) obj ) . id == id : false ;
20
53
}
21
54
22
55
internal struct Result {
@@ -28,17 +61,17 @@ internal struct Result {
28
61
29
62
Result ( JObject result , JObject error )
30
63
{
31
- if ( result != null && error != null )
32
- throw new ArgumentException ( $ "Both { nameof ( result ) } and { nameof ( error ) } arguments cannot be non-null.") ;
33
-
34
- bool resultHasError = String . Compare ( ( result ? [ "result" ] as JObject ) ? [ "subtype" ] ? . Value < string > ( ) , "error" ) == 0 ;
35
- if ( result != null && resultHasError ) {
36
- this . Value = null ;
37
- this . Error = result ;
38
- } else {
39
- this . Value = result ;
40
- this . Error = error ;
41
- }
64
+ if ( result != null && error != null )
65
+ throw new ArgumentException ( $ "Both { nameof ( result ) } and { nameof ( error ) } arguments cannot be non-null.") ;
66
+
67
+ bool resultHasError = String . Compare ( ( result ? [ "result" ] as JObject ) ? [ "subtype" ] ? . Value < string > ( ) , "error" ) == 0 ;
68
+ if ( result != null && resultHasError ) {
69
+ this . Value = null ;
70
+ this . Error = result ;
71
+ } else {
72
+ this . Value = result ;
73
+ this . Error = error ;
74
+ }
42
75
}
43
76
44
77
public static Result FromJson ( JObject obj )
@@ -120,12 +153,13 @@ public Task Pump (CancellationToken token)
120
153
internal class DevToolsProxy {
121
154
TaskCompletionSource < bool > side_exception = new TaskCompletionSource < bool > ( ) ;
122
155
TaskCompletionSource < bool > client_initiated_close = new TaskCompletionSource < bool > ( ) ;
123
- List < ( MessageId , TaskCompletionSource < Result > ) > pending_cmds = new List < ( MessageId , TaskCompletionSource < Result > ) > ( ) ;
156
+ Dictionary < MessageId , TaskCompletionSource < Result > > pending_cmds = new Dictionary < MessageId , TaskCompletionSource < Result > > ( ) ;
124
157
ClientWebSocket browser ;
125
158
WebSocket ide ;
126
159
int next_cmd_id ;
127
160
List < Task > pending_ops = new List < Task > ( ) ;
128
161
List < DevToolsQueue > queues = new List < DevToolsQueue > ( ) ;
162
+
129
163
protected readonly ILogger logger ;
130
164
131
165
public DevToolsProxy ( ILoggerFactory loggerFactory )
@@ -219,11 +253,11 @@ void OnResponse (MessageId id, Result result)
219
253
{
220
254
//logger.LogTrace ("got id {0} res {1}", id, result);
221
255
// Fixme
222
- var idx = pending_cmds . FindIndex ( e => e . Item1 . id == id . id && e . Item1 . sessionId == id . sessionId ) ;
223
- var item = pending_cmds [ idx ] ;
224
- pending_cmds . RemoveAt ( idx ) ;
225
-
226
- item . Item2 . SetResult ( result ) ;
256
+ if ( pending_cmds . Remove ( id , out var task ) ) {
257
+ task . SetResult ( result ) ;
258
+ return ;
259
+ }
260
+ logger . LogError ( "Cannot respond to command: {id} with result: {result} - command is not pending" , id , result ) ;
227
261
}
228
262
229
263
void ProcessBrowserMessage ( string msg , CancellationToken token )
@@ -232,17 +266,20 @@ void ProcessBrowserMessage (string msg, CancellationToken token)
232
266
var res = JObject . Parse ( msg ) ;
233
267
234
268
if ( res [ "id" ] == null )
235
- pending_ops . Add ( OnEvent ( new SessionId { sessionId = res [ "sessionId" ] ? . Value < string > ( ) } , res [ "method" ] . Value < string > ( ) , res [ "params" ] as JObject , token ) ) ;
269
+ pending_ops . Add ( OnEvent ( new SessionId ( res [ "sessionId" ] ? . Value < string > ( ) ) , res [ "method" ] . Value < string > ( ) , res [ "params" ] as JObject , token ) ) ;
236
270
else
237
- OnResponse ( new MessageId { id = res [ "id" ] . Value < int > ( ) , sessionId = res [ "sessionId" ] ? . Value < string > ( ) } , Result . FromJson ( res ) ) ;
271
+ OnResponse ( new MessageId ( res [ "sessionId" ] ? . Value < string > ( ) , res [ "id" ] . Value < int > ( ) ) , Result . FromJson ( res ) ) ;
238
272
}
239
273
240
274
void ProcessIdeMessage ( string msg , CancellationToken token )
241
275
{
242
276
Log ( "protocol" , $ "ide: { msg } ") ;
243
277
if ( ! string . IsNullOrEmpty ( msg ) ) {
244
278
var res = JObject . Parse ( msg ) ;
245
- 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 ) ) ;
279
+ pending_ops . Add ( OnCommand (
280
+ new MessageId ( res [ "sessionId" ] ? . Value < string > ( ) , res [ "id" ] . Value < int > ( ) ) ,
281
+ res [ "method" ] . Value < string > ( ) ,
282
+ res [ "params" ] as JObject , token ) ) ;
246
283
}
247
284
}
248
285
@@ -263,9 +300,9 @@ Task<Result> SendCommandInternal (SessionId sessionId, string method, JObject ar
263
300
} ) ;
264
301
var tcs = new TaskCompletionSource < Result > ( ) ;
265
302
266
- var msgId = new MessageId { id = id , sessionId = sessionId . sessionId } ;
303
+ var msgId = new MessageId ( sessionId . sessionId , id ) ;
267
304
//Log ("verbose", $"add cmd id {sessionId}-{id}");
268
- pending_cmds . Add ( ( msgId , tcs ) ) ;
305
+ pending_cmds [ msgId ] = tcs ;
269
306
270
307
Send ( this . browser , o , token ) ;
271
308
return tcs . Task ;
0 commit comments