diff --git a/components/script/dom/documentfragment.rs b/components/script/dom/documentfragment.rs index 2e504750947..00718d0534d 100644 --- a/components/script/dom/documentfragment.rs +++ b/components/script/dom/documentfragment.rs @@ -27,7 +27,7 @@ pub struct DocumentFragment { impl DocumentFragment { /// Creates a new DocumentFragment. - fn new_inherited(document: &Document) -> DocumentFragment { + pub fn new_inherited(document: &Document) -> DocumentFragment { DocumentFragment { node: Node::new_inherited(document), } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index c3d5fbb55d0..bce6a22cc46 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -2372,7 +2372,7 @@ impl ElementMethods for Element { NodeTypeId::Document(_) => return Err(Error::NoModificationAllowed), // Step 4. - NodeTypeId::DocumentFragment => { + NodeTypeId::DocumentFragment(_) => { let body_elem = Element::create( QualName::new(None, ns!(html), local_name!("body")), None, diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 813f4659a08..17d55d3c3a3 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -454,6 +454,7 @@ pub mod serviceworkercontainer; pub mod serviceworkerglobalscope; pub mod serviceworkerregistration; pub mod servoparser; +pub mod shadowroot; pub mod storage; pub mod storageevent; pub mod stylepropertymapreadonly; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 3331686eef4..a015324b449 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -14,6 +14,7 @@ use crate::dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMe use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; +use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; use crate::dom::bindings::conversions::{self, DerivedFrom}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; @@ -1559,7 +1560,7 @@ impl Node { ) -> ErrorResult { // Step 1. match parent.type_id() { - NodeTypeId::Document(_) | NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => (), + NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (), _ => return Err(Error::HierarchyRequest), } @@ -1587,7 +1588,7 @@ impl Node { return Err(Error::HierarchyRequest); } }, - NodeTypeId::DocumentFragment | + NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(_) | NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) | NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (), @@ -1598,7 +1599,7 @@ impl Node { if parent.is::() { match node.type_id() { // Step 6.1 - NodeTypeId::DocumentFragment => { + NodeTypeId::DocumentFragment(_) => { // Step 6.1.1(b) if node.children().any(|c| c.is::()) { return Err(Error::HierarchyRequest); @@ -1723,7 +1724,7 @@ impl Node { } } rooted_vec!(let mut new_nodes); - let new_nodes = if let NodeTypeId::DocumentFragment = node.type_id() { + let new_nodes = if let NodeTypeId::DocumentFragment(_) = node.type_id() { // Step 3. new_nodes.extend(node.children().map(|kid| Dom::from_ref(&*kid))); // Step 4. @@ -1809,7 +1810,7 @@ impl Node { // Step 3. rooted_vec!(let mut added_nodes); let added_nodes = if let Some(node) = node.as_ref() { - if let NodeTypeId::DocumentFragment = node.type_id() { + if let NodeTypeId::DocumentFragment(_) = node.type_id() { added_nodes.extend(node.children().map(|child| Dom::from_ref(&*child))); added_nodes.r() } else { @@ -1935,7 +1936,7 @@ impl Node { ); DomRoot::upcast::(doctype) }, - NodeTypeId::DocumentFragment => { + NodeTypeId::DocumentFragment(_) => { let doc_fragment = DocumentFragment::new(&document); DomRoot::upcast::(doc_fragment) }, @@ -2068,7 +2069,7 @@ impl Node { .GetDocumentElement() .as_ref() .map_or(ns!(), |elem| elem.locate_namespace(prefix)), - NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => ns!(), + NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(), _ => node .GetParentElement() .as_ref() @@ -2093,7 +2094,7 @@ impl NodeMethods for Node { NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE, NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE, NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE, - NodeTypeId::DocumentFragment => NodeConstants::DOCUMENT_FRAGMENT_NODE, + NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE, NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE, } } @@ -2113,7 +2114,7 @@ impl NodeMethods for Node { }, NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"), NodeTypeId::DocumentType => self.downcast::().unwrap().name().clone(), - NodeTypeId::DocumentFragment => DOMString::from("#document-fragment"), + NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"), NodeTypeId::Document(_) => DOMString::from("#document"), } } @@ -2129,7 +2130,7 @@ impl NodeMethods for Node { NodeTypeId::CharacterData(..) | NodeTypeId::Element(..) | NodeTypeId::DocumentType | - NodeTypeId::DocumentFragment => Some(self.owner_doc()), + NodeTypeId::DocumentFragment(_) => Some(self.owner_doc()), NodeTypeId::Document(_) => None, } } @@ -2198,7 +2199,7 @@ impl NodeMethods for Node { // https://dom.spec.whatwg.org/#dom-node-textcontent fn GetTextContent(&self) -> Option { match self.type_id() { - NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => { + NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => { let content = Node::collect_text_contents(self.traverse_preorder()); Some(content) }, @@ -2214,7 +2215,7 @@ impl NodeMethods for Node { fn SetTextContent(&self, value: Option) { let value = value.unwrap_or_default(); match self.type_id() { - NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => { + NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => { // Step 1-2. let node = if value.is_empty() { None @@ -2247,7 +2248,7 @@ impl NodeMethods for Node { fn ReplaceChild(&self, node: &Node, child: &Node) -> Fallible> { // Step 1. match self.type_id() { - NodeTypeId::Document(_) | NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => (), + NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (), _ => return Err(Error::HierarchyRequest), } @@ -2277,7 +2278,7 @@ impl NodeMethods for Node { if self.is::() { match node.type_id() { // Step 6.1 - NodeTypeId::DocumentFragment => { + NodeTypeId::DocumentFragment(_) => { // Step 6.1.1(b) if node.children().any(|c| c.is::()) { return Err(Error::HierarchyRequest); @@ -2350,7 +2351,8 @@ impl NodeMethods for Node { // Step 12. rooted_vec!(let mut nodes); - let nodes = if node.type_id() == NodeTypeId::DocumentFragment { + let nodes = if node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) || + node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) { nodes.extend(node.children().map(|node| Dom::from_ref(&*node))); nodes.r() } else { @@ -2612,7 +2614,7 @@ impl NodeMethods for Node { .unwrap() .GetDocumentElement() .and_then(|element| element.lookup_prefix(namespace)), - NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => None, + NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None, _ => self .GetParentElement() .and_then(|element| element.lookup_prefix(namespace)), diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index 630c4acd245..9a1bc5db7a6 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -10,6 +10,7 @@ use crate::dom::bindings::codegen::Bindings::RangeBinding::RangeMethods; use crate::dom::bindings::codegen::Bindings::RangeBinding::{self, RangeConstants}; use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; +use crate::dom::bindings::codegen::InheritTypes::DocumentFragmentTypeId; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId}; @@ -763,7 +764,8 @@ impl RangeMethods for Range { // Step 11 let new_offset = new_offset + - if node.type_id() == NodeTypeId::DocumentFragment { + if node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::DocumentFragment) || + node.type_id() == NodeTypeId::DocumentFragment(DocumentFragmentTypeId::ShadowRoot) { node.len() } else { 1 @@ -878,7 +880,7 @@ impl RangeMethods for Range { // Step 2. match new_parent.type_id() { - NodeTypeId::Document(_) | NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => { + NodeTypeId::Document(_) | NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => { return Err(Error::InvalidNodeType); }, _ => (), @@ -954,7 +956,7 @@ impl RangeMethods for Range { let node = self.StartContainer(); let owner_doc = node.owner_doc(); let element = match node.type_id() { - NodeTypeId::Document(_) | NodeTypeId::DocumentFragment => None, + NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) => None, NodeTypeId::Element(_) => Some(DomRoot::downcast::(node).unwrap()), NodeTypeId::CharacterData(CharacterDataTypeId::Comment) | NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(), diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index 965982d8b51..c9e3a06f34f 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -249,7 +249,7 @@ impl<'a> Serialize for &'a Node { serializer.write_processing_instruction(&pi.target(), &data)?; }, - NodeTypeId::DocumentFragment => {}, + NodeTypeId::DocumentFragment(_) => {}, NodeTypeId::Document(_) => panic!("Can't serialize Document node itself"), NodeTypeId::Element(_) => panic!("Element shouldn't appear here"), diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs new file mode 100644 index 00000000000..bb3b646a9d2 --- /dev/null +++ b/components/script/dom/shadowroot.rs @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use crate::dom::documentfragment::DocumentFragment; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootBinding::ShadowRootMethods; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootMode; +use crate::dom::bindings::root::{Dom, DomRoot}; +use crate::dom::document::Document; +use crate::dom::element::Element; +use dom_struct::dom_struct; + +// https://dom.spec.whatwg.org/#interface-shadowroot +#[dom_struct] +pub struct ShadowRoot { + document_fragment: DocumentFragment, + host: Dom, +} + +impl ShadowRoot { + #[allow(dead_code)] + pub fn new_inherited(host: &Element, document: &Document) -> ShadowRoot { + ShadowRoot { + document_fragment: DocumentFragment::new_inherited(document), + host: Dom::from_ref(host), + } + } +} + +impl ShadowRootMethods for ShadowRoot { + /// https://dom.spec.whatwg.org/#dom-shadowroot-mode + fn Mode(&self) -> ShadowRootMode { + ShadowRootMode::Closed + } + + /// https://dom.spec.whatwg.org/#dom-shadowroot-host + fn Host(&self) -> DomRoot { + DomRoot::from_ref(&self.host) + } +} diff --git a/components/script/dom/webidls/ShadowRoot.webidl b/components/script/dom/webidls/ShadowRoot.webidl new file mode 100644 index 00000000000..f8372bdb6cd --- /dev/null +++ b/components/script/dom/webidls/ShadowRoot.webidl @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +/* + * The origin of this IDL file is: + * https://dom.spec.whatwg.org/#interface-shadowroot + */ + +[Exposed=Window] +interface ShadowRoot : DocumentFragment { + readonly attribute ShadowRootMode mode; + readonly attribute Element host; +}; + +enum ShadowRootMode { "open", "closed"};