style: Serialize NaN and infinity angles as per spec

`NaN`, `infinity`, and `-infinity` angles should be specially serialized.

Also fixed a few relevant WPT tests which did not follow spec.
(see https://github.com/web-platform-tests/wpt/pull/38825)

Adjusted WPT test expectations, 40 newly pass 🎉

Differential Revision: https://phabricator.services.mozilla.com/D171658
This commit is contained in:
CanadaHonk 2023-03-07 00:02:55 +00:00 committed by Martin Robinson
parent 7b28572309
commit a8fef9d4f2
3 changed files with 66 additions and 16 deletions

View file

@ -92,6 +92,39 @@ where
serialize_name(&ident, dest)
}
fn nan_inf_enabled() -> bool {
static_prefs::pref!("layout.css.nan-inf.enabled")
}
/// Serialize a specified dimension with unit, calc, and NaN/infinity handling (if enabled)
pub fn serialize_specified_dimension<W>(v: f32, unit: &str, was_calc: bool, dest: &mut CssWriter<W>) -> fmt::Result
where
W: Write,
{
if was_calc {
dest.write_str("calc(")?;
}
if !v.is_finite() && nan_inf_enabled() {
if v.is_nan() {
dest.write_str("NaN * 1")?;
} else if v == f32::INFINITY {
dest.write_str("infinity * 1")?;
} else if v == f32::NEG_INFINITY {
dest.write_str("-infinity * 1")?;
}
} else {
v.to_css(dest)?;
}
dest.write_str(unit)?;
if was_calc {
dest.write_char(')')?;
}
Ok(())
}
/// A CSS string stored as an `Atom`.
#[repr(transparent)]
#[derive(

View file

@ -39,12 +39,7 @@ impl Zero for AngleDimension {
}
fn is_zero(&self) -> bool {
match *self {
AngleDimension::Deg(ref f) |
AngleDimension::Grad(ref f) |
AngleDimension::Rad(ref f) |
AngleDimension::Turn(ref f) => *f == 0.,
}
self.unitless_value() == 0.0
}
}
@ -63,6 +58,24 @@ impl AngleDimension {
AngleDimension::Grad(gradians) => gradians * DEG_PER_GRAD,
}
}
fn unitless_value(&self) -> CSSFloat {
match *self {
AngleDimension::Deg(v) |
AngleDimension::Rad(v) |
AngleDimension::Turn(v) |
AngleDimension::Grad(v) => v,
}
}
fn unit(&self) -> &'static str {
match *self {
AngleDimension::Deg(_) => "deg",
AngleDimension::Rad(_) => "rad",
AngleDimension::Turn(_) => "turn",
AngleDimension::Grad(_) => "grad"
}
}
}
/// A specified Angle value, which is just the angle dimension, plus whether it
@ -92,14 +105,7 @@ impl ToCss for Angle {
where
W: Write,
{
if self.was_calc {
dest.write_str("calc(")?;
}
self.value.to_css(dest)?;
if self.was_calc {
dest.write_char(')')?;
}
Ok(())
crate::values::serialize_specified_dimension(self.value.unitless_value(), self.value.unit(), self.was_calc, dest)
}
}
@ -108,7 +114,7 @@ impl ToComputedValue for Angle {
#[inline]
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
ComputedAngle::from_degrees(self.degrees())
ComputedAngle::from_degrees(crate::values::normalize(self.degrees()))
}
#[inline]
@ -170,6 +176,12 @@ impl Angle {
was_calc: true,
}
}
/// Returns the unit of the angle.
#[inline]
pub fn unit(&self) -> &'static str {
self.value.unit()
}
}
/// Whether to allow parsing an unitless zero as a valid angle.

View file

@ -836,7 +836,12 @@ impl CalcNode {
Leaf::Angle(ref angle) => Ok(angle.degrees()),
_ => Err(()),
})?;
Ok(Angle::from_calc(crate::values::normalize(degrees)))
let result = Angle::from_calc(if nan_inf_enabled() {
degrees
} else {
crate::values::normalize(degrees)
});
Ok(result)
}
/// Tries to simplify this expression into a `<number>` value.