Break TraversalFlags::ForReconstruct down into several independent pieces.

These will be useful in followup work.

MozReview-Commit-ID: Dyp9R0PG36v
This commit is contained in:
Bobby Holley 2017-07-26 16:57:13 -07:00
parent 5c6d3b820e
commit 6148db670b
3 changed files with 41 additions and 30 deletions

View file

@ -302,8 +302,8 @@ trait PrivateMatchMethods: TElement {
new_values: &Arc<ComputedValues>,
pseudo: Option<&PseudoElement>)
-> ChildCascadeRequirement {
// Don't accumulate damage if we're in a restyle for reconstruction.
if shared_context.traversal_flags.contains(traversal_flags::ForReconstruct) {
// Don't accumulate damage if we're in a forgetful traversal.
if shared_context.traversal_flags.contains(traversal_flags::Forgetful) {
return ChildCascadeRequirement::MustCascadeChildren;
}
@ -499,8 +499,8 @@ pub trait MatchMethods : TElement {
}
}
// Don't accumulate damage if we're in a restyle for reconstruction.
if context.shared.traversal_flags.contains(traversal_flags::ForReconstruct) {
// Don't accumulate damage if we're in a forgetful traversal.
if context.shared.traversal_flags.contains(traversal_flags::Forgetful) {
return ChildCascadeRequirement::MustCascadeChildren;
}

View file

@ -170,11 +170,6 @@ pub trait DomTraversal<E: TElement> : Sync {
shared_context: &SharedStyleContext,
traversal_flags: TraversalFlags
) -> PreTraverseToken {
debug_assert!(!(traversal_flags.contains(traversal_flags::ForReconstruct) &&
traversal_flags.contains(traversal_flags::UnstyledChildrenOnly)),
"must not specify FOR_RECONSTRUCT in combination with \
UNSTYLED_CHILDREN_ONLY");
if traversal_flags.contains(traversal_flags::UnstyledChildrenOnly) {
if root.borrow_data().map_or(true, |d| d.has_styles() && d.styles.is_display_none()) {
return PreTraverseToken {
@ -314,9 +309,11 @@ pub trait DomTraversal<E: TElement> : Sync {
// to traverse any element with damage so that we can perform fixup /
// reconstruction on our way back up the tree.
//
// We also need to traverse nodes with explicit damage and no other
// restyle data, so that this damage can be cleared.
if (cfg!(feature = "servo") || traversal_flags.contains(traversal_flags::ForReconstruct)) &&
// In aggressively forgetful traversals (where we seek out and clear damage
// in addition to not computing it) we also need to traverse nodes with
// explicit damage and no other restyle data, so that this damage can be cleared.
if (cfg!(feature = "servo") ||
traversal_flags.contains(traversal_flags::AggressivelyForgetful)) &&
!data.restyle.damage.is_empty() {
return true;
}
@ -566,7 +563,6 @@ where
// * We generated a reconstruct hint on self (which could mean that we
// switched from display:none to something else, which means the children
// need initial styling).
// * This is a reconstruct traversal.
// * This is a servo non-incremental traversal.
//
// Additionally, there are a few scenarios where we avoid traversing the
@ -576,7 +572,6 @@ where
!propagated_hint.is_empty() ||
context.thread_local.is_initial_style() ||
data.restyle.reconstructed_self() ||
flags.contains(traversal_flags::ForReconstruct) ||
is_servo_nonincremental_layout();
traverse_children = traverse_children &&
@ -594,17 +589,18 @@ where
);
}
// If we are in a restyle for reconstruction, drop the existing restyle
// If we are in a forgetful traversal, drop the existing restyle
// data here, since we won't need to perform a post-traversal to pick up
// any change hints.
if context.shared.traversal_flags.contains(traversal_flags::ForReconstruct) {
if flags.contains(traversal_flags::Forgetful) {
data.clear_restyle_state();
}
// There are two cases when we want to clear the dity descendants bit here
// after styling this element.
// after styling this element. The first case is when we were explicitly
// asked to clear the bit by the caller.
//
// The first case is when this element is the root of a display:none
// The second case is when this element is the root of a display:none
// subtree, even if the style didn't change (since, if the style did change,
// we'd have already cleared it above).
//
@ -613,14 +609,16 @@ where
// moderately expensive). Instead, DOM implementations can unconditionally
// set the dirty descendants bit on any styled parent, and let the traversal
// sort it out.
//
// The second case is when we are in a restyle for reconstruction, where we
// won't need to perform a post-traversal to pick up any change hints.
if data.styles.is_display_none() ||
context.shared.traversal_flags.contains(traversal_flags::ForReconstruct) {
if flags.contains(traversal_flags::ClearDirtyDescendants) ||
data.styles.is_display_none() {
unsafe { element.unset_dirty_descendants(); }
}
// Similarly, check if we're supposed to clear the animation bit.
if flags.contains(traversal_flags::ClearAnimationOnlyDirtyDescendants) {
unsafe { element.unset_animation_only_dirty_descendants(); }
}
context.thread_local.end_element(element);
}
@ -777,10 +775,9 @@ where
// Set the dirty descendants bit on the parent as needed, so that we
// can find elements during the post-traversal.
//
// If we are in a restyle for reconstruction, there is no need to
// perform a post-traversal, so we don't need to set the dirty
// descendants bit on the parent.
if !flags.contains(traversal_flags::ForReconstruct) && !is_initial_style {
// Note that these bits may be cleared again at the bottom of
// recalc_style_at if requested by the caller.
if !is_initial_style {
if flags.for_animation_only() {
unsafe { element.set_animation_only_dirty_descendants(); }
} else {

View file

@ -18,8 +18,18 @@ bitflags! {
const ForCSSRuleChanges = 1 << 1,
/// Traverse only unstyled children of the root and their descendants.
const UnstyledChildrenOnly = 1 << 2,
/// FIXME(bholley): This will go away.
const ForReconstruct = 1 << 3,
/// A forgetful traversal ignores the previous state of the frame tree, and
/// thus does not compute damage or maintain other state describing the styles
/// pre-traversal. A forgetful traversal is usually the right thing if you
/// aren't going to do a post-traversal.
const Forgetful = 1 << 3,
/// Actively seeks out and clears change hints that may have been posted into
/// the tree. Nonsensical without also passing Forgetful.
const AggressivelyForgetful = 1 << 4,
/// Clears the dirty descendants bit in the subtree.
const ClearDirtyDescendants = 1 << 5,
/// Clears the animation-only dirty descendants bit in the subtree.
const ClearAnimationOnlyDirtyDescendants = 1 << 6,
}
}
@ -46,7 +56,11 @@ pub fn assert_traversal_flags_match() {
ServoTraversalFlags_AnimationOnly => AnimationOnly,
ServoTraversalFlags_ForCSSRuleChanges => ForCSSRuleChanges,
ServoTraversalFlags_UnstyledChildrenOnly => UnstyledChildrenOnly,
ServoTraversalFlags_ForReconstruct => ForReconstruct,
ServoTraversalFlags_Forgetful => Forgetful,
ServoTraversalFlags_AggressivelyForgetful => AggressivelyForgetful,
ServoTraversalFlags_ClearDirtyDescendants => ClearDirtyDescendants,
ServoTraversalFlags_ClearAnimationOnlyDirtyDescendants =>
ClearAnimationOnlyDirtyDescendants,
}
}