aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/invalidation/element
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2019-11-21 10:32:10 +0000
committerEmilio Cobos Álvarez <emilio@crisal.io>2019-11-30 20:45:03 +0100
commitf8ceb5cb8409f434ec4acec8ab9c186bea45bcbe (patch)
tree53a411befd1ed157af6d2126f88991b25f5e1a8a /components/style/invalidation/element
parente3009a4de9186c648c0a3beef4fdde6ce66b1a3b (diff)
downloadservo-f8ceb5cb8409f434ec4acec8ab9c186bea45bcbe.tar.gz
servo-f8ceb5cb8409f434ec4acec8ab9c186bea45bcbe.zip
style: Invalidate parts in nested shadow trees correctly.
Differential Revision: https://phabricator.services.mozilla.com/D54010
Diffstat (limited to 'components/style/invalidation/element')
-rw-r--r--components/style/invalidation/element/element_wrapper.rs18
-rw-r--r--components/style/invalidation/element/invalidator.rs68
2 files changed, 61 insertions, 25 deletions
diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs
index e17e42a31c0..bc74527bf16 100644
--- a/components/style/invalidation/element/element_wrapper.rs
+++ b/components/style/invalidation/element/element_wrapper.rs
@@ -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 {
diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs
index 9e8309396cd..8bc898f9587 100644
--- a/components/style/invalidation/element/invalidator.rs
+++ b/components/style/invalidation/element/invalidator.rs
@@ -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(