From 778da0175ed015229a36b4b340ca39e6e7d9715c Mon Sep 17 00:00:00 2001 From: Callum Law Date: Wed, 6 Aug 2025 16:29:12 +1200 Subject: [PATCH] LibWeb: Clamp and censor top-level calc results We now clamp the values returned from calc into the allowed range (where we know it) and censor any `NaN`s to `0` both when we resolve and when we serialize. Gains us 76 WPT passes. --- .../CSS/StyleValues/CalculatedStyleValue.cpp | 110 +++++++++++++++--- .../parsing/border-radius-computed.txt | 5 +- .../parsing/flex-basis-computed.txt | 6 +- .../css/css-flexbox/parsing/flex-computed.txt | 5 +- .../css-fonts/parsing/font-width-computed.txt | 8 +- .../parsing/max-height-computed.txt | 6 +- .../css-sizing/parsing/max-width-computed.txt | 6 +- .../parsing/min-height-computed.txt | 6 +- .../css-sizing/parsing/min-width-computed.txt | 6 +- .../animations/calc-interpolation.txt | 52 ++++----- .../css-values/calc-infinity-nan-computed.txt | 18 +-- .../css/css-values/calc-numbers.txt | 18 +++ .../css/css-values/typed_arithmetic.txt | 31 +++++ .../css/css-values/calc-numbers.html | 100 ++++++++++++++++ .../css/css-values/typed_arithmetic.html | 58 +++++++++ 15 files changed, 361 insertions(+), 74 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-numbers.txt create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-numbers.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-values/typed_arithmetic.html diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index c8dae846660..da7cd415bdc 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -130,6 +130,66 @@ static NonnullRefPtr simplify_2_children(T const& origina return original; } +static CalculationNode::NumericValue clamp_and_censor_numeric_value(NumericCalculationNode const& node, CalculationContext const& context) +{ + auto value = node.value(); + + Optional accepted_range = value.visit( + [&](Number const&) { return context.resolve_numbers_as_integers ? context.accepted_type_ranges.get(ValueType::Integer) : context.accepted_type_ranges.get(ValueType::Number); }, + [&](Angle const&) { return context.accepted_type_ranges.get(ValueType::Angle); }, + [&](Flex const&) { return context.accepted_type_ranges.get(ValueType::Flex); }, + [&](Frequency const&) { return context.accepted_type_ranges.get(ValueType::Frequency); }, + [&](Length const&) { return context.accepted_type_ranges.get(ValueType::Length); }, + [&](Percentage const&) { return context.accepted_type_ranges.get(ValueType::Percentage); }, + [&](Resolution const&) { return context.accepted_type_ranges.get(ValueType::Resolution); }, + [&](Time const&) { return context.accepted_type_ranges.get(ValueType::Time); }); + + if (!accepted_range.has_value()) { + dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Calculation context missing accepted type range {}", node.numeric_type()); + // FIXME: Min and max values for Integer should be based on i32 rather than float + accepted_range = { AK::NumericLimits::lowest(), AK::NumericLimits::max() }; + } + + auto clamp_and_censor = [&](double value, double min, double max) { + // https://drafts.csswg.org/css-values/#calc-ieee + // NaN does not escape a top-level calculation; it’s censored into a zero value. + if (isnan(value)) + value = 0; + + // https://drafts.csswg.org/css-values/#calc-range + // the value resulting from a top-level calculation must be clamped to the range allowed in the target context. + // Clamping is performed on computed values to the extent possible, and also on used values if computation was + // unable to sufficiently simplify the expression to allow range-checking. + return clamp(value, min, max); + }; + + return value.visit( + [&](Number const& value) -> CalculationNode::NumericValue { + return Number { value.type(), clamp_and_censor(context.resolve_numbers_as_integers ? value.integer_value() : value.value(), accepted_range->min, accepted_range->max) }; + }, + [&](Angle const& value) -> CalculationNode::NumericValue { + return Angle { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }, + [&](Flex const& value) -> CalculationNode::NumericValue { + return Flex { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }, + [&](Frequency const& value) -> CalculationNode::NumericValue { + return Frequency { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }, + [&](Length const& value) -> CalculationNode::NumericValue { + return Length { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }, + [&](Percentage const& value) -> CalculationNode::NumericValue { + return Percentage { clamp_and_censor(value.value(), accepted_range->min, accepted_range->max) }; + }, + [&](Resolution const& value) -> CalculationNode::NumericValue { + return Resolution { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }, + [&](Time const& value) -> CalculationNode::NumericValue { + return Time { clamp_and_censor(value.raw_value(), accepted_range->min, accepted_range->max), value.type() }; + }); +} + static String serialize_a_calculation_tree(CalculationNode const&, CalculationContext const&, SerializationMode); // https://drafts.csswg.org/css-values-4/#serialize-a-math-function @@ -141,8 +201,9 @@ static String serialize_a_math_function(CalculationNode const& fn, CalculationCo // the serialization being produced is of a computed value or later, then clamp the value to the range allowed // for its context (if necessary), then serialize the value as normal and return the result. if (fn.type() == CalculationNode::Type::Numeric && serialization_mode == SerializationMode::ResolvedValue) { - // FIXME: Clamp the value. Note that we might have an infinite/nan value here. - return static_cast(fn).value_to_string(); + auto clamped_value = clamp_and_censor_numeric_value(static_cast(fn), context); + + return clamped_value.visit([&](auto const& value) { return value.to_string(serialization_mode); }); } // 2. If fn represents an infinite or NaN value: @@ -2757,12 +2818,40 @@ Optional CalculatedStyleValue::resolve_valu auto raw_value = value->value(); // https://drafts.csswg.org/css-values/#calc-ieee - // FIXME: NaN does not escape a top-level calculation; it’s censored into a zero value. + // NaN does not escape a top-level calculation; it’s censored into a zero value. + if (isnan(raw_value)) + raw_value = 0; // https://drafts.csswg.org/css-values/#calc-range - // FIXME: the value resulting from a top-level calculation must be clamped to the range allowed in the target - // context. Clamping is performed on computed values to the extent possible, and also on used values if - // computation was unable to sufficiently simplify the expression to allow range-checking. + // the value resulting from a top-level calculation must be clamped to the range allowed in the target context. + // Clamping is performed on computed values to the extent possible, and also on used values if computation was + // unable to sufficiently simplify the expression to allow range-checking. + Optional accepted_range; + + if (value->type()->matches_number(m_context.percentages_resolve_as)) + accepted_range = m_context.resolve_numbers_as_integers ? m_context.accepted_type_ranges.get(ValueType::Integer) : m_context.accepted_type_ranges.get(ValueType::Number); + else if (value->type()->matches_angle_percentage(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Angle); + else if (value->type()->matches_flex(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Flex); + else if (value->type()->matches_frequency_percentage(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Frequency); + else if (value->type()->matches_length_percentage(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Length); + else if (value->type()->matches_percentage()) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Percentage); + else if (value->type()->matches_resolution(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Resolution); + else if (value->type()->matches_time_percentage(m_context.percentages_resolve_as)) + accepted_range = m_context.accepted_type_ranges.get(ValueType::Time); + + if (!accepted_range.has_value()) { + dbgln_if(LIBWEB_CSS_DEBUG, "FIXME: Calculation context missing accepted type range {}", value->type()); + // FIXME: Infinity for integers should be i32 max rather than float max + accepted_range = { AK::NumericLimits::lowest(), AK::NumericLimits::max() }; + } + + raw_value = clamp(raw_value, accepted_range->min, accepted_range->max); return ResolvedValue { raw_value, value->type() }; } @@ -2912,15 +3001,8 @@ Optional CalculatedStyleValue::resolve_number(CalculationResolutionConte { auto result = resolve_value(context); - if (result.has_value() && result->type.has_value() && result->type->matches_number(m_context.percentages_resolve_as)) { - auto value = result->value; - - // FIXME: This can be removed once it is upstreamed to `resolve_value` - if (isnan(value)) - return 0.; - + if (result.has_value() && result->type.has_value() && result->type->matches_number(m_context.percentages_resolve_as)) return result->value; - } return {}; } diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/border-radius-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/border-radius-computed.txt index 02907f80c75..80293b66809 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/border-radius-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/parsing/border-radius-computed.txt @@ -2,8 +2,7 @@ Harness status: OK Found 14 tests -13 Pass -1 Fail +14 Pass Pass Property border-radius value '1px' Pass Property border-radius value '1px 2% 3px 4%' Pass Property border-radius value '5em / 1px 2% 3px 4%' @@ -13,7 +12,7 @@ Pass Property border-radius value '1px 1px 1px 1px / 1px 1px 2% 1px' Pass Property border-radius value '1px 1px 2% 2%' Pass Property border-radius value '1px 2% 1px 1px' Pass Property border-radius value '1px 2% 2% 2% / 1px 2% 3px 2%' -Fail Property border-top-left-radius value 'calc(-0.5em + 10px)' +Pass Property border-top-left-radius value 'calc(-0.5em + 10px)' Pass Property border-top-right-radius value '20%' Pass Property border-bottom-right-radius value 'calc(0.5em + 10px) 40%' Pass Property border-bottom-left-radius value '50% 60px' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-basis-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-basis-computed.txt index e025013da3d..107471dd4b0 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-basis-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-basis-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 12 tests -10 Pass -2 Fail +11 Pass +1 Fail Pass Property flex-basis value '1px' Pass Property flex-basis value '400%' Pass Property flex-basis value 'auto' @@ -12,7 +12,7 @@ Pass Property flex-basis value 'fit-content' Pass Property flex-basis value 'min-content' Pass Property flex-basis value 'max-content' Pass Property flex-basis value 'calc(10px + 0.5em)' -Fail Property flex-basis value 'calc(10px - 0.5em)' +Pass Property flex-basis value 'calc(10px - 0.5em)' Pass Property flex-basis value 'calc(10%)' Pass Property flex-basis value 'calc(0% + 10px)' Fail Property flex-basis value 'calc(10% + 0px)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-computed.txt index 1cf2e7b80d4..4fdb0d792b4 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-flexbox/parsing/flex-computed.txt @@ -2,8 +2,7 @@ Harness status: OK Found 8 tests -7 Pass -1 Fail +8 Pass Pass Property flex value 'none' Pass Property flex value '1' Pass Property flex value '2 3' @@ -11,4 +10,4 @@ Pass Property flex value '4 5 6px' Pass Property flex value '7% 8' Pass Property flex value '8 auto' Pass Property flex value 'calc(10px + 0.5em)' -Fail Property flex value 'calc(10px - 0.5em)' \ No newline at end of file +Pass Property flex value 'calc(10px - 0.5em)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/parsing/font-width-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/parsing/font-width-computed.txt index c8838621d99..61d9d2981e1 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/parsing/font-width-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-fonts/parsing/font-width-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 30 tests -8 Pass -22 Fail +10 Pass +20 Fail Fail Property font-width value 'ultra-condensed' Fail Property font-width value 'extra-condensed' Fail Property font-width value 'condensed' @@ -16,7 +16,7 @@ Fail Property font-width value 'ultra-expanded' Pass Property font-width value '234.5%' Pass Property font-width value 'calc(100%)' Pass Property font-width value 'calc(0%)' -Fail Property font-width value 'calc(-100%)' +Pass Property font-width value 'calc(-100%)' Pass Property font-width value 'calc(100% + 100%)' Fail Property font-width value 'calc(100% + (sign(20cqw - 10px) * 5%))' Fail Property font-stretch value 'ultra-condensed' @@ -31,6 +31,6 @@ Fail Property font-stretch value 'ultra-expanded' Pass Property font-stretch value '234.5%' Pass Property font-stretch value 'calc(100%)' Pass Property font-stretch value 'calc(0%)' -Fail Property font-stretch value 'calc(-100%)' +Pass Property font-stretch value 'calc(-100%)' Pass Property font-stretch value 'calc(100% + 100%)' Fail Property font-stretch value 'calc(100% + (sign(20cqw - 10px) * 5%))' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-height-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-height-computed.txt index f96dbc8bd92..55a521a703b 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-height-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-height-computed.txt @@ -2,15 +2,15 @@ Harness status: OK Found 12 tests -10 Pass -2 Fail +11 Pass +1 Fail Pass Property max-height value 'none' Pass Property max-height value 'min-content' Pass Property max-height value 'max-content' Pass Property max-height value '10px' Pass Property max-height value '20%' Pass Property max-height value 'calc(10% + 40px)' -Fail Property max-height value 'calc(10px - 0.5em)' +Pass Property max-height value 'calc(10px - 0.5em)' Pass Property max-height value 'calc(10px + 0.5em)' Pass Property max-height value 'fit-content(10px)' Pass Property max-height value 'fit-content(20%)' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-width-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-width-computed.txt index 344cee3ba0d..ceeb1a50646 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-width-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/max-width-computed.txt @@ -2,15 +2,15 @@ Harness status: OK Found 12 tests -10 Pass -2 Fail +11 Pass +1 Fail Pass Property max-width value 'none' Pass Property max-width value 'min-content' Pass Property max-width value 'max-content' Pass Property max-width value '10px' Pass Property max-width value '20%' Pass Property max-width value 'calc(10% + 40px)' -Fail Property max-width value 'calc(10px - 0.5em)' +Pass Property max-width value 'calc(10px - 0.5em)' Pass Property max-width value 'calc(10px + 0.5em)' Pass Property max-width value 'fit-content(10px)' Pass Property max-width value 'fit-content(20%)' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-height-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-height-computed.txt index 18524e776a5..a9ad528c586 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-height-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-height-computed.txt @@ -2,14 +2,14 @@ Harness status: OK Found 11 tests -9 Pass -2 Fail +10 Pass +1 Fail Pass Property min-height value 'min-content' Pass Property min-height value 'max-content' Pass Property min-height value '10px' Pass Property min-height value '20%' Pass Property min-height value 'calc(10% + 40px)' -Fail Property min-height value 'calc(10px - 0.5em)' +Pass Property min-height value 'calc(10px - 0.5em)' Pass Property min-height value 'calc(10px + 0.5em)' Pass Property min-height value 'fit-content(10px)' Pass Property min-height value 'fit-content(20%)' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-width-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-width-computed.txt index 4b71f43d67e..48275235f20 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-width-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-sizing/parsing/min-width-computed.txt @@ -2,14 +2,14 @@ Harness status: OK Found 11 tests -9 Pass -2 Fail +10 Pass +1 Fail Pass Property min-width value 'min-content' Pass Property min-width value 'max-content' Pass Property min-width value '10px' Pass Property min-width value '20%' Pass Property min-width value 'calc(10% + 40px)' -Fail Property min-width value 'calc(10px - 0.5em)' +Pass Property min-width value 'calc(10px - 0.5em)' Pass Property min-width value 'calc(10px + 0.5em)' Pass Property min-width value 'fit-content(10px)' Pass Property min-width value 'fit-content(20%)' diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/animations/calc-interpolation.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/animations/calc-interpolation.txt index 450b3c894e2..cabb99481dc 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/animations/calc-interpolation.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/animations/calc-interpolation.txt @@ -2,36 +2,36 @@ Harness status: OK Found 140 tests -70 Pass -70 Fail -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [NaNpx] +84 Pass +56 Fail +Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [-8.50705e+37px] Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0) should be [0px] -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [NaNpx] -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [NaNpx] -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [NaNpx] -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (1) should be [NaNpx] -Fail CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [NaNpx] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [NaNpx] +Pass CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [8.50705e+37px] +Pass CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [1.70141e+38px] +Pass CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [2.552115e+38px] +Pass CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (1) should be [3.40282e+38px] +Pass CSS Transitions: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [4.2535250000000006e+38px] +Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [-8.50705e+37px] Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0) should be [0px] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [NaNpx] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [NaNpx] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [NaNpx] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (1) should be [NaNpx] -Fail CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [NaNpx] -Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [NaNpx] +Pass CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [8.50705e+37px] +Pass CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [1.70141e+38px] +Pass CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [2.552115e+38px] +Pass CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (1) should be [3.40282e+38px] +Pass CSS Transitions with transition: all: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [4.2535250000000006e+38px] +Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [-3.40282e+38px] Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0) should be [0px] -Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [NaNpx] -Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [NaNpx] -Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [NaNpx] -Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (1) should be [NaNpx] -Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [NaNpx] -Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [NaNpx] +Fail CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [3.40282e+38px] +Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [3.40282e+38px] +Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [3.40282e+38px] +Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (1) should be [3.40282e+38px] +Pass CSS Animations: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [3.40282e+38px] +Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (-0.25) should be [-3.40282e+38px] Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (0) should be [0px] -Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [NaNpx] -Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [NaNpx] -Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [NaNpx] -Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (1) should be [NaNpx] -Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [NaNpx] +Fail Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.25) should be [3.40282e+38px] +Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.5) should be [3.40282e+38px] +Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (0.75) should be [3.40282e+38px] +Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (1) should be [3.40282e+38px] +Pass Web Animations: property from [0px] to [calc(infinity * 1px)] at (1.25) should be [3.40282e+38px] Fail CSS Transitions: property from [calc(50% - 25px)] to [calc(100% - 10px)] at (-0.25) should be [-10px] Fail CSS Transitions: property from [calc(50% - 25px)] to [calc(100% - 10px)] at (0) should be [0px] Fail CSS Transitions: property from [calc(50% - 25px)] to [calc(100% - 10px)] at (0.25) should be [10px] diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-computed.txt index b4eabf37f73..6b76d26d188 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-computed.txt @@ -2,8 +2,8 @@ Harness status: OK Found 45 tests -26 Pass -19 Fail +33 Pass +12 Fail Pass Property width value 'calc(NaN * 1px)' Pass Property width value 'calc(NaN * 1%)' Pass Property width value 'calc(infinity * 1px)' @@ -30,13 +30,13 @@ Pass Property margin-left value 'calc(-infinity * 1%)' Pass Property margin-left value 'calc(max(10000px, 0px) + min(-infinity * 1px, infinity * 1px))' Pass Property margin-left value 'calc(-infinity * 1px - infinity * 1px)' Pass Property margin-left value 'calc(min(-infinity * 1px, 10px))' -Fail Property animation-duration value 'calc(NaN * 1s)' -Fail Property animation-duration value 'calc(infinity * 1s)' -Fail Property animation-duration value 'calc(1 / 0 * 1s)' -Fail Property animation-duration value 'calc(max(infinity * 1s, 10s)' -Fail Property transition-delay value 'calc(-infinity* 1s)' -Fail Property transition-delay value 'calc(max(10000s, 0s) + min(-infinity * 1s, infinity * 1s))' -Fail Property transition-delay value 'calc(min(-infinity * 1s, 10s))' +Pass Property animation-duration value 'calc(NaN * 1s)' +Pass Property animation-duration value 'calc(infinity * 1s)' +Pass Property animation-duration value 'calc(1 / 0 * 1s)' +Pass Property animation-duration value 'calc(max(infinity * 1s, 10s)' +Pass Property transition-delay value 'calc(-infinity* 1s)' +Pass Property transition-delay value 'calc(max(10000s, 0s) + min(-infinity * 1s, infinity * 1s))' +Pass Property transition-delay value 'calc(min(-infinity * 1s, 10s))' Fail Property rotate(calc(infinity * 1deg)) value expected same with rotate(0deg) in +/-0.0001 Fail Property rotate(calc(-infinity * 1deg)) value expected same with rotate(0deg) in +/-0.0001 Fail Property rotate(calc(NaN * 1deg)) value expected same with rotate(0deg) in +/-0.0001 diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-numbers.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-numbers.txt new file mode 100644 index 00000000000..2fcacbc73cf --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-numbers.txt @@ -0,0 +1,18 @@ +Harness status: OK + +Found 12 tests + +11 Pass +1 Fail +Pass testing tab-size: calc(2 * 3) +Pass testing tab-size: calc(2 * -4) +Pass testing opacity: calc(2 / 4) +Pass testing tab-size: calc(2 / 4) +Pass testing opacity: calc(2 / 4) * 1px +Fail testing opacity: calc(90%) +Pass testing tab-size: calc(1 + 1px) +Pass testing tab-size: calc(1 + 100%) +Pass testing tab-size: calc(100%) +Pass testing tab-size: calc(10px) bla +Pass testing tab-size: calc(bla) 10px +Pass testing tab-size: calc(10px) \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt new file mode 100644 index 00000000000..a1ff3508bcf --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/typed_arithmetic.txt @@ -0,0 +1,31 @@ +Harness status: OK + +Found 25 tests + +19 Pass +6 Fail +Pass min(1em, 110px / 10px * 1px) should be used-value-equivalent to 10px +Pass max(10px, 110px / 10px * 1px) should be used-value-equivalent to 11px +Pass max(1em + 2px, 110px / 10px * 1px) should be used-value-equivalent to 12px +Pass max(1em + 2%, 110px / 10px * 1px) should be used-value-equivalent to 12px +Pass clamp(110px / 10px * 1px, 1em + 200%, 200% * 1% / 1em) should be used-value-equivalent to 20px +Pass calc(3 + sign(10px / 1rem - sign(1em + 1px))) should be used-value-equivalent to 3 +Pass calc(10em / 1em) should be used-value-equivalent to 10 +Pass calc(10em / 1rem) should be used-value-equivalent to 10 +Pass calc(10em / 1px) should be used-value-equivalent to 100 +Pass calc(1px / 10em * NaN) should be used-value-equivalent to 0 +Pass Property width value 'calc(1px * 10em / 0em)' +Pass Property width value 'calc(1px / 1px * 10em * infinity)' +Fail Property margin-left value 'calc(1px * 10em / -0em)' +Pass Property z-index value 'calc(10em / 0em)' +Pass sign(-0em / 1px) should be used-value-equivalent to 0 +Fail clamp(-1, 1 / sign(-0em / 1px), 1) should be used-value-equivalent to -1 +Fail sign( 0cqi / 1px) should be used-value-equivalent to 0 +Fail clamp(-1, 1 / sign( 0cqi / 1px), 1) should be used-value-equivalent to 1 +Pass sign(atan2(-0cap / 1px, 0em / 1px)) should be used-value-equivalent to 0 +Fail clamp(-1, 1 / sign(atan2(-0cap / 1px, 0em / 1px)), 1) should be used-value-equivalent to -1 +Pass sign(exp(-1vh / 0px)) should be used-value-equivalent to 0 +Pass clamp(-1, 1 / sign(exp(-1vh / 0px)), 1) should be used-value-equivalent to 1 +Fail calc(20cqw / 1rem) should be used-value-equivalent to 2 +Pass Property animation-duration value 'calc(2s / (10s - 10s) * 1s)' +Pass subtraction of angle unit: deg minus turn \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-numbers.html b/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-numbers.html new file mode 100644 index 00000000000..f8caa46cc47 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-numbers.html @@ -0,0 +1,100 @@ + + + + + CSS Values and Units Test: computed value of 'tab-size' and 'opacity' when specified with calc() function + + + + + + + + + + + + + + + + +
+ + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-values/typed_arithmetic.html b/Tests/LibWeb/Text/input/wpt-import/css/css-values/typed_arithmetic.html new file mode 100644 index 00000000000..b849cccdb84 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-values/typed_arithmetic.html @@ -0,0 +1,58 @@ + +CSS Values: typed arithmetic tests + + + + + + +
+
+
+