diff --git a/dotnet/src/webdriver/BiDi/Communication/Broker.cs b/dotnet/src/webdriver/BiDi/Communication/Broker.cs index e5946ba349394..64f82aa59499f 100644 --- a/dotnet/src/webdriver/BiDi/Communication/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Communication/Broker.cs @@ -38,7 +38,7 @@ public sealed class Broker : IAsyncDisposable private readonly ITransport _transport; private readonly ConcurrentDictionary _pendingCommands = new(); - private readonly BlockingCollection _pendingEvents = []; + private readonly BlockingCollection<(string Method, EventArgs Params)> _pendingEvents = []; private readonly Dictionary _eventTypesMap = []; private readonly ConcurrentDictionary> _eventHandlers = new(); @@ -143,20 +143,20 @@ public async Task ExecuteCommandAsync(TCommand comma where TResult : EmptyResult { command.Id = Interlocked.Increment(ref _currentCommandId); - var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var timeout = options?.Timeout ?? TimeSpan.FromSeconds(30); using var cts = new CancellationTokenSource(timeout); cts.Token.Register(() => tcs.TrySetCanceled(cts.Token)); - var commandInfo = new CommandInfo(command.Id, command.ResultType, tcs); + var commandInfo = new CommandInfo(command.Id, tcs, jsonResultTypeInfo); _pendingCommands[command.Id] = commandInfo; var data = JsonSerializer.SerializeToUtf8Bytes(command, jsonCommandTypeInfo); await _transport.SendAsync(data, cts.Token).ConfigureAwait(false); - var resultJson = await tcs.Task.ConfigureAwait(false); - return JsonSerializer.Deserialize(resultJson, jsonResultTypeInfo)!; + + return (TResult)await tcs.Task.ConfigureAwait(false); } - public async Task SubscribeAsync(string eventName, Action action, SubscriptionOptions? options, JsonTypeInfo jsonTypeInfo) + public async Task SubscribeAsync(string eventName, Action action, SubscriptionOptions? options, JsonTypeInfo jsonTypeInfo) where TEventArgs : EventArgs { _eventTypesMap[eventName] = jsonTypeInfo; @@ -185,7 +185,7 @@ public async Task SubscribeAsync(string eventName, Act } } - public async Task SubscribeAsync(string eventName, Func func, SubscriptionOptions? options, JsonTypeInfo jsonTypeInfo) + public async Task SubscribeAsync(string eventName, Func func, SubscriptionOptions? options, JsonTypeInfo jsonTypeInfo) where TEventArgs : EventArgs { _eventTypesMap[eventName] = jsonTypeInfo; @@ -301,7 +301,7 @@ private void ProcessReceivedMessage(byte[]? data) if (_pendingCommands.TryGetValue(id.Value, out var successCommand)) { - successCommand.TaskCompletionSource.SetResult(JsonElement.ParseValue(ref resultReader)); + successCommand.TaskCompletionSource.SetResult((EmptyResult)JsonSerializer.Deserialize(ref resultReader, successCommand.JsonResultTypeInfo)!); _pendingCommands.TryRemove(id.Value, out _); } else @@ -318,7 +318,7 @@ private void ProcessReceivedMessage(byte[]? data) { var eventArgs = (EventArgs)JsonSerializer.Deserialize(ref paramsReader, eventInfo)!; - var messageEvent = new MessageEvent(method, eventArgs); + var messageEvent = (method, eventArgs); _pendingEvents.Add(messageEvent); } else @@ -345,10 +345,12 @@ private void ProcessReceivedMessage(byte[]? data) } } - class CommandInfo(long id, Type resultType, TaskCompletionSource taskCompletionSource) + class CommandInfo(long id, TaskCompletionSource taskCompletionSource, JsonTypeInfo jsonResultTypeInfo) { public long Id { get; } = id; - public TaskCompletionSource TaskCompletionSource { get; } = taskCompletionSource; + public TaskCompletionSource TaskCompletionSource { get; } = taskCompletionSource; + + public JsonTypeInfo JsonResultTypeInfo { get; } = jsonResultTypeInfo; }; } diff --git a/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs b/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs index 4f291fcb8da08..16e95beec1265 100644 --- a/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs +++ b/dotnet/src/webdriver/BiDi/Communication/EventHandler.cs @@ -23,32 +23,32 @@ namespace OpenQA.Selenium.BiDi.Communication; -public abstract class EventHandler(string eventName, Type eventArgsType, IEnumerable? contexts = null) +public abstract class EventHandler(string eventName, IEnumerable? contexts = null) { public string EventName { get; } = eventName; - public Type EventArgsType { get; set; } = eventArgsType; + public IEnumerable? Contexts { get; } = contexts; - public abstract ValueTask InvokeAsync(object args); + public abstract ValueTask InvokeAsync(EventArgs args); } internal class AsyncEventHandler(string eventName, Func func, IEnumerable? contexts = null) - : EventHandler(eventName, typeof(TEventArgs), contexts) where TEventArgs : EventArgs + : EventHandler(eventName, contexts) where TEventArgs : EventArgs { private readonly Func _func = func; - public override async ValueTask InvokeAsync(object args) + public override async ValueTask InvokeAsync(EventArgs args) { await _func((TEventArgs)args).ConfigureAwait(false); } } internal class SyncEventHandler(string eventName, Action action, IEnumerable? contexts = null) - : EventHandler(eventName, typeof(TEventArgs), contexts) where TEventArgs : EventArgs + : EventHandler(eventName, contexts) where TEventArgs : EventArgs { private readonly Action _action = action; - public override ValueTask InvokeAsync(object args) + public override ValueTask InvokeAsync(EventArgs args) { _action((TEventArgs)args); diff --git a/dotnet/src/webdriver/BiDi/Communication/Message.cs b/dotnet/src/webdriver/BiDi/Communication/Message.cs deleted file mode 100644 index 03f948cc18873..0000000000000 --- a/dotnet/src/webdriver/BiDi/Communication/Message.cs +++ /dev/null @@ -1,34 +0,0 @@ -// -// Licensed to the Software Freedom Conservancy (SFC) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The SFC licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -namespace OpenQA.Selenium.BiDi.Communication; - -internal abstract record Message; - -internal record MessageSuccess(long Id, EmptyResult Result) : Message; - -internal record MessageError(long Id) : Message -{ - public string? Error { get; set; } - - public string? Message { get; set; } -} - -internal record MessageEvent(string Method, EventArgs Params) : Message; -