diff --git a/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BiDiDoubleConverter.cs b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BiDiDoubleConverter.cs
new file mode 100644
index 0000000000000..4154d2ac74cca
--- /dev/null
+++ b/dotnet/src/webdriver/BiDi/Communication/Json/Converters/BiDiDoubleConverter.cs
@@ -0,0 +1,92 @@
+//
+// 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;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace OpenQA.Selenium.BiDi.Communication.Json.Converters;
+
+///
+/// Serializes and deserializes into a
+/// BiDi spec-compliant number value.
+///
+internal sealed class BiDiDoubleConverter : JsonConverter
+{
+ public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ if (reader.TryGetDouble(out double d))
+ {
+ return d;
+ }
+
+ var str = reader.GetString() ?? throw new JsonException();
+
+ if (str.Equals("-0", StringComparison.Ordinal))
+ {
+ return -0.0;
+ }
+ else if (str.Equals("NaN", StringComparison.Ordinal))
+ {
+ return double.NaN;
+ }
+ else if (str.Equals("Infinity", StringComparison.Ordinal))
+ {
+ return double.PositiveInfinity;
+ }
+ else if (str.Equals("-Infinity", StringComparison.Ordinal))
+ {
+ return double.NegativeInfinity;
+ }
+
+ throw new JsonException();
+ }
+
+ public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
+ {
+ if (double.IsNaN(value))
+ {
+ writer.WriteStringValue("NaN");
+ }
+ else if (double.IsPositiveInfinity(value))
+ {
+ writer.WriteStringValue("Infinity");
+ }
+ else if (double.IsNegativeInfinity(value))
+ {
+ writer.WriteStringValue("-Infinity");
+ }
+ else if (IsNegativeZero(value))
+ {
+ writer.WriteStringValue("-0");
+ }
+ else
+ {
+ writer.WriteNumberValue(value);
+ }
+
+ static bool IsNegativeZero(double x)
+ {
+ // Negative zero is less trivial to test, because 0 == -0 is true
+ // We need to do a bit pattern comparison
+
+ return BitConverter.DoubleToInt64Bits(x) == BitConverter.DoubleToInt64Bits(-0.0);
+ }
+ }
+}
diff --git a/dotnet/src/webdriver/BiDi/Script/LocalValue.cs b/dotnet/src/webdriver/BiDi/Script/LocalValue.cs
index 0409f4542b7df..ce37fca5c26d6 100644
--- a/dotnet/src/webdriver/BiDi/Script/LocalValue.cs
+++ b/dotnet/src/webdriver/BiDi/Script/LocalValue.cs
@@ -24,6 +24,7 @@
using System.Numerics;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
+using OpenQA.Selenium.BiDi.Communication.Json.Converters;
namespace OpenQA.Selenium.BiDi.Script;
@@ -282,7 +283,7 @@ private static LocalValue ReflectionBasedConvertFrom(object? value)
public abstract record PrimitiveProtocolLocalValue : LocalValue;
-public record NumberLocalValue(double Value) : PrimitiveProtocolLocalValue
+public record NumberLocalValue([property: JsonConverter(typeof(BiDiDoubleConverter))] double Value) : PrimitiveProtocolLocalValue
{
public static explicit operator NumberLocalValue(double n) => new NumberLocalValue(n);
}
diff --git a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs
index d1ac8be390be0..1d66710fa563d 100644
--- a/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs
+++ b/dotnet/src/webdriver/BiDi/Script/RemoteValue.cs
@@ -22,6 +22,7 @@
using System.Numerics;
using System.Text.Json;
using System.Text.Json.Serialization;
+using OpenQA.Selenium.BiDi.Communication.Json.Converters;
namespace OpenQA.Selenium.BiDi.Script;
@@ -97,7 +98,7 @@ public abstract record RemoteValue
}
}
-public record NumberRemoteValue(double Value) : PrimitiveProtocolRemoteValue;
+public record NumberRemoteValue([property: JsonConverter(typeof(BiDiDoubleConverter))] double Value) : PrimitiveProtocolRemoteValue;
public record BooleanRemoteValue(bool Value) : PrimitiveProtocolRemoteValue;
diff --git a/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs b/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs
index e265e7f4f5d8f..6a75d595c5034 100644
--- a/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs
+++ b/dotnet/test/common/BiDi/Script/CallFunctionLocalValueTest.cs
@@ -221,8 +221,6 @@ public async Task CanCallFunctionWithArgumentNumberZero()
}
[Test]
- [IgnoreBrowser(Selenium.Browser.Edge, "Chromium can't handle -0 argument as a number: https://github.com/w3c/webdriver-bidi/issues/887")]
- [IgnoreBrowser(Selenium.Browser.Chrome, "Chromium can't handle -0 argument as a number: https://github.com/w3c/webdriver-bidi/issues/887")]
public async Task CanCallFunctionWithArgumentNumberNegativeZero()
{
var arg = new NumberLocalValue(double.NegativeZero);