diff options
author | Kenzie Raditya Tirtarahardja <kenzieradityatirtarahardja18@gmail.com> | 2025-04-16 11:54:33 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-16 03:54:33 +0000 |
commit | cef7aa58ec3dc6b5e2ee729cc4b2c8a9c85fe681 (patch) | |
tree | 3e84df0332727ee777b842fb618ade3e1015b840 | |
parent | da4ea0f0965414733f0352e76ff416b1ded75a08 (diff) | |
download | servo-cef7aa58ec3dc6b5e2ee729cc4b2c8a9c85fe681.tar.gz servo-cef7aa58ec3dc6b5e2ee729cc4b2c8a9c85fe681.zip |
Refactor retrieving element container in webdriver into function (#36467)
Refactor getting an element's container. Previously this is inlined and
only done for `HTMLOptionElement`.
[Try](https://github.com/PotatoCP/servo/actions/runs/14399482275)
Fixes: #24106
Signed-off-by: Kenzie Raditya Tirtarahardja <kenzieradityatirtarahardja.18@gmail.com>
Co-authored-by: Kenzie Raditya Tirtarahardja <kenzieradityatirtarahardja.18@gmail.com>
-rw-r--r-- | components/script/webdriver_handlers.rs | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 5e7c2b6c057..ed9f9d5e0c1 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -60,6 +60,7 @@ use crate::dom::htmldatalistelement::HTMLDataListElement; use crate::dom::htmlelement::HTMLElement; use crate::dom::htmliframeelement::HTMLIFrameElement; use crate::dom::htmlinputelement::{HTMLInputElement, InputType}; +use crate::dom::htmloptgroupelement::HTMLOptGroupElement; use crate::dom::htmloptionelement::HTMLOptionElement; use crate::dom::htmlselectelement::HTMLSelectElement; use crate::dom::node::{Node, NodeTraits, ShadowIncluding}; @@ -1191,6 +1192,35 @@ pub(crate) fn handle_get_url( .unwrap(); } +fn get_option_parent(node: &Node) -> Option<DomRoot<Node>> { + // Get parent for `<option>` or `<optiongrp>` based on container spec: + // > 1. Let datalist parent be the first datalist element reached by traversing the tree + // > in reverse order from element, or undefined if the root of the tree is reached. + // > 2. Let select parent be the first select element reached by traversing the tree in + // > 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>()) + }) +} + +// https://w3c.github.io/webdriver/#dfn-container +fn get_container(node: &Node) -> Option<DomRoot<Node>> { + if node.is::<HTMLOptionElement>() { + return get_option_parent(node); + } + if node.is::<HTMLOptGroupElement>() { + let option_parent = get_option_parent(node); + return option_parent.or_else(|| Some(DomRoot::from_ref(node))); + } + Some(DomRoot::from_ref(node)) +} + // https://w3c.github.io/webdriver/#element-click pub(crate) fn handle_element_click( documents: &DocumentCollection, @@ -1210,6 +1240,10 @@ pub(crate) fn handle_element_click( } } + let Some(container) = get_container(&node) else { + return Err(ErrorStatus::UnknownError); + }; + // Step 5 // TODO: scroll into view @@ -1222,32 +1256,14 @@ pub(crate) fn handle_element_click( // Step 8 match node.downcast::<HTMLOptionElement>() { Some(option_element) => { - // https://w3c.github.io/webdriver/#dfn-container - let root_node = node.GetRootNode(&GetRootNodeOptions::empty()); - let datalist_parent = node - .preceding_nodes(&root_node) - .find(|preceding| preceding.is::<HTMLDataListElement>()); - let select_parent = node - .preceding_nodes(&root_node) - .find(|preceding| preceding.is::<HTMLSelectElement>()); - - // Step 8.1 - let parent_node = match datalist_parent { - Some(datalist_parent) => datalist_parent, - None => match select_parent { - Some(select_parent) => select_parent, - None => return Err(ErrorStatus::UnknownError), - }, - }; - // Steps 8.2 - 8.4 - let event_target = parent_node.upcast::<EventTarget>(); + let event_target = container.upcast::<EventTarget>(); event_target.fire_event(atom!("mouseover"), can_gc); event_target.fire_event(atom!("mousemove"), can_gc); event_target.fire_event(atom!("mousedown"), can_gc); // Step 8.5 - match parent_node.downcast::<HTMLElement>() { + match container.downcast::<HTMLElement>() { Some(html_element) => html_element.Focus(can_gc), None => return Err(ErrorStatus::UnknownError), } @@ -1261,7 +1277,7 @@ pub(crate) fn handle_element_click( let previous_selectedness = option_element.Selected(); // Step 8.6.3 - match parent_node.downcast::<HTMLSelectElement>() { + match container.downcast::<HTMLSelectElement>() { Some(select_element) => { if select_element.Multiple() { option_element.SetSelected(!option_element.Selected()); |