From 2947d4ac56b8565ab6f76b20596566eff3919ebb Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:44:30 +0300 Subject: [PATCH 01/11] [dotnet] [bidi] Dedicated json context for Browser module --- .../webdriver/BiDi/Browser/BrowserModule.cs | 29 +++++++++++++++++-- .../BiDi/Json/BiDiJsonSerializerContext.cs | 16 ---------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index 6cf8c78c25e3b..17faf8400eb71 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -18,18 +18,20 @@ // using OpenQA.Selenium.BiDi.Json; +using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Browser; public sealed class BrowserModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private BrowserJsonSerializerContext _jsonContext = null!; public async Task CloseAsync(CloseOptions? options = null) { - return await Broker.ExecuteCommandAsync(new CloseCommand(), options, _jsonContext.Browser_CloseCommand, _jsonContext.Browser_CloseResult).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CloseCommand(), options, _jsonContext.CloseCommand, _jsonContext.CloseResult).ConfigureAwait(false); } public async Task CreateUserContextAsync(CreateUserContextOptions? options = null) @@ -80,6 +82,27 @@ public async Task SetDownloadBehaviorDeniedAsync(SetD protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + var browserOptions = new JsonSerializerOptions(options) + { + TypeInfoResolverChain = { new BiDiJsonSerializerContext(options) } + }; + + _jsonContext = new BrowserJsonSerializerContext(browserOptions); } } + +[JsonSerializable(typeof(CloseCommand))] +[JsonSerializable(typeof(CloseResult))] +[JsonSerializable(typeof(CreateUserContextCommand))] +[JsonSerializable(typeof(CreateUserContextResult))] +[JsonSerializable(typeof(GetUserContextsCommand))] +[JsonSerializable(typeof(GetUserContextsResult))] +[JsonSerializable(typeof(RemoveUserContextCommand))] +[JsonSerializable(typeof(RemoveUserContextResult))] +[JsonSerializable(typeof(GetClientWindowsCommand))] +[JsonSerializable(typeof(GetClientWindowsResult))] +[JsonSerializable(typeof(SetDownloadBehaviorCommand))] +[JsonSerializable(typeof(SetDownloadBehaviorResult))] +[JsonSerializable(typeof(IReadOnlyList))] +[JsonSerializable(typeof(IReadOnlyList))] +internal partial class BrowserJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs index 046e3a4938b96..e8dde96b3d201 100644 --- a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs +++ b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs @@ -81,22 +81,6 @@ namespace OpenQA.Selenium.BiDi.Json; [JsonSerializable(typeof(Session.UnsubscribeByIdCommand))] [JsonSerializable(typeof(Session.UnsubscribeResult))] -[JsonSerializable(typeof(Browser.CloseCommand), TypeInfoPropertyName = "Browser_CloseCommand")] -[JsonSerializable(typeof(Browser.CloseResult), TypeInfoPropertyName = "Browser_CloseResult")] -[JsonSerializable(typeof(Browser.CreateUserContextCommand))] -[JsonSerializable(typeof(Browser.CreateUserContextResult))] -[JsonSerializable(typeof(Browser.GetUserContextsCommand))] -[JsonSerializable(typeof(Browser.GetUserContextsResult))] -[JsonSerializable(typeof(Browser.RemoveUserContextCommand))] -[JsonSerializable(typeof(Browser.RemoveUserContextResult))] -[JsonSerializable(typeof(Browser.GetClientWindowsCommand))] -[JsonSerializable(typeof(Browser.GetClientWindowsResult))] -[JsonSerializable(typeof(Browser.SetDownloadBehaviorCommand))] -[JsonSerializable(typeof(Browser.SetDownloadBehaviorResult))] -[JsonSerializable(typeof(IReadOnlyList))] -[JsonSerializable(typeof(IReadOnlyList))] - - [JsonSerializable(typeof(BrowsingContext.ActivateCommand))] [JsonSerializable(typeof(BrowsingContext.ActivateResult))] [JsonSerializable(typeof(BrowsingContext.CaptureScreenshotCommand))] From 59576b17b6e1a37c9fbd6c16d84bc1762299ce24 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:57:50 +0300 Subject: [PATCH 02/11] Modify existing options --- dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index 17faf8400eb71..84e041be7b436 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -82,12 +82,9 @@ public async Task SetDownloadBehaviorDeniedAsync(SetD protected override void Initialize(JsonSerializerOptions options) { - var browserOptions = new JsonSerializerOptions(options) - { - TypeInfoResolverChain = { new BiDiJsonSerializerContext(options) } - }; + options.TypeInfoResolverChain.Add(new BiDiJsonSerializerContext()); - _jsonContext = new BrowserJsonSerializerContext(browserOptions); + _jsonContext = new BrowserJsonSerializerContext(options); } } From 03cf7ef3e76f66a990d0a893c2db0b69a9d1b453 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sat, 29 Nov 2025 19:14:55 +0300 Subject: [PATCH 03/11] Plus BrowsingContext --- .../webdriver/BiDi/Browser/BrowserModule.cs | 3 -- .../BrowsingContext/BrowsingContextModule.cs | 44 +++++++++++++++++-- .../BiDi/Json/BiDiJsonSerializerContext.cs | 35 --------------- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index 84e041be7b436..c20b6c565c70f 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -17,7 +17,6 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; @@ -82,8 +81,6 @@ public async Task SetDownloadBehaviorDeniedAsync(SetD protected override void Initialize(JsonSerializerOptions options) { - options.TypeInfoResolverChain.Add(new BiDiJsonSerializerContext()); - _jsonContext = new BrowserJsonSerializerContext(options); } } diff --git a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs index d865759e51c5e..1e6b1ca4e3d70 100644 --- a/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs +++ b/dotnet/src/webdriver/BiDi/BrowsingContext/BrowsingContextModule.cs @@ -17,16 +17,16 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.BrowsingContext; public sealed class BrowsingContextModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private BrowsingContextJsonSerializerContext _jsonContext = null!; public async Task CreateAsync(ContextType type, CreateOptions? options = null) { @@ -67,7 +67,7 @@ public async Task CloseAsync(BrowsingContext context, CloseOptions? { var @params = new CloseParameters(context, options?.PromptUnload); - return await Broker.ExecuteCommandAsync(new CloseCommand(@params), options, _jsonContext.BrowsingContext_CloseCommand, _jsonContext.BrowsingContext_CloseResult).ConfigureAwait(false); + return await Broker.ExecuteCommandAsync(new CloseCommand(@params), options, _jsonContext.CloseCommand, _jsonContext.CloseResult).ConfigureAwait(false); } public async Task TraverseHistoryAsync(BrowsingContext context, int delta, TraverseHistoryOptions? options = null) @@ -254,6 +254,42 @@ public async Task OnUserPromptClosedAsync(Action Date: Sat, 29 Nov 2025 19:31:37 +0300 Subject: [PATCH 04/11] Split for all modules --- .../BiDi/Emulation/EmulationModule.cs | 22 +++- .../src/webdriver/BiDi/Input/InputModule.cs | 18 +++- .../BiDi/Json/BiDiJsonSerializerContext.cs | 101 ------------------ dotnet/src/webdriver/BiDi/Log/LogModule.cs | 9 +- .../webdriver/BiDi/Network/NetworkModule.cs | 38 ++++++- .../src/webdriver/BiDi/Script/ScriptModule.cs | 24 ++++- .../webdriver/BiDi/Session/SessionModule.cs | 18 +++- .../webdriver/BiDi/Storage/StorageModule.cs | 14 ++- .../BiDi/WebExtension/WebExtensionModule.cs | 12 ++- 9 files changed, 131 insertions(+), 125 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs index 09b110c480e55..e4993e9b6209e 100644 --- a/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs +++ b/dotnet/src/webdriver/BiDi/Emulation/EmulationModule.cs @@ -17,15 +17,15 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Emulation; public sealed class EmulationModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private EmulationJsonSerializerContext _jsonContext = null!; public async Task SetTimezoneOverrideAsync(string? timezone, SetTimezoneOverrideOptions? options = null) { @@ -94,6 +94,22 @@ public async Task SetGeolocationPositionErrorOverr protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new EmulationJsonSerializerContext(options); } } + +[JsonSerializable(typeof(SetTimezoneOverrideCommand))] +[JsonSerializable(typeof(SetTimezoneOverrideResult))] +[JsonSerializable(typeof(SetUserAgentOverrideCommand))] +[JsonSerializable(typeof(SetUserAgentOverrideResult))] +[JsonSerializable(typeof(SetLocaleOverrideCommand))] +[JsonSerializable(typeof(SetLocaleOverrideResult))] +[JsonSerializable(typeof(SetForcedColorsModeThemeOverrideCommand))] +[JsonSerializable(typeof(SetForcedColorsModeThemeOverrideResult))] +[JsonSerializable(typeof(SetScriptingEnabledCommand))] +[JsonSerializable(typeof(SetScriptingEnabledResult))] +[JsonSerializable(typeof(SetScreenOrientationOverrideCommand))] +[JsonSerializable(typeof(SetScreenOrientationOverrideResult))] +[JsonSerializable(typeof(SetGeolocationOverrideCommand))] +[JsonSerializable(typeof(SetGeolocationOverrideResult))] +internal partial class EmulationJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Input/InputModule.cs b/dotnet/src/webdriver/BiDi/Input/InputModule.cs index 341c0999b88d2..fb6ded16381d4 100644 --- a/dotnet/src/webdriver/BiDi/Input/InputModule.cs +++ b/dotnet/src/webdriver/BiDi/Input/InputModule.cs @@ -17,16 +17,16 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Input; public sealed class InputModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private InputJsonSerializerContext _jsonContext = null!; public async Task PerformActionsAsync(BrowsingContext.BrowsingContext context, IEnumerable actions, PerformActionsOptions? options = null) { @@ -51,6 +51,18 @@ public async Task SetFilesAsync(BrowsingContext.BrowsingContext protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new InputJsonSerializerContext(options); } } + +[JsonSerializable(typeof(PerformActionsCommand))] +[JsonSerializable(typeof(PerformActionsResult))] +[JsonSerializable(typeof(ReleaseActionsCommand))] +[JsonSerializable(typeof(ReleaseActionsResult))] +[JsonSerializable(typeof(SetFilesCommand))] +[JsonSerializable(typeof(SetFilesResult))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(IEnumerable))] +internal partial class InputJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs index ad6d437a2b85f..476f7387ef1c2 100644 --- a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs +++ b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs @@ -17,7 +17,6 @@ // under the License. // -using System.Collections.Generic; using System.Text.Json.Serialization; namespace OpenQA.Selenium.BiDi.Json; @@ -69,104 +68,4 @@ namespace OpenQA.Selenium.BiDi.Json; [JsonSerializable(typeof(Command))] [JsonSerializable(typeof(EmptyResult))] - -[JsonSerializable(typeof(Session.StatusCommand))] -[JsonSerializable(typeof(Session.StatusResult))] -[JsonSerializable(typeof(Session.NewCommand))] -[JsonSerializable(typeof(Session.NewResult))] -[JsonSerializable(typeof(Session.EndCommand))] -[JsonSerializable(typeof(Session.EndResult))] -[JsonSerializable(typeof(Session.SubscribeCommand))] -[JsonSerializable(typeof(Session.SubscribeResult))] -[JsonSerializable(typeof(Session.UnsubscribeByIdCommand))] -[JsonSerializable(typeof(Session.UnsubscribeResult))] - -[JsonSerializable(typeof(Network.AddDataCollectorCommand))] -[JsonSerializable(typeof(Network.AddDataCollectorResult))] -[JsonSerializable(typeof(Network.AddInterceptCommand))] -[JsonSerializable(typeof(Network.AddInterceptResult))] -[JsonSerializable(typeof(Network.ContinueRequestCommand))] -[JsonSerializable(typeof(Network.ContinueRequestResult))] -[JsonSerializable(typeof(Network.ContinueResponseCommand))] -[JsonSerializable(typeof(Network.ContinueResponseResult))] -[JsonSerializable(typeof(Network.ContinueWithAuthCommand))] -[JsonSerializable(typeof(Network.ContinueWithAuthResult))] -[JsonSerializable(typeof(Network.FailRequestCommand))] -[JsonSerializable(typeof(Network.FailRequestResult))] -[JsonSerializable(typeof(Network.GetDataCommand))] -[JsonSerializable(typeof(Network.GetDataResult))] -[JsonSerializable(typeof(Network.ProvideResponseCommand))] -[JsonSerializable(typeof(Network.ProvideResponseResult))] -[JsonSerializable(typeof(Network.RemoveDataCollectorCommand))] -[JsonSerializable(typeof(Network.RemoveDataCollectorResult))] -[JsonSerializable(typeof(Network.RemoveInterceptCommand))] -[JsonSerializable(typeof(Network.RemoveInterceptResult))] -[JsonSerializable(typeof(Network.SetCacheBehaviorCommand))] -[JsonSerializable(typeof(Network.SetCacheBehaviorResult))] -[JsonSerializable(typeof(Network.SetExtraHeadersCommand))] -[JsonSerializable(typeof(Network.SetExtraHeadersResult))] - -[JsonSerializable(typeof(Network.BeforeRequestSentEventArgs))] -[JsonSerializable(typeof(Network.ResponseStartedEventArgs))] -[JsonSerializable(typeof(Network.ResponseCompletedEventArgs))] -[JsonSerializable(typeof(Network.FetchErrorEventArgs))] -[JsonSerializable(typeof(Network.AuthRequiredEventArgs))] - -[JsonSerializable(typeof(Script.AddPreloadScriptCommand))] -[JsonSerializable(typeof(Script.AddPreloadScriptResult))] -[JsonSerializable(typeof(Script.DisownCommand))] -[JsonSerializable(typeof(Script.DisownResult))] -[JsonSerializable(typeof(Script.CallFunctionCommand))] -[JsonSerializable(typeof(Script.EvaluateResult))] -[JsonSerializable(typeof(Script.EvaluateCommand))] -[JsonSerializable(typeof(Script.EvaluateResult))] -[JsonSerializable(typeof(Script.GetRealmsCommand))] -[JsonSerializable(typeof(Script.GetRealmsResult))] -[JsonSerializable(typeof(Script.RemovePreloadScriptCommand))] -[JsonSerializable(typeof(Script.RemovePreloadScriptResult))] - -[JsonSerializable(typeof(Script.MessageEventArgs))] -[JsonSerializable(typeof(Script.RealmDestroyedEventArgs))] -[JsonSerializable(typeof(IReadOnlyList))] - -[JsonSerializable(typeof(Log.LogEntry))] - -[JsonSerializable(typeof(Storage.GetCookiesCommand))] -[JsonSerializable(typeof(Storage.GetCookiesResult))] -[JsonSerializable(typeof(Storage.SetCookieCommand))] -[JsonSerializable(typeof(Storage.SetCookieResult))] -[JsonSerializable(typeof(Storage.DeleteCookiesCommand))] -[JsonSerializable(typeof(Storage.DeleteCookiesResult))] - -[JsonSerializable(typeof(Input.PerformActionsCommand))] -[JsonSerializable(typeof(Input.PerformActionsResult))] -[JsonSerializable(typeof(Input.ReleaseActionsCommand))] -[JsonSerializable(typeof(Input.ReleaseActionsResult))] -[JsonSerializable(typeof(Input.SetFilesCommand))] -[JsonSerializable(typeof(Input.SetFilesResult))] -[JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] -[JsonSerializable(typeof(IEnumerable))] - -[JsonSerializable(typeof(WebExtension.InstallCommand))] -[JsonSerializable(typeof(WebExtension.InstallResult))] -[JsonSerializable(typeof(WebExtension.UninstallCommand))] -[JsonSerializable(typeof(WebExtension.UninstallResult))] - -[JsonSerializable(typeof(Emulation.SetTimezoneOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetTimezoneOverrideResult))] -[JsonSerializable(typeof(Emulation.SetUserAgentOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetUserAgentOverrideResult))] -[JsonSerializable(typeof(Emulation.SetLocaleOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetLocaleOverrideResult))] -[JsonSerializable(typeof(Emulation.SetForcedColorsModeThemeOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetForcedColorsModeThemeOverrideResult))] -[JsonSerializable(typeof(Emulation.SetScriptingEnabledCommand))] -[JsonSerializable(typeof(Emulation.SetScriptingEnabledResult))] -[JsonSerializable(typeof(Emulation.SetScreenOrientationOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetScreenOrientationOverrideResult))] -[JsonSerializable(typeof(Emulation.SetGeolocationOverrideCommand))] -[JsonSerializable(typeof(Emulation.SetGeolocationOverrideResult))] - internal partial class BiDiJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index a51ad3f9a4802..157ff9e7115e1 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -17,16 +17,16 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Log; public sealed class LogModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private LogJsonSerializerContext _jsonContext = null!; public async Task OnEntryAddedAsync(Func handler, SubscriptionOptions? options = null) { @@ -40,6 +40,9 @@ public async Task OnEntryAddedAsync(Action handler, Subs protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new LogJsonSerializerContext(options); } } + +[JsonSerializable(typeof(LogEntry))] +internal partial class LogJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs index eb2ba0068665d..74b874078e237 100644 --- a/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs +++ b/dotnet/src/webdriver/BiDi/Network/NetworkModule.cs @@ -17,17 +17,17 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System; using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Network; public sealed partial class NetworkModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private NetworkJsonSerializerContext _jsonContext = null!; public async Task AddDataCollectorAsync(IEnumerable DataTypes, int MaxEncodedDataSize, AddDataCollectorOptions? options = null) { @@ -179,6 +179,38 @@ public async Task OnAuthRequiredAsync(Action -using OpenQA.Selenium.BiDi.Json; using System; using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Script; public sealed class ScriptModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private ScriptJsonSerializerContext _jsonContext = null!; public async Task EvaluateAsync(string expression, bool awaitPromise, Target target, EvaluateOptions? options = null) { @@ -117,6 +117,24 @@ public async Task OnRealmDestroyedAsync(Action))] +internal partial class ScriptJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Session/SessionModule.cs b/dotnet/src/webdriver/BiDi/Session/SessionModule.cs index e9076badbcb0b..368349c1a1dc4 100644 --- a/dotnet/src/webdriver/BiDi/Session/SessionModule.cs +++ b/dotnet/src/webdriver/BiDi/Session/SessionModule.cs @@ -17,16 +17,16 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Collections.Generic; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Session; internal sealed class SessionModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private SessionJsonSerializerContext _jsonContext = null!; public async Task StatusAsync(StatusOptions? options = null) { @@ -61,6 +61,18 @@ public async Task EndAsync(EndOptions? options = null) protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new SessionJsonSerializerContext(options); } } + +[JsonSerializable(typeof(StatusCommand))] +[JsonSerializable(typeof(StatusResult))] +[JsonSerializable(typeof(NewCommand))] +[JsonSerializable(typeof(NewResult))] +[JsonSerializable(typeof(EndCommand))] +[JsonSerializable(typeof(EndResult))] +[JsonSerializable(typeof(SubscribeCommand))] +[JsonSerializable(typeof(SubscribeResult))] +[JsonSerializable(typeof(UnsubscribeByIdCommand))] +[JsonSerializable(typeof(UnsubscribeResult))] +internal partial class SessionJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs index 48a0d6c11031c..d2ef4c263f515 100644 --- a/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs +++ b/dotnet/src/webdriver/BiDi/Storage/StorageModule.cs @@ -17,15 +17,15 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.Storage; public sealed class StorageModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private StorageJsonSerializerContext _jsonContext = null!; public async Task GetCookiesAsync(GetCookiesOptions? options = null) { @@ -50,6 +50,14 @@ public async Task SetCookieAsync(PartialCookie cookie, SetCooki protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new StorageJsonSerializerContext(options); } } + +[JsonSerializable(typeof(GetCookiesCommand))] +[JsonSerializable(typeof(GetCookiesResult))] +[JsonSerializable(typeof(SetCookieCommand))] +[JsonSerializable(typeof(SetCookieResult))] +[JsonSerializable(typeof(DeleteCookiesCommand))] +[JsonSerializable(typeof(DeleteCookiesResult))] +internal partial class StorageJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs index a44ee2c75d21d..86cfea9d1f9a5 100644 --- a/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs +++ b/dotnet/src/webdriver/BiDi/WebExtension/WebExtensionModule.cs @@ -17,15 +17,15 @@ // under the License. // -using OpenQA.Selenium.BiDi.Json; using System.Text.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace OpenQA.Selenium.BiDi.WebExtension; public sealed class WebExtensionModule : Module { - private BiDiJsonSerializerContext _jsonContext = null!; + private WebExtensionJsonSerializerContext _jsonContext = null!; public async Task InstallAsync(ExtensionData extensionData, InstallOptions? options = null) { @@ -43,6 +43,12 @@ public async Task UninstallAsync(Extension extension, Uninstall protected override void Initialize(JsonSerializerOptions options) { - _jsonContext = new BiDiJsonSerializerContext(options); + _jsonContext = new WebExtensionJsonSerializerContext(options); } } + +[JsonSerializable(typeof(InstallCommand))] +[JsonSerializable(typeof(InstallResult))] +[JsonSerializable(typeof(UninstallCommand))] +[JsonSerializable(typeof(UninstallResult))] +internal partial class WebExtensionJsonSerializerContext : JsonSerializerContext; From ea73ee5a4a45ad4d25e7eb5a7851d300021b2aa6 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sat, 29 Nov 2025 19:45:08 +0300 Subject: [PATCH 05/11] Fail command fast --- dotnet/src/webdriver/BiDi/Broker.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Broker.cs b/dotnet/src/webdriver/BiDi/Broker.cs index 1eaf30797b8ba..fadd08e5937fc 100644 --- a/dotnet/src/webdriver/BiDi/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Broker.cs @@ -272,10 +272,22 @@ private void ProcessReceivedMessage(byte[]? data) case "success": if (id is null) throw new JsonException("The remote end responded with 'success' message type, but missed required 'id' property."); - if (_pendingCommands.TryGetValue(id.Value, out var successCommand)) + if (_pendingCommands.TryGetValue(id.Value, out var command)) { - successCommand.TaskCompletionSource.SetResult((EmptyResult)JsonSerializer.Deserialize(ref resultReader, successCommand.JsonResultTypeInfo)!); - _pendingCommands.TryRemove(id.Value, out _); + try + { + var commandResult = (EmptyResult)JsonSerializer.Deserialize(ref resultReader, command.JsonResultTypeInfo)!; + + command.TaskCompletionSource.SetResult(commandResult); + } + catch (Exception ex) + { + command.TaskCompletionSource.SetException(ex); + } + finally + { + _pendingCommands.TryRemove(id.Value, out _); + } } else { From 2e2b85bf8e854e05d068d0a77f580d26a3670350 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 14:49:12 +0300 Subject: [PATCH 06/11] Fix tests --- .../BiDi/Json/BiDiJsonSerializerContext.cs | 45 ------------------- dotnet/src/webdriver/BiDi/Log/LogModule.cs | 6 +++ .../src/webdriver/BiDi/Script/ScriptModule.cs | 41 +++++++++++++++++ 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs index 476f7387ef1c2..184c44b195c02 100644 --- a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs +++ b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs @@ -21,51 +21,6 @@ namespace OpenQA.Selenium.BiDi.Json; -#region https://github.com/dotnet/runtime/issues/72604 -[JsonSerializable(typeof(Script.EvaluateResultSuccess))] -[JsonSerializable(typeof(Script.EvaluateResultException))] - -[JsonSerializable(typeof(Script.NumberRemoteValue))] -[JsonSerializable(typeof(Script.BooleanRemoteValue))] -[JsonSerializable(typeof(Script.BigIntRemoteValue))] -[JsonSerializable(typeof(Script.StringRemoteValue))] -[JsonSerializable(typeof(Script.NullRemoteValue))] -[JsonSerializable(typeof(Script.UndefinedRemoteValue))] -[JsonSerializable(typeof(Script.SymbolRemoteValue))] -[JsonSerializable(typeof(Script.ArrayRemoteValue))] -[JsonSerializable(typeof(Script.ObjectRemoteValue))] -[JsonSerializable(typeof(Script.FunctionRemoteValue))] -[JsonSerializable(typeof(Script.RegExpRemoteValue))] -[JsonSerializable(typeof(Script.DateRemoteValue))] -[JsonSerializable(typeof(Script.MapRemoteValue))] -[JsonSerializable(typeof(Script.SetRemoteValue))] -[JsonSerializable(typeof(Script.WeakMapRemoteValue))] -[JsonSerializable(typeof(Script.WeakSetRemoteValue))] -[JsonSerializable(typeof(Script.GeneratorRemoteValue))] -[JsonSerializable(typeof(Script.ErrorRemoteValue))] -[JsonSerializable(typeof(Script.ProxyRemoteValue))] -[JsonSerializable(typeof(Script.PromiseRemoteValue))] -[JsonSerializable(typeof(Script.TypedArrayRemoteValue))] -[JsonSerializable(typeof(Script.ArrayBufferRemoteValue))] -[JsonSerializable(typeof(Script.NodeListRemoteValue))] -[JsonSerializable(typeof(Script.HtmlCollectionRemoteValue))] -[JsonSerializable(typeof(Script.NodeRemoteValue))] -[JsonSerializable(typeof(Script.WindowProxyRemoteValue))] - -[JsonSerializable(typeof(Script.WindowRealmInfo))] -[JsonSerializable(typeof(Script.DedicatedWorkerRealmInfo))] -[JsonSerializable(typeof(Script.SharedWorkerRealmInfo))] -[JsonSerializable(typeof(Script.ServiceWorkerRealmInfo))] -[JsonSerializable(typeof(Script.WorkerRealmInfo))] -[JsonSerializable(typeof(Script.PaintWorkletRealmInfo))] -[JsonSerializable(typeof(Script.AudioWorkletRealmInfo))] -[JsonSerializable(typeof(Script.WorkletRealmInfo))] - -[JsonSerializable(typeof(Log.GenericLogEntry))] -[JsonSerializable(typeof(Log.ConsoleLogEntry))] -[JsonSerializable(typeof(Log.JavascriptLogEntry))] -#endregion - [JsonSerializable(typeof(Command))] [JsonSerializable(typeof(EmptyResult))] internal partial class BiDiJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index 157ff9e7115e1..134cd175a0b69 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -44,5 +44,11 @@ protected override void Initialize(JsonSerializerOptions options) } } +#region https://github.com/dotnet/runtime/issues/72604 +[JsonSerializable(typeof(GenericLogEntry))] +[JsonSerializable(typeof(ConsoleLogEntry))] +[JsonSerializable(typeof(JavascriptLogEntry))] +#endregion + [JsonSerializable(typeof(LogEntry))] internal partial class LogJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs index 28b37c866f905..1a50def06f8a6 100644 --- a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs +++ b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs @@ -121,6 +121,47 @@ protected override void Initialize(JsonSerializerOptions options) } } +#region https://github.com/dotnet/runtime/issues/72604 +[JsonSerializable(typeof(EvaluateResultSuccess))] +[JsonSerializable(typeof(EvaluateResultException))] + +[JsonSerializable(typeof(NumberRemoteValue))] +[JsonSerializable(typeof(BooleanRemoteValue))] +[JsonSerializable(typeof(BigIntRemoteValue))] +[JsonSerializable(typeof(StringRemoteValue))] +[JsonSerializable(typeof(NullRemoteValue))] +[JsonSerializable(typeof(UndefinedRemoteValue))] +[JsonSerializable(typeof(SymbolRemoteValue))] +[JsonSerializable(typeof(ArrayRemoteValue))] +[JsonSerializable(typeof(ObjectRemoteValue))] +[JsonSerializable(typeof(FunctionRemoteValue))] +[JsonSerializable(typeof(RegExpRemoteValue))] +[JsonSerializable(typeof(DateRemoteValue))] +[JsonSerializable(typeof(MapRemoteValue))] +[JsonSerializable(typeof(SetRemoteValue))] +[JsonSerializable(typeof(WeakMapRemoteValue))] +[JsonSerializable(typeof(WeakSetRemoteValue))] +[JsonSerializable(typeof(GeneratorRemoteValue))] +[JsonSerializable(typeof(ErrorRemoteValue))] +[JsonSerializable(typeof(ProxyRemoteValue))] +[JsonSerializable(typeof(PromiseRemoteValue))] +[JsonSerializable(typeof(TypedArrayRemoteValue))] +[JsonSerializable(typeof(ArrayBufferRemoteValue))] +[JsonSerializable(typeof(NodeListRemoteValue))] +[JsonSerializable(typeof(HtmlCollectionRemoteValue))] +[JsonSerializable(typeof(NodeRemoteValue))] +[JsonSerializable(typeof(WindowProxyRemoteValue))] + +[JsonSerializable(typeof(WindowRealmInfo))] +[JsonSerializable(typeof(DedicatedWorkerRealmInfo))] +[JsonSerializable(typeof(SharedWorkerRealmInfo))] +[JsonSerializable(typeof(ServiceWorkerRealmInfo))] +[JsonSerializable(typeof(WorkerRealmInfo))] +[JsonSerializable(typeof(PaintWorkletRealmInfo))] +[JsonSerializable(typeof(AudioWorkletRealmInfo))] +[JsonSerializable(typeof(WorkletRealmInfo))] +#endregion + [JsonSerializable(typeof(AddPreloadScriptCommand))] [JsonSerializable(typeof(AddPreloadScriptResult))] [JsonSerializable(typeof(DisownCommand))] From f03c6f4593a79fc26a5f5d74f66db794d149e1a5 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 14:50:08 +0300 Subject: [PATCH 07/11] Delete BiDiJsonSerializerContext.cs --- .../BiDi/Json/BiDiJsonSerializerContext.cs | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs diff --git a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs b/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs deleted file mode 100644 index 184c44b195c02..0000000000000 --- a/dotnet/src/webdriver/BiDi/Json/BiDiJsonSerializerContext.cs +++ /dev/null @@ -1,26 +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. -// - -using System.Text.Json.Serialization; - -namespace OpenQA.Selenium.BiDi.Json; - -[JsonSerializable(typeof(Command))] -[JsonSerializable(typeof(EmptyResult))] -internal partial class BiDiJsonSerializerContext : JsonSerializerContext; From ce3db7a67e296c01a72623318bf48da772c96fae Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:15:15 +0300 Subject: [PATCH 08/11] Script dependencies --- dotnet/src/webdriver/BiDi/Log/LogModule.cs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index 134cd175a0b69..832f675f18fac 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -44,6 +44,35 @@ protected override void Initialize(JsonSerializerOptions options) } } +#region https://github.com/dotnet/runtime/issues/72604 Script dependencies +[JsonSerializable(typeof(Script.NumberRemoteValue))] +[JsonSerializable(typeof(Script.BooleanRemoteValue))] +[JsonSerializable(typeof(Script.BigIntRemoteValue))] +[JsonSerializable(typeof(Script.StringRemoteValue))] +[JsonSerializable(typeof(Script.NullRemoteValue))] +[JsonSerializable(typeof(Script.UndefinedRemoteValue))] +[JsonSerializable(typeof(Script.SymbolRemoteValue))] +[JsonSerializable(typeof(Script.ArrayRemoteValue))] +[JsonSerializable(typeof(Script.ObjectRemoteValue))] +[JsonSerializable(typeof(Script.FunctionRemoteValue))] +[JsonSerializable(typeof(Script.RegExpRemoteValue))] +[JsonSerializable(typeof(Script.DateRemoteValue))] +[JsonSerializable(typeof(Script.MapRemoteValue))] +[JsonSerializable(typeof(Script.SetRemoteValue))] +[JsonSerializable(typeof(Script.WeakMapRemoteValue))] +[JsonSerializable(typeof(Script.WeakSetRemoteValue))] +[JsonSerializable(typeof(Script.GeneratorRemoteValue))] +[JsonSerializable(typeof(Script.ErrorRemoteValue))] +[JsonSerializable(typeof(Script.ProxyRemoteValue))] +[JsonSerializable(typeof(Script.PromiseRemoteValue))] +[JsonSerializable(typeof(Script.TypedArrayRemoteValue))] +[JsonSerializable(typeof(Script.ArrayBufferRemoteValue))] +[JsonSerializable(typeof(Script.NodeListRemoteValue))] +[JsonSerializable(typeof(Script.HtmlCollectionRemoteValue))] +[JsonSerializable(typeof(Script.NodeRemoteValue))] +[JsonSerializable(typeof(Script.WindowProxyRemoteValue))] +#endregion + #region https://github.com/dotnet/runtime/issues/72604 [JsonSerializable(typeof(GenericLogEntry))] [JsonSerializable(typeof(ConsoleLogEntry))] From 23e42249a0437ee7224f758a1d91ac978481e37b Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:22:23 +0300 Subject: [PATCH 09/11] Clarify dependency --- dotnet/src/webdriver/BiDi/Log/LogModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/src/webdriver/BiDi/Log/LogModule.cs b/dotnet/src/webdriver/BiDi/Log/LogModule.cs index 832f675f18fac..34ea0e1d66c4c 100644 --- a/dotnet/src/webdriver/BiDi/Log/LogModule.cs +++ b/dotnet/src/webdriver/BiDi/Log/LogModule.cs @@ -44,7 +44,7 @@ protected override void Initialize(JsonSerializerOptions options) } } -#region https://github.com/dotnet/runtime/issues/72604 Script dependencies +#region https://github.com/dotnet/runtime/issues/72604 Script.RemoteValue type dependency [JsonSerializable(typeof(Script.NumberRemoteValue))] [JsonSerializable(typeof(Script.BooleanRemoteValue))] [JsonSerializable(typeof(Script.BigIntRemoteValue))] From ee978e8edb9eb00eff1ceb6c487cf3a77914da9b Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:30:30 +0300 Subject: [PATCH 10/11] Remove IReadOnlyList from context --- dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs | 3 --- dotnet/src/webdriver/BiDi/Script/ScriptModule.cs | 1 - 2 files changed, 4 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs index c20b6c565c70f..a1427163d6e24 100644 --- a/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs +++ b/dotnet/src/webdriver/BiDi/Browser/BrowserModule.cs @@ -17,7 +17,6 @@ // under the License. // -using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -97,6 +96,4 @@ protected override void Initialize(JsonSerializerOptions options) [JsonSerializable(typeof(GetClientWindowsResult))] [JsonSerializable(typeof(SetDownloadBehaviorCommand))] [JsonSerializable(typeof(SetDownloadBehaviorResult))] -[JsonSerializable(typeof(IReadOnlyList))] -[JsonSerializable(typeof(IReadOnlyList))] internal partial class BrowserJsonSerializerContext : JsonSerializerContext; diff --git a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs index 1a50def06f8a6..e13d907e47ec3 100644 --- a/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs +++ b/dotnet/src/webdriver/BiDi/Script/ScriptModule.cs @@ -177,5 +177,4 @@ protected override void Initialize(JsonSerializerOptions options) [JsonSerializable(typeof(MessageEventArgs))] [JsonSerializable(typeof(RealmDestroyedEventArgs))] -[JsonSerializable(typeof(IReadOnlyList))] internal partial class ScriptJsonSerializerContext : JsonSerializerContext; From d9eea44f90c7ff5e50179088158b6a94e99b9b2b Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:37:21 +0300 Subject: [PATCH 11/11] Improve null forgiving --- dotnet/src/webdriver/BiDi/Broker.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Broker.cs b/dotnet/src/webdriver/BiDi/Broker.cs index fadd08e5937fc..4eea29ef77432 100644 --- a/dotnet/src/webdriver/BiDi/Broker.cs +++ b/dotnet/src/webdriver/BiDi/Broker.cs @@ -276,9 +276,10 @@ private void ProcessReceivedMessage(byte[]? data) { try { - var commandResult = (EmptyResult)JsonSerializer.Deserialize(ref resultReader, command.JsonResultTypeInfo)!; + var commandResult = JsonSerializer.Deserialize(ref resultReader, command.JsonResultTypeInfo) + ?? throw new JsonException("Remote end returned null command result in the 'result' property."); - command.TaskCompletionSource.SetResult(commandResult); + command.TaskCompletionSource.SetResult((EmptyResult)commandResult); } catch (Exception ex) {