Skip to content

Commit fdcc277

Browse files
committed
Simplify
1 parent b1a4722 commit fdcc277

File tree

5 files changed

+119
-93
lines changed

5 files changed

+119
-93
lines changed

dotnet/src/webdriver/BiDi/Communication/Broker.cs

Lines changed: 92 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
using OpenQA.Selenium.BiDi.Communication.Json;
2121
using OpenQA.Selenium.BiDi.Communication.Json.Converters;
22-
using OpenQA.Selenium.BiDi.Communication.Json.Internal;
2322
using OpenQA.Selenium.BiDi.Communication.Transport;
2423
using OpenQA.Selenium.Internal.Logging;
2524
using System;
@@ -33,19 +32,19 @@
3332

3433
namespace OpenQA.Selenium.BiDi.Communication;
3534

36-
public class Broker : IAsyncDisposable
35+
public sealed class Broker : IAsyncDisposable
3736
{
3837
private readonly ILogger _logger = Log.GetLogger<Broker>();
3938

4039
private readonly BiDi _bidi;
4140
private readonly ITransport _transport;
4241

43-
private readonly ConcurrentDictionary<int, (Command, TaskCompletionSource<object>)> _pendingCommands = new();
42+
private readonly ConcurrentDictionary<long, (Command, TaskCompletionSource<object>)> _pendingCommands = new();
4443
private readonly BlockingCollection<MessageEvent> _pendingEvents = [];
4544

4645
private readonly ConcurrentDictionary<string, List<EventHandler>> _eventHandlers = new();
4746

48-
private int _currentCommandId;
47+
private long _currentCommandId;
4948

5049
private static readonly TaskFactory _myTaskFactory = new(CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskContinuationOptions.None, TaskScheduler.Default);
5150

@@ -126,49 +125,11 @@ private async Task ReceiveMessagesAsync(CancellationToken cancellationToken)
126125
{
127126
var data = await _transport.ReceiveAsync(cancellationToken).ConfigureAwait(false);
128127

129-
Utf8JsonReader utfJsonReader = new(new ReadOnlySpan<byte>(data));
130-
utfJsonReader.Read();
131-
var messageType = utfJsonReader.GetDiscriminator("type");
132-
133-
switch (messageType)
134-
{
135-
case "success":
136-
var successId = int.Parse(utfJsonReader.GetDiscriminator("id"));
137-
var successCommand = _pendingCommands[successId];
138-
var messageSuccess = JsonSerializer.Deserialize(ref utfJsonReader, successCommand.Item1.ResultType, _jsonSerializerContext);
139-
140-
successCommand.Item2.SetResult(messageSuccess);
141-
142-
_pendingCommands.TryRemove(successId, out _);
143-
break;
144-
145-
case "event":
146-
utfJsonReader.Read();
147-
utfJsonReader.Read();
148-
var method = utfJsonReader.GetString();
149-
150-
utfJsonReader.Read();
151-
152-
// TODO: Just get type info from existing subscribers, should be better
153-
var type = _eventHandlers[method].First().EventArgsType;
154-
155-
var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref utfJsonReader, type, _jsonSerializerContext);
156-
157-
var messageEvent = new MessageEvent(method, eventArgs);
158-
_pendingEvents.Add(messageEvent);
159-
break;
160-
161-
case "error":
162-
var messageError = JsonSerializer.Deserialize(ref utfJsonReader, _jsonSerializerContext.MessageError);
163-
var errorCommand = _pendingCommands[messageError.Id];
164-
errorCommand.Item2.SetException(new BiDiException($"{messageError.Error}: {messageError.Message}"));
165-
_pendingCommands.TryRemove(messageError.Id, out _);
166-
break;
167-
}
128+
ProcessReceivedMessage(data);
168129
}
169130
catch (Exception ex)
170131
{
171-
if (!cancellationToken.IsCancellationRequested)
132+
if (cancellationToken.IsCancellationRequested is not true)
172133
{
173134
_logger.Error($"Couldn't process received BiDi remote message: {ex}");
174135
}
@@ -227,7 +188,7 @@ public async Task<TResult> ExecuteCommandAsync<TCommand, TResult>(TCommand comma
227188
{
228189
var result = await ExecuteCommandCoreAsync(command, options).ConfigureAwait(false);
229190

230-
return ((MessageSuccess<TResult>)result).Result;
191+
return (TResult)result;
231192
}
232193

233194
private async Task<object> ExecuteCommandCoreAsync<TCommand>(TCommand command, CommandOptions? options)
@@ -249,7 +210,7 @@ private async Task<object> ExecuteCommandCoreAsync<TCommand>(TCommand command, C
249210

250211
await _transport.SendAsync(data, cts.Token).ConfigureAwait(false);
251212

252-
return await tcs.Task;
213+
return await tcs.Task.ConfigureAwait(false);
253214
}
254215

255216
public async Task<Subscription> SubscribeAsync<TEventArgs>(string eventName, Action<TEventArgs> action, SubscriptionOptions? options = null)
@@ -336,12 +297,6 @@ public async Task UnsubscribeAsync(Modules.Session.Subscription subscription, Ev
336297
}
337298

338299
public async ValueTask DisposeAsync()
339-
{
340-
await DisposeAsyncCore();
341-
GC.SuppressFinalize(this);
342-
}
343-
344-
protected virtual async ValueTask DisposeAsyncCore()
345300
{
346301
_pendingEvents.CompleteAdding();
347302

@@ -353,5 +308,90 @@ protected virtual async ValueTask DisposeAsyncCore()
353308
}
354309

355310
_transport.Dispose();
311+
312+
GC.SuppressFinalize(this);
313+
}
314+
315+
private void ProcessReceivedMessage(byte[]? data)
316+
{
317+
long? id = default;
318+
string? type = default;
319+
string? method = default;
320+
string? error = default;
321+
string? message = default;
322+
Utf8JsonReader resultReader = default;
323+
Utf8JsonReader paramsReader = default;
324+
325+
Utf8JsonReader reader = new(new ReadOnlySpan<byte>(data));
326+
reader.Read();
327+
328+
reader.Read(); // "{"
329+
330+
while (reader.TokenType == JsonTokenType.PropertyName)
331+
{
332+
string? propertyName = reader.GetString();
333+
reader.Read();
334+
335+
switch (propertyName)
336+
{
337+
case "id":
338+
id = reader.GetInt64();
339+
break;
340+
341+
case "type":
342+
type = reader.GetString();
343+
break;
344+
345+
case "method":
346+
method = reader.GetString();
347+
break;
348+
349+
case "result":
350+
resultReader = reader; // cloning reader with current position
351+
break;
352+
353+
case "params":
354+
paramsReader = reader; // cloning reader with current position
355+
break;
356+
357+
case "error":
358+
error = reader.GetString();
359+
break;
360+
361+
case "message":
362+
message = reader.GetString();
363+
break;
364+
}
365+
366+
reader.Skip();
367+
reader.Read();
368+
}
369+
370+
switch (type)
371+
{
372+
case "success":
373+
var successCommand = _pendingCommands[id.Value];
374+
var messageSuccess = JsonSerializer.Deserialize(ref resultReader, successCommand.Item1.ResultType, _jsonSerializerContext);
375+
successCommand.Item2.SetResult(messageSuccess);
376+
_pendingCommands.TryRemove(id.Value, out _);
377+
break;
378+
379+
case "event":
380+
// TODO: Just get type info from existing subscribers, should be better
381+
var eventType = _eventHandlers[method].First().EventArgsType;
382+
383+
var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventType, _jsonSerializerContext);
384+
385+
var messageEvent = new MessageEvent(method, eventArgs);
386+
_pendingEvents.Add(messageEvent);
387+
break;
388+
389+
case "error":
390+
var messageError = new MessageError(id.Value) { Error = error, Message = message };
391+
var errorCommand = _pendingCommands[messageError.Id];
392+
errorCommand.Item2.SetException(new BiDiException($"{messageError.Error}: {messageError.Message}"));
393+
_pendingCommands.TryRemove(messageError.Id, out _);
394+
break;
395+
}
356396
}
357397
}

