diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index 2f127d73b79..708a284e607 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -25,6 +25,7 @@ use net_traits::CoreResourceMsg::{ DeleteCookie, DeleteCookies, GetCookiesDataForUrl, SetCookieForUrl, }; use net_traits::IpcSend; +use script_bindings::codegen::GenericBindings::ShadowRootBinding::ShadowRootMethods; use script_bindings::conversions::is_array_like; use servo_url::ServoUrl; use webdriver::common::{WebElement, WebFrame, WebWindow}; @@ -64,6 +65,7 @@ use crate::dom::htmloptionelement::HTMLOptionElement; use crate::dom::htmlselectelement::HTMLSelectElement; use crate::dom::node::{Node, NodeTraits, ShadowIncluding}; use crate::dom::nodelist::NodeList; +use crate::dom::types::ShadowRoot; use crate::dom::window::Window; use crate::dom::xmlserializer::XMLSerializer; 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_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)] +/// +fn get_known_shadow_root( + documents: &DocumentCollection, + pipeline: PipelineId, + node_id: String, +) -> Result, 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::() { + 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::(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) +} + /// fn get_known_element( documents: &DocumentCollection, @@ -79,11 +136,10 @@ fn get_known_element( ) -> Result, ErrorStatus> { let doc = documents .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, // and reference return error with error code no such element. 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); } // 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. - if node.is_none() { + let Some(node) = node else { return Err(ErrorStatus::StaleElementReference); - } + }; // 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 - // or if it is not connected. - let element = DomRoot::from_ref(node.unwrap().downcast::().unwrap()); - if !element.owner_document().is_active() || !element.is_connected() { + let element = DomRoot::downcast::(node).unwrap(); + if is_stale(&element) { return Err(ErrorStatus::StaleElementReference); } // Step 5. Return success with data node.