diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 63e465ccae8..f1e11a38a7d 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -528,7 +528,7 @@ impl Document { return; } - let parent = match node.inclusive_ancestors(ShadowIncluding::Yes).nth(1) { + let parent = match node.parent_in_flat_tree() { Some(parent) => parent, None => { // There is no parent so this is the Document node, so we @@ -542,7 +542,7 @@ impl Document { // ancestors as dirty until the document element. for ancestor in dirty_root .upcast::() - .inclusive_ancestors(ShadowIncluding::Yes) + .inclusive_ancestors_in_flat_tree() { if ancestor.is::() { ancestor.set_flag(NodeFlags::HAS_DIRTY_DESCENDANTS, true); @@ -596,13 +596,11 @@ impl Document { Some(root) => root, }; - for ancestor in element - .upcast::() - .inclusive_ancestors(ShadowIncluding::Yes) - { + for ancestor in element.upcast::().inclusive_ancestors_in_flat_tree() { if ancestor.get_flag(NodeFlags::HAS_DIRTY_DESCENDANTS) { return; } + if ancestor.is::() { ancestor.set_flag(NodeFlags::HAS_DIRTY_DESCENDANTS, true); } @@ -610,13 +608,13 @@ impl Document { let new_dirty_root = element .upcast::() - .common_ancestor(dirty_root.upcast(), ShadowIncluding::Yes) + .common_ancestor_in_flat_tree(dirty_root.upcast()) .expect("Couldn't find common ancestor"); let mut has_dirty_descendants = true; for ancestor in dirty_root .upcast::() - .inclusive_ancestors(ShadowIncluding::Yes) + .inclusive_ancestors_in_flat_tree() { ancestor.set_flag(NodeFlags::HAS_DIRTY_DESCENDANTS, has_dirty_descendants); has_dirty_descendants &= *ancestor != *new_dirty_root; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 4653139ed12..428a8d075b3 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -777,6 +777,14 @@ impl Node { }) } + pub(crate) fn common_ancestor_in_flat_tree(&self, other: &Node) -> Option> { + self.inclusive_ancestors_in_flat_tree().find(|ancestor| { + other + .inclusive_ancestors_in_flat_tree() + .any(|node| node == *ancestor) + }) + } + pub(crate) fn is_inclusive_ancestor_of(&self, parent: &Node) -> bool { self == parent || self.is_ancestor_of(parent) } @@ -1395,6 +1403,35 @@ impl Node { .slottable_data .manual_slot_assignment = manually_assigned_slot.map(Dom::from_ref); } + + /// Gets the parent of this node from the perspective of layout and style. + /// + /// The returned node is the node's assigned slot, if any, or the + /// shadow host if it's a shadow root. Otherwise, it is the node's + /// parent. + pub(crate) fn parent_in_flat_tree(&self) -> Option> { + if let Some(assigned_slot) = self.assigned_slot() { + return Some(DomRoot::upcast(assigned_slot)); + } + + let parent_or_none = self.GetParentNode(); + if let Some(parent) = parent_or_none.as_deref() { + if let Some(shadow_root) = parent.downcast::() { + return Some(DomRoot::from_ref(shadow_root.Host().upcast::())); + } + } + + parent_or_none + } + + pub(crate) fn inclusive_ancestors_in_flat_tree( + &self, + ) -> impl Iterator> + use<> { + SimpleNodeIterator { + current: Some(DomRoot::from_ref(self)), + next_node: move |n| n.parent_in_flat_tree(), + } + } } /// Iterate through `nodes` until we find a `Node` that is not in `not_in`