LibWeb: Ensure selected options collection is created prior to access

This commit is contained in:
Tim Ledbetter 2025-02-06 11:14:55 +00:00 committed by Tim Flynn
commit 8b2de413ae
Notes: github-actions[bot] 2025-02-08 12:33:22 +00:00
4 changed files with 111 additions and 1 deletions

View file

@ -718,7 +718,8 @@ bool HTMLSelectElement::suffering_from_being_missing() const
// If the element has its required attribute specified, and either none of the option elements in the select element's list of options have their selectedness
// set to true, or the only option element in the select element's list of options with its selectedness set to true is the placeholder label option, then the element is suffering from being
// missing.
return has_attribute(HTML::AttributeNames::required) && (m_selected_options->length() == 0 || (m_selected_options->length() == 1 && m_selected_options->item(0) == placeholder_label_option()));
auto selected_options = this->selected_options();
return has_attribute(HTML::AttributeNames::required) && (selected_options->length() == 0 || (selected_options->length() == 1 && selected_options->item(0) == placeholder_label_option()));
}
}

View file

@ -43,6 +43,7 @@ public:
void remove(WebIDL::Long);
GC::Ref<DOM::HTMLCollection> selected_options();
GC::Ref<DOM::HTMLCollection> selected_options() const { return const_cast<HTMLSelectElement*>(this)->selected_options(); }
WebIDL::Long selected_index() const;
void set_selected_index(WebIDL::Long);

View file

@ -0,0 +1,35 @@
Harness status: OK
Found 29 tests
28 Pass
1 Fail
Pass Element.closest with context node 'test12' and selector 'select'
Pass Element.closest with context node 'test13' and selector 'fieldset'
Pass Element.closest with context node 'test13' and selector 'div'
Pass Element.closest with context node 'test3' and selector 'body'
Pass Element.closest with context node 'test4' and selector '[default]'
Pass Element.closest with context node 'test4' and selector '[selected]'
Pass Element.closest with context node 'test11' and selector '[selected]'
Pass Element.closest with context node 'test12' and selector '[name="form-a"]'
Pass Element.closest with context node 'test13' and selector 'form[name="form-a"]'
Pass Element.closest with context node 'test9' and selector 'input[required]'
Pass Element.closest with context node 'test9' and selector 'select[required]'
Pass Element.closest with context node 'test13' and selector 'div:not(.div1)'
Pass Element.closest with context node 'test6' and selector 'div.div3'
Pass Element.closest with context node 'test1' and selector 'div#test7'
Pass Element.closest with context node 'test12' and selector '.div3 > .div2'
Pass Element.closest with context node 'test12' and selector '.div3 > .div1'
Pass Element.closest with context node 'test9' and selector 'form > input[required]'
Pass Element.closest with context node 'test12' and selector 'fieldset > select[required]'
Pass Element.closest with context node 'test6' and selector 'input + fieldset'
Pass Element.closest with context node 'test3' and selector 'form + form'
Pass Element.closest with context node 'test5' and selector 'form + form'
Pass Element.closest with context node 'test10' and selector ':empty'
Pass Element.closest with context node 'test11' and selector ':last-child'
Pass Element.closest with context node 'test12' and selector ':first-child'
Pass Element.closest with context node 'test11' and selector ':invalid'
Pass Element.closest with context node 'test4' and selector ':scope'
Pass Element.closest with context node 'test4' and selector 'select > :scope'
Pass Element.closest with context node 'test4' and selector 'div > :scope'
Fail Element.closest with context node 'test4' and selector ':has(> :scope)'

View file

@ -0,0 +1,73 @@
<!DOCTYPE HTML>
<meta charset=utf8>
<title>Test for Element.closest</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<body id="body">
<div id="test8" class="div3" style="display:none">
<div id="test7" class="div2">
<div id="test6" class="div1">
<form id="test10" class="form2"></form>
<form id="test5" class="form1" name="form-a">
<input id="test1" class="input1" required>
<fieldset class="fieldset2" id="test2">
<select id="test3" class="select1" required>
<option default id="test4" value="">Test4</option>
<option selected id="test11">Test11</option>
<option id="test12">Test12</option>
<option id="test13">Test13</option>
</select>
<input id="test9" type="text" required>
</fieldset>
</form>
</div>
</div>
</div>
<div id=log></div>
<script>
do_test("select" , "test12", "test3");
do_test("fieldset" , "test13", "test2");
do_test("div" , "test13", "test6");
do_test("body" , "test3" , "body");
do_test("[default]" , "test4" , "test4");
do_test("[selected]" , "test4" , "");
do_test("[selected]" , "test11", "test11");
do_test('[name="form-a"]' , "test12", "test5");
do_test('form[name="form-a"]' , "test13", "test5");
do_test("input[required]" , "test9" , "test9");
do_test("select[required]" , "test9" , "");
do_test("div:not(.div1)" , "test13", "test7");
do_test("div.div3" , "test6" , "test8");
do_test("div#test7" , "test1" , "test7");
do_test(".div3 > .div2" , "test12", "test7");
do_test(".div3 > .div1" , "test12", "");
do_test("form > input[required]" , "test9" , "");
do_test("fieldset > select[required]", "test12", "test3");
do_test("input + fieldset" , "test6" , "");
do_test("form + form" , "test3" , "test5");
do_test("form + form" , "test5" , "test5");
do_test(":empty" , "test10", "test10");
do_test(":last-child" , "test11", "test2");
do_test(":first-child" , "test12", "test3");
do_test(":invalid" , "test11", "test2");
do_test(":scope" , "test4", "test4");
do_test("select > :scope" , "test4", "test4");
do_test("div > :scope" , "test4", "");
do_test(":has(> :scope)" , "test4", "test3");
function do_test(aSelector, aElementId, aTargetId) {
test(function() {
var el = document.getElementById(aElementId).closest(aSelector);
if (el === null) {
assert_equals("", aTargetId, aSelector);
} else {
assert_equals(el.id, aTargetId, aSelector);
}
}, "Element.closest with context node '" + aElementId + "' and selector '" + aSelector + "'");
}
</script>