Explorar o código

LibWeb: Cast to the correct type in `Element::auto_directionality()`

Previously, we always cast to a HTMLInputElement when getting the value
of an auto directionality form associated element. This caused
undefined behavior when determining the directionality of an element
that wasn't a HTMLInputElement.
Tim Ledbetter hai 1 ano
pai
achega
d6297ec074

+ 30 - 0
Tests/LibWeb/Text/expected/css/dir-pseudo-on-form-associated-element.txt

@@ -0,0 +1,30 @@
+Testing input element with type=text
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): false
+Input matches :dir(rtl): true
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): false
+Input matches :dir(rtl): true
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Testing textarea element
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): false
+Input matches :dir(rtl): true
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): false
+Input matches :dir(rtl): true
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false
+Input matches :dir(ltr): true
+Input matches :dir(rtl): false

+ 0 - 14
Tests/LibWeb/Text/expected/css/dir-pseudo-on-input-element.txt

@@ -1,14 +0,0 @@
-Input matches :dir(ltr): true
-Input matches :dir(rtl): false
-Input matches :dir(ltr): true
-Input matches :dir(rtl): false
-Input matches :dir(ltr): false
-Input matches :dir(rtl): true
-Input matches :dir(ltr): true
-Input matches :dir(rtl): false
-Input matches :dir(ltr): false
-Input matches :dir(rtl): true
-Input matches :dir(ltr): true
-Input matches :dir(rtl): false
-Input matches :dir(ltr): true
-Input matches :dir(rtl): false

+ 53 - 0
Tests/LibWeb/Text/input/css/dir-pseudo-on-form-associated-element.html

@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<style>
+    .test {
+        font-size: 12px;
+    }
+</style>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        function testSelectorMatch(input, selector) {
+            println(`Input matches ${selector}: ${input.matches(selector)}`);
+        }
+
+        function testElementDirectionality(element) {
+            element.value = "Well hello friends!"
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.dir = "invalid";
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.dir = "rtl";
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.dir = "auto"
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.value = "حسنًا ، مرحباً أيها الأصدقاء";
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.dir = "ltr"
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+
+            element.removeAttribute("dir");
+            testSelectorMatch(element, ":dir(ltr)");
+            testSelectorMatch(element, ":dir(rtl)");
+        }
+        
+        println("Testing input element with type=text");
+        const textInput = document.createElement("input");
+        textInput.type = "text";
+        testElementDirectionality(textInput);
+        
+        println("Testing textarea element");
+        const textAreaElement = document.createElement("textarea");
+        testElementDirectionality(textAreaElement);
+    });
+</script>

+ 0 - 44
Tests/LibWeb/Text/input/css/dir-pseudo-on-input-element.html

@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<style>
-    .test {
-        font-size: 12px;
-    }
-</style>
-<script src="../include.js"></script>
-<script>
-    test(() => {
-        function testSelectorMatch(input, selector) {
-            println(`Input matches ${selector}: ${input.matches(selector)}`);
-        }
-
-        const input = document.createElement("input");
-        input.type = "text";
-        input.value = "Well hello friends!"
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.dir = "invalid";
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.dir = "rtl";
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.dir = "auto"
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.value = "حسنًا ، مرحباً أيها الأصدقاء";
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.dir = "ltr"
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-
-        input.removeAttribute("dir");
-        testSelectorMatch(input, ":dir(ltr)");
-        testSelectorMatch(input, ":dir(rtl)");
-    });
-</script>

+ 3 - 1
Userland/Libraries/LibWeb/DOM/Element.cpp

@@ -2373,7 +2373,9 @@ Optional<Element::Directionality> Element::auto_directionality() const
 
 
     // 1. If element is an auto-directionality form-associated element:
     // 1. If element is an auto-directionality form-associated element:
     if (is_auto_directionality_form_associated_element()) {
     if (is_auto_directionality_form_associated_element()) {
-        auto const& value = static_cast<HTML::HTMLInputElement const&>(*this).value();
+        auto const* form_associated_element = dynamic_cast<HTML::FormAssociatedElement const*>(this);
+        VERIFY(form_associated_element);
+        auto const& value = form_associated_element->value();
 
 
         // 1. If element's value contains a character of bidirectional character type AL or R,
         // 1. If element's value contains a character of bidirectional character type AL or R,
         //    and there is no character of bidirectional character type L anywhere before it in the element's value, then return 'rtl'.
         //    and there is no character of bidirectional character type L anywhere before it in the element's value, then return 'rtl'.