dotnet/src/webdriver/BiDi/Communication/Command.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ protected Command(string method, Type resultType)
3434
public string Method { get; }
3535

3636
[JsonPropertyOrder(0)]
37-
public int Id { get; internal set; }
37+
public long Id { get; internal set; }
3838

3939
[JsonIgnore]
4040
public Type ResultType { get; }
4141
}
4242

43-
internal abstract class Command<TCommandParameters, TCommandResult>(TCommandParameters @params, string method) : Command(method, typeof(MessageSuccess<TCommandResult>))
43+
internal abstract class Command<TCommandParameters, TCommandResult>(TCommandParameters @params, string method) : Command(method, typeof(TCommandResult))
4444
where TCommandParameters : CommandParameters
4545
where TCommandResult : EmptyResult
4646
{

dotnet/src/webdriver/BiDi/Communication/Json/BiDiJsonSerializerContext.cs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace OpenQA.Selenium.BiDi.Communication.Json;
2424

2525
#region https://github.com/dotnet/runtime/issues/72604
2626
//[JsonSerializable(typeof(MessageSuccess))]
27-
[JsonSerializable(typeof(MessageSuccess<EmptyResult>))]
27+
[JsonSerializable(typeof(EmptyResult))]
2828
[JsonSerializable(typeof(MessageError))]
2929
[JsonSerializable(typeof(MessageEvent))]
3030

@@ -75,54 +75,54 @@ namespace OpenQA.Selenium.BiDi.Communication.Json;
7575
[JsonSerializable(typeof(Message))]
7676

7777
[JsonSerializable(typeof(Modules.Session.StatusCommand))]
78-
[JsonSerializable(typeof(MessageSuccess<Modules.Session.StatusResult>))]
78+
[JsonSerializable(typeof(Modules.Session.StatusResult))]
7979
[JsonSerializable(typeof(Modules.Session.NewCommand))]
80-
[JsonSerializable(typeof(MessageSuccess<Modules.Session.NewResult>))]
80+
[JsonSerializable(typeof(Modules.Session.NewResult))]
8181
[JsonSerializable(typeof(Modules.Session.EndCommand))]
8282
[JsonSerializable(typeof(Modules.Session.SubscribeCommand))]
83-
[JsonSerializable(typeof(MessageSuccess<Modules.Session.SubscribeResult>))]
83+
[JsonSerializable(typeof(Modules.Session.SubscribeResult))]
8484
[JsonSerializable(typeof(Modules.Session.UnsubscribeByIdCommand))]
8585
[JsonSerializable(typeof(Modules.Session.UnsubscribeByAttributesCommand))]
8686

8787
[JsonSerializable(typeof(Modules.Browser.CloseCommand), TypeInfoPropertyName = "Browser_CloseCommand")]
8888
[JsonSerializable(typeof(Modules.Browser.CreateUserContextCommand))]
8989
[JsonSerializable(typeof(Modules.Browser.GetUserContextsCommand))]
90-
[JsonSerializable(typeof(MessageSuccess<Modules.Browser.GetUserContextsResult>))]
90+
[JsonSerializable(typeof(Modules.Browser.GetUserContextsResult))]
9191
[JsonSerializable(typeof(Modules.Browser.RemoveUserContextCommand))]
9292
[JsonSerializable(typeof(Modules.Browser.GetClientWindowsCommand))]
93-
[JsonSerializable(typeof(MessageSuccess<Modules.Browser.GetClientWindowsResult>))]
94-
[JsonSerializable(typeof(MessageSuccess<Modules.Browser.UserContextInfo>))]
93+
[JsonSerializable(typeof(Modules.Browser.GetClientWindowsResult))]
94+
[JsonSerializable(typeof(Modules.Browser.UserContextInfo))]
9595
[JsonSerializable(typeof(IReadOnlyList<Modules.Browser.UserContextInfo>))]
9696
[JsonSerializable(typeof(IReadOnlyList<Modules.Browser.ClientWindowInfo>))]
9797

9898

9999
[JsonSerializable(typeof(Modules.BrowsingContext.ActivateCommand))]
100100
[JsonSerializable(typeof(Modules.BrowsingContext.CaptureScreenshotCommand))]
101-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.CaptureScreenshotResult>))]
101+
[JsonSerializable(typeof(Modules.BrowsingContext.CaptureScreenshotResult))]
102102
[JsonSerializable(typeof(Modules.BrowsingContext.CloseCommand), TypeInfoPropertyName = "BrowsingContext_CloseCommand")]
103103
[JsonSerializable(typeof(Modules.BrowsingContext.CreateCommand))]
104-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.CreateResult>))]
104+
[JsonSerializable(typeof(Modules.BrowsingContext.CreateResult))]
105105
[JsonSerializable(typeof(Modules.BrowsingContext.GetTreeCommand))]
106-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.GetTreeResult>))]
106+
[JsonSerializable(typeof(Modules.BrowsingContext.GetTreeResult))]
107107
[JsonSerializable(typeof(Modules.BrowsingContext.HandleUserPromptCommand))]
108108
[JsonSerializable(typeof(Modules.BrowsingContext.LocateNodesCommand))]
109-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.LocateNodesResult>))]
109+
[JsonSerializable(typeof(Modules.BrowsingContext.LocateNodesResult))]
110110
[JsonSerializable(typeof(Modules.BrowsingContext.NavigateCommand))]
111-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.NavigateResult>))]
111+
[JsonSerializable(typeof(Modules.BrowsingContext.NavigateResult))]
112112
[JsonSerializable(typeof(Modules.BrowsingContext.PrintCommand))]
113-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.PrintResult>))]
113+
[JsonSerializable(typeof(Modules.BrowsingContext.PrintResult))]
114114
[JsonSerializable(typeof(Modules.BrowsingContext.ReloadCommand))]
115115
[JsonSerializable(typeof(Modules.BrowsingContext.SetViewportCommand))]
116116
[JsonSerializable(typeof(Modules.BrowsingContext.TraverseHistoryCommand))]
117-
[JsonSerializable(typeof(MessageSuccess<Modules.BrowsingContext.TraverseHistoryResult>))]
117+
[JsonSerializable(typeof(Modules.BrowsingContext.TraverseHistoryResult))]
118118
[JsonSerializable(typeof(Modules.BrowsingContext.BrowsingContextInfo))]
119119
[JsonSerializable(typeof(Modules.BrowsingContext.NavigationInfo))]
120120

