Bug 1505489 - Add plumbing code to invalidate shadow parts. r=heycam

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.

Depends on D32641

Differential Revision: https://phabricator.services.mozilla.com/D32642

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2019-06-11 17:41:51 +00:00
parent c4dbe4893c
commit 103cf22ede
5 changed files with 72 additions and 4 deletions

View File

@ -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) -> &[<Self::ConcreteNode as TNode>::ConcreteElement]
where
Self: 'a
{
&[]
}
/// Get a list of elements with a given ID in this shadow root, sorted by
/// tree position.
///

View File

@ -185,6 +185,21 @@ impl<'lr> TShadowRoot for GeckoShadowRoot<'lr> {
bindings::Gecko_ShadowRoot_GetElementsWithId(self.0, id.as_ptr())
}))
}
#[inline]
fn parts<'a>(&self) -> &[<Self::ConcreteNode as TNode>::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.

View File

@ -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,
}
}
}

View File

@ -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

View File

@ -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,