ShadowRoot interface

This commit is contained in:
Fernando Jiménez Moreno 2019-01-21 15:58:54 +01:00
parent cbcf21c248
commit 18ae0fcbd6
8 changed files with 82 additions and 22 deletions

View file

@ -27,7 +27,7 @@ pub struct DocumentFragment {
impl DocumentFragment { impl DocumentFragment {
/// Creates a new DocumentFragment. /// Creates a new DocumentFragment.
fn new_inherited(document: &Document) -> DocumentFragment { pub fn new_inherited(document: &Document) -> DocumentFragment {
DocumentFragment { DocumentFragment {
node: Node::new_inherited(document), node: Node::new_inherited(document),
} }

View file

@ -2372,7 +2372,7 @@ impl ElementMethods for Element {
NodeTypeId::Document(_) => return Err(Error::NoModificationAllowed), NodeTypeId::Document(_) => return Err(Error::NoModificationAllowed),
// Step 4. // Step 4.
NodeTypeId::DocumentFragment => { NodeTypeId::DocumentFragment(_) => {
let body_elem = Element::create( let body_elem = Element::create(
QualName::new(None, ns!(html), local_name!("body")), QualName::new(None, ns!(html), local_name!("body")),
None, None,

View file

@ -454,6 +454,7 @@ pub mod serviceworkercontainer;
pub mod serviceworkerglobalscope; pub mod serviceworkerglobalscope;
pub mod serviceworkerregistration; pub mod serviceworkerregistration;
pub mod servoparser; pub mod servoparser;
pub mod shadowroot;
pub mod storage; pub mod storage;
pub mod storageevent; pub mod storageevent;
pub mod stylepropertymapreadonly; pub mod stylepropertymapreadonly;

View file

@ -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::NodeListBinding::NodeListMethods;
use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; 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::codegen::UnionTypes::NodeOrString;
use crate::dom::bindings::conversions::{self, DerivedFrom}; use crate::dom::bindings::conversions::{self, DerivedFrom};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
@ -1559,7 +1560,7 @@ impl Node {
) -> ErrorResult { ) -> ErrorResult {
// Step 1. // Step 1.
match parent.type_id() { match parent.type_id() {
NodeTypeId::Document(_) | NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => (), NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (),
_ => return Err(Error::HierarchyRequest), _ => return Err(Error::HierarchyRequest),
} }
@ -1587,7 +1588,7 @@ impl Node {
return Err(Error::HierarchyRequest); return Err(Error::HierarchyRequest);
} }
}, },
NodeTypeId::DocumentFragment | NodeTypeId::DocumentFragment(_) |
NodeTypeId::Element(_) | NodeTypeId::Element(_) |
NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) | NodeTypeId::CharacterData(CharacterDataTypeId::ProcessingInstruction) |
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (), NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => (),
@ -1598,7 +1599,7 @@ impl Node {
if parent.is::<Document>() { if parent.is::<Document>() {
match node.type_id() { match node.type_id() {
// Step 6.1 // Step 6.1
NodeTypeId::DocumentFragment => { NodeTypeId::DocumentFragment(_) => {
// Step 6.1.1(b) // Step 6.1.1(b)
if node.children().any(|c| c.is::<Text>()) { if node.children().any(|c| c.is::<Text>()) {
return Err(Error::HierarchyRequest); return Err(Error::HierarchyRequest);
@ -1723,7 +1724,7 @@ impl Node {
} }
} }
rooted_vec!(let mut new_nodes); 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. // Step 3.
new_nodes.extend(node.children().map(|kid| Dom::from_ref(&*kid))); new_nodes.extend(node.children().map(|kid| Dom::from_ref(&*kid)));
// Step 4. // Step 4.
@ -1809,7 +1810,7 @@ impl Node {
// Step 3. // Step 3.
rooted_vec!(let mut added_nodes); rooted_vec!(let mut added_nodes);
let added_nodes = if let Some(node) = node.as_ref() { 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.extend(node.children().map(|child| Dom::from_ref(&*child)));
added_nodes.r() added_nodes.r()
} else { } else {
@ -1935,7 +1936,7 @@ impl Node {
); );
DomRoot::upcast::<Node>(doctype) DomRoot::upcast::<Node>(doctype)
}, },
NodeTypeId::DocumentFragment => { NodeTypeId::DocumentFragment(_) => {
let doc_fragment = DocumentFragment::new(&document); let doc_fragment = DocumentFragment::new(&document);
DomRoot::upcast::<Node>(doc_fragment) DomRoot::upcast::<Node>(doc_fragment)
}, },
@ -2068,7 +2069,7 @@ impl Node {
.GetDocumentElement() .GetDocumentElement()
.as_ref() .as_ref()
.map_or(ns!(), |elem| elem.locate_namespace(prefix)), .map_or(ns!(), |elem| elem.locate_namespace(prefix)),
NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => ns!(), NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => ns!(),
_ => node _ => node
.GetParentElement() .GetParentElement()
.as_ref() .as_ref()
@ -2093,7 +2094,7 @@ impl NodeMethods for Node {
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE, NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => NodeConstants::COMMENT_NODE,
NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE, NodeTypeId::Document(_) => NodeConstants::DOCUMENT_NODE,
NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE, NodeTypeId::DocumentType => NodeConstants::DOCUMENT_TYPE_NODE,
NodeTypeId::DocumentFragment => NodeConstants::DOCUMENT_FRAGMENT_NODE, NodeTypeId::DocumentFragment(_) => NodeConstants::DOCUMENT_FRAGMENT_NODE,
NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE, NodeTypeId::Element(_) => NodeConstants::ELEMENT_NODE,
} }
} }
@ -2113,7 +2114,7 @@ impl NodeMethods for Node {
}, },
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"), NodeTypeId::CharacterData(CharacterDataTypeId::Comment) => DOMString::from("#comment"),
NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(), NodeTypeId::DocumentType => self.downcast::<DocumentType>().unwrap().name().clone(),
NodeTypeId::DocumentFragment => DOMString::from("#document-fragment"), NodeTypeId::DocumentFragment(_) => DOMString::from("#document-fragment"),
NodeTypeId::Document(_) => DOMString::from("#document"), NodeTypeId::Document(_) => DOMString::from("#document"),
} }
} }
@ -2129,7 +2130,7 @@ impl NodeMethods for Node {
NodeTypeId::CharacterData(..) | NodeTypeId::CharacterData(..) |
NodeTypeId::Element(..) | NodeTypeId::Element(..) |
NodeTypeId::DocumentType | NodeTypeId::DocumentType |
NodeTypeId::DocumentFragment => Some(self.owner_doc()), NodeTypeId::DocumentFragment(_) => Some(self.owner_doc()),
NodeTypeId::Document(_) => None, NodeTypeId::Document(_) => None,
} }
} }
@ -2198,7 +2199,7 @@ impl NodeMethods for Node {
// https://dom.spec.whatwg.org/#dom-node-textcontent // https://dom.spec.whatwg.org/#dom-node-textcontent
fn GetTextContent(&self) -> Option<DOMString> { fn GetTextContent(&self) -> Option<DOMString> {
match self.type_id() { match self.type_id() {
NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => { NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
let content = Node::collect_text_contents(self.traverse_preorder()); let content = Node::collect_text_contents(self.traverse_preorder());
Some(content) Some(content)
}, },
@ -2214,7 +2215,7 @@ impl NodeMethods for Node {
fn SetTextContent(&self, value: Option<DOMString>) { fn SetTextContent(&self, value: Option<DOMString>) {
let value = value.unwrap_or_default(); let value = value.unwrap_or_default();
match self.type_id() { match self.type_id() {
NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => { NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => {
// Step 1-2. // Step 1-2.
let node = if value.is_empty() { let node = if value.is_empty() {
None None
@ -2247,7 +2248,7 @@ impl NodeMethods for Node {
fn ReplaceChild(&self, node: &Node, child: &Node) -> Fallible<DomRoot<Node>> { fn ReplaceChild(&self, node: &Node, child: &Node) -> Fallible<DomRoot<Node>> {
// Step 1. // Step 1.
match self.type_id() { match self.type_id() {
NodeTypeId::Document(_) | NodeTypeId::DocumentFragment | NodeTypeId::Element(..) => (), NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => (),
_ => return Err(Error::HierarchyRequest), _ => return Err(Error::HierarchyRequest),
} }
@ -2277,7 +2278,7 @@ impl NodeMethods for Node {
if self.is::<Document>() { if self.is::<Document>() {
match node.type_id() { match node.type_id() {
// Step 6.1 // Step 6.1
NodeTypeId::DocumentFragment => { NodeTypeId::DocumentFragment(_) => {
// Step 6.1.1(b) // Step 6.1.1(b)
if node.children().any(|c| c.is::<Text>()) { if node.children().any(|c| c.is::<Text>()) {
return Err(Error::HierarchyRequest); return Err(Error::HierarchyRequest);
@ -2350,7 +2351,8 @@ impl NodeMethods for Node {
// Step 12. // Step 12.
rooted_vec!(let mut nodes); 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.extend(node.children().map(|node| Dom::from_ref(&*node)));
nodes.r() nodes.r()
} else { } else {
@ -2612,7 +2614,7 @@ impl NodeMethods for Node {
.unwrap() .unwrap()
.GetDocumentElement() .GetDocumentElement()
.and_then(|element| element.lookup_prefix(namespace)), .and_then(|element| element.lookup_prefix(namespace)),
NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => None, NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => None,
_ => self _ => self
.GetParentElement() .GetParentElement()
.and_then(|element| element.lookup_prefix(namespace)), .and_then(|element| element.lookup_prefix(namespace)),

View file

@ -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::RangeBinding::{self, RangeConstants};
use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods; use crate::dom::bindings::codegen::Bindings::TextBinding::TextMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; 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::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId}; use crate::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId};
@ -763,7 +764,8 @@ impl RangeMethods for Range {
// Step 11 // Step 11
let new_offset = new_offset + 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() node.len()
} else { } else {
1 1
@ -878,7 +880,7 @@ impl RangeMethods for Range {
// Step 2. // Step 2.
match new_parent.type_id() { match new_parent.type_id() {
NodeTypeId::Document(_) | NodeTypeId::DocumentType | NodeTypeId::DocumentFragment => { NodeTypeId::Document(_) | NodeTypeId::DocumentType | NodeTypeId::DocumentFragment(_) => {
return Err(Error::InvalidNodeType); return Err(Error::InvalidNodeType);
}, },
_ => (), _ => (),
@ -954,7 +956,7 @@ impl RangeMethods for Range {
let node = self.StartContainer(); let node = self.StartContainer();
let owner_doc = node.owner_doc(); let owner_doc = node.owner_doc();
let element = match node.type_id() { let element = match node.type_id() {
NodeTypeId::Document(_) | NodeTypeId::DocumentFragment => None, NodeTypeId::Document(_) | NodeTypeId::DocumentFragment(_) => None,
NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()), NodeTypeId::Element(_) => Some(DomRoot::downcast::<Element>(node).unwrap()),
NodeTypeId::CharacterData(CharacterDataTypeId::Comment) | NodeTypeId::CharacterData(CharacterDataTypeId::Comment) |
NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(), NodeTypeId::CharacterData(CharacterDataTypeId::Text(_)) => node.GetParentElement(),

View file

@ -249,7 +249,7 @@ impl<'a> Serialize for &'a Node {
serializer.write_processing_instruction(&pi.target(), &data)?; serializer.write_processing_instruction(&pi.target(), &data)?;
}, },
NodeTypeId::DocumentFragment => {}, NodeTypeId::DocumentFragment(_) => {},
NodeTypeId::Document(_) => panic!("Can't serialize Document node itself"), NodeTypeId::Document(_) => panic!("Can't serialize Document node itself"),
NodeTypeId::Element(_) => panic!("Element shouldn't appear here"), NodeTypeId::Element(_) => panic!("Element shouldn't appear here"),

View file

@ -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<Element>,
}
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<Element> {
DomRoot::from_ref(&self.host)
}
}

View file

@ -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"};