121121
[JsonSerializable(typeof(Modules.BrowsingContext.UserPromptOpenedEventArgs))]
122122
[JsonSerializable(typeof(Modules.BrowsingContext.UserPromptClosedEventArgs))]
123123

124124
[JsonSerializable(typeof(Modules.Network.AddInterceptCommand))]
125-
[JsonSerializable(typeof(MessageSuccess<Modules.Network.AddInterceptResult>))]
125+
[JsonSerializable(typeof(Modules.Network.AddInterceptResult))]
126126
[JsonSerializable(typeof(Modules.Network.ContinueRequestCommand))]
127127
[JsonSerializable(typeof(Modules.Network.ContinueResponseCommand))]
128128
[JsonSerializable(typeof(Modules.Network.ContinueWithAuthCommand))]
@@ -138,13 +138,13 @@ namespace OpenQA.Selenium.BiDi.Communication.Json;
138138
[JsonSerializable(typeof(Modules.Network.AuthRequiredEventArgs))]
139139

140140
[JsonSerializable(typeof(Modules.Script.AddPreloadScriptCommand))]
141-
[JsonSerializable(typeof(MessageSuccess<Modules.Script.AddPreloadScriptResult>))]
141+
[JsonSerializable(typeof(Modules.Script.AddPreloadScriptResult))]
142142
[JsonSerializable(typeof(Modules.Script.DisownCommand))]
143143
[JsonSerializable(typeof(Modules.Script.CallFunctionCommand))]
144144
[JsonSerializable(typeof(Modules.Script.EvaluateCommand))]
145-
[JsonSerializable(typeof(MessageSuccess<Modules.Script.EvaluateResult>))]
145+
[JsonSerializable(typeof(Modules.Script.EvaluateResult))]
146146
[JsonSerializable(typeof(Modules.Script.GetRealmsCommand))]
147-
[JsonSerializable(typeof(MessageSuccess<Modules.Script.GetRealmsResult>))]
147+
[JsonSerializable(typeof(Modules.Script.GetRealmsResult))]
148148
[JsonSerializable(typeof(Modules.Script.RemovePreloadScriptCommand))]
149149

