瀏覽代碼

LibWeb: Handle calculations without a context better

stelar7 9 月之前
父節點
當前提交
4408ea7c9b

+ 1 - 0
Tests/LibWeb/Text/expected/css/calc-missing-context.txt

@@ -0,0 +1 @@
+NO CRASH

+ 15 - 0
Tests/LibWeb/Text/input/css/calc-missing-context.html

@@ -0,0 +1,15 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        const testElement = document.getElementById('target');
+        testElement.style = "";
+
+        testElement.style.transform = 'rotate(atan2(1rem, -1rem))';
+
+        getComputedStyle(testElement).transform;
+
+        println("NO CRASH");
+
+    });
+</script>
+<div id="target"></div>

+ 4 - 1
Userland/Libraries/LibWeb/CSS/Length.h

@@ -178,11 +178,14 @@ public:
     {
         if (is_auto())
             return 0;
+        if (is_absolute())
+            return absolute_length_to_px();
         if (is_font_relative())
             return font_relative_length_to_px(font_metrics, root_font_metrics);
         if (is_viewport_relative())
             return viewport_relative_length_to_px(viewport_rect);
-        return absolute_length_to_px();
+
+        VERIFY_NOT_REACHED();
     }
 
     ALWAYS_INLINE CSSPixels absolute_length_to_px() const

+ 21 - 2
Userland/Libraries/LibWeb/CSS/StyleValues/CSSMathValue.cpp

@@ -40,10 +40,23 @@ static double resolve_value(CSSMathValue::CalculationResult::Value value, Option
         [](Angle const& angle) { return angle.to_degrees(); },
         [](Flex const& flex) { return flex.to_fr(); },
         [](Frequency const& frequency) { return frequency.to_hertz(); },
-        [&context](Length const& length) { return length.to_px(*context).to_double(); },
         [](Percentage const& percentage) { return percentage.value(); },
         [](Resolution const& resolution) { return resolution.to_dots_per_pixel(); },
-        [](Time const& time) { return time.to_seconds(); });
+        [](Time const& time) { return time.to_seconds(); },
+        [&context](Length const& length) {
+            // Handle some common cases first, so we can resolve more without a context
+            if (length.is_auto())
+                return 0.0;
+
+            if (length.is_absolute())
+                return length.absolute_length_to_px().to_double();
+
+            // If we dont have a context, we cant resolve the length, so return NAN
+            if (!context.has_value())
+                return Number(Number::Type::Number, NAN).value();
+
+            return length.to_px(*context).to_double();
+        });
 }
 
 static Optional<CSSNumericType> add_the_types(Vector<NonnullOwnPtr<CalculationNode>> const& nodes, PropertyID property_id)
@@ -2390,6 +2403,12 @@ void CSSMathValue::CalculationResult::add_or_subtract_internal(SumOperation op,
             }
         },
         [&](Length const& length) {
+            if (!context.has_value()) {
+                dbgln("CSSMathValue::CalculationResult::add_or_subtract_internal: Length without context");
+                m_value = Length::make_px(0);
+                return;
+            }
+
             auto this_px = length.to_px(*context);
             if (other.m_value.has<Length>()) {
                 auto other_px = other.m_value.get<Length>().to_px(*context);