Title: [291911] trunk
Revision
291911
Author
[email protected]
Date
2022-03-25 18:45:25 -0700 (Fri, 25 Mar 2022)

Log Message

Incorrect handling of NaN inside calc() for top-level calculation
https://bugs.webkit.org/show_bug.cgi?id=234176

Reviewed by Simon Fraser.

LayoutTests/imported/w3c:

* web-platform-tests/css/css-values/calc-infinity-nan-computed-expected.txt: Added.
* web-platform-tests/css/css-values/calc-infinity-nan-computed.html: Added.
* web-platform-tests/css/css-values/round-function-expected.txt:
* web-platform-tests/css/css-values/round-function.html:

Source/WebCore:

Add function to convert any top level NaN values to infinity values as per the spec.
This only affects the computed value of the calc _expression_, not its serialization.

Test: imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed.html

* css/calc/CSSCalcOperationNode.cpp:
(WebCore::CSSCalcOperationNode::combineChildren):
(WebCore::convertToTopLevelValue):
(WebCore::CSSCalcOperationNode::evaluateOperator):
* css/calc/CSSCalcOperationNode.h:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (291910 => 291911)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2022-03-26 01:45:25 UTC (rev 291911)
@@ -1,3 +1,15 @@
+2022-03-25  Nikolaos Mouchtaris  <[email protected]>
+
+        Incorrect handling of NaN inside calc() for top-level calculation
+        https://bugs.webkit.org/show_bug.cgi?id=234176
+
+        Reviewed by Simon Fraser.
+
+        * web-platform-tests/css/css-values/calc-infinity-nan-computed-expected.txt: Added.
+        * web-platform-tests/css/css-values/calc-infinity-nan-computed.html: Added.
+        * web-platform-tests/css/css-values/round-function-expected.txt:
+        * web-platform-tests/css/css-values/round-function.html:
+
 2022-03-25  Youenn Fablet  <[email protected]>
 
         Add support for focused and visible ServiceWorkerWindowClient states

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed-expected.txt (0 => 291911)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed-expected.txt	2022-03-26 01:45:25 UTC (rev 291911)
@@ -0,0 +1,36 @@
+
+PASS Property width value 'calc(NaN * 1px)'
+PASS Property width value 'calc(infinity * 1px)'
+PASS Property width value 'calc(infinity * 1cm)'
+PASS Property width value 'calc(NaN * 1rem)'
+FAIL Property width value 'calc(infinity * 1px - infinity * 1%)' assert_greater_than_equal: calc(infinity * 1px - infinity * 1%) expected a number greater than or equal to 33554400 but got 0
+PASS Property width value 'calc(infinity * 1px + infinity * 1%)'
+PASS Property width value 'calc(min(NaN * 1px, infinity * 1px) + max(infinity * 1px, -infinity * 1px))'
+FAIL Property width value 'calc(infinity * 1px - max(infinity * 1%, 0%))' assert_greater_than_equal: calc(infinity * 1px - max(infinity * 1%, 0%)) expected a number greater than or equal to 33554400 but got 0
+PASS Property width value 'calc(max(infinity * 1px, 10px))'
+PASS Property margin-left value 'calc(-infinity * 1px)'
+PASS Property margin-left value 'calc(min(1px, -infinity * 1%))'
+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))'
+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 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(-infinity * 1deg)) value expected same with rotate(0deg) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(NaN * 1deg)) value expected same with rotate(0deg) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(infinity * 1turn)) value expected same with rotate(0turn) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(-infinity * 1turn)) value expected same with rotate(0turn) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(NaN * 1turn)) value expected same with rotate(0turn) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(infinity * 1rad)) value expected same with rotate(0rad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(-infinity * 1rad)) value expected same with rotate(0rad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(NaN * 1rad)) value expected same with rotate(0rad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(infinity * 1grad)) value expected same with rotate(0grad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(-infinity * 1grad)) value expected same with rotate(0grad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+FAIL Property rotate(calc(NaN * 1grad)) value expected same with rotate(0grad) in +/-0.0001 assert_array_approx_equals: lengths differ, expected 6 got 16
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed.html (0 => 291911)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed.html	2022-03-26 01:45:25 UTC (rev 291911)
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Infinity and NaN: calc() computed value.</title>
+<link rel="author" title="Seokho Song"  href=""
+<link rel="help" href=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<div id="target"></div>
+<script>
+const APPROX_INFINITY = 3.35544e+07;
+const APPROX_NEGATIVE_INFINITY = -APPROX_INFINITY;
+
+// For <length>
+test_computed_value_greater_or_lower_than("width", "calc(NaN * 1px)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(infinity * 1px)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(infinity * 1cm)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(NaN * 1rem)", APPROX_INFINITY);
+
+test_computed_value_greater_or_lower_than("width", "calc(infinity * 1px - infinity * 1%)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(infinity * 1px + infinity * 1%)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(min(NaN * 1px, infinity * 1px) + max(infinity * 1px, -infinity * 1px))", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("width", "calc(infinity * 1px - max(infinity * 1%, 0%))", APPROX_INFINITY);
+
+test_computed_value_greater_or_lower_than("width", "calc(max(infinity * 1px, 10px))", APPROX_INFINITY);
+
+test_computed_value_greater_or_lower_than("margin-left", "calc(-infinity * 1px)", APPROX_NEGATIVE_INFINITY);
+test_computed_value_greater_or_lower_than("margin-left", "calc(min(1px, -infinity * 1%))", APPROX_NEGATIVE_INFINITY);
+
+test_computed_value_greater_or_lower_than("margin-left", "calc(-infinity * 1%)", APPROX_NEGATIVE_INFINITY);
+test_computed_value_greater_or_lower_than("margin-left", "calc(max(10000px, 0px) + min(-infinity * 1px, infinity * 1px))", APPROX_NEGATIVE_INFINITY);
+
+test_computed_value_greater_or_lower_than("margin-left", "calc(-infinity * 1px - infinity * 1px)", APPROX_NEGATIVE_INFINITY);
+test_computed_value_greater_or_lower_than("margin-left", "calc(min(-infinity * 1px, 10px))", APPROX_NEGATIVE_INFINITY);
+
+// For <time>
+test_computed_value_greater_or_lower_than("animation-duration", "calc(NaN * 1s)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("animation-duration", "calc(infinity * 1s)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("animation-duration", "calc(1 / 0 * 1s)", APPROX_INFINITY);
+test_computed_value_greater_or_lower_than("animation-duration", "calc(max(infinity * 1s, 10s)", APPROX_INFINITY);
+
+test_computed_value_greater_or_lower_than("transition-delay", "calc(-infinity* 1s)", APPROX_NEGATIVE_INFINITY);
+test_computed_value_greater_or_lower_than("transition-delay", "calc(max(10000s, 0s) + min(-infinity * 1s, infinity * 1s))", APPROX_NEGATIVE_INFINITY);
+test_computed_value_greater_or_lower_than("transition-delay", "calc(min(-infinity * 1s, 10s))", APPROX_NEGATIVE_INFINITY);
+
+// For <angle>
+compareValueCloseTo("transform", "rotate(calc(infinity * 1deg))", 0.0001, "rotate(0deg)" );
+compareValueCloseTo("transform", "rotate(calc(-infinity * 1deg))", 0.0001, "rotate(0deg)");
+compareValueCloseTo("transform", "rotate(calc(NaN * 1deg))", 0.0001, "rotate(0deg)");
+
+compareValueCloseTo("transform", "rotate(calc(infinity * 1turn))", 0.0001, "rotate(0turn)" );
+compareValueCloseTo("transform", "rotate(calc(-infinity * 1turn))", 0.0001, "rotate(0turn)");
+compareValueCloseTo("transform", "rotate(calc(NaN * 1turn))", 0.0001, "rotate(0turn)");
+
+compareValueCloseTo("transform", "rotate(calc(infinity * 1rad))", 0.0001, "rotate(0rad)" );
+compareValueCloseTo("transform", "rotate(calc(-infinity * 1rad))", 0.0001, "rotate(0rad)");
+compareValueCloseTo("transform", "rotate(calc(NaN * 1rad))", 0.0001, "rotate(0rad)");
+
+compareValueCloseTo("transform", "rotate(calc(infinity * 1grad))", 0.0001, "rotate(0grad)" );
+compareValueCloseTo("transform", "rotate(calc(-infinity * 1grad))", 0.0001, "rotate(0grad)");
+compareValueCloseTo("transform", "rotate(calc(NaN * 1grad))", 0.0001, "rotate(0grad)");
+
+</script>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt (291910 => 291911)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function-expected.txt	2022-03-26 01:45:25 UTC (rev 291911)
@@ -35,16 +35,11 @@
 PASS round(13px, -10px) should be used-value-equivalent to 10px
 PASS round(-13px, -10px) should be used-value-equivalent to -10px
 PASS round(-18px, -10px) should be used-value-equivalent to -20px
-PASS round(5, 0) should be used-value-equivalent to calc(NaN)
-PASS calc(-1 * round(5, 0)) should be used-value-equivalent to calc(NaN)
-PASS round(infinity, infinity) should be used-value-equivalent to calc(NaN)
-PASS calc(-1 * round(infinity, infinity)) should be used-value-equivalent to calc(NaN)
-PASS round(infinity, -infinity) should be used-value-equivalent to calc(NaN)
-PASS calc(-1 * round(infinity, -infinity)) should be used-value-equivalent to calc(NaN)
-PASS round(-infinity, infinity) should be used-value-equivalent to calc(NaN)
-PASS calc(-1 * round(-infinity, infinity)) should be used-value-equivalent to calc(NaN)
-PASS round(-infinity, -infinity) should be used-value-equivalent to calc(NaN)
-PASS calc(-1 * round(-infinity, -infinity)) should be used-value-equivalent to calc(NaN)
+PASS round(5, 0) should be used-value-equivalent to calc(infinity)
+PASS round(infinity, infinity) should be used-value-equivalent to calc(infinity)
+PASS round(infinity, -infinity) should be used-value-equivalent to calc(infinity)
+PASS round(-infinity, infinity) should be used-value-equivalent to calc(infinity)
+PASS round(-infinity, -infinity) should be used-value-equivalent to calc(infinity)
 PASS round(infinity, 5) should be used-value-equivalent to calc(infinity)
 PASS round(infinity, -5) should be used-value-equivalent to calc(infinity)
 PASS round(-infinity, 5) should be used-value-equivalent to calc(-infinity)

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function.html (291910 => 291911)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function.html	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-values/round-function.html	2022-03-26 01:45:25 UTC (rev 291911)
@@ -61,12 +61,12 @@
 // Extreme cases:
 
 // 0 step is NaN
-test_nan("round(5, 0)");
+test_plus_infinity("round(5, 0)");
 // both infinite is NaN
-test_nan("round(infinity, infinity)");
-test_nan("round(infinity, -infinity)");
-test_nan("round(-infinity, infinity)");
-test_nan("round(-infinity, -infinity)");
+test_plus_infinity("round(infinity, infinity)");
+test_plus_infinity("round(infinity, -infinity)");
+test_plus_infinity("round(-infinity, infinity)");
+test_plus_infinity("round(-infinity, -infinity)");
 
 // infinite value with finite step is the same infinity
 test_plus_infinity("round(infinity, 5)");

Modified: trunk/Source/WebCore/ChangeLog (291910 => 291911)


--- trunk/Source/WebCore/ChangeLog	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/Source/WebCore/ChangeLog	2022-03-26 01:45:25 UTC (rev 291911)
@@ -1,3 +1,21 @@
+2022-03-25  Nikolaos Mouchtaris  <[email protected]>
+
+        Incorrect handling of NaN inside calc() for top-level calculation
+        https://bugs.webkit.org/show_bug.cgi?id=234176
+
+        Reviewed by Simon Fraser.
+
+        Add function to convert any top level NaN values to infinity values as per the spec.
+        This only affects the computed value of the calc _expression_, not its serialization.
+
+        Test: imported/w3c/web-platform-tests/css/css-values/calc-infinity-nan-computed.html
+
+        * css/calc/CSSCalcOperationNode.cpp:
+        (WebCore::CSSCalcOperationNode::combineChildren):
+        (WebCore::convertToTopLevelValue):
+        (WebCore::CSSCalcOperationNode::evaluateOperator):
+        * css/calc/CSSCalcOperationNode.h:
+
 2022-03-25  Chris Dumez  <[email protected]>
 
         Use StringView::split() instead of String::split() in more places

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp (291910 => 291911)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.cpp	2022-03-26 01:45:25 UTC (rev 291911)
@@ -623,7 +623,8 @@
 {
     if (isIdentity() || !m_children.size())
         return;
-
+    m_isRoot = IsRoot::No;
+    
     if (m_children.size() < 2) {
         if (m_children.size() == 1 && isTrigNode()) {
             double resolvedValue = doubleValue(m_children[0]->primitiveType());

Modified: trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h (291910 => 291911)


--- trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2022-03-26 01:38:42 UTC (rev 291910)
+++ trunk/Source/WebCore/css/calc/CSSCalcOperationNode.h	2022-03-26 01:45:25 UTC (rev 291911)
@@ -33,6 +33,8 @@
 class CSSCalcOperationNode final : public CSSCalcExpressionNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    enum class IsRoot : bool { No, Yes };
+    
     static RefPtr<CSSCalcOperationNode> create(CalcOperator, RefPtr<CSSCalcExpressionNode>&& leftSide, RefPtr<CSSCalcExpressionNode>&& rightSide);
     static RefPtr<CSSCalcOperationNode> createSum(Vector<Ref<CSSCalcExpressionNode>>&& values);
     static RefPtr<CSSCalcOperationNode> createProduct(Vector<Ref<CSSCalcExpressionNode>>&& values);
@@ -125,10 +127,18 @@
             return &rightSide;
         return nullptr;
     }
-
+    
+    static double convertToTopLevelValue(double value)
+    {
+        if (isnan(value))
+            value = std::numeric_limits<double>::infinity();
+        return value;
+    }
+    
     double evaluate(const Vector<double>& children) const
     {
-        return evaluateOperator(m_operator, children);
+        auto result = evaluateOperator(m_operator, children);
+        return m_isRoot == IsRoot::No ? result : convertToTopLevelValue(result);
     }
 
     static double evaluateOperator(CalcOperator, const Vector<double>&);
@@ -144,6 +154,7 @@
     CalcOperator m_operator;
     Vector<Ref<CSSCalcExpressionNode>> m_children;
     bool m_allowsNegativePercentageReference = false;
+    IsRoot m_isRoot = IsRoot::Yes;
 };
 
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to