From ea69bbc75b6a40af77df5528b23a05b29385f488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Mon, 28 Jan 2019 15:48:12 +0100 Subject: [PATCH] Node retargeting algorithm --- components/script/dom/node.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 6527a4a904f..6c509d70c16 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -640,6 +640,10 @@ impl Node { parent.ancestors().any(|ancestor| &*ancestor == self) } + fn is_shadow_including_inclusive_ancestor_of(&self, node: &Node) -> bool { + node.shadow_including_inclusive_ancestors().any(|ancestor| &*ancestor == self) + } + pub fn following_siblings(&self) -> impl Iterator> { SimpleNodeIterator { current: self.GetNextSibling(), @@ -905,6 +909,20 @@ impl Node { } } + /// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor + pub fn shadow_including_inclusive_ancestors(&self) -> impl Iterator> { + SimpleNodeIterator { + current: Some(DomRoot::from_ref(self)), + next_node: |n| { + if let Some(shadow_root) = n.downcast::() { + Some(DomRoot::from_ref(shadow_root.Host().upcast::())) + } else { + n.GetParentNode() + } + }, + } + } + pub fn owner_doc(&self) -> DomRoot { self.owner_doc.get().unwrap() } @@ -1087,6 +1105,19 @@ impl Node { None } } + + /// https://dom.spec.whatwg.org/#retarget + pub fn retarget(&self, a: &Node, b: &Node) -> DomRoot { + let mut a = DomRoot::from_ref(&*a); + loop { + let a_root = a.GetRootNode(&GetRootNodeOptions::empty()); + if !a_root.is::() || a_root.is_shadow_including_inclusive_ancestor_of(b) { + return DomRoot::from_ref(&a); + } + + a = DomRoot::from_ref(a_root.downcast::().unwrap().Host().upcast::()); + } + } } /// Iterate through `nodes` until we find a `Node` that is not in `not_in`