diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-01-30 16:19:40 +0100 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-04-26 10:17:46 +0200 |
commit | 2e5c0584637079889f4ed490b98afe07445f26d5 (patch) | |
tree | 6ea30c1008277842b80a0780da33582af54be66b /components/script/dom/node.rs | |
parent | f6ba16588280aa6c2dcd872860a181c74b270c9b (diff) | |
download | servo-2e5c0584637079889f4ed490b98afe07445f26d5.tar.gz servo-2e5c0584637079889f4ed490b98afe07445f26d5.zip |
Implement concept of shadow including tree order
Diffstat (limited to 'components/script/dom/node.rs')
-rw-r--r-- | components/script/dom/node.rs | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index cecad5d7b76..d8c1a2f4d5d 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -291,7 +291,7 @@ impl Node { let parent_in_doc = self.is_in_doc(); let parent_in_shadow_tree = self.is_in_shadow_tree(); let parent_is_connected = self.is_connected(); - for node in new_child.traverse_preorder() { + for node in new_child.traverse_preorder(/* shadow including */ false) { if parent_in_shadow_tree { if let Some(shadow_root) = self.downcast::<ShadowRoot>() { node.set_owner_shadow_root(&*shadow_root); @@ -355,7 +355,7 @@ impl Node { child.composed_parent_node.set(None); self.children_count.set(self.children_count.get() - 1); - for node in child.traverse_preorder() { + for node in child.traverse_preorder(/* shadow including */ true) { // Out-of-document elements never have the descendants flag set. node.set_flag( NodeFlags::IS_IN_DOC | @@ -365,7 +365,7 @@ impl Node { false, ); } - for node in child.traverse_preorder() { + for node in child.traverse_preorder(/* shadow including */ true) { // This needs to be in its own loop, because unbind_from_tree may // rely on the state of IS_IN_DOC of the context node's descendants, // e.g. when removing a <form>. @@ -628,8 +628,8 @@ impl Node { } /// Iterates over this node and all its descendants, in preorder. - pub fn traverse_preorder(&self) -> TreeIterator { - TreeIterator::new(self) + pub fn traverse_preorder(&self, shadow_including: bool) -> TreeIterator { + TreeIterator::new(self, shadow_including) } pub fn inclusively_following_siblings(&self) -> impl Iterator<Item = DomRoot<Node>> { @@ -876,7 +876,7 @@ impl Node { self.owner_doc().quirks_mode(), ); Ok(self - .traverse_preorder() + .traverse_preorder(/* shadow including */ false) .filter_map(DomRoot::downcast) .find(|element| matches_selector_list(&selectors, element, &mut ctx))) }, @@ -894,7 +894,7 @@ impl Node { Err(_) => Err(Error::Syntax), // Step 3. Ok(selectors) => { - let mut descendants = self.traverse_preorder(); + let mut descendants = self.traverse_preorder(/* shadow including */ false); // Skip the root of the tree. assert!(&*descendants.next().unwrap() == self); Ok(QuerySelectorIterator::new(descendants, selectors)) @@ -917,16 +917,16 @@ impl Node { } } - pub fn inclusive_ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> { - SimpleNodeIterator { + pub fn inclusive_ancestors(&self) -> Box<Iterator<Item = DomRoot<Node>>> { + Box::new(SimpleNodeIterator { current: Some(DomRoot::from_ref(self)), next_node: |n| n.GetParentNode(), - } + }) } /// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor - pub fn shadow_including_inclusive_ancestors(&self) -> impl Iterator<Item = DomRoot<Node>> { - SimpleNodeIterator { + pub fn shadow_including_inclusive_ancestors(&self) -> Box<Iterator<Item = DomRoot<Node>>> { + Box::new(SimpleNodeIterator { current: Some(DomRoot::from_ref(self)), next_node: |n| { if let Some(shadow_root) = n.downcast::<ShadowRoot>() { @@ -935,7 +935,7 @@ impl Node { n.GetParentNode() } }, - } + }) } pub fn owner_doc(&self) -> DomRoot<Document> { @@ -1505,13 +1505,15 @@ where pub struct TreeIterator { current: Option<DomRoot<Node>>, depth: usize, + shadow_including: bool, } impl TreeIterator { - fn new(root: &Node) -> TreeIterator { + fn new(root: &Node, shadow_including: bool) -> TreeIterator { TreeIterator { current: Some(DomRoot::from_ref(root)), depth: 0, + shadow_including, } } @@ -1522,7 +1524,13 @@ impl TreeIterator { } fn next_skipping_children_impl(&mut self, current: DomRoot<Node>) -> Option<DomRoot<Node>> { - for ancestor in current.inclusive_ancestors() { + let iter = if self.shadow_including { + current.shadow_including_inclusive_ancestors() + } else { + current.inclusive_ancestors() + }; + + for ancestor in iter { if self.depth == 0 { break; } @@ -1542,8 +1550,18 @@ impl Iterator for TreeIterator { type Item = DomRoot<Node>; // https://dom.spec.whatwg.org/#concept-tree-order + // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order fn next(&mut self) -> Option<DomRoot<Node>> { let current = self.current.take()?; + + if !self.shadow_including { + if let Some(element) = current.downcast::<Element>() { + if element.is_shadow_host() { + return self.next_skipping_children_impl(current); + } + } + } + if let Some(first_child) = current.GetFirstChild() { self.current = Some(first_child); self.depth += 1; @@ -1626,11 +1644,11 @@ impl Node { // Step 3. if &*old_doc != document { // Step 3.1. - for descendant in node.traverse_preorder() { + for descendant in node.traverse_preorder(/* shadow including */ true) { descendant.set_owner_doc(document); } for descendant in node - .traverse_preorder() + .traverse_preorder(/* shadow including */ true) .filter_map(|d| d.as_custom_element()) { // Step 3.2. @@ -1640,7 +1658,7 @@ impl Node { None, ); } - for descendant in node.traverse_preorder() { + for descendant in node.traverse_preorder(/* shadow including */ true) { // Step 3.3. vtable_for(&descendant).adopting_steps(&old_doc); } @@ -1861,7 +1879,7 @@ impl Node { parent.add_child(*kid, child); // Step 7.7. for descendant in kid - .traverse_preorder() + .traverse_preorder(/* shadow including */ true) .filter_map(DomRoot::downcast::<Element>) { // Step 7.7.2. @@ -2306,7 +2324,9 @@ impl NodeMethods for Node { fn GetTextContent(&self) -> Option<DOMString> { match self.type_id() { NodeTypeId::DocumentFragment(_) | NodeTypeId::Element(..) => { - let content = Node::collect_text_contents(self.traverse_preorder()); + let content = Node::collect_text_contents( + self.traverse_preorder(/* shadow including */ false), + ); Some(content) }, NodeTypeId::CharacterData(..) => { @@ -3143,7 +3163,7 @@ where let elem_node = elem.upcast::<Node>(); let mut head: usize = 0; - for node in tree_root.traverse_preorder() { + for node in tree_root.traverse_preorder(/* shadow including */ false) { let head_node = DomRoot::upcast::<Node>(DomRoot::from_ref(&*self[head])); if head_node == node { head += 1; |