mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
style: Invalidate style using the DOM tree, and scan pseudo-elements and NAC separately.
Bug: 1371130 Reviewed-By: heycam MozReview-Commit-ID: IU1TbVf4Zz9
This commit is contained in:
parent
b894c361e0
commit
459b22a985
1 changed files with 116 additions and 10 deletions
|
@ -270,6 +270,86 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
any_invalidated
|
any_invalidated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invalidate_pseudo_element_or_nac(
|
||||||
|
&mut self,
|
||||||
|
child: E,
|
||||||
|
invalidations: &InvalidationVector
|
||||||
|
) -> bool {
|
||||||
|
let mut child_data = child.mutate_data();
|
||||||
|
let child_data = child_data.as_mut().map(|d| &mut **d);
|
||||||
|
|
||||||
|
let mut child_invalidator = TreeStyleInvalidator::new(
|
||||||
|
child,
|
||||||
|
child_data,
|
||||||
|
self.shared_context
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||||
|
let mut sibling_invalidations = InvalidationVector::new();
|
||||||
|
|
||||||
|
let invalidated = child_invalidator.process_descendant_invalidations(
|
||||||
|
invalidations,
|
||||||
|
&mut invalidations_for_descendants,
|
||||||
|
&mut sibling_invalidations,
|
||||||
|
);
|
||||||
|
|
||||||
|
debug_assert!(child.implemented_pseudo_element().is_none() ||
|
||||||
|
sibling_invalidations.is_empty(),
|
||||||
|
"pseudos can't generate sibling invalidations, since \
|
||||||
|
using them in other position that isn't the \
|
||||||
|
rightmost part of the selector is invalid \
|
||||||
|
(for now at least)");
|
||||||
|
|
||||||
|
// For NAC roots, we can ignore sibling invalidations, since they don't
|
||||||
|
// have any siblings.
|
||||||
|
|
||||||
|
let invalidated_children =
|
||||||
|
child_invalidator.invalidate_descendants(
|
||||||
|
&invalidations_for_descendants
|
||||||
|
);
|
||||||
|
|
||||||
|
invalidated || invalidated_children
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate_pseudo_elements_and_nac(
|
||||||
|
&mut self,
|
||||||
|
invalidations: &InvalidationVector
|
||||||
|
) -> bool {
|
||||||
|
let mut any_pseudo = false;
|
||||||
|
|
||||||
|
if let Some(before) = self.element.before_pseudo_element() {
|
||||||
|
any_pseudo |=
|
||||||
|
self.invalidate_pseudo_element_or_nac(before, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(after) = self.element.after_pseudo_element() {
|
||||||
|
any_pseudo |=
|
||||||
|
self.invalidate_pseudo_element_or_nac(after, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
|
let element = self.element;
|
||||||
|
element.each_anonymous_content_child(|pseudo| {
|
||||||
|
let invalidated =
|
||||||
|
self.invalidate_pseudo_element_or_nac(pseudo, invalidations);
|
||||||
|
|
||||||
|
if invalidated {
|
||||||
|
let mut current = pseudo.traversal_parent();
|
||||||
|
while let Some(parent) = current.take() {
|
||||||
|
if parent == self.element {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { parent.set_dirty_descendants() };
|
||||||
|
current = parent.traversal_parent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
any_pseudo |= invalidated;
|
||||||
|
});
|
||||||
|
|
||||||
|
any_pseudo
|
||||||
|
}
|
||||||
|
|
||||||
/// Given a descendant invalidation list, go through the current element's
|
/// Given a descendant invalidation list, go through the current element's
|
||||||
/// descendants, and invalidate style on them.
|
/// descendants, and invalidate style on them.
|
||||||
fn invalidate_descendants(
|
fn invalidate_descendants(
|
||||||
|
@ -296,7 +376,9 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
let mut sibling_invalidations = InvalidationVector::new();
|
let mut sibling_invalidations = InvalidationVector::new();
|
||||||
|
|
||||||
let mut any_children = false;
|
let mut any_children = false;
|
||||||
for child in self.element.as_node().traversal_children() {
|
|
||||||
|
// NB: DOM children!
|
||||||
|
for child in self.element.as_node().children() {
|
||||||
let child = match child.as_element() {
|
let child = match child.as_element() {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => continue,
|
None => continue,
|
||||||
|
@ -312,22 +394,46 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||||
any_children |= child_invalidator.process_sibling_invalidations(
|
let mut invalidated_child = false;
|
||||||
&mut invalidations_for_descendants,
|
|
||||||
&mut sibling_invalidations,
|
|
||||||
);
|
|
||||||
|
|
||||||
any_children |= child_invalidator.process_descendant_invalidations(
|
invalidated_child |=
|
||||||
invalidations,
|
child_invalidator.process_sibling_invalidations(
|
||||||
&mut invalidations_for_descendants,
|
&mut invalidations_for_descendants,
|
||||||
&mut sibling_invalidations,
|
&mut sibling_invalidations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
invalidated_child |=
|
||||||
|
child_invalidator.process_descendant_invalidations(
|
||||||
|
invalidations,
|
||||||
|
&mut invalidations_for_descendants,
|
||||||
|
&mut sibling_invalidations,
|
||||||
|
);
|
||||||
|
|
||||||
|
// The child may not be a flattened tree child of the current
|
||||||
|
// element, but may be arbitrarily deep.
|
||||||
|
//
|
||||||
|
// Since we keep the traversal flags in terms of the flattened tree,
|
||||||
|
// we need to propagate it as appropriate.
|
||||||
|
if invalidated_child {
|
||||||
|
let mut current = child.traversal_parent();
|
||||||
|
while let Some(parent) = current.take() {
|
||||||
|
if parent == self.element {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { parent.set_dirty_descendants() };
|
||||||
|
current = parent.traversal_parent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
any_children |= invalidated_child;
|
||||||
any_children |= child_invalidator.invalidate_descendants(
|
any_children |= child_invalidator.invalidate_descendants(
|
||||||
&invalidations_for_descendants
|
&invalidations_for_descendants
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
any_children |= self.invalidate_pseudo_elements_and_nac(invalidations);
|
||||||
|
|
||||||
if any_children {
|
if any_children {
|
||||||
unsafe { self.element.set_dirty_descendants() };
|
unsafe { self.element.set_dirty_descendants() };
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue