mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
style: Get rid of unstyled children only traversals.
They're useless now, provided we remove the hack to not traverse XBL-bound elements on initial styling. Bug: 1418456 Reviewed-by: heycam MozReview-Commit-ID: AvBVdyF1wb6
This commit is contained in:
parent
63bd783c55
commit
b1fecea0aa
4 changed files with 18 additions and 80 deletions
|
@ -557,11 +557,6 @@ pub trait TElement
|
||||||
!data.hint.has_animation_hint_or_recascade();
|
!data.hint.has_animation_hint_or_recascade();
|
||||||
}
|
}
|
||||||
|
|
||||||
if traversal_flags.contains(TraversalFlags::UnstyledOnly) {
|
|
||||||
// We don't process invalidations in UnstyledOnly mode.
|
|
||||||
return data.has_styles();
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.has_snapshot() && !self.handled_snapshot() {
|
if self.has_snapshot() && !self.handled_snapshot() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,13 +146,6 @@ pub trait DomTraversal<E: TElement> : Sync {
|
||||||
) -> PreTraverseToken<E> {
|
) -> PreTraverseToken<E> {
|
||||||
let traversal_flags = shared_context.traversal_flags;
|
let traversal_flags = shared_context.traversal_flags;
|
||||||
|
|
||||||
// If this is an unstyled-only traversal, the caller has already verified
|
|
||||||
// that there's something to traverse, and we don't need to do any
|
|
||||||
// invalidation since we're not doing any restyling.
|
|
||||||
if traversal_flags.contains(TraversalFlags::UnstyledOnly) {
|
|
||||||
return PreTraverseToken(Some(root))
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut data = root.mutate_data();
|
let mut data = root.mutate_data();
|
||||||
let mut data = data.as_mut().map(|d| &mut **d);
|
let mut data = data.as_mut().map(|d| &mut **d);
|
||||||
|
|
||||||
|
@ -208,11 +201,6 @@ pub trait DomTraversal<E: TElement> : Sync {
|
||||||
debug!("element_needs_traversal({:?}, {:?}, {:?})",
|
debug!("element_needs_traversal({:?}, {:?}, {:?})",
|
||||||
el, traversal_flags, data);
|
el, traversal_flags, data);
|
||||||
|
|
||||||
if traversal_flags.contains(TraversalFlags::UnstyledOnly) {
|
|
||||||
return data.map_or(true, |d| !d.has_styles()) || el.has_dirty_descendants();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// In case of animation-only traversal we need to traverse the element
|
// In case of animation-only traversal we need to traverse the element
|
||||||
// if the element has animation only dirty descendants bit,
|
// if the element has animation only dirty descendants bit,
|
||||||
// animation-only restyle hint or recascade.
|
// animation-only restyle hint or recascade.
|
||||||
|
@ -266,7 +254,6 @@ pub trait DomTraversal<E: TElement> : Sync {
|
||||||
&self,
|
&self,
|
||||||
context: &mut StyleContext<E>,
|
context: &mut StyleContext<E>,
|
||||||
parent: E,
|
parent: E,
|
||||||
is_initial_style: bool,
|
|
||||||
parent_data: &ElementData,
|
parent_data: &ElementData,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug_assert!(cfg!(feature = "gecko") ||
|
debug_assert!(cfg!(feature = "gecko") ||
|
||||||
|
@ -278,33 +265,6 @@ pub trait DomTraversal<E: TElement> : Sync {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gecko-only XBL handling.
|
|
||||||
//
|
|
||||||
// If we're computing initial styles and the parent has a Gecko XBL
|
|
||||||
// binding, that binding may inject anonymous children and remap the
|
|
||||||
// explicit children to an insertion point (or hide them entirely). It
|
|
||||||
// may also specify a scoped stylesheet, which changes the rules that
|
|
||||||
// apply within the subtree. These two effects can invalidate the result
|
|
||||||
// of property inheritance and selector matching (respectively) within
|
|
||||||
// the subtree.
|
|
||||||
//
|
|
||||||
// To avoid wasting work, we defer initial styling of XBL subtrees until
|
|
||||||
// frame construction, which does an explicit traversal of the unstyled
|
|
||||||
// children after shuffling the subtree. That explicit traversal may in
|
|
||||||
// turn find other bound elements, which get handled in the same way.
|
|
||||||
//
|
|
||||||
// We explicitly avoid handling restyles here (explicitly removing or
|
|
||||||
// changing bindings), since that adds complexity and is rarer. If it
|
|
||||||
// happens, we may just end up doing wasted work, since Gecko
|
|
||||||
// recursively drops Servo ElementData when the XBL insertion parent of
|
|
||||||
// an Element is changed.
|
|
||||||
if cfg!(feature = "gecko") && is_initial_style &&
|
|
||||||
parent_data.styles.primary().has_moz_binding()
|
|
||||||
{
|
|
||||||
debug!("Parent {:?} has XBL binding, deferring traversal", parent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +384,7 @@ where
|
||||||
let is_initial_style = !data.has_styles();
|
let is_initial_style = !data.has_styles();
|
||||||
|
|
||||||
context.thread_local.statistics.elements_traversed += 1;
|
context.thread_local.statistics.elements_traversed += 1;
|
||||||
debug_assert!(flags.intersects(TraversalFlags::AnimationOnly | TraversalFlags::UnstyledOnly) ||
|
debug_assert!(flags.intersects(TraversalFlags::AnimationOnly) ||
|
||||||
!element.has_snapshot() || element.handled_snapshot(),
|
!element.has_snapshot() || element.handled_snapshot(),
|
||||||
"Should've handled snapshots here already");
|
"Should've handled snapshots here already");
|
||||||
|
|
||||||
|
@ -471,15 +431,11 @@ where
|
||||||
// those operations and compute the propagated restyle hint (unless we're
|
// those operations and compute the propagated restyle hint (unless we're
|
||||||
// not processing invalidations, in which case don't need to propagate it
|
// not processing invalidations, in which case don't need to propagate it
|
||||||
// and must avoid clearing it).
|
// and must avoid clearing it).
|
||||||
let propagated_hint = if flags.contains(TraversalFlags::UnstyledOnly) {
|
debug_assert!(flags.for_animation_only() ||
|
||||||
RestyleHint::empty()
|
!data.hint.has_animation_hint(),
|
||||||
} else {
|
"animation restyle hint should be handled during \
|
||||||
debug_assert!(flags.for_animation_only() ||
|
animation-only restyles");
|
||||||
!data.hint.has_animation_hint(),
|
let propagated_hint = data.hint.propagate(&flags);
|
||||||
"animation restyle hint should be handled during \
|
|
||||||
animation-only restyles");
|
|
||||||
data.hint.propagate(&flags)
|
|
||||||
};
|
|
||||||
|
|
||||||
trace!("propagated_hint={:?}, cascade_requirement={:?}, \
|
trace!("propagated_hint={:?}, cascade_requirement={:?}, \
|
||||||
is_display_none={:?}, implementing_pseudo={:?}",
|
is_display_none={:?}, implementing_pseudo={:?}",
|
||||||
|
@ -518,7 +474,7 @@ where
|
||||||
|
|
||||||
traverse_children =
|
traverse_children =
|
||||||
traverse_children &&
|
traverse_children &&
|
||||||
!traversal.should_cull_subtree(context, element, is_initial_style, &data);
|
!traversal.should_cull_subtree(context, element, &data);
|
||||||
|
|
||||||
// Examine our children, and enqueue the appropriate ones for traversal.
|
// Examine our children, and enqueue the appropriate ones for traversal.
|
||||||
if traverse_children {
|
if traverse_children {
|
||||||
|
@ -800,12 +756,6 @@ where
|
||||||
propagated_hint,
|
propagated_hint,
|
||||||
child.implemented_pseudo_element());
|
child.implemented_pseudo_element());
|
||||||
|
|
||||||
// Make sure to not run style invalidation of styled elements in an
|
|
||||||
// unstyled-children-only traversal.
|
|
||||||
if child_data.is_some() && flags.intersects(TraversalFlags::UnstyledOnly) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref mut child_data) = child_data {
|
if let Some(ref mut child_data) = child_data {
|
||||||
let mut child_hint = propagated_hint;
|
let mut child_hint = propagated_hint;
|
||||||
match cascade_requirement {
|
match cascade_requirement {
|
||||||
|
|
|
@ -16,9 +16,6 @@ bitflags! {
|
||||||
/// Traverse and update all elements with CSS animations since
|
/// Traverse and update all elements with CSS animations since
|
||||||
/// @keyframes rules may have changed. Triggered by CSS rule changes.
|
/// @keyframes rules may have changed. Triggered by CSS rule changes.
|
||||||
const ForCSSRuleChanges = 1 << 1;
|
const ForCSSRuleChanges = 1 << 1;
|
||||||
/// Styles unstyled elements, but does not handle invalidations on
|
|
||||||
/// already-styled elements.
|
|
||||||
const UnstyledOnly = 1 << 2;
|
|
||||||
/// A forgetful traversal ignores the previous state of the frame tree, and
|
/// A forgetful traversal ignores the previous state of the frame tree, and
|
||||||
/// thus does not compute damage or maintain other state describing the styles
|
/// thus does not compute damage or maintain other state describing the styles
|
||||||
/// pre-traversal. A forgetful traversal is usually the right thing if you
|
/// pre-traversal. A forgetful traversal is usually the right thing if you
|
||||||
|
@ -61,7 +58,6 @@ pub fn assert_traversal_flags_match() {
|
||||||
check_traversal_flags! {
|
check_traversal_flags! {
|
||||||
ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly,
|
ServoTraversalFlags_AnimationOnly => TraversalFlags::AnimationOnly,
|
||||||
ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges,
|
ServoTraversalFlags_ForCSSRuleChanges => TraversalFlags::ForCSSRuleChanges,
|
||||||
ServoTraversalFlags_UnstyledOnly => TraversalFlags::UnstyledOnly,
|
|
||||||
ServoTraversalFlags_Forgetful => TraversalFlags::Forgetful,
|
ServoTraversalFlags_Forgetful => TraversalFlags::Forgetful,
|
||||||
ServoTraversalFlags_ClearDirtyBits => TraversalFlags::ClearDirtyBits,
|
ServoTraversalFlags_ClearDirtyBits => TraversalFlags::ClearDirtyBits,
|
||||||
ServoTraversalFlags_ClearAnimationOnlyDirtyDescendants =>
|
ServoTraversalFlags_ClearAnimationOnlyDirtyDescendants =>
|
||||||
|
|
|
@ -294,21 +294,18 @@ pub extern "C" fn Servo_TraverseSubtree(
|
||||||
|
|
||||||
debug!("Servo_TraverseSubtree (flags={:?})", traversal_flags);
|
debug!("Servo_TraverseSubtree (flags={:?})", traversal_flags);
|
||||||
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
||||||
// It makes no sense to do an animation restyle when we're styling
|
|
||||||
// newly-inserted content.
|
|
||||||
if !traversal_flags.contains(TraversalFlags::UnstyledOnly) {
|
|
||||||
let needs_animation_only_restyle =
|
|
||||||
element.has_animation_only_dirty_descendants() ||
|
|
||||||
element.has_animation_restyle_hints();
|
|
||||||
|
|
||||||
if needs_animation_only_restyle {
|
let needs_animation_only_restyle =
|
||||||
debug!("Servo_TraverseSubtree doing animation-only restyle (aodd={})",
|
element.has_animation_only_dirty_descendants() ||
|
||||||
element.has_animation_only_dirty_descendants());
|
element.has_animation_restyle_hints();
|
||||||
traverse_subtree(element,
|
|
||||||
raw_data,
|
if needs_animation_only_restyle {
|
||||||
traversal_flags | TraversalFlags::AnimationOnly,
|
debug!("Servo_TraverseSubtree doing animation-only restyle (aodd={})",
|
||||||
unsafe { &*snapshots });
|
element.has_animation_only_dirty_descendants());
|
||||||
}
|
traverse_subtree(element,
|
||||||
|
raw_data,
|
||||||
|
traversal_flags | TraversalFlags::AnimationOnly,
|
||||||
|
unsafe { &*snapshots });
|
||||||
}
|
}
|
||||||
|
|
||||||
traverse_subtree(element,
|
traverse_subtree(element,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue