style: Restyle pseudo-elements as well on part attribute changes

Refactor a bit the code to unify how we deal with this conditional
restyling (we had similar code for
MustCascadeChildrenIfInheritResetStyle).

Differential Revision: https://phabricator.services.mozilla.com/D172890
This commit is contained in:
Emilio Cobos Álvarez 2023-03-27 18:17:56 +00:00 committed by Martin Robinson
parent 398df68d38
commit 78c1c53ccd
6 changed files with 132 additions and 180 deletions

View file

@ -4,6 +4,7 @@
//! Per-node data used in style calculation. //! Per-node data used in style calculation.
use crate::computed_value_flags::ComputedValueFlags;
use crate::context::{SharedStyleContext, StackLimitChecker}; use crate::context::{SharedStyleContext, StackLimitChecker};
use crate::dom::TElement; use crate::dom::TElement;
use crate::invalidation::element::invalidator::InvalidationResult; use crate::invalidation::element::invalidator::InvalidationResult;
@ -193,8 +194,6 @@ impl ElementStyles {
/// Whether this element uses viewport units. /// Whether this element uses viewport units.
pub fn viewport_unit_usage(&self) -> ViewportUnitUsage { pub fn viewport_unit_usage(&self) -> ViewportUnitUsage {
use crate::computed_value_flags::ComputedValueFlags;
fn usage_from_flags(flags: ComputedValueFlags) -> ViewportUnitUsage { fn usage_from_flags(flags: ComputedValueFlags) -> ViewportUnitUsage {
if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES) { if flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES) {
return ViewportUnitUsage::FromQuery; return ViewportUnitUsage::FromQuery;
@ -366,52 +365,88 @@ impl ElementData {
/// Returns the kind of restyling that we're going to need to do on this /// Returns the kind of restyling that we're going to need to do on this
/// element, based of the stored restyle hint. /// element, based of the stored restyle hint.
pub fn restyle_kind(&self, shared_context: &SharedStyleContext) -> RestyleKind { pub fn restyle_kind(&self, shared_context: &SharedStyleContext) -> Option<RestyleKind> {
if shared_context.traversal_flags.for_animation_only() { if shared_context.traversal_flags.for_animation_only() {
return self.restyle_kind_for_animation(shared_context); return self.restyle_kind_for_animation(shared_context);
} }
if !self.has_styles() { let style = match self.styles.primary {
return RestyleKind::MatchAndCascade; Some(ref s) => s,
None => return Some(RestyleKind::MatchAndCascade),
};
let hint = self.hint;
if hint.is_empty() {
return None;
} }
if self.hint.match_self() { let needs_to_match_self = hint.intersects(RestyleHint::RESTYLE_SELF) ||
return RestyleKind::MatchAndCascade; (hint.intersects(RestyleHint::RESTYLE_SELF_IF_PSEUDO) && style.is_pseudo_style());
if needs_to_match_self {
return Some(RestyleKind::MatchAndCascade);
} }
if self.hint.has_replacements() { if hint.has_replacements() {
debug_assert!( debug_assert!(
!self.hint.has_animation_hint(), !hint.has_animation_hint(),
"Animation only restyle hint should have already processed" "Animation only restyle hint should have already processed"
); );
return RestyleKind::CascadeWithReplacements(self.hint & RestyleHint::replacements()); return Some(RestyleKind::CascadeWithReplacements(
hint & RestyleHint::replacements(),
));
} }
debug_assert!( let needs_to_recascade_self = hint.intersects(RestyleHint::RECASCADE_SELF) ||
self.hint.has_recascade_self(), (hint.intersects(RestyleHint::RECASCADE_SELF_IF_INHERIT_RESET_STYLE) &&
"We definitely need to do something: {:?}!", style.flags.contains(ComputedValueFlags::INHERITS_RESET_STYLE));
self.hint if needs_to_recascade_self {
); return Some(RestyleKind::CascadeOnly);
return RestyleKind::CascadeOnly; }
None
} }
/// Returns the kind of restyling for animation-only restyle. /// Returns the kind of restyling for animation-only restyle.
fn restyle_kind_for_animation(&self, shared_context: &SharedStyleContext) -> RestyleKind { fn restyle_kind_for_animation(
&self,
shared_context: &SharedStyleContext,
) -> Option<RestyleKind> {
debug_assert!(shared_context.traversal_flags.for_animation_only()); debug_assert!(shared_context.traversal_flags.for_animation_only());
debug_assert!( debug_assert!(
self.has_styles(), self.has_styles(),
"Unstyled element shouldn't be traversed during \ "animation traversal doesn't care about unstyled elements"
animation-only traversal"
); );
// return either CascadeWithReplacements or CascadeOnly in case of // FIXME: We should ideally restyle here, but it is a hack to work around our weird
// animation-only restyle. I.e. animation-only restyle never does // animation-only traversal stuff: If we're display: none and the rules we could
// selector matching. // match could change, we consider our style up-to-date. This is because re-cascading with
if self.hint.has_animation_hint() { // and old style doesn't guarantee returning the correct animation style (that's
return RestyleKind::CascadeWithReplacements(self.hint & RestyleHint::for_animations()); // bug 1393323). So if our display changed, and it changed from display: none, we would
// incorrectly forget about it and wouldn't be able to correctly style our descendants
// later.
// XXX Figure out if this still makes sense.
let hint = self.hint;
if self.styles.is_display_none() && hint.intersects(RestyleHint::RESTYLE_SELF) {
return None;
} }
return RestyleKind::CascadeOnly; let style = self.styles.primary();
// Return either CascadeWithReplacements or CascadeOnly in case of
// animation-only restyle. I.e. animation-only restyle never does
// selector matching.
if hint.has_animation_hint() {
return Some(RestyleKind::CascadeWithReplacements(
hint & RestyleHint::for_animations(),
));
}
let needs_to_recascade_self = hint.intersects(RestyleHint::RECASCADE_SELF) ||
(hint.intersects(RestyleHint::RECASCADE_SELF_IF_INHERIT_RESET_STYLE) &&
style.flags.contains(ComputedValueFlags::INHERITS_RESET_STYLE));
if needs_to_recascade_self {
return Some(RestyleKind::CascadeOnly);
}
return None;
} }
/// Drops any restyle state from the element. /// Drops any restyle state from the element.
@ -482,7 +517,13 @@ impl ElementData {
) { ) {
return false; return false;
} }
if !self.styles.primary().get_box().clone_container_type().is_normal() { if !self
.styles
.primary()
.get_box()
.clone_container_type()
.is_normal()
{
return false; return false;
} }
true true

View file

@ -17,7 +17,6 @@ use crate::properties::{AnimationDeclarations, ComputedValues, PropertyDeclarati
use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl}; use crate::selector_parser::{AttrValue, Lang, PseudoElement, SelectorImpl};
use crate::shared_lock::{Locked, SharedRwLock}; use crate::shared_lock::{Locked, SharedRwLock};
use crate::stylist::CascadeData; use crate::stylist::CascadeData;
use crate::traversal_flags::TraversalFlags;
use crate::values::AtomIdent; use crate::values::AtomIdent;
use crate::values::computed::Display; use crate::values::computed::Display;
use crate::{LocalName, Namespace, WeakAtom}; use crate::{LocalName, Namespace, WeakAtom};
@ -587,51 +586,6 @@ pub trait TElement:
/// Flags this element as having handled already its snapshot. /// Flags this element as having handled already its snapshot.
unsafe fn set_handled_snapshot(&self); unsafe fn set_handled_snapshot(&self);
/// Returns whether the element's styles are up-to-date for |traversal_flags|.
fn has_current_styles_for_traversal(
&self,
data: &ElementData,
traversal_flags: TraversalFlags,
) -> bool {
if traversal_flags.for_animation_only() {
// In animation-only restyle we never touch snapshots and don't care
// about them. But we can't assert '!self.handled_snapshot()'
// here since there are some cases that a second animation-only
// restyle which is a result of normal restyle (e.g. setting
// animation-name in normal restyle and creating a new CSS
// animation in a SequentialTask) is processed after the normal
// traversal in that we had elements that handled snapshot.
if !data.has_styles() {
return false;
}
if !data.hint.has_animation_hint_or_recascade() {
return true;
}
// FIXME: This should ideally always return false, but it is a hack
// to work around our weird animation-only traversal
// stuff: If we're display: none and the rules we could match could
// change, we consider our style up-to-date. This is because
// re-cascading with and old style doesn't guarantee returning the
// correct animation style (that's bug 1393323). So if our display
// changed, and it changed from display: none, we would incorrectly
// forget about it and wouldn't be able to correctly style our
// descendants later.
if data.styles.is_display_none() && data.hint.match_self() {
return true;
}
return false;
}
if self.has_snapshot() && !self.handled_snapshot() {
return false;
}
data.has_styles() && !data.hint.has_non_animation_invalidations()
}
/// Returns whether the element's styles are up-to-date after traversal /// Returns whether the element's styles are up-to-date after traversal
/// (i.e. in post traversal). /// (i.e. in post traversal).
fn has_current_styles(&self, data: &ElementData) -> bool { fn has_current_styles(&self, data: &ElementData) -> bool {

View file

@ -9,38 +9,48 @@ use crate::traversal_flags::TraversalFlags;
bitflags! { bitflags! {
/// The kind of restyle we need to do for a given element. /// The kind of restyle we need to do for a given element.
#[repr(C)] #[repr(C)]
pub struct RestyleHint: u8 { pub struct RestyleHint: u16 {
/// Do a selector match of the element. /// Do a selector match of the element.
const RESTYLE_SELF = 1 << 0; const RESTYLE_SELF = 1 << 0;
/// Do a selector match of the element's pseudo-elements. Always to be combined with
/// RESTYLE_SELF.
const RESTYLE_PSEUDOS = 1 << 1;
/// Do a selector match if the element is a pseudo-element.
const RESTYLE_SELF_IF_PSEUDO = 1 << 2;
/// Do a selector match of the element's descendants. /// Do a selector match of the element's descendants.
const RESTYLE_DESCENDANTS = 1 << 1; const RESTYLE_DESCENDANTS = 1 << 3;
/// Recascade the current element. /// Recascade the current element.
const RECASCADE_SELF = 1 << 2; const RECASCADE_SELF = 1 << 4;
/// Recascade the current element if it inherits any reset style.
const RECASCADE_SELF_IF_INHERIT_RESET_STYLE = 1 << 5;
/// Recascade all descendant elements. /// Recascade all descendant elements.
const RECASCADE_DESCENDANTS = 1 << 3; const RECASCADE_DESCENDANTS = 1 << 6;
/// Replace the style data coming from CSS transitions without updating /// Replace the style data coming from CSS transitions without updating
/// any other style data. This hint is only processed in animation-only /// any other style data. This hint is only processed in animation-only
/// traversal which is prior to normal traversal. /// traversal which is prior to normal traversal.
const RESTYLE_CSS_TRANSITIONS = 1 << 4; const RESTYLE_CSS_TRANSITIONS = 1 << 7;
/// Replace the style data coming from CSS animations without updating /// Replace the style data coming from CSS animations without updating
/// any other style data. This hint is only processed in animation-only /// any other style data. This hint is only processed in animation-only
/// traversal which is prior to normal traversal. /// traversal which is prior to normal traversal.
const RESTYLE_CSS_ANIMATIONS = 1 << 5; const RESTYLE_CSS_ANIMATIONS = 1 << 8;
/// Don't re-run selector-matching on the element, only the style /// Don't re-run selector-matching on the element, only the style
/// attribute has changed, and this change didn't have any other /// attribute has changed, and this change didn't have any other
/// dependencies. /// dependencies.
const RESTYLE_STYLE_ATTRIBUTE = 1 << 6; const RESTYLE_STYLE_ATTRIBUTE = 1 << 9;
/// Replace the style data coming from SMIL animations without updating /// Replace the style data coming from SMIL animations without updating
/// any other style data. This hint is only processed in animation-only /// any other style data. This hint is only processed in animation-only
/// traversal which is prior to normal traversal. /// traversal which is prior to normal traversal.
const RESTYLE_SMIL = 1 << 7; const RESTYLE_SMIL = 1 << 10;
} }
} }
@ -70,11 +80,7 @@ impl RestyleHint {
/// Returns whether we need to restyle this element. /// Returns whether we need to restyle this element.
pub fn has_non_animation_invalidations(&self) -> bool { pub fn has_non_animation_invalidations(&self) -> bool {
self.intersects( !(*self & !Self::for_animations()).is_empty()
RestyleHint::RESTYLE_SELF |
RestyleHint::RECASCADE_SELF |
(Self::replacements() & !Self::for_animations()),
)
} }
/// Propagates this restyle hint to a child element. /// Propagates this restyle hint to a child element.
@ -98,16 +104,19 @@ impl RestyleHint {
mem::replace(self, Self::empty()).propagate_for_non_animation_restyle() mem::replace(self, Self::empty()).propagate_for_non_animation_restyle()
} }
/// Returns a new `CascadeHint` appropriate for children of the current /// Returns a new `RestyleHint` appropriate for children of the current element.
/// element.
fn propagate_for_non_animation_restyle(&self) -> Self { fn propagate_for_non_animation_restyle(&self) -> Self {
if self.contains(RestyleHint::RESTYLE_DESCENDANTS) { if self.contains(RestyleHint::RESTYLE_DESCENDANTS) {
return Self::restyle_subtree(); return Self::restyle_subtree();
} }
if self.contains(RestyleHint::RECASCADE_DESCENDANTS) { let mut result = Self::empty();
return Self::recascade_subtree(); if self.contains(RestyleHint::RESTYLE_PSEUDOS) {
result |= Self::RESTYLE_SELF_IF_PSEUDO;
} }
Self::empty() if self.contains(RestyleHint::RECASCADE_DESCENDANTS) {
result |= Self::recascade_subtree();
}
result
} }
/// Returns a hint that contains all the replacement hints. /// Returns a hint that contains all the replacement hints.
@ -123,12 +132,6 @@ impl RestyleHint {
RestyleHint::RESTYLE_CSS_TRANSITIONS RestyleHint::RESTYLE_CSS_TRANSITIONS
} }
/// Returns whether the hint specifies that the currently element must be
/// recascaded.
pub fn has_recascade_self(&self) -> bool {
self.contains(RestyleHint::RECASCADE_SELF)
}
/// Returns whether the hint specifies that an animation cascade level must /// Returns whether the hint specifies that an animation cascade level must
/// be replaced. /// be replaced.
#[inline] #[inline]
@ -140,7 +143,7 @@ impl RestyleHint {
/// be replaced. /// be replaced.
#[inline] #[inline]
pub fn has_animation_hint_or_recascade(&self) -> bool { pub fn has_animation_hint_or_recascade(&self) -> bool {
self.intersects(Self::for_animations() | RestyleHint::RECASCADE_SELF) self.intersects(Self::for_animations() | Self::RECASCADE_SELF | Self::RECASCADE_SELF_IF_INHERIT_RESET_STYLE)
} }
/// Returns whether the hint specifies some restyle work other than an /// Returns whether the hint specifies some restyle work other than an
@ -150,13 +153,6 @@ impl RestyleHint {
!(*self & !Self::for_animations()).is_empty() !(*self & !Self::for_animations()).is_empty()
} }
/// Returns whether the hint specifies that selector matching must be re-run
/// for the element.
#[inline]
pub fn match_self(&self) -> bool {
self.intersects(RestyleHint::RESTYLE_SELF)
}
/// Returns whether the hint specifies that some cascade levels must be /// Returns whether the hint specifies that some cascade levels must be
/// replaced. /// replaced.
#[inline] #[inline]
@ -169,16 +165,14 @@ impl RestyleHint {
pub fn remove_animation_hints(&mut self) { pub fn remove_animation_hints(&mut self) {
self.remove(Self::for_animations()); self.remove(Self::for_animations());
// While RECASCADE_SELF is not animation-specific, we only ever add and // While RECASCADE_SELF is not animation-specific, we only ever add and process it during
// process it during traversal. If we are here, removing animation // traversal. If we are here, removing animation hints, then we are in an animation-only
// hints, then we are in an animation-only traversal, and we know that // traversal, and we know that any RECASCADE_SELF flag must have been set due to changes in
// any RECASCADE_SELF flag must have been set due to changes in // inherited values after restyling for animations, and thus we want to remove it so that
// inherited values after restyling for animations, and thus we want to // we don't later try to restyle the element during a normal restyle.
// remove it so that we don't later try to restyle the element during a // (We could have separate RECASCADE_SELF_NORMAL and RECASCADE_SELF_ANIMATIONS flags to
// normal restyle. (We could have separate RECASCADE_SELF_NORMAL and // make it clear, but this isn't currently necessary.)
// RECASCADE_SELF_ANIMATIONS flags to make it clear, but this isn't self.remove(Self::RECASCADE_SELF | Self::RECASCADE_SELF_IF_INHERIT_RESET_STYLE);
// currently necessary.)
self.remove(RestyleHint::RECASCADE_SELF);
} }
} }

View file

@ -75,13 +75,6 @@ pub enum ChildRestyleRequirement {
MustMatchDescendants = 4, MustMatchDescendants = 4,
} }
impl ChildRestyleRequirement {
/// Whether we can unconditionally skip the cascade.
pub fn can_skip_cascade(&self) -> bool {
matches!(*self, ChildRestyleRequirement::CanSkipCascade)
}
}
/// Determines which styles are being cascaded currently. /// Determines which styles are being cascaded currently.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum CascadeVisitedMode { enum CascadeVisitedMode {

View file

@ -800,11 +800,6 @@ impl<E: TElement> StyleSharingCache<E> {
return None; return None;
} }
debug_assert!(target.has_current_styles_for_traversal(
&candidate.element.borrow_data().unwrap(),
shared.traversal_flags,
));
debug!( debug!(
"Sharing allowed between {:?} and {:?}", "Sharing allowed between {:?} and {:?}",
target.element, candidate.element target.element, candidate.element

View file

@ -5,7 +5,7 @@
//! Traversing the DOM tree; the bloom filter. //! Traversing the DOM tree; the bloom filter.
use crate::context::{ElementCascadeInputs, SharedStyleContext, StyleContext}; use crate::context::{ElementCascadeInputs, SharedStyleContext, StyleContext};
use crate::data::{ElementData, ElementStyles}; use crate::data::{ElementData, ElementStyles, RestyleKind};
use crate::dom::{NodeInfo, OpaqueNode, TElement, TNode}; use crate::dom::{NodeInfo, OpaqueNode, TElement, TNode};
use crate::invalidation::element::restyle_hints::RestyleHint; use crate::invalidation::element::restyle_hints::RestyleHint;
use crate::matching::{ChildRestyleRequirement, MatchMethods}; use crate::matching::{ChildRestyleRequirement, MatchMethods};
@ -217,16 +217,12 @@ pub trait DomTraversal<E: TElement>: Sync {
el, traversal_flags, data el, traversal_flags, data
); );
// 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
// if the element has animation only dirty descendants bit, // animation only dirty descendants bit, animation-only restyle hint.
// animation-only restyle hint or recascade.
if traversal_flags.for_animation_only() { if traversal_flags.for_animation_only() {
return data.map_or(false, |d| d.has_styles()) && return data.map_or(false, |d| d.has_styles()) &&
(el.has_animation_only_dirty_descendants() || (el.has_animation_only_dirty_descendants() ||
data.as_ref() data.as_ref().unwrap().hint.has_animation_hint_or_recascade());
.unwrap()
.hint
.has_animation_hint_or_recascade());
} }
// Non-incremental layout visits every node. // Non-incremental layout visits every node.
@ -411,13 +407,11 @@ pub fn recalc_style_at<E, D, F>(
"Should've handled snapshots here already" "Should've handled snapshots here already"
); );
let compute_self = !element.has_current_styles_for_traversal(data, flags); let restyle_kind = data.restyle_kind(&context.shared);
debug!( debug!(
"recalc_style_at: {:?} (compute_self={:?}, \ "recalc_style_at: {:?} (restyle_kind={:?}, dirty_descendants={:?}, data={:?})",
dirty_descendants={:?}, data={:?})",
element, element,
compute_self, restyle_kind,
element.has_dirty_descendants(), element.has_dirty_descendants(),
data data
); );
@ -425,8 +419,8 @@ pub fn recalc_style_at<E, D, F>(
let mut child_restyle_requirement = ChildRestyleRequirement::CanSkipCascade; let mut child_restyle_requirement = ChildRestyleRequirement::CanSkipCascade;
// Compute style for this element if necessary. // Compute style for this element if necessary.
if compute_self { if let Some(restyle_kind) = restyle_kind {
child_restyle_requirement = compute_style(traversal_data, context, element, data); child_restyle_requirement = compute_style(traversal_data, context, element, data, restyle_kind);
if element.is_in_native_anonymous_subtree() { if element.is_in_native_anonymous_subtree() {
// We must always cascade native anonymous subtrees, since they // We must always cascade native anonymous subtrees, since they
@ -468,8 +462,7 @@ pub fn recalc_style_at<E, D, F>(
"animation restyle hint should be handled during \ "animation restyle hint should be handled during \
animation-only restyles" animation-only restyles"
); );
let propagated_hint = data.hint.propagate(&flags); let mut propagated_hint = data.hint.propagate(&flags);
trace!( trace!(
"propagated_hint={:?}, restyle_requirement={:?}, \ "propagated_hint={:?}, restyle_requirement={:?}, \
is_display_none={:?}, implementing_pseudo={:?}", is_display_none={:?}, implementing_pseudo={:?}",
@ -478,11 +471,23 @@ pub fn recalc_style_at<E, D, F>(
data.styles.is_display_none(), data.styles.is_display_none(),
element.implemented_pseudo_element() element.implemented_pseudo_element()
); );
debug_assert!(
element.has_current_styles_for_traversal(data, flags), // Integrate the child cascade requirement into the propagated hint.
"Should have computed style or haven't yet valid computed \ match child_restyle_requirement {
style in case of animation-only restyle" ChildRestyleRequirement::CanSkipCascade => {},
); ChildRestyleRequirement::MustCascadeDescendants => {
propagated_hint |= RestyleHint::RECASCADE_SELF | RestyleHint::RECASCADE_DESCENDANTS;
},
ChildRestyleRequirement::MustCascadeChildrenIfInheritResetStyle => {
propagated_hint |= RestyleHint::RECASCADE_SELF_IF_INHERIT_RESET_STYLE;
},
ChildRestyleRequirement::MustCascadeChildren => {
propagated_hint |= RestyleHint::RECASCADE_SELF;
},
ChildRestyleRequirement::MustMatchDescendants => {
propagated_hint |= RestyleHint::restyle_subtree();
},
}
let has_dirty_descendants_for_this_restyle = if flags.for_animation_only() { let has_dirty_descendants_for_this_restyle = if flags.for_animation_only() {
element.has_animation_only_dirty_descendants() element.has_animation_only_dirty_descendants()
@ -496,14 +501,12 @@ pub fn recalc_style_at<E, D, F>(
// //
// * We have the dirty descendants bit. // * We have the dirty descendants bit.
// * We're propagating a restyle hint. // * We're propagating a restyle hint.
// * We can't skip the cascade.
// * This is a servo non-incremental traversal. // * This is a servo non-incremental traversal.
// //
// We only do this if we're not a display: none root, since in that case // We only do this if we're not a display: none root, since in that case
// it's useless to style children. // it's useless to style children.
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_restyle_requirement.can_skip_cascade() ||
is_servo_nonincremental_layout(); is_servo_nonincremental_layout();
traverse_children = traverse_children && !data.styles.is_display_none(); traverse_children = traverse_children && !data.styles.is_display_none();
@ -515,7 +518,6 @@ pub fn recalc_style_at<E, D, F>(
element, element,
data, data,
propagated_hint, propagated_hint,
child_restyle_requirement,
is_initial_style, is_initial_style,
note_child, note_child,
); );
@ -548,6 +550,7 @@ fn compute_style<E>(
context: &mut StyleContext<E>, context: &mut StyleContext<E>,
element: E, element: E,
data: &mut ElementData, data: &mut ElementData,
kind: RestyleKind,
) -> ChildRestyleRequirement ) -> ChildRestyleRequirement
where where
E: TElement, E: TElement,
@ -555,8 +558,6 @@ where
use crate::data::RestyleKind::*; use crate::data::RestyleKind::*;
context.thread_local.statistics.elements_styled += 1; context.thread_local.statistics.elements_styled += 1;
let kind = data.restyle_kind(context.shared);
debug!("compute_style: {:?} (kind={:?})", element, kind); debug!("compute_style: {:?} (kind={:?})", element, kind);
if data.has_styles() { if data.has_styles() {
@ -733,7 +734,6 @@ fn note_children<E, D, F>(
element: E, element: E,
data: &ElementData, data: &ElementData,
propagated_hint: RestyleHint, propagated_hint: RestyleHint,
restyle_requirement: ChildRestyleRequirement,
is_initial_style: bool, is_initial_style: bool,
mut note_child: F, mut note_child: F,
) where ) where
@ -769,32 +769,7 @@ fn note_children<E, D, F>(
); );
if let Some(ref mut child_data) = child_data { if let Some(ref mut child_data) = child_data {
let mut child_hint = propagated_hint; child_data.hint.insert(propagated_hint);
match restyle_requirement {
ChildRestyleRequirement::CanSkipCascade => {},
ChildRestyleRequirement::MustCascadeDescendants => {
child_hint |= RestyleHint::RECASCADE_SELF | RestyleHint::RECASCADE_DESCENDANTS;
},
ChildRestyleRequirement::MustCascadeChildrenIfInheritResetStyle => {
use crate::computed_value_flags::ComputedValueFlags;
if child_data
.styles
.primary()
.flags
.contains(ComputedValueFlags::INHERITS_RESET_STYLE)
{
child_hint |= RestyleHint::RECASCADE_SELF;
}
},
ChildRestyleRequirement::MustCascadeChildren => {
child_hint |= RestyleHint::RECASCADE_SELF;
},
ChildRestyleRequirement::MustMatchDescendants => {
child_hint |= RestyleHint::restyle_subtree();
},
}
child_data.hint.insert(child_hint);
// Handle element snapshots and invalidation of descendants and siblings // Handle element snapshots and invalidation of descendants and siblings
// as needed. // as needed.