diff --git a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index 42a8dd3f44c..e71e69636f3 100644 --- a/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -1217,7 +1217,8 @@ CalculatedStyleValue::CalculationResult ClampCalculationNode::resolve(Calculatio if (chosen_value == max_value) return max_node; - VERIFY_NOT_REACHED(); + // NOTE: Non-finite values end up here. + return CalculatedStyleValue::CalculationResult { chosen_value, numeric_type() }; } NonnullRefPtr ClampCalculationNode::with_simplified_children(CalculationContext const& context, CalculationResolutionContext const& resolution_context) const diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-serialize-length.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-serialize-length.txt new file mode 100644 index 00000000000..467671914b7 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-values/calc-infinity-nan-serialize-length.txt @@ -0,0 +1,47 @@ +Harness status: OK + +Found 41 tests + +29 Pass +12 Fail +Pass 'calc(1px * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1% * NaN)' as a specified value should serialize as 'calc(NaN * 1%)'. +Pass 'calc(1in * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1cm * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1mm * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1q * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1pt * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1pc * NaN)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * nan)' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1px * infinity / infinity)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * 0 * infinity)' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * (infinity + -infinity))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * (-infinity + infinity))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * (infinity - infinity))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * infinity)' as a specified value should serialize as 'calc(infinity * 1px)'. +Pass 'calc(1px * -infinity)' as a specified value should serialize as 'calc(-infinity * 1px)'. +Pass 'calc(1% * infinity)' as a specified value should serialize as 'calc(infinity * 1%)'. +Pass 'calc(1% * -infinity)' as a specified value should serialize as 'calc(-infinity * 1%)'. +Pass 'calc(1px * iNFinIty)' as a specified value should serialize as 'calc(infinity * 1px)'. +Pass 'calc(1px * (infinity + infinity))' as a specified value should serialize as 'calc(infinity * 1px)'. +Pass 'calc(1px * (-infinity + -infinity))' as a specified value should serialize as 'calc(-infinity * 1px)'. +Pass 'calc(1px * 1/infinity)' as a specified value should serialize as 'calc(0px)'. +Pass 'calc(1px * infinity * infinity)' as a specified value should serialize as 'calc(infinity * 1px)'. +Pass 'calc(1px * -infinity * -infinity)' as a specified value should serialize as 'calc(infinity * 1px)'. +Fail 'calc(1 * max(INFinity*3px, 0px))' as a specified value should serialize as 'calc(infinity * 1px)'. +Pass 'calc(1 * min(inFInity*4px, 0px))' as a specified value should serialize as 'calc(0px)'. +Fail 'calc(1 * max(nAn*2px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1 * min(nan*3px, 0px))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1 * clamp(-INFINITY*20px, 0px, infiniTY*10px))' as a specified value should serialize as 'calc(0px)'. +Pass 'calc(1px * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1px * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1px * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1px * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1px * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1px)'. +Pass 'calc(1px * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0px)'. +Pass 'calc(1px * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10px)'. +Fail 'calc(1 * min(NaN * 1pt, NaN * 1cm))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1 * max(NaN * 1cm, NaN * 2Q))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1 * min(NaN * 2px, NaN * 4em))' as a specified value should serialize as 'calc(NaN * 1px)'. +Fail 'calc(1 * clamp(NaN * 2em, NaN * 4px, NaN * 8pt))' as a specified value should serialize as 'clamp(NaN * 1em, NaN * 1px, NaN * 1px)'. \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-infinity-nan-serialize-length.html b/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-infinity-nan-serialize-length.html new file mode 100644 index 00000000000..03d6efb067f --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-values/calc-infinity-nan-serialize-length.html @@ -0,0 +1,67 @@ + +Infinity and NaN: calc() serialization for length values. + + + + + +
+
+ \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/support/serialize-testcommon.js b/Tests/LibWeb/Text/input/wpt-import/css/support/serialize-testcommon.js new file mode 100644 index 00000000000..18cebf538ef --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/support/serialize-testcommon.js @@ -0,0 +1,94 @@ +"use strict"; + + +/* Functions to test serialization of properties. + +Each takes (property, testString, expectedSerialization) arguments. + +These functions depend on a #target element existing in the page, +and will error if they don't find one. + +Note that test_computed_serialization and test_used_serialization +are identical except for assertion messages; +you need to choose properties with the correct resolved values +to test the value stage that you want. + + +For ease of use, it's recommended that you define and use +the following function in your test page: + +function test_serialization(t,s,c,u, {prop}={}) { + test_specified_serialization(prop || 'text-indent', t, s); + test_computed_serialization(prop || 'text-indent', t, c); + if(u) test_used_serialization(prop || 'margin-left', t, u); +} + +(swapping the property names for what you're expecting to test) + +Then you can write tests easily as: + +test_serialization( + 'calc(min(1%, 2%) + max(3%, 4%) + 10%)', // test string + 'calc(15%)', // expected specified value + '15%', // expected computed value + '15px'); // expected used value + +*/ + + + + +function test_specified_serialization(prop, t, e) { + const el = document.querySelector("#target"); + if(!el) throw new Exception("Couldn't find #target element to run tests on."); + test(()=>{ + el.style[prop] = ''; + el.style[prop] = t; + const tValue = el.style[prop]; + assert_not_equals(tValue, '', `'${t}' should be valid in ${prop}.`); + + el.style[prop] = ''; + el.style[prop] = e; + const eValue = el.style[prop]; + assert_not_equals(eValue, '', `'${e}' should be valid in ${prop}.`); + assert_equals(eValue, e, `'${e}' should round-trip exactly in specified values.`); + + assert_equals(tValue, e, `'${t}' and '${e}' should serialize the same in specified values.`); + }, `'${t}' as a specified value should serialize as '${e}'.`); +} +function test_computed_serialization(prop, t, e) { + const el = document.querySelector("#target"); + if(!el) throw new Exception("Couldn't find #target element to run tests on."); + test(()=>{ + el.style[prop] = ''; + el.style[prop] = t; + const tValue = getComputedStyle(el)[prop]; + assert_not_equals(tValue, '', `'${t}' should be valid in ${prop}.`); + + el.style[prop] = ''; + el.style[prop] = e; + const eValue = getComputedStyle(el)[prop]; + assert_not_equals(eValue, '', `'${e}' should be valid in ${prop}.`); + assert_equals(eValue, e, `'${e}' should round-trip exactly in computed values.`); + + assert_equals(tValue, e, `'${t}' and '${e}' should serialize the same in computed values.`); + }, `'${t}' as a computed value should serialize as '${e}'.`); +} +function test_used_serialization(prop, t, e) { + const el = document.querySelector("#target"); + if(!el) throw new Exception("Couldn't find #target element to run tests on."); + test(()=>{ + el.style[prop] = ''; + el.style[prop] = t; + const tValue = getComputedStyle(el)[prop]; + assert_not_equals(tValue, '', `'${t}' should be valid in ${prop}.`); + + el.style[prop] = ''; + el.style[prop] = e; + const eValue = getComputedStyle(el)[prop]; + assert_not_equals(eValue, '', `'${e}' should be valid in ${prop}.`); + assert_equals(eValue, e, `'${e}' should round-trip exactly in used values.`); + + assert_equals(tValue, e, `'${t}' and '${e}' should serialize the same in used values.`); + }, `'${t}' as a used value should serialize as '${e}'.`); +} \ No newline at end of file