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.
This commit is contained in:
Tim Ledbetter 2024-05-28 06:42:08 +01:00 committed by Andreas Kling
parent 0b0ad5c9db
commit d6297ec074
5 changed files with 86 additions and 59 deletions

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -2373,7 +2373,9 @@ Optional<Element::Directionality> Element::auto_directionality() const
// 1. If element is an 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,
// and there is no character of bidirectional character type L anywhere before it in the element's value, then return 'rtl'.