diff --git a/components/style/data.rs b/components/style/data.rs index 07870fad7a6..38099cb6eb6 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -69,14 +69,23 @@ impl RestyleData { } /// Clear all the restyle state associated with this element. - fn clear(&mut self) { - *self = Self::new(); + /// + /// FIXME(bholley): The only caller of this should probably just assert that + /// the hint is empty and call clear_flags_and_damage(). + fn clear_restyle_state(&mut self) { + self.clear_restyle_flags_and_damage(); + self.hint = RestyleHint::empty(); } /// Clear restyle flags and damage. - fn clear_flags_and_damage(&mut self) { + /// + /// Note that we don't touch the TRAVERSED_WITHOUT_STYLING bit, which gets + /// set to the correct value on each traversal. There's no reason anyone + /// needs to clear it, and clearing it accidentally mid-traversal could + /// cause incorrect style sharing behavior. + fn clear_restyle_flags_and_damage(&mut self) { self.damage = RestyleDamage::empty(); - self.flags = RestyleFlags::empty(); + self.flags = self.flags & TRAVERSED_WITHOUT_STYLING; } /// Returns whether this element or any ancestor is going to be @@ -420,12 +429,12 @@ impl ElementData { /// Drops any restyle state from the element. pub fn clear_restyle_state(&mut self) { - self.restyle.clear(); + self.restyle.clear_restyle_state(); } /// Drops restyle flags and damage from the element. pub fn clear_restyle_flags_and_damage(&mut self) { - self.restyle.clear_flags_and_damage(); + self.restyle.clear_restyle_flags_and_damage(); } } diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs index fd65de440b4..f11d46f59f3 100644 --- a/components/style/gecko/pseudo_element_definition.mako.rs +++ b/components/style/gecko/pseudo_element_definition.mako.rs @@ -15,6 +15,8 @@ pub enum PseudoElement { % endfor } +/// Important: If you change this, you should also update Gecko's +/// nsCSSPseudoElements::IsEagerlyCascadedInServo. <% EAGER_PSEUDOS = ["Before", "After", "FirstLine", "FirstLetter"] %> <% TREE_PSEUDOS = [pseudo for pseudo in PSEUDOS if pseudo.is_tree_pseudo_element()] %> <% SIMPLE_PSEUDOS = [pseudo for pseudo in PSEUDOS if not pseudo.is_tree_pseudo_element()] %> diff --git a/components/style/traversal.rs b/components/style/traversal.rs index a430ad22ad7..c0e795f13a1 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -603,7 +603,7 @@ where // data here, since we won't need to perform a post-traversal to pick up // any change hints. if flags.contains(traversal_flags::Forgetful) { - data.clear_restyle_state(); + data.clear_restyle_flags_and_damage(); } // There are two cases when we want to clear the dity descendants bit here diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index a8fadfc202c..0f66aefe6df 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -258,6 +258,8 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, let element = GeckoElement(root); + debug!("Servo_TraverseSubtree (flags={:?})", traversal_flags); + // It makes no sense to do an animation restyle when we're restyling // newly-inserted content. if !traversal_flags.contains(traversal_flags::UnstyledChildrenOnly) { @@ -266,6 +268,8 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, element.has_animation_restyle_hints(); if needs_animation_only_restyle { + debug!("Servo_TraverseSubtree doing animation-only restyle (aodd={})", + element.has_animation_only_dirty_descendants()); traverse_subtree(element, raw_data, traversal_flags | traversal_flags::AnimationOnly, @@ -274,6 +278,8 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, } if traversal_flags.for_animation_only() { + debug!("Servo_TraverseSubtree complete (animation-only, aodd={})", + element.has_animation_only_dirty_descendants()); return element.has_animation_only_dirty_descendants() || element.borrow_data().unwrap().restyle.is_restyle(); } @@ -283,6 +289,11 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed, traversal_flags, unsafe { &*snapshots }); + debug!("Servo_TraverseSubtree complete (dd={}, aodd={}, restyle={:?})", + element.has_dirty_descendants(), + element.has_animation_only_dirty_descendants(), + element.borrow_data().unwrap().restyle); + element.has_dirty_descendants() || element.has_animation_only_dirty_descendants() || element.borrow_data().unwrap().restyle.contains_restyle_data()