mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
style: Serialize NaN and infinity numbers
Added NaN/inf serialization of <number> and changed calc() code to not remove NaN/infinity in code using it. This change is unfortunately imperfect as some things using <number> still refuse to serialize NaN/infinity for some reason (scale()?), but this bug/patch is just for <number> so leaving that out of scope for this. Also added new WPT test file for number NaN/inf serialization based on existing serialization tests (all pass already!). 5 other WPT subtests now newly pass. Differential Revision: https://phabricator.services.mozilla.com/D178587
This commit is contained in:
parent
dcb61c095f
commit
a10df24ffb
3 changed files with 37 additions and 23 deletions
|
@ -99,6 +99,14 @@ fn nan_inf_enabled() -> bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Serialize a number with calc, and NaN/infinity handling (if enabled)
|
||||
pub fn serialize_number<W>(v: f32, was_calc: bool, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
serialize_specified_dimension(v, "", was_calc, dest)
|
||||
}
|
||||
|
||||
/// Serialize a specified dimension with unit, calc, and NaN/infinity handling (if enabled)
|
||||
pub fn serialize_specified_dimension<W>(
|
||||
v: f32,
|
||||
|
@ -120,11 +128,15 @@ where
|
|||
// requires an expression like calc(infinity * 1px)."
|
||||
|
||||
if v.is_nan() {
|
||||
dest.write_str("NaN * 1")?;
|
||||
dest.write_str("NaN")?;
|
||||
} else if v == f32::INFINITY {
|
||||
dest.write_str("infinity * 1")?;
|
||||
dest.write_str("infinity")?;
|
||||
} else if v == f32::NEG_INFINITY {
|
||||
dest.write_str("-infinity * 1")?;
|
||||
dest.write_str("-infinity")?;
|
||||
}
|
||||
|
||||
if !unit.is_empty() {
|
||||
dest.write_str(" * 1")?;
|
||||
}
|
||||
} else {
|
||||
v.to_css(dest)?;
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::values::generics::calc::{MinMaxOp, ModRemOp, RoundingStrategy, SortKe
|
|||
use crate::values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
|
||||
use crate::values::specified::length::{ContainerRelativeLength, ViewportPercentageLength};
|
||||
use crate::values::specified::{self, Angle, Resolution, Time};
|
||||
use crate::values::{CSSFloat, CSSInteger};
|
||||
use crate::values::{serialize_number, serialize_percentage, CSSFloat, CSSInteger};
|
||||
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp;
|
||||
|
@ -131,9 +131,9 @@ impl ToCss for Leaf {
|
|||
{
|
||||
match *self {
|
||||
Self::Length(ref l) => l.to_css(dest),
|
||||
Self::Number(ref n) => n.to_css(dest),
|
||||
Self::Number(n) => serialize_number(n, /* was_calc = */ false, dest),
|
||||
Self::Resolution(ref r) => r.to_css(dest),
|
||||
Self::Percentage(p) => crate::values::serialize_percentage(p, dest),
|
||||
Self::Percentage(p) => serialize_percentage(p, dest),
|
||||
Self::Angle(ref a) => a.to_css(dest),
|
||||
Self::Time(ref t) => t.to_css(dest),
|
||||
}
|
||||
|
@ -887,10 +887,16 @@ impl CalcNode {
|
|||
|
||||
/// Tries to simplify this expression into a `<number>` value.
|
||||
fn to_number(&self) -> Result<CSSFloat, ()> {
|
||||
self.resolve(|leaf| match *leaf {
|
||||
let number = self.resolve(|leaf| match *leaf {
|
||||
Leaf::Number(n) => Ok(n),
|
||||
_ => Err(()),
|
||||
})
|
||||
})?;
|
||||
let result = if nan_inf_enabled() {
|
||||
number
|
||||
} else {
|
||||
crate::values::normalize(number)
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Tries to simplify this expression into a `<percentage>` value.
|
||||
|
@ -992,7 +998,6 @@ impl CalcNode {
|
|||
) -> Result<CSSFloat, ParseError<'i>> {
|
||||
Self::parse(context, input, function, CalcUnits::empty())?
|
||||
.to_number()
|
||||
.map(crate::values::normalize)
|
||||
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ use super::generics::{self, GreaterThanOrEqualToOne, NonNegative};
|
|||
use super::{CSSFloat, CSSInteger};
|
||||
use crate::context::QuirksMode;
|
||||
use crate::parser::{Parse, ParserContext};
|
||||
use crate::values::serialize_atom_identifier;
|
||||
use crate::values::specified::calc::CalcNode;
|
||||
use crate::values::{serialize_atom_identifier, serialize_number};
|
||||
use crate::{Atom, Namespace, One, Prefix, Zero};
|
||||
use cssparser::{Parser, Token};
|
||||
use std::fmt::{self, Write};
|
||||
|
@ -196,15 +196,15 @@ fn parse_number_with_clamping_mode<'i, 't>(
|
|||
match *input.next()? {
|
||||
Token::Number { value, .. } if clamping_mode.is_ok(context.parsing_mode, value) => {
|
||||
Ok(Number {
|
||||
value: value.min(f32::MAX).max(f32::MIN),
|
||||
value,
|
||||
calc_clamping_mode: None,
|
||||
})
|
||||
},
|
||||
Token::Function(ref name) => {
|
||||
let function = CalcNode::math_function(context, name, location)?;
|
||||
let result = CalcNode::parse_number(context, input, function)?;
|
||||
let value = CalcNode::parse_number(context, input, function)?;
|
||||
Ok(Number {
|
||||
value: result.min(f32::MAX).max(f32::MIN),
|
||||
value,
|
||||
calc_clamping_mode: Some(clamping_mode),
|
||||
})
|
||||
},
|
||||
|
@ -264,8 +264,12 @@ impl Number {
|
|||
/// Returns the numeric value, clamped if needed.
|
||||
#[inline]
|
||||
pub fn get(&self) -> f32 {
|
||||
self.calc_clamping_mode
|
||||
.map_or(self.value, |mode| mode.clamp(self.value))
|
||||
crate::values::normalize(
|
||||
self.calc_clamping_mode
|
||||
.map_or(self.value, |mode| mode.clamp(self.value)),
|
||||
)
|
||||
.min(f32::MAX)
|
||||
.max(f32::MIN)
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
|
@ -316,14 +320,7 @@ impl ToCss for Number {
|
|||
where
|
||||
W: Write,
|
||||
{
|
||||
if self.calc_clamping_mode.is_some() {
|
||||
dest.write_str("calc(")?;
|
||||
}
|
||||
self.value.to_css(dest)?;
|
||||
if self.calc_clamping_mode.is_some() {
|
||||
dest.write_char(')')?;
|
||||
}
|
||||
Ok(())
|
||||
serialize_number(self.value, self.calc_clamping_mode.is_some(), dest)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue