webdriver: Search ancestors instead of preceding nodes when computing container for option&optgroup (#38491)

Fix the bug from 6 years ago https://github.com/servo/servo/pull/24090.

According to [spec](https://w3c.github.io/webdriver/#dfn-container), we
should search ancestor instead of preceding nodes (which is reverse
order of pre-order DFS and can end up weird places) when computing
container for `option`&`optgroup`.


Testing: Update WPT.
Fixes: https://github.com/servo/servo/pull/36467#discussion_r2255834497.

---------

Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
This commit is contained in:
Euclid Ye 2025-08-06 16:54:45 +08:00 committed by GitHub
parent 17a269a8ad
commit 98522db8be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 43 additions and 67 deletions

View file

@ -44,7 +44,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputE
use crate::dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::{GetRootNodeOptions, NodeMethods};
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::Bindings::XMLSerializerBinding::XMLSerializerMethods;
use crate::dom::bindings::codegen::Bindings::XPathResultBinding::{
@ -1781,14 +1781,17 @@ fn get_option_parent(node: &Node) -> Option<DomRoot<Element>> {
// > reverse order from element, or undefined if the root of the tree is reached.
// > 3. If datalist parent is undefined, the element context is select parent.
// > Otherwise, the element context is datalist parent.
let root_node = node.GetRootNode(&GetRootNodeOptions::empty());
node.preceding_nodes(&root_node)
.find(|preceding| preceding.is::<HTMLDataListElement>())
.or_else(|| {
node.preceding_nodes(&root_node)
.find(|preceding| preceding.is::<HTMLSelectElement>())
})
.map(|result_node| DomRoot::downcast::<Element>(result_node).unwrap())
let mut candidate_select = None;
for ancestor in node.ancestors() {
if ancestor.is::<HTMLDataListElement>() {
return Some(DomRoot::downcast::<Element>(ancestor).unwrap());
} else if candidate_select.is_none() && ancestor.is::<HTMLSelectElement>() {
candidate_select = Some(ancestor);
}
}
candidate_select.map(|ancestor| DomRoot::downcast::<Element>(ancestor).unwrap())
}
/// <https://w3c.github.io/webdriver/#dfn-container>

View file

@ -1,6 +1,6 @@
[add.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_cookie_unsupported_scheme[about\]]
expected: FAIL

View file

@ -1,3 +1,3 @@
[delete.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,3 +1,3 @@
[click.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -8,9 +8,6 @@
[test_input_append]
expected: FAIL
[test_textarea_append]
expected: FAIL
[test_input_insert_when_focused]
expected: FAIL

View file

@ -16,3 +16,6 @@
[test_transparent_element]
expected: FAIL
[test_obscured_element]
expected: FAIL

View file

@ -1,3 +1,3 @@
[find.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,6 +1,6 @@
[find.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_parent_htmldocument]
expected: FAIL

View file

@ -10,6 +10,3 @@
[test_seen_nodes[https coop\]]
expected: FAIL
[test_removed_iframe]
expected: FAIL

View file

@ -1,3 +1,6 @@
[get.py]
[test_get_confirm_text]
expected: FAIL
[test_get_prompt_text]
expected: FAIL

View file

@ -1,6 +1,6 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_computed_roles[<article>foo</article>-article-article\]]
expected: FAIL

View file

@ -0,0 +1,3 @@
[file.py]
[test_get_current_url_file_protocol]
expected: ERROR

View file

@ -1,3 +0,0 @@
[get.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,3 +1,3 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,6 +1,6 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_web_reference[shadowRoot-ShadowRoot\]]
expected: FAIL

View file

@ -1,3 +1,3 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,3 +1,3 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,6 +1,6 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_get_element_tag_name]
expected: FAIL

View file

@ -1,6 +1,6 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_shadow_root_slot[custom outside\]]
expected: FAIL

View file

@ -1,6 +1,6 @@
[get.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_get_named_session_cookie]
expected: FAIL

View file

@ -1,3 +1,3 @@
[source.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,3 +0,0 @@
[get.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,3 +0,0 @@
[get.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,3 +0,0 @@
[get.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,6 +1,6 @@
[enabled.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_option_with_select[disabled\]]
expected: FAIL

View file

@ -10,6 +10,3 @@
[test_maximize_twice_is_idempotent]
expected: FAIL
[test_no_browsing_context]
expected: ERROR

View file

@ -3,7 +3,7 @@
expected: FAIL
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_response_payload]
expected: FAIL

View file

@ -1,3 +0,0 @@
[new.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,6 +1,6 @@
[key.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_key_down_closes_browsing_context]
expected: FAIL

View file

@ -1,6 +1,6 @@
[pointer_mouse.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_pointer_down_closes_browsing_context]
expected: FAIL

View file

@ -1,6 +1,6 @@
[pointer_touch.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_pointer_down_closes_browsing_context]
expected: FAIL

View file

@ -3,7 +3,7 @@
expected: FAIL
[test_no_browsing_context]
expected: ERROR
expected: FAIL
[test_html_document]
expected: FAIL

View file

@ -1,3 +1,3 @@
[release.py]
[test_no_browsing_context]
expected: ERROR
expected: FAIL

View file

@ -1,12 +1,9 @@
[switch.py]
[test_no_browsing_context[0\]]
expected: ERROR
expected: FAIL
[test_no_browsing_context[id2\]]
expected: FAIL
[test_find_element_while_frame_is_still_loading]
expected: FAIL
[test_no_browsing_context[None\]]
expected: ERROR

View file

@ -1,3 +0,0 @@
[switch.py]
[test_no_browsing_context]
expected: FAIL

View file

@ -1,3 +0,0 @@
[screenshot.py]
[test_no_browsing_context]
expected: ERROR

View file

@ -1,3 +0,0 @@
[screenshot.py]
[test_no_browsing_context]
expected: ERROR