aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-12-17 17:56:15 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2018-01-09 14:26:02 +0100
commitb26f3280d2f470e25c63d2acb10a80c97d08b3ab (patch)
tree6c0c1e9b051fa4f499d0f3169debd25f103f9a1c /components
parent040379208e5cc648cf7ebde30b2a42e70c15e602 (diff)
downloadservo-b26f3280d2f470e25c63d2acb10a80c97d08b3ab.tar.gz
servo-b26f3280d2f470e25c63d2acb10a80c97d08b3ab.zip
style: Add invalidation support for ::slotted().
Bug: 1424607 Reviewed-by: heycam MozReview-Commit-ID: 8pIVUx27o7x
Diffstat (limited to 'components')
-rw-r--r--components/layout_thread/dom_wrapper.rs4
-rw-r--r--components/style/dom.rs14
-rw-r--r--components/style/dom_apis.rs7
-rw-r--r--components/style/gecko/wrapper.rs39
-rw-r--r--components/style/invalidation/element/collector.rs70
-rw-r--r--components/style/invalidation/element/invalidation_map.rs54
-rw-r--r--components/style/invalidation/element/invalidator.rs192
7 files changed, 282 insertions, 98 deletions
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs
index e595ac06f45..8a8a2b57131 100644
--- a/components/layout_thread/dom_wrapper.rs
+++ b/components/layout_thread/dom_wrapper.rs
@@ -363,6 +363,10 @@ impl<'le> TElement for ServoLayoutElement<'le> {
LayoutIterator(self.as_node().dom_children())
}
+ fn is_html_element(&self) -> bool {
+ unsafe { self.element.is_html_element() }
+ }
+
fn style_attribute(&self) -> Option<ArcBorrow<StyleLocked<PropertyDeclarationBlock>>> {
unsafe {
(*self.element.style_attribute()).as_ref().map(|x| x.borrow_arc())
diff --git a/components/style/dom.rs b/components/style/dom.rs
index ea438b66dd9..85f4f49c4b7 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -416,6 +416,20 @@ pub trait TElement
F: FnMut(Self),
{}
+ /// Return whether this element is an element in the HTML namespace.
+ fn is_html_element(&self) -> bool;
+
+ /// Returns whether this element is a <html:slot> element.
+ fn is_html_slot_element(&self) -> bool {
+ self.get_local_name() == &*local_name!("slot") &&
+ self.is_html_element()
+ }
+
+ /// Return the list of slotted nodes of this node.
+ fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
+ &[]
+ }
+
/// For a given NAC element, return the closest non-NAC ancestor, which is
/// guaranteed to exist.
fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> {
diff --git a/components/style/dom_apis.rs b/components/style/dom_apis.rs
index 8f6ea273aa0..c1c5c989193 100644
--- a/components/style/dom_apis.rs
+++ b/components/style/dom_apis.rs
@@ -8,7 +8,8 @@
use Atom;
use context::QuirksMode;
use dom::{TDocument, TElement, TNode};
-use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
+use invalidation::element::invalidator::{DescendantInvalidationLists, Invalidation};
+use invalidation::element::invalidator::{InvalidationProcessor, InvalidationVector};
use selectors::{Element, NthIndexCache, SelectorList};
use selectors::attr::CaseSensitivity;
use selectors::matching::{self, MatchingContext, MatchingMode};
@@ -143,7 +144,7 @@ where
&mut self,
element: E,
self_invalidations: &mut InvalidationVector<'a>,
- descendant_invalidations: &mut InvalidationVector<'a>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
_sibling_invalidations: &mut InvalidationVector<'a>,
) -> bool {
// TODO(emilio): If the element is not a root element, and
@@ -163,7 +164,7 @@ where
let target_vector =
if self.matching_context.scope_element.is_some() {
- descendant_invalidations
+ &mut descendant_invalidations.dom_descendants
} else {
self_invalidations
};
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index ff0f9634afb..401479b950b 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -610,10 +610,7 @@ impl<'le> GeckoElement<'le> {
self.as_node().node_info().mInner.mNamespaceID
}
- fn is_html_element(&self) -> bool {
- self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
- }
-
+ #[inline]
fn is_xul_element(&self) -> bool {
self.namespace_id() == (structs::root::kNameSpaceID_XUL as i32)
}
@@ -974,6 +971,40 @@ impl<'le> TElement for GeckoElement<'le> {
self.as_node().owner_doc().as_node()
}
+
+ #[inline]
+ fn is_html_element(&self) -> bool {
+ self.namespace_id() == (structs::root::kNameSpaceID_XHTML as i32)
+ }
+
+ /// Return the list of slotted nodes of this node.
+ #[inline]
+ fn slotted_nodes(&self) -> &[Self::ConcreteNode] {
+ if !self.is_html_slot_element() || !self.is_in_shadow_tree() {
+ return &[];
+ }
+
+ let slot: &structs::HTMLSlotElement = unsafe {
+ mem::transmute(self.0)
+ };
+
+ if cfg!(debug_assertions) {
+ let base: &RawGeckoElement = &slot._base._base._base._base;
+ assert_eq!(base as *const _, self.0 as *const _, "Bad cast");
+ }
+
+ let assigned_nodes: &[structs::RefPtr<structs::nsINode>] =
+ &*slot.mAssignedNodes;
+
+ debug_assert_eq!(
+ mem::size_of::<structs::RefPtr<structs::nsINode>>(),
+ mem::size_of::<Self::ConcreteNode>(),
+ "Bad cast!"
+ );
+
+ unsafe { mem::transmute(assigned_nodes) }
+ }
+
/// Execute `f` for each anonymous content child element (apart from
/// ::before and ::after) whose originating element is `self`.
fn each_anonymous_content_child<F>(&self, mut f: F)
diff --git a/components/style/invalidation/element/collector.rs b/components/style/invalidation/element/collector.rs
index 4f0460502c4..008d6e428ea 100644
--- a/components/style/invalidation/element/collector.rs
+++ b/components/style/invalidation/element/collector.rs
@@ -13,7 +13,8 @@ use dom::TElement;
use element_state::ElementState;
use invalidation::element::element_wrapper::{ElementSnapshot, ElementWrapper};
use invalidation::element::invalidation_map::*;
-use invalidation::element::invalidator::{InvalidationVector, Invalidation, InvalidationProcessor};
+use invalidation::element::invalidator::{DescendantInvalidationLists, InvalidationVector};
+use invalidation::element::invalidator::{Invalidation, InvalidationProcessor};
use invalidation::element::restyle_hints::RestyleHint;
use selector_map::SelectorMap;
use selector_parser::Snapshot;
@@ -47,7 +48,7 @@ where
classes_removed: &'a SmallVec<[Atom; 8]>,
classes_added: &'a SmallVec<[Atom; 8]>,
state_changes: ElementState,
- descendant_invalidations: &'a mut InvalidationVector<'selectors>,
+ descendant_invalidations: &'a mut DescendantInvalidationLists<'selectors>,
sibling_invalidations: &'a mut InvalidationVector<'selectors>,
invalidates_self: bool,
}
@@ -109,7 +110,7 @@ where
&mut self,
element: E,
_self_invalidations: &mut InvalidationVector<'a>,
- descendant_invalidations: &mut InvalidationVector<'a>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
sibling_invalidations: &mut InvalidationVector<'a>,
) -> bool {
debug_assert!(element.has_snapshot(), "Why bothering?");
@@ -236,7 +237,10 @@ where
//
// This number is completely made-up, but the page that made us add this
// code generated 1960+ invalidations (bug 1420741).
- if descendant_invalidations.len() > 150 {
+ //
+ // We don't look at slotted_descendants because those don't propagate
+ // down more than one level anyway.
+ if descendant_invalidations.dom_descendants.len() > 150 {
self.data.hint.insert(RestyleHint::RESTYLE_DESCENDANTS);
}
@@ -509,36 +513,52 @@ where
}
fn note_dependency(&mut self, dependency: &'selectors Dependency) {
- if dependency.affects_self() {
+ debug_assert!(self.dependency_may_be_relevant(dependency));
+
+ let invalidation_kind = dependency.invalidation_kind();
+ if matches!(invalidation_kind, DependencyInvalidationKind::Element) {
self.invalidates_self = true;
+ return;
}
- if dependency.affects_descendants() {
- debug_assert_ne!(dependency.selector_offset, 0);
- debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
- debug_assert!(!dependency.affects_later_siblings());
- self.descendant_invalidations.push(Invalidation::new(
- &dependency.selector,
- dependency.selector.len() - dependency.selector_offset + 1,
- ));
- } else if dependency.affects_later_siblings() {
- debug_assert_ne!(dependency.selector_offset, 0);
- debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
- self.sibling_invalidations.push(Invalidation::new(
- &dependency.selector,
- dependency.selector.len() - dependency.selector_offset + 1,
- ));
+ debug_assert_ne!(dependency.selector_offset, 0);
+ debug_assert_ne!(
+ dependency.selector_offset,
+ dependency.selector.len()
+ );
+
+ let invalidation = Invalidation::new(
+ &dependency.selector,
+ dependency.selector.len() - dependency.selector_offset + 1,
+ );
+
+ match invalidation_kind {
+ DependencyInvalidationKind::Element => unreachable!(),
+ DependencyInvalidationKind::ElementAndDescendants => {
+ self.invalidates_self = true;
+ self.descendant_invalidations.dom_descendants.push(invalidation);
+ }
+ DependencyInvalidationKind::Descendants => {
+ self.descendant_invalidations.dom_descendants.push(invalidation);
+ }
+ DependencyInvalidationKind::Siblings => {
+ self.sibling_invalidations.push(invalidation);
+ }
+ DependencyInvalidationKind::SlottedElements => {
+ self.descendant_invalidations.slotted_descendants.push(invalidation);
+ }
}
}
/// Returns whether `dependency` may cause us to invalidate the style of
/// more elements than what we've already invalidated.
fn dependency_may_be_relevant(&self, dependency: &Dependency) -> bool {
- if dependency.affects_descendants() || dependency.affects_later_siblings() {
- return true;
+ match dependency.invalidation_kind() {
+ DependencyInvalidationKind::Element => !self.invalidates_self,
+ DependencyInvalidationKind::SlottedElements => self.element.is_html_slot_element(),
+ DependencyInvalidationKind::ElementAndDescendants |
+ DependencyInvalidationKind::Siblings |
+ DependencyInvalidationKind::Descendants => true,
}
-
- debug_assert!(dependency.affects_self());
- !self.invalidates_self
}
}
diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs
index 0ae08aa0bfa..809d3eb4a78 100644
--- a/components/style/invalidation/element/invalidation_map.rs
+++ b/components/style/invalidation/element/invalidation_map.rs
@@ -63,6 +63,25 @@ pub struct Dependency {
pub selector_offset: usize,
}
+/// The kind of elements down the tree this dependency may affect.
+#[derive(Debug, Eq, PartialEq)]
+pub enum DependencyInvalidationKind {
+ /// This dependency may affect the element that changed itself.
+ Element,
+ /// This dependency affects the style of the element itself, and also the
+ /// style of its descendants.
+ ///
+ /// TODO(emilio): Each time this feels more of a hack for eager pseudos...
+ ElementAndDescendants,
+ /// This dependency may affect descendants down the tree.
+ Descendants,
+ /// This dependency may affect siblings to the right of the element that
+ /// changed.
+ Siblings,
+ /// This dependency may affect slotted elements of the element that changed.
+ SlottedElements,
+}
+
impl Dependency {
/// Returns the combinator to the right of the partial selector this
/// dependency represents.
@@ -76,28 +95,19 @@ impl Dependency {
Some(self.selector.combinator_at_match_order(self.selector_offset - 1))
}
- /// Whether this dependency affects the style of the element.
- ///
- /// NOTE(emilio): pseudo-elements need to be here to account for eager
- /// pseudos, since they just grab the style from the originating element.
- ///
- /// TODO(emilio): We could look at the selector itself to see if it's an
- /// eager pseudo, and return false here if not.
- pub fn affects_self(&self) -> bool {
- matches!(self.combinator(), None | Some(Combinator::PseudoElement))
- }
-
- /// Whether this dependency may affect style of any of our descendants.
- pub fn affects_descendants(&self) -> bool {
- matches!(self.combinator(), Some(Combinator::PseudoElement) |
- Some(Combinator::Child) |
- Some(Combinator::Descendant))
- }
-
- /// Whether this dependency may affect style of any of our later siblings.
- pub fn affects_later_siblings(&self) -> bool {
- matches!(self.combinator(), Some(Combinator::NextSibling) |
- Some(Combinator::LaterSibling))
+ /// The kind of invalidation that this would generate.
+ pub fn invalidation_kind(&self) -> DependencyInvalidationKind {
+ match self.combinator() {
+ None => DependencyInvalidationKind::Element,
+ Some(Combinator::Child) |
+ Some(Combinator::Descendant) => DependencyInvalidationKind::Descendants,
+ Some(Combinator::LaterSibling) |
+ Some(Combinator::NextSibling) => DependencyInvalidationKind::Siblings,
+ // TODO(emilio): We could look at the selector itself to see if it's
+ // an eager pseudo, and return only Descendants here if not.
+ Some(Combinator::PseudoElement) => DependencyInvalidationKind::ElementAndDescendants,
+ Some(Combinator::SlotAssignment) => DependencyInvalidationKind::SlottedElements,
+ }
}
}
diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs
index 62bac3fd8be..14aa084a1b0 100644
--- a/components/style/invalidation/element/invalidator.rs
+++ b/components/style/invalidation/element/invalidator.rs
@@ -39,7 +39,7 @@ where
&mut self,
element: E,
self_invalidations: &mut InvalidationVector<'a>,
- descendant_invalidations: &mut InvalidationVector<'a>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'a>,
sibling_invalidations: &mut InvalidationVector<'a>,
) -> bool;
@@ -58,6 +58,25 @@ where
fn invalidated_descendants(&mut self, element: E, child: E);
}
+/// Different invalidation lists for descendants.
+#[derive(Debug, Default)]
+pub struct DescendantInvalidationLists<'a> {
+ /// Invalidations for normal DOM children and pseudo-elements.
+ ///
+ /// TODO(emilio): Having a list of invalidations just for pseudo-elements
+ /// may save some work here and there.
+ pub dom_descendants: InvalidationVector<'a>,
+ /// Invalidations for slotted children of an element.
+ pub slotted_descendants: InvalidationVector<'a>,
+}
+
+impl<'a> DescendantInvalidationLists<'a> {
+ fn is_empty(&self) -> bool {
+ self.dom_descendants.is_empty() &&
+ self.slotted_descendants.is_empty()
+ }
+}
+
/// The struct that takes care of encapsulating all the logic on where and how
/// element styles need to be invalidated.
pub struct TreeStyleInvalidator<'a, 'b, E, P: 'a>
@@ -75,13 +94,22 @@ where
/// A vector of invalidations, optimized for small invalidation sets.
pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
+/// The kind of descendant invalidation we're processing.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+enum DescendantInvalidationKind {
+ /// A DOM descendant invalidation.
+ Dom,
+ /// A ::slotted() descendant invalidation.
+ Slotted,
+}
+
/// The kind of invalidation we're processing.
///
/// We can use this to avoid pushing invalidations of the same kind to our
/// descendants or siblings.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum InvalidationKind {
- Descendant,
+ Descendant(DescendantInvalidationKind),
Sibling,
}
@@ -126,21 +154,27 @@ impl<'a> Invalidation<'a> {
//
// We should be able to do better here!
match self.selector.combinator_at_parse_order(self.offset - 1) {
+ Combinator::Descendant |
+ Combinator::LaterSibling |
+ Combinator::PseudoElement => true,
+ Combinator::SlotAssignment |
Combinator::NextSibling |
Combinator::Child => false,
- _ => true,
}
}
fn kind(&self) -> InvalidationKind {
if self.offset == 0 {
- return InvalidationKind::Descendant;
+ return InvalidationKind::Descendant(DescendantInvalidationKind::Dom);
}
- if self.selector.combinator_at_parse_order(self.offset - 1).is_ancestor() {
- InvalidationKind::Descendant
- } else {
- InvalidationKind::Sibling
+ match self.selector.combinator_at_parse_order(self.offset - 1) {
+ Combinator::Child |
+ Combinator::Descendant |
+ Combinator::PseudoElement => InvalidationKind::Descendant(DescendantInvalidationKind::Dom),
+ Combinator::SlotAssignment => InvalidationKind::Descendant(DescendantInvalidationKind::Slotted),
+ Combinator::NextSibling |
+ Combinator::LaterSibling => InvalidationKind::Sibling,
}
}
}
@@ -230,7 +264,7 @@ where
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
let mut self_invalidations = InvalidationVector::new();
- let mut descendant_invalidations = InvalidationVector::new();
+ let mut descendant_invalidations = DescendantInvalidationLists::default();
let mut sibling_invalidations = InvalidationVector::new();
let mut invalidated_self = self.processor.collect_invalidations(
@@ -242,7 +276,7 @@ where
debug!("Collected invalidations (self: {}): ", invalidated_self);
debug!(" > self: {}, {:?}", self_invalidations.len(), self_invalidations);
- debug!(" > descendants: {}, {:?}", descendant_invalidations.len(), descendant_invalidations);
+ debug!(" > descendants: {:?}", descendant_invalidations);
debug!(" > siblings: {}, {:?}", sibling_invalidations.len(), sibling_invalidations);
let invalidated_self_from_collection = invalidated_self;
@@ -251,6 +285,7 @@ where
&self_invalidations,
&mut descendant_invalidations,
&mut sibling_invalidations,
+ DescendantInvalidationKind::Dom,
);
if invalidated_self && !invalidated_self_from_collection {
@@ -260,7 +295,11 @@ where
let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
- InvalidationResult { invalidated_self, invalidated_descendants, invalidated_siblings }
+ InvalidationResult {
+ invalidated_self,
+ invalidated_descendants,
+ invalidated_siblings,
+ }
}
/// Go through later DOM siblings, invalidating style as needed using the
@@ -286,7 +325,8 @@ where
self.processor,
);
- let mut invalidations_for_descendants = InvalidationVector::new();
+ let mut invalidations_for_descendants =
+ DescendantInvalidationLists::default();
let invalidated_sibling =
sibling_invalidator.process_sibling_invalidations(
&mut invalidations_for_descendants,
@@ -301,7 +341,7 @@ where
any_invalidated |=
sibling_invalidator.invalidate_descendants(
- &invalidations_for_descendants
+ &invalidations_for_descendants,
);
if sibling_invalidations.is_empty() {
@@ -324,7 +364,8 @@ where
let result = self.invalidate_child(
child,
invalidations,
- &mut sibling_invalidations
+ &mut sibling_invalidations,
+ DescendantInvalidationKind::Dom,
);
// Roots of NAC subtrees can indeed generate sibling invalidations, but
@@ -344,8 +385,10 @@ where
child: E,
invalidations: &[Invalidation<'b>],
sibling_invalidations: &mut InvalidationVector<'b>,
+ descendant_invalidation_kind: DescendantInvalidationKind,
) -> bool {
- let mut invalidations_for_descendants = InvalidationVector::new();
+ let mut invalidations_for_descendants =
+ DescendantInvalidationLists::default();
let mut invalidated_child = false;
let invalidated_descendants = {
@@ -366,13 +409,16 @@ where
invalidations,
&mut invalidations_for_descendants,
sibling_invalidations,
+ descendant_invalidation_kind,
);
if invalidated_child {
child_invalidator.processor.invalidated_self(child);
}
- child_invalidator.invalidate_descendants(&invalidations_for_descendants)
+ child_invalidator.invalidate_descendants(
+ &invalidations_for_descendants,
+ )
};
// The child may not be a flattened tree child of the current element,
@@ -418,10 +464,6 @@ where
//
// This probably needs a shadow root check on `child` here, and
// recursing if that's the case.
- //
- // Also, what's the deal with HTML <content>? We don't need to
- // support that for now, though we probably need to recurse into the
- // distributed children too.
let child = match child.as_element() {
Some(e) => e,
None => continue,
@@ -431,15 +473,14 @@ where
child,
invalidations,
&mut sibling_invalidations,
+ DescendantInvalidationKind::Dom,
);
}
any_descendant
}
- /// Given a descendant invalidation list, go through the current element's
- /// descendants, and invalidate style on them.
- fn invalidate_descendants(
+ fn invalidate_slotted_elements(
&mut self,
invalidations: &[Invalidation<'b>],
) -> bool {
@@ -447,22 +488,40 @@ where
return false;
}
- debug!("StyleTreeInvalidator::invalidate_descendants({:?})",
- self.element);
- debug!(" > {:?}", invalidations);
+ let mut any = false;
- let should_process =
- self.processor.should_process_descendants(self.element);
+ let mut sibling_invalidations = InvalidationVector::new();
+ let element = self.element;
+ for node in element.slotted_nodes() {
+ let element = match node.as_element() {
+ Some(e) => e,
+ None => continue,
+ };
- if !should_process {
- return false;
+ any |= self.invalidate_child(
+ element,
+ invalidations,
+ &mut sibling_invalidations,
+ DescendantInvalidationKind::Slotted,
+ );
+
+ debug_assert!(
+ sibling_invalidations.is_empty(),
+ "::slotted() shouldn't have sibling combinators to the right, \
+ this makes no sense! {:?}",
+ sibling_invalidations
+ );
}
- if let Some(checker) = self.stack_limit_checker {
- if checker.limit_exceeded() {
- self.processor.recursion_limit_exceeded(self.element);
- return true;
- }
+ any
+ }
+
+ fn invalidate_non_slotted_descendants(
+ &mut self,
+ invalidations: &[Invalidation<'b>],
+ ) -> bool {
+ if invalidations.is_empty() {
+ return false;
}
if self.processor.light_tree_only() {
@@ -477,8 +536,6 @@ where
self.invalidate_dom_descendants_of(anon_content, invalidations);
}
- // TODO(emilio): Having a list of invalidations just for pseudo-elements
- // may save some work here and there.
if let Some(before) = self.element.before_pseudo_element() {
any_descendant |=
self.invalidate_pseudo_element_or_nac(before, invalidations);
@@ -498,6 +555,44 @@ where
any_descendant
}
+ /// Given the descendant invalidation lists, go through the current
+ /// element's descendants, and invalidate style on them.
+ fn invalidate_descendants(
+ &mut self,
+ invalidations: &DescendantInvalidationLists<'b>,
+ ) -> bool {
+ if invalidations.is_empty() {
+ return false;
+ }
+
+ debug!("StyleTreeInvalidator::invalidate_descendants({:?})",
+ self.element);
+ debug!(" > {:?}", invalidations);
+
+ let should_process =
+ self.processor.should_process_descendants(self.element);
+
+ if !should_process {
+ return false;
+ }
+
+ if let Some(checker) = self.stack_limit_checker {
+ if checker.limit_exceeded() {
+ self.processor.recursion_limit_exceeded(self.element);
+ return true;
+ }
+ }
+
+ let mut any_descendant = false;
+
+ any_descendant |=
+ self.invalidate_non_slotted_descendants(&invalidations.dom_descendants);
+ any_descendant |=
+ self.invalidate_slotted_elements(&invalidations.slotted_descendants);
+
+ any_descendant
+ }
+
/// Process the given sibling invalidations coming from our previous
/// sibling.
///
@@ -511,7 +606,7 @@ where
/// Returns whether invalidated the current element's style.
fn process_sibling_invalidations(
&mut self,
- descendant_invalidations: &mut InvalidationVector<'b>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
sibling_invalidations: &mut InvalidationVector<'b>,
) -> bool {
let mut i = 0;
@@ -547,8 +642,9 @@ where
fn process_descendant_invalidations(
&mut self,
invalidations: &[Invalidation<'b>],
- descendant_invalidations: &mut InvalidationVector<'b>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
sibling_invalidations: &mut InvalidationVector<'b>,
+ descendant_invalidation_kind: DescendantInvalidationKind,
) -> bool {
let mut invalidated = false;
@@ -557,14 +653,19 @@ where
invalidation,
descendant_invalidations,
sibling_invalidations,
- InvalidationKind::Descendant,
+ InvalidationKind::Descendant(descendant_invalidation_kind),
);
invalidated |= result.invalidated_self;
if invalidation.effective_for_next() {
let mut invalidation = invalidation.clone();
invalidation.matched_by_any_previous |= result.matched;
- descendant_invalidations.push(invalidation.clone());
+ debug_assert_eq!(
+ descendant_invalidation_kind,
+ DescendantInvalidationKind::Dom,
+ "Slotted invalidations don't propagate."
+ );
+ descendant_invalidations.dom_descendants.push(invalidation);
}
}
@@ -580,7 +681,7 @@ where
fn process_invalidation(
&mut self,
invalidation: &Invalidation<'b>,
- descendant_invalidations: &mut InvalidationVector<'b>,
+ descendant_invalidations: &mut DescendantInvalidationLists<'b>,
sibling_invalidations: &mut InvalidationVector<'b>,
invalidation_kind: InvalidationKind,
) -> SingleInvalidationResult {
@@ -732,8 +833,11 @@ where
already been matched before");
} else {
match next_invalidation_kind {
- InvalidationKind::Descendant => {
- descendant_invalidations.push(next_invalidation);
+ InvalidationKind::Descendant(DescendantInvalidationKind::Dom) => {
+ descendant_invalidations.dom_descendants.push(next_invalidation);
+ }
+ InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => {
+ descendant_invalidations.slotted_descendants.push(next_invalidation);
}
InvalidationKind::Sibling => {
sibling_invalidations.push(next_invalidation);