style: Stop inspecting children to recascade them just because we reframed.

We only need to do this when display changes from none to non-none, so handle it
explicitly when computing the cascade requirement.

This patch also removes a few conditions that are redundant because they're
handled also by the cascade requirement check, like the initial styling.
This commit is contained in:
Emilio Cobos Álvarez 2017-11-09 16:02:59 +01:00
parent 5200ded17c
commit 3a5d70f106
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 21 additions and 16 deletions

View file

@ -13,6 +13,7 @@ use data::ElementData;
use dom::TElement; use dom::TElement;
use invalidation::element::restyle_hints::RestyleHint; use invalidation::element::restyle_hints::RestyleHint;
use properties::ComputedValues; use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use rule_tree::{CascadeLevel, StrongRuleNode}; use rule_tree::{CascadeLevel, StrongRuleNode};
use selector_parser::{PseudoElement, RestyleDamage}; use selector_parser::{PseudoElement, RestyleDamage};
use selectors::matching::ElementSelectorFlags; use selectors::matching::ElementSelectorFlags;
@ -142,8 +143,6 @@ trait PrivateMatchMethods: TElement {
old_values: Option<&Arc<ComputedValues>>, old_values: Option<&Arc<ComputedValues>>,
new_values: &ComputedValues, new_values: &ComputedValues,
) -> bool { ) -> bool {
use properties::longhands::display::computed_value as display;
let new_box_style = new_values.get_box(); let new_box_style = new_values.get_box();
let has_new_animation_style = new_box_style.specifies_animations(); let has_new_animation_style = new_box_style.specifies_animations();
let has_animations = self.has_css_animations(); let has_animations = self.has_css_animations();
@ -182,7 +181,6 @@ trait PrivateMatchMethods: TElement {
restyle_hints: RestyleHint restyle_hints: RestyleHint
) { ) {
use context::PostAnimationTasks; use context::PostAnimationTasks;
use properties::longhands::display::computed_value as display;
if !restyle_hints.intersects(RestyleHint::RESTYLE_SMIL) { if !restyle_hints.intersects(RestyleHint::RESTYLE_SMIL) {
return; return;
@ -365,6 +363,16 @@ trait PrivateMatchMethods: TElement {
let old_display = old_values.get_box().clone_display(); let old_display = old_values.get_box().clone_display();
let new_display = new_values.get_box().clone_display(); let new_display = new_values.get_box().clone_display();
// If we used to be a display: none element, and no longer are,
// our children need to be restyled because they're unstyled.
//
// NOTE(emilio): Gecko has the special-case of -moz-binding, but
// that gets handled on the frame constructor when processing
// the reframe, so no need to handle that here.
if old_display == display::T::none && old_display != new_display {
return ChildCascadeRequirement::MustCascadeChildren
}
// Blockification of children may depend on our display value, // Blockification of children may depend on our display value,
// so we need to actually do the recascade. We could potentially // so we need to actually do the recascade. We could potentially
// do better, but it doesn't seem worth it. // do better, but it doesn't seem worth it.

View file

@ -508,22 +508,19 @@ where
// Before examining each child individually, try to prove that our children // Before examining each child individually, try to prove that our children
// don't need style processing. They need processing if any of the following // don't need style processing. They need processing if any of the following
// conditions hold: // conditions hold:
//
// * We have the dirty descendants bit. // * We have the dirty descendants bit.
// * We're propagating a hint. // * We're propagating a restyle hint.
// * This is the initial style. // * We can't skip the cascade.
// * 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 servo non-incremental traversal. // * This is a servo non-incremental traversal.
// //
// Additionally, there are a few scenarios where we avoid traversing the // Additionally, there are a few scenarios where we avoid traversing the
// subtree even if descendant styles are out of date. These cases are // subtree even if descendant styles are out of date. These cases are
// enumerated in should_cull_subtree(). // enumerated in should_cull_subtree().
let mut traverse_children = has_dirty_descendants_for_this_restyle || let mut traverse_children =
has_dirty_descendants_for_this_restyle ||
!propagated_hint.is_empty() || !propagated_hint.is_empty() ||
!child_cascade_requirement.can_skip_cascade() || !child_cascade_requirement.can_skip_cascade() ||
context.thread_local.is_initial_style() ||
data.reconstructed_self() ||
is_servo_nonincremental_layout(); is_servo_nonincremental_layout();
traverse_children = traverse_children =