150150
[JsonSerializable(typeof(Modules.Script.MessageEventArgs))]
@@ -154,11 +154,11 @@ namespace OpenQA.Selenium.BiDi.Communication.Json;
154154
[JsonSerializable(typeof(Modules.Log.LogEntry))]
155155

156156
[JsonSerializable(typeof(Modules.Storage.GetCookiesCommand))]
157-
[JsonSerializable(typeof(MessageSuccess<Modules.Storage.GetCookiesResult>))]
157+
[JsonSerializable(typeof(Modules.Storage.GetCookiesResult))]
158158
[JsonSerializable(typeof(Modules.Storage.SetCookieCommand))]
159-
[JsonSerializable(typeof(MessageSuccess<Modules.Storage.SetCookieResult>))]
159+
[JsonSerializable(typeof(Modules.Storage.SetCookieResult))]
160160
[JsonSerializable(typeof(Modules.Storage.DeleteCookiesCommand))]
161-
[JsonSerializable(typeof(MessageSuccess<Modules.Storage.DeleteCookiesResult>))]
161+
[JsonSerializable(typeof(Modules.Storage.DeleteCookiesResult))]
162162

163163
[JsonSerializable(typeof(Modules.Input.PerformActionsCommand))]
164164
[JsonSerializable(typeof(Modules.Input.ReleaseActionsCommand))]

