style: Invalidate parts in nested shadow trees correctly.

Differential Revision: https://phabricator.services.mozilla.com/D54010
This commit is contained in:
Emilio Cobos Álvarez 2019-11-21 10:32:10 +00:00
parent e3009a4de9
commit f8ceb5cb84
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
6 changed files with 104 additions and 43 deletions

View file

@ -62,6 +62,12 @@ pub trait ElementSnapshot: Sized {
/// called if `has_attrs()` returns true.
fn is_part(&self, name: &Atom) -> bool;
/// See Element::exported_part.
fn exported_part(&self, name: &Atom) -> Option<Atom>;
/// See Element::imported_part.
fn imported_part(&self, name: &Atom) -> Option<Atom>;
/// A callback that should be called for each class of the snapshot. Should
/// only be called if `has_attrs()` returns true.
fn each_class<F>(&self, _: F)
@ -366,13 +372,17 @@ where
}
fn exported_part(&self, name: &Atom) -> Option<Atom> {
// FIXME(emilio): Implement for proper invalidation.
self.element.exported_part(name)
match self.snapshot() {
Some(snapshot) if snapshot.has_attrs() => snapshot.exported_part(name),
_ => self.element.exported_part(name),
}
}
fn imported_part(&self, name: &Atom) -> Option<Atom> {
// FIXME(emilio): Implement for proper invalidation.
self.element.imported_part(name)
match self.snapshot() {
Some(snapshot) if snapshot.has_attrs() => snapshot.imported_part(name),
_ => self.element.imported_part(name),
}
}
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {

View file

@ -129,6 +129,10 @@ enum InvalidationKind {
pub struct Invalidation<'a> {
selector: &'a Selector<SelectorImpl>,
/// The right shadow host from where the rule came from, if any.
///
/// This is needed to ensure that we match the selector with the right
/// state, as whether some selectors like :host and ::part() match depends
/// on it.
scope: Option<OpaqueElement>,
/// The offset of the selector pointing to a compound selector.
///
@ -479,6 +483,47 @@ where
any_descendant
}
fn invalidate_parts_in_shadow_tree(
&mut self,
shadow: <E::ConcreteNode as TNode>::ConcreteShadowRoot,
invalidations: &[Invalidation<'b>],
) -> bool {
debug_assert!(!invalidations.is_empty());
let mut any = false;
let mut sibling_invalidations = InvalidationVector::new();
for node in shadow.as_node().dom_descendants() {
let element = match node.as_element() {
Some(e) => e,
None => continue,
};
if element.has_part_attr() {
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
);
}
if let Some(shadow) = element.shadow_root() {
if element.exports_any_part() {
any |= self.invalidate_parts_in_shadow_tree(shadow, invalidations)
}
}
}
any
}
fn invalidate_parts(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
if invalidations.is_empty() {
return false;
@ -489,26 +534,7 @@ where
None => return false,
};
let mut any = false;
let mut sibling_invalidations = InvalidationVector::new();
// FIXME(emilio): We also need to invalidate parts in descendant shadow
// hosts that have exportparts attributes.
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
self.invalidate_parts_in_shadow_tree(shadow, invalidations)
}
fn invalidate_slotted_elements(&mut self, invalidations: &[Invalidation<'b>]) -> bool {
@ -733,7 +759,7 @@ where
);
let matching_result = {
let mut context = self.processor.matching_context();
let context = self.processor.matching_context();
context.current_host = invalidation.scope;
matches_compound_selector_from(