aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenzie Raditya Tirtarahardja <kenzieradityatirtarahardja18@gmail.com>2025-04-16 11:54:33 +0800
committerGitHub <noreply@github.com>2025-04-16 03:54:33 +0000
commitcef7aa58ec3dc6b5e2ee729cc4b2c8a9c85fe681 (patch)
tree3e84df0332727ee777b842fb618ade3e1015b840
parentda4ea0f0965414733f0352e76ff416b1ded75a08 (diff)
downloadservo-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.rs58
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());