From 9f7149cc99afbcfa3c6e8fbacdd2a712a63aef24 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Thu, 5 Mar 2026 19:11:14 +0300 Subject: [PATCH 1/2] [bidi] Convert RemoteValue to IDictionary --- .../src/webdriver/BiDi/Script/RemoteValue.cs | 25 +++++++ .../BiDi/Script/RemoteValueConversionTests.cs | 72 +++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs index 9f7698575506a..4be020a825912 100644 --- a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs +++ b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs @@ -98,6 +98,10 @@ public abstract record RemoteValue => ConvertRemoteValuesToArray(a.Value, t.GetElementType()!), (ArrayRemoteValue a, Type t) when t.IsGenericType && t.IsAssignableFrom(typeof(List<>).MakeGenericType(t.GetGenericArguments()[0])) => ConvertRemoteValuesToGenericList(a.Value, typeof(List<>).MakeGenericType(t.GetGenericArguments()[0])), + (MapRemoteValue m, Type t) when t.IsGenericType && t.GetGenericArguments().Length == 2 && t.IsAssignableFrom(typeof(Dictionary<,>).MakeGenericType(t.GetGenericArguments())) + => ConvertRemoteValuesToDictionary(m.Value, typeof(Dictionary<,>).MakeGenericType(t.GetGenericArguments())), + (ObjectRemoteValue o, Type t) when t.IsGenericType && t.GetGenericArguments().Length == 2 && t.IsAssignableFrom(typeof(Dictionary<,>).MakeGenericType(t.GetGenericArguments())) + => ConvertRemoteValuesToDictionary(o.Value, typeof(Dictionary<,>).MakeGenericType(t.GetGenericArguments())), (_, Type t) when Nullable.GetUnderlyingType(t) is { } underlying => ConvertToNullable(underlying), @@ -150,6 +154,27 @@ private static TResult ConvertRemoteValuesToGenericList(IEnumerable(IReadOnlyList>? remoteValues, Type dictionaryType) + { + var typeArgs = dictionaryType.GetGenericArguments(); + var dict = (System.Collections.IDictionary)Activator.CreateInstance(dictionaryType)!; + + if (remoteValues is not null) + { + var convertKeyMethod = typeof(RemoteValue).GetMethod(nameof(ConvertTo))!.MakeGenericMethod(typeArgs[0]); + var convertValueMethod = typeof(RemoteValue).GetMethod(nameof(ConvertTo))!.MakeGenericMethod(typeArgs[1]); + + foreach (var pair in remoteValues) + { + var convertedKey = convertKeyMethod.Invoke(pair[0], null)!; + var convertedValue = convertValueMethod.Invoke(pair[1], null); + dict.Add(convertedKey, convertedValue); + } + } + + return (TResult)dict; + } } public abstract record PrimitiveProtocolRemoteValue : RemoteValue; diff --git a/dotnet/test/common/BiDi/Script/RemoteValueConversionTests.cs b/dotnet/test/common/BiDi/Script/RemoteValueConversionTests.cs index b453272371a51..ddc04be9af2f9 100644 --- a/dotnet/test/common/BiDi/Script/RemoteValueConversionTests.cs +++ b/dotnet/test/common/BiDi/Script/RemoteValueConversionTests.cs @@ -286,4 +286,76 @@ static void AssertValue(IEnumerable value) Assert.That(value, Is.Empty); } } + + [Test] + public void CanConvertMapRemoteValueToDictionary() + { + MapRemoteValue arg = new() + { + Value = + [ + [new StringRemoteValue("key1"), new NumberRemoteValue(1)], + [new StringRemoteValue("key2"), new NumberRemoteValue(2)], + ] + }; + + AssertValue(arg.ConvertTo>()); + AssertValue(arg.ConvertTo>()); + + static void AssertValue(IDictionary value) + { + Assert.That(value, Has.Count.EqualTo(2)); + Assert.That(value["key1"], Is.EqualTo(1)); + Assert.That(value["key2"], Is.EqualTo(2)); + } + } + + [Test] + public void CanConvertEmptyMapRemoteValueToDictionary() + { + MapRemoteValue arg = new(); + + AssertValue(arg.ConvertTo>()); + + static void AssertValue(IDictionary value) + { + Assert.That(value, Is.Empty); + } + } + + [Test] + public void CanConvertObjectRemoteValueToDictionary() + { + ObjectRemoteValue arg = new() + { + Value = + [ + [new StringRemoteValue("a"), new BooleanRemoteValue(true)], + [new StringRemoteValue("b"), new BooleanRemoteValue(false)], + ] + }; + + AssertValue(arg.ConvertTo>()); + AssertValue(arg.ConvertTo>()); + + static void AssertValue(IDictionary value) + { + Assert.That(value, Has.Count.EqualTo(2)); + Assert.That(value["a"], Is.True); + Assert.That(value["b"], Is.False); + } + } + + [Test] + public void CanConvertEmptyObjectRemoteValueToDictionary() + { + ObjectRemoteValue arg = new(); + + AssertValue(arg.ConvertTo>()); + + static void AssertValue(IDictionary value) + { + Assert.That(value, Is.Empty); + } + } } From c96796f5064ad7c71267f7ba422110524fc5dc16 Mon Sep 17 00:00:00 2001 From: Nikolay Borisenko <22616990+nvborisenko@users.noreply.github.com> Date: Thu, 5 Mar 2026 19:22:30 +0300 Subject: [PATCH 2/2] Pair guard --- dotnet/src/webdriver/BiDi/Script/RemoteValue.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs index 4be020a825912..a567009a5895a 100644 --- a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs +++ b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs @@ -167,6 +167,11 @@ private static TResult ConvertRemoteValuesToDictionary(IReadOnlyList