mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
script::webdriver_handlers: Implement "get a known shadow root" (#37546)
Implement "get a known shadow root" and reduce some duplication This is still a preparation PR to ["find element(s) from shadow root"](https://w3c.github.io/webdriver/#find-element-from-shadow-root) Testing: No Behaviour change. --------- Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
This commit is contained in:
parent
ed9a79f3f4
commit
212ce933e5
1 changed files with 62 additions and 8 deletions
|
@ -25,6 +25,7 @@ use net_traits::CoreResourceMsg::{
|
||||||
DeleteCookie, DeleteCookies, GetCookiesDataForUrl, SetCookieForUrl,
|
DeleteCookie, DeleteCookies, GetCookiesDataForUrl, SetCookieForUrl,
|
||||||
};
|
};
|
||||||
use net_traits::IpcSend;
|
use net_traits::IpcSend;
|
||||||
|
use script_bindings::codegen::GenericBindings::ShadowRootBinding::ShadowRootMethods;
|
||||||
use script_bindings::conversions::is_array_like;
|
use script_bindings::conversions::is_array_like;
|
||||||
use servo_url::ServoUrl;
|
use servo_url::ServoUrl;
|
||||||
use webdriver::common::{WebElement, WebFrame, WebWindow};
|
use webdriver::common::{WebElement, WebFrame, WebWindow};
|
||||||
|
@ -64,6 +65,7 @@ use crate::dom::htmloptionelement::HTMLOptionElement;
|
||||||
use crate::dom::htmlselectelement::HTMLSelectElement;
|
use crate::dom::htmlselectelement::HTMLSelectElement;
|
||||||
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
|
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
|
||||||
use crate::dom::nodelist::NodeList;
|
use crate::dom::nodelist::NodeList;
|
||||||
|
use crate::dom::types::ShadowRoot;
|
||||||
use crate::dom::window::Window;
|
use crate::dom::window::Window;
|
||||||
use crate::dom::xmlserializer::XMLSerializer;
|
use crate::dom::xmlserializer::XMLSerializer;
|
||||||
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
|
use crate::realms::{AlreadyInRealm, InRealm, enter_realm};
|
||||||
|
@ -71,6 +73,61 @@ use crate::script_module::ScriptFetchOptions;
|
||||||
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
||||||
use crate::script_thread::ScriptThread;
|
use crate::script_thread::ScriptThread;
|
||||||
|
|
||||||
|
fn is_stale(element: &Element) -> bool {
|
||||||
|
// An element is stale if its node document is not the active document
|
||||||
|
// or if it is not connected.
|
||||||
|
!element.owner_document().is_active() || !element.is_connected()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-shadow-root>
|
||||||
|
fn get_known_shadow_root(
|
||||||
|
documents: &DocumentCollection,
|
||||||
|
pipeline: PipelineId,
|
||||||
|
node_id: String,
|
||||||
|
) -> Result<DomRoot<ShadowRoot>, ErrorStatus> {
|
||||||
|
let doc = documents
|
||||||
|
.find_document(pipeline)
|
||||||
|
.ok_or(ErrorStatus::NoSuchWindow)?;
|
||||||
|
// Step 1. If not node reference is known with session, session's current browsing context,
|
||||||
|
// and reference return error with error code no such shadow root.
|
||||||
|
if !ScriptThread::has_node_id(pipeline, &node_id) {
|
||||||
|
return Err(ErrorStatus::NoSuchShadowRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2. Let node be the result of get a node with session,
|
||||||
|
// session's current browsing context, and reference.
|
||||||
|
let node = find_node_by_unique_id_in_document(&doc, node_id);
|
||||||
|
|
||||||
|
// Step 3. If node is not null and node does not implement ShadowRoot
|
||||||
|
// return error with error code no such shadow root.
|
||||||
|
if let Some(ref node) = node {
|
||||||
|
if !node.is::<ShadowRoot>() {
|
||||||
|
return Err(ErrorStatus::NoSuchShadowRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.1. If node is null return error with error code detached shadow root.
|
||||||
|
let Some(node) = node else {
|
||||||
|
return Err(ErrorStatus::DetachedShadowRoot);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 4.2. If node is detached return error with error code detached shadow root.
|
||||||
|
// A shadow root is detached if its node document is not the active document
|
||||||
|
// or if the element node referred to as its host is stale.
|
||||||
|
let shadow_root = DomRoot::downcast::<ShadowRoot>(node).unwrap();
|
||||||
|
if !shadow_root.owner_document().is_active() {
|
||||||
|
return Err(ErrorStatus::DetachedShadowRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
let host = shadow_root.Host();
|
||||||
|
if is_stale(&host) {
|
||||||
|
return Err(ErrorStatus::DetachedShadowRoot);
|
||||||
|
}
|
||||||
|
// Step 5. Return success with data node.
|
||||||
|
Ok(shadow_root)
|
||||||
|
}
|
||||||
|
|
||||||
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-element>
|
/// <https://w3c.github.io/webdriver/#dfn-get-a-known-element>
|
||||||
fn get_known_element(
|
fn get_known_element(
|
||||||
documents: &DocumentCollection,
|
documents: &DocumentCollection,
|
||||||
|
@ -79,11 +136,10 @@ fn get_known_element(
|
||||||
) -> Result<DomRoot<Element>, ErrorStatus> {
|
) -> Result<DomRoot<Element>, ErrorStatus> {
|
||||||
let doc = documents
|
let doc = documents
|
||||||
.find_document(pipeline)
|
.find_document(pipeline)
|
||||||
.expect("webdriver_handlers::Document should exists");
|
.ok_or(ErrorStatus::NoSuchWindow)?;
|
||||||
// Step 1. If not node reference is known with session, session's current browsing context,
|
// Step 1. If not node reference is known with session, session's current browsing context,
|
||||||
// and reference return error with error code no such element.
|
// and reference return error with error code no such element.
|
||||||
if !ScriptThread::has_node_id(pipeline, &node_id) {
|
if !ScriptThread::has_node_id(pipeline, &node_id) {
|
||||||
// If the node is known, but not found in the document, it is stale.
|
|
||||||
return Err(ErrorStatus::NoSuchElement);
|
return Err(ErrorStatus::NoSuchElement);
|
||||||
}
|
}
|
||||||
// Step 2.Let node be the result of get a node with session,
|
// Step 2.Let node be the result of get a node with session,
|
||||||
|
@ -98,14 +154,12 @@ fn get_known_element(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Step 4.1. If node is null return error with error code stale element reference.
|
// Step 4.1. If node is null return error with error code stale element reference.
|
||||||
if node.is_none() {
|
let Some(node) = node else {
|
||||||
return Err(ErrorStatus::StaleElementReference);
|
return Err(ErrorStatus::StaleElementReference);
|
||||||
}
|
};
|
||||||
// Step 4.2. If node is stale return error with error code stale element reference.
|
// Step 4.2. If node is stale return error with error code stale element reference.
|
||||||
// An element is stale if its node document is not the active document
|
let element = DomRoot::downcast::<Element>(node).unwrap();
|
||||||
// or if it is not connected.
|
if is_stale(&element) {
|
||||||
let element = DomRoot::from_ref(node.unwrap().downcast::<Element>().unwrap());
|
|
||||||
if !element.owner_document().is_active() || !element.is_connected() {
|
|
||||||
return Err(ErrorStatus::StaleElementReference);
|
return Err(ErrorStatus::StaleElementReference);
|
||||||
}
|
}
|
||||||
// Step 5. Return success with data node.
|
// Step 5. Return success with data node.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue