diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index bce6a22cc46..dcc89638e8a 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -76,6 +76,7 @@ use crate::dom::node::{NodeDamage, NodeFlags, UnbindContext}; use crate::dom::nodelist::NodeList; use crate::dom::promise::Promise; use crate::dom::servoparser::ServoParser; +use crate::dom::shadowroot::ShadowRoot; use crate::dom::text::Text; use crate::dom::validation::Validatable; use crate::dom::virtualmethods::{vtable_for, VirtualMethods}; @@ -170,6 +171,10 @@ pub struct Element { custom_element_definition: DomRefCell>>, /// custom_element_state: Cell, + /// https://dom.spec.whatwg.org/#dom-element-shadowroot + /// XXX This is currently not exposed to web content. Only for + /// internal use. + shadow_root: MutNullableDom, } impl fmt::Debug for Element { @@ -297,6 +302,7 @@ impl Element { custom_element_reaction_queue: Default::default(), custom_element_definition: Default::default(), custom_element_state: Cell::new(CustomElementState::Uncustomized), + shadow_root: Default::default(), } } @@ -436,6 +442,53 @@ impl Element { box_.clone_overflow_y() == overflow_y::computed_value::T::Hidden }) } + + fn is_shadow_host(&self) -> bool { + self.shadow_root.get().is_some() + } + + /// https://dom.spec.whatwg.org/#dom-element-attachshadow + /// XXX This is not exposed to web content yet. It is meant to be used + /// for UA widgets only. + pub fn attach_shadow(&self) -> Fallible> { + // Step 1. + if self.namespace != ns!(html) { + return Err(Error::NotSupported); + } + + // Step 2. + match self.local_name() { + &local_name!("article") | + &local_name!("aside") | + &local_name!("blockquote") | + &local_name!("body") | + &local_name!("div") | + &local_name!("footer") | + &local_name!("h1") | + &local_name!("h2") | + &local_name!("h3") | + &local_name!("h4") | + &local_name!("h5") | + &local_name!("h6") | + &local_name!("header") | + &local_name!("main") | + &local_name!("nav") | + &local_name!("p") | + &local_name!("section") | + &local_name!("span") => {}, + _ => return Err(Error::NotSupported), + }; + + // Step 3. + if self.is_shadow_host() { + return Err(Error::InvalidState); + } + + // Steps 4, 5 and 6. + Ok(self + .shadow_root + .or_init(|| ShadowRoot::new(self, &*self.node.owner_doc()))) + } } #[allow(unsafe_code)] diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index 7f21ca57ad0..c16c77f6b64 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -4,9 +4,10 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods; use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods; -use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootMode; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{self, ShadowRootMode}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::num::Finite; +use crate::dom::bindings::reflector::reflect_dom_object; use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; use crate::dom::cssstylesheet::CSSStyleSheet; use crate::dom::document::Document; @@ -35,8 +36,7 @@ pub struct ShadowRoot { } impl ShadowRoot { - #[allow(dead_code)] - pub fn new_inherited(host: &Element, document: &Document) -> ShadowRoot { + fn new_inherited(host: &Element, document: &Document) -> ShadowRoot { ShadowRoot { document_fragment: DocumentFragment::new_inherited(document), has_browsing_context: true, @@ -46,6 +46,14 @@ impl ShadowRoot { } } + pub fn new(host: &Element, document: &Document) -> DomRoot { + reflect_dom_object( + Box::new(ShadowRoot::new_inherited(host, document)), + document.window(), + ShadowRootBinding::Wrap, + ) + } + pub fn get_focused_element(&self) -> Option> { //XXX get retargeted focused element None