From 2943e3a84979e37d32ae75e3d5a21aadefb33487 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Wed, 4 Mar 2026 03:26:00 +0300 Subject: [PATCH 1/4] [dotnet] [bidi] Cache BrowsingContext/UserContext per session --- .../BiDi/Json/Converters/BrowserUserContextConverter.cs | 8 +++++++- .../BiDi/Json/Converters/BrowsingContextConverter.cs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs index 47e1a2cc4ee1f..a420f53bf7a14 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs @@ -17,6 +17,8 @@ // under the License. // +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; using OpenQA.Selenium.BiDi.Browser; @@ -25,11 +27,15 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter { + private static readonly ConditionalWeakTable> s_cache = []; + public override UserContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = reader.GetString(); - return new UserContext(id!) { BiDi = bidi }; + var sessionCache = s_cache.GetValue(bidi, _ => new ConcurrentDictionary()); + + return sessionCache.GetOrAdd(id!, key => new UserContext(key) { BiDi = bidi }); } public override void Write(Utf8JsonWriter writer, UserContext value, JsonSerializerOptions options) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs index e91923d49fa01..342f3d896ebcc 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs @@ -17,6 +17,8 @@ // under the License. // +using System.Collections.Concurrent; +using System.Runtime.CompilerServices; using System.Text.Json; using System.Text.Json.Serialization; @@ -24,13 +26,17 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter { + private static readonly ConditionalWeakTable> s_cache = []; + private readonly IBiDi _bidi = bidi; public override BrowsingContext.BrowsingContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = reader.GetString(); - return new BrowsingContext.BrowsingContext(id!) { BiDi = _bidi }; + var sessionCache = s_cache.GetValue(_bidi, _ => new ConcurrentDictionary()); + + return sessionCache.GetOrAdd(id!, key => new BrowsingContext.BrowsingContext(_bidi, key)); } public override void Write(Utf8JsonWriter writer, BrowsingContext.BrowsingContext value, JsonSerializerOptions options) From 1f09c1cef487a9b43d497e4f3ff1e1f474283442 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Wed, 4 Mar 2026 03:48:09 +0300 Subject: [PATCH 2/4] Limit --- .../BiDi/Json/Converters/BrowserUserContextConverter.cs | 9 ++++++++- .../BiDi/Json/Converters/BrowsingContextConverter.cs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs index a420f53bf7a14..480c7b69ab123 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs @@ -27,7 +27,9 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter { - private static readonly ConditionalWeakTable> s_cache = []; + private const int MaxCacheSize = 1_000; + + private static readonly ConditionalWeakTable> s_cache = new(); public override UserContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { @@ -35,6 +37,11 @@ internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter new ConcurrentDictionary()); + if (sessionCache.Count >= MaxCacheSize) + { + sessionCache.Clear(); + } + return sessionCache.GetOrAdd(id!, key => new UserContext(key) { BiDi = bidi }); } diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs index 342f3d896ebcc..33986fada2172 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs @@ -26,7 +26,9 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter { - private static readonly ConditionalWeakTable> s_cache = []; + private const int MaxCacheSize = 1_000; + + private static readonly ConditionalWeakTable> s_cache = new(); private readonly IBiDi _bidi = bidi; @@ -36,6 +38,11 @@ internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter new ConcurrentDictionary()); + if (sessionCache.Count >= MaxCacheSize) + { + sessionCache.Clear(); + } + return sessionCache.GetOrAdd(id!, key => new BrowsingContext.BrowsingContext(_bidi, key)); } From 0e7d262b0f19765873bd36e71aaaf13df2843274 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:26:16 +0300 Subject: [PATCH 3/4] UserContext ctor --- .../BiDi/Json/Converters/BrowserUserContextConverter.cs | 2 +- .../BiDi/Json/Converters/BrowsingContextConverter.cs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs index 480c7b69ab123..68ef2a92a6e4c 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs @@ -42,7 +42,7 @@ internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter new UserContext(key) { BiDi = bidi }); + return sessionCache.GetOrAdd(id!, key => new UserContext(bidi, key)); } public override void Write(Utf8JsonWriter writer, UserContext value, JsonSerializerOptions options) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs index 33986fada2172..b9505aaf45017 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs @@ -30,20 +30,18 @@ internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter> s_cache = new(); - private readonly IBiDi _bidi = bidi; - public override BrowsingContext.BrowsingContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var id = reader.GetString(); - var sessionCache = s_cache.GetValue(_bidi, _ => new ConcurrentDictionary()); + var sessionCache = s_cache.GetValue(bidi, _ => new ConcurrentDictionary()); if (sessionCache.Count >= MaxCacheSize) { sessionCache.Clear(); } - return sessionCache.GetOrAdd(id!, key => new BrowsingContext.BrowsingContext(_bidi, key)); + return sessionCache.GetOrAdd(id!, key => new BrowsingContext.BrowsingContext(bidi, key)); } public override void Write(Utf8JsonWriter writer, BrowsingContext.BrowsingContext value, JsonSerializerOptions options) From 7bd7d0f10d28bdc352acf827818751678f78f126 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:35:00 +0300 Subject: [PATCH 4/4] Rely on bidi lifecycle --- .../BiDi/Json/Converters/BrowserUserContextConverter.cs | 7 ------- .../BiDi/Json/Converters/BrowsingContextConverter.cs | 7 ------- 2 files changed, 14 deletions(-) diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs index 68ef2a92a6e4c..e1e939ba11196 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowserUserContextConverter.cs @@ -27,8 +27,6 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter { - private const int MaxCacheSize = 1_000; - private static readonly ConditionalWeakTable> s_cache = new(); public override UserContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -37,11 +35,6 @@ internal class BrowserUserContextConverter(IBiDi bidi) : JsonConverter new ConcurrentDictionary()); - if (sessionCache.Count >= MaxCacheSize) - { - sessionCache.Clear(); - } - return sessionCache.GetOrAdd(id!, key => new UserContext(bidi, key)); } diff --git a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs index b9505aaf45017..86d7c77c7f074 100644 --- a/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs +++ b/dotnet/src/webdriver/BiDi/Json/Converters/BrowsingContextConverter.cs @@ -26,8 +26,6 @@ namespace OpenQA.Selenium.BiDi.Json.Converters; internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter { - private const int MaxCacheSize = 1_000; - private static readonly ConditionalWeakTable> s_cache = new(); public override BrowsingContext.BrowsingContext? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -36,11 +34,6 @@ internal class BrowsingContextConverter(IBiDi bidi) : JsonConverter new ConcurrentDictionary()); - if (sessionCache.Count >= MaxCacheSize) - { - sessionCache.Clear(); - } - return sessionCache.GetOrAdd(id!, key => new BrowsingContext.BrowsingContext(bidi, key)); }