webdriver: Serialize as i64 if the JS Number has no fractional part (#39186)

JavaScript Number does not have Integer type, except for recently added
`BigInt`. That's why we removed `Int` variant from `JSValue` earlier in
#38748. However, the Serde deserialization is strict: when it expects
`u64`, it cannot deserialize "3.0". But when it expects `f64`, it can
still deserialize "3".

Now, we serialize as i64 if the JS Number has no fractional part. This
not only fixes regression, but also improves the case where we have an
integer not representable by i32 and previously would be parsed as f64
again.

Testing: `./mach test-wpt -r
/infrastructure/testdriver/actions/eventOrder.html --headless --product
servodriver` no longer fails when deserializing HTTP request.
Fixes: #39181

Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
Euclid Ye 2025-09-06 22:38:32 +08:00 committed by GitHub
parent 7f5533d0b5
commit bd3231847e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -254,10 +254,15 @@ impl Serialize for SendableJSValue {
S: Serializer,
{
match self.0 {
JSValue::Undefined => serializer.serialize_unit(),
JSValue::Null => serializer.serialize_unit(),
JSValue::Undefined | JSValue::Null => serializer.serialize_unit(),
JSValue::Boolean(x) => serializer.serialize_bool(x),
JSValue::Number(x) => serializer.serialize_f64(x),
JSValue::Number(x) => {
if x.fract() == 0.0 {
serializer.serialize_i64(x as i64)
} else {
serializer.serialize_f64(x)
}
},
JSValue::String(ref x) => serializer.serialize_str(x),
JSValue::Element(ref x) => WebElement(x.clone()).serialize(serializer),
JSValue::ShadowRoot(ref x) => ShadowRoot(x.clone()).serialize(serializer),