From f0bf7d6481a97bd75264af3d379bff5338d174b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 11 Jun 2019 17:41:51 +0000 Subject: [PATCH] style: Add plumbing code to invalidate shadow parts. Still does nothing, since we still do not collect part rules, but this is all the plumbing that should allow us to invalidate parts when attributes or state change on their ancestors. Differential Revision: https://phabricator.services.mozilla.com/D32642 --- components/style/dom.rs | 8 ++++ components/style/gecko/wrapper.rs | 15 +++++++ .../invalidation/element/invalidation_map.rs | 4 +- .../style/invalidation/element/invalidator.rs | 45 +++++++++++++++++-- .../element/state_and_attributes.rs | 4 ++ 5 files changed, 72 insertions(+), 4 deletions(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index 04d6a79b384..0a743c60207 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -346,6 +346,14 @@ pub trait TShadowRoot: Sized + Copy + Clone + PartialEq { where Self: 'a; + /// Get the list of shadow parts for this shadow root. + fn parts<'a>(&self) -> &[::ConcreteElement] + where + Self: 'a + { + &[] + } + /// Get a list of elements with a given ID in this shadow root, sorted by /// tree position. /// diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 3ce9e6fe6ab..aa59df56bde 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -185,6 +185,21 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> { bindings::Gecko_ShadowRoot_GetElementsWithId(self.0, id.as_ptr()) })) } + + #[inline] + fn parts<'a>(&self) -> &[::ConcreteElement] + where + Self: 'a + { + let slice: &[*const RawGeckoElement] = &*self.0.mParts; + + #[allow(dead_code)] + unsafe fn static_assert() { + mem::transmute::<*const RawGeckoElement, GeckoElement<'static>>(0xbadc0de as *const _); + } + + unsafe { mem::transmute(slice) } + } } /// A simple wrapper over a non-null Gecko node (`nsINode`) pointer. diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index 63d6eb6acc4..e0b9cf8d747 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -66,6 +66,8 @@ pub enum DependencyInvalidationKind { Siblings, /// This dependency may affect slotted elements of the element that changed. SlottedElements, + /// This dependency may affect parts of the element that changed. + Parts, } impl Dependency { @@ -98,7 +100,7 @@ impl Dependency { // an eager pseudo, and return only Descendants here if not. Some(Combinator::PseudoElement) => DependencyInvalidationKind::ElementAndDescendants, Some(Combinator::SlotAssignment) => DependencyInvalidationKind::SlottedElements, - Some(Combinator::Part) => unimplemented!("Need to add invalidation for shadow parts"), + Some(Combinator::Part) => DependencyInvalidationKind::Parts, } } } diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index ec1548f4aa3..f00aa57fcff 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -72,11 +72,14 @@ pub struct DescendantInvalidationLists<'a> { pub dom_descendants: InvalidationVector<'a>, /// Invalidations for slotted children of an element. pub slotted_descendants: InvalidationVector<'a>, + /// Invalidations for ::part()s of an element. + pub parts: InvalidationVector<'a>, } impl<'a> DescendantInvalidationLists<'a> { fn is_empty(&self) -> bool { - self.dom_descendants.is_empty() && self.slotted_descendants.is_empty() + self.dom_descendants.is_empty() && self.slotted_descendants.is_empty() && + self.parts.is_empty() } } @@ -104,6 +107,8 @@ enum DescendantInvalidationKind { Dom, /// A ::slotted() descendant invalidation. Slotted, + /// A ::part() descendant invalidation. + Part, } /// The kind of invalidation we're processing. @@ -175,7 +180,7 @@ impl<'a> Invalidation<'a> { InvalidationKind::Descendant(DescendantInvalidationKind::Dom) }, Combinator::Part => { - unimplemented!("Need to add invalidation for shadow parts"); + InvalidationKind::Descendant(DescendantInvalidationKind::Part) }, Combinator::SlotAssignment => { InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) @@ -472,6 +477,36 @@ where any_descendant } + fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool { + if invalidations.is_empty() { + return false; + } + + let shadow = match self.element.shadow_root() { + Some(s) => s, + None => return false, + }; + + let mut any = false; + let mut sibling_invalidations = InvalidationVector::new(); + for element in shadow.parts() { + any |= self.invalidate_child( + *element, + invalidations, + &mut sibling_invalidations, + DescendantInvalidationKind::Part, + ); + debug_assert!( + sibling_invalidations.is_empty(), + "::part() shouldn't have sibling combinators to the right, \ + this makes no sense! {:?}", + sibling_invalidations + ); + } + any + } + + fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool { if invalidations.is_empty() { return false; @@ -598,6 +633,7 @@ where any_descendant |= self.invalidate_non_slotted_descendants(&invalidations.dom_descendants); any_descendant |= self.invalidate_slotted_elements(&invalidations.slotted_descendants); + any_descendant |= self.invalidate_parts(&invalidations.parts); any_descendant } @@ -672,7 +708,7 @@ where debug_assert_eq!( descendant_invalidation_kind, DescendantInvalidationKind::Dom, - "Slotted invalidations don't propagate." + "Slotted or part invalidations don't propagate." ); descendant_invalidations.dom_descendants.push(invalidation); } @@ -860,6 +896,9 @@ where .dom_descendants .push(next_invalidation); }, + InvalidationKind::Descendant(DescendantInvalidationKind::Part) => { + descendant_invalidations.parts.push(next_invalidation); + }, InvalidationKind::Descendant(DescendantInvalidationKind::Slotted) => { descendant_invalidations .slotted_descendants diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index a49bb6306c5..eccc5f60bbf 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -472,6 +472,9 @@ where DependencyInvalidationKind::Siblings => { self.sibling_invalidations.push(invalidation); }, + DependencyInvalidationKind::Parts => { + self.descendant_invalidations.parts.push(invalidation); + }, DependencyInvalidationKind::SlottedElements => { self.descendant_invalidations .slotted_descendants @@ -486,6 +489,7 @@ where match dependency.invalidation_kind() { DependencyInvalidationKind::Element => !self.invalidates_self, DependencyInvalidationKind::SlottedElements => self.element.is_html_slot_element(), + DependencyInvalidationKind::Parts => self.element.shadow_root().is_some(), DependencyInvalidationKind::ElementAndDescendants | DependencyInvalidationKind::Siblings | DependencyInvalidationKind::Descendants => true,