dotnet/src/webdriver/BiDi/Communication/Json/Internal/JsonExtensions.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,7 @@ public static string GetDiscriminator(this ref Utf8JsonReader reader, string nam
4040

4141
if (propertyName == name)
4242
{
43-
if (readerClone.TokenType == JsonTokenType.Number)
44-
{
45-
discriminator = readerClone.GetInt64().ToString();
46-
}
47-
else
48-
{
49-
discriminator = readerClone.GetString();
50-
}
43+
discriminator = readerClone.GetString();
5144

5245
break;
5346
}
@@ -56,6 +49,6 @@ public static string GetDiscriminator(this ref Utf8JsonReader reader, string nam
5649
readerClone.Read();
5750
}
5851

59-
return discriminator ?? throw new JsonException($"Couldn't determine '{name}' descriminator.");
52+
return discriminator ?? throw new JsonException($"Couldn't determine '{name}' discriminator.");
6053
}
6154
}

dotnet/src/webdriver/BiDi/Communication/Message.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,13 @@
1717
// under the License.
1818
// </copyright>
1919

20-
using System;
21-
2220
namespace OpenQA.Selenium.BiDi.Communication;
2321

24-
// https://github.com/dotnet/runtime/issues/72604
25-
//[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")]
26-
//[JsonDerivedType(typeof(MessageSuccess), "success")]
27-
//[JsonDerivedType(typeof(MessageError), "error")]
28-
//[JsonDerivedType(typeof(MessageEvent), "event")]
2922
internal abstract record Message;
3023

31-
internal record MessageSuccess<T>(int Id, T Result) : Message;
24+
internal record MessageSuccess(long Id, EmptyResult Result) : Message;
3225

33-
internal record MessageError(int Id) : Message
26+
internal record MessageError(long Id) : Message
3427
{
3528
public string? Error { get; set; }
3629

0 commit comments

Comments
 (0)