Auto merge of #18173 - emilio:invalidation-dirty-thingie, r=bholley

style: Keep dirty bit invariants during invalidation.

There's the question of whether should we be recursing into the invalidation
code for elements without data... Probably not, but that's a somewhat more
risky change.

Bug: 1391444

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18173)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-08-21 13:21:20 -05:00 committed by GitHub
commit 05f2001914

View file

@ -29,6 +29,15 @@ pub struct TreeStyleInvalidator<'a, 'b: 'a, E>
where E: TElement, where E: TElement,
{ {
element: E, element: E,
// TODO(emilio): It's tempting enough to just avoid running invalidation for
// elements without data.
//
// But that's be wrong for sibling invalidations when a new element has been
// inserted in the tree and still has no data (though I _think_ the slow
// selector bits save us, it'd be nice not to depend on them).
//
// Seems like we could at least avoid running invalidation for the
// descendants if an element has no data, though.
data: Option<&'a mut ElementData>, data: Option<&'a mut ElementData>,
shared_context: &'a SharedStyleContext<'b>, shared_context: &'a SharedStyleContext<'b>,
} }
@ -353,7 +362,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
// //
// Since we keep the traversal flags in terms of the flattened tree, // Since we keep the traversal flags in terms of the flattened tree,
// we need to propagate it as appropriate. // we need to propagate it as appropriate.
if invalidated_child { if invalidated_child && child.get_data().is_some() {
let mut current = child.traversal_parent(); let mut current = child.traversal_parent();
while let Some(parent) = current.take() { while let Some(parent) = current.take() {
if parent == self.element { if parent == self.element {
@ -470,7 +479,7 @@ impl<'a, 'b: 'a, E> TreeStyleInvalidator<'a, 'b, E>
any_descendant |= self.invalidate_nac(invalidations); any_descendant |= self.invalidate_nac(invalidations);
if any_descendant { if any_descendant && self.data.as_ref().map_or(false, |d| !d.styles.is_display_none()) {
unsafe { self.element.set_dirty_descendants() }; unsafe { self.element.set_dirty_descendants() };
} }