diff --git a/components/style/context.rs b/components/style/context.rs index 38af94f7584..a39ab809b5b 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -5,11 +5,11 @@ //! The context within which style is calculated. #[cfg(feature = "servo")] use animation::Animation; -#[cfg(feature = "servo")] use animation::PropertyAnimation; use app_units::Au; use bloom::StyleBloom; use data::{EagerPseudoStyles, ElementData}; -use dom::{OpaqueNode, TNode, TElement, SendElement}; +use dom::{TElement, SendElement}; +#[cfg(feature = "servo")] use dom::OpaqueNode; use euclid::ScaleFactor; use euclid::Size2D; use fnv::FnvHashMap; @@ -285,23 +285,6 @@ impl ElementCascadeInputs { } } -/// Information about the current element being processed. We group this -/// together into a single struct within ThreadLocalStyleContext so that we can -/// instantiate and destroy it easily at the beginning and end of element -/// processing. -pub struct CurrentElementInfo { - /// The element being processed. Currently we use an OpaqueNode since we - /// only use this for identity checks, but we could use SendElement if there - /// were a good reason to. - element: OpaqueNode, - /// Whether the element is being styled for the first time. - is_initial_style: bool, - /// A Vec of possibly expired animations. Used only by Servo. - #[allow(dead_code)] - #[cfg(feature = "servo")] - pub possibly_expired_animations: Vec, -} - /// Statistics gathered during the traversal. We gather statistics on each /// thread and then combine them after the threads join via the Add /// implementation below. @@ -712,8 +695,6 @@ pub struct ThreadLocalStyleContext { pub selector_flags: SelectorFlagsMap, /// Statistics about the traversal. pub statistics: TraversalStatistics, - /// Information related to the current element, non-None during processing. - pub current_element_info: Option, /// The struct used to compute and cache font metrics from style /// for evaluation of the font-relative em/ch units and font-size pub font_metrics_provider: E::FontMetricsProvider, @@ -736,7 +717,6 @@ impl ThreadLocalStyleContext { tasks: SequentialTaskList(Vec::new()), selector_flags: SelectorFlagsMap::new(), statistics: TraversalStatistics::default(), - current_element_info: None, font_metrics_provider: E::FontMetricsProvider::create_from(shared), stack_limit_checker: StackLimitChecker::new( (STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024), @@ -754,55 +734,16 @@ impl ThreadLocalStyleContext { tasks: SequentialTaskList(Vec::new()), selector_flags: SelectorFlagsMap::new(), statistics: TraversalStatistics::default(), - current_element_info: None, font_metrics_provider: E::FontMetricsProvider::create_from(shared), stack_limit_checker: StackLimitChecker::new( (STYLE_THREAD_STACK_SIZE_KB - STACK_SAFETY_MARGIN_KB) * 1024), nth_index_cache: NthIndexCache::default(), } } - - #[cfg(feature = "gecko")] - /// Notes when the style system starts traversing an element. - pub fn begin_element(&mut self, element: E, data: &ElementData) { - debug_assert!(self.current_element_info.is_none()); - self.current_element_info = Some(CurrentElementInfo { - element: element.as_node().opaque(), - is_initial_style: !data.has_styles(), - }); - } - - #[cfg(feature = "servo")] - /// Notes when the style system starts traversing an element. - pub fn begin_element(&mut self, element: E, data: &ElementData) { - debug_assert!(self.current_element_info.is_none()); - self.current_element_info = Some(CurrentElementInfo { - element: element.as_node().opaque(), - is_initial_style: !data.has_styles(), - possibly_expired_animations: Vec::new(), - }); - } - - /// Notes when the style system finishes traversing an element. - pub fn end_element(&mut self, element: E) { - debug_assert!(self.current_element_info.is_some()); - debug_assert!(self.current_element_info.as_ref().unwrap().element == - element.as_node().opaque()); - self.current_element_info = None; - } - - /// Returns true if the current element being traversed is being styled for - /// the first time. - /// - /// Panics if called while no element is being traversed. - pub fn is_initial_style(&self) -> bool { - self.current_element_info.as_ref().unwrap().is_initial_style - } } impl Drop for ThreadLocalStyleContext { fn drop(&mut self) { - debug_assert!(self.current_element_info.is_none()); debug_assert!(thread_state::get() == ThreadState::LAYOUT); // Apply any slow selector flags that need to be set on parents. diff --git a/components/style/matching.rs b/components/style/matching.rs index fbf872908e2..d71bf828ac7 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -298,13 +298,11 @@ trait PrivateMatchMethods: TElement { use animation; use dom::TNode; - let possibly_expired_animations = - &mut context.thread_local.current_element_info.as_mut().unwrap() - .possibly_expired_animations; + let mut possibly_expired_animations = vec![]; let shared_context = context.shared; if let Some(ref mut old) = *old_values { self.update_animations_for_cascade(shared_context, old, - possibly_expired_animations, + &mut possibly_expired_animations, &context.thread_local.font_metrics_provider); } diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 3244750a3d5..8b0943a58c8 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -273,6 +273,7 @@ pub trait DomTraversal : Sync { &self, context: &mut StyleContext, parent: E, + is_initial_style: bool, parent_data: &ElementData, ) -> bool { debug_assert!(cfg!(feature = "gecko") || @@ -304,7 +305,7 @@ pub trait DomTraversal : Sync { // 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") && context.thread_local.is_initial_style() && + if cfg!(feature = "gecko") && is_initial_style && parent_data.styles.primary().has_moz_binding() { debug!("Parent {:?} has XBL binding, deferring traversal", parent); @@ -427,7 +428,8 @@ where use traversal_flags::TraversalFlags; let flags = context.shared.traversal_flags; - context.thread_local.begin_element(element, data); + let is_initial_style = !data.has_styles(); + context.thread_local.statistics.elements_traversed += 1; debug_assert!(flags.intersects(TraversalFlags::AnimationOnly | TraversalFlags::UnstyledOnly) || !element.has_snapshot() || element.handled_snapshot(), @@ -524,8 +526,9 @@ where data.reconstructed_self() || is_servo_nonincremental_layout(); - traverse_children = traverse_children && - !traversal.should_cull_subtree(context, element, &data); + traverse_children = + traverse_children && + !traversal.should_cull_subtree(context, element, is_initial_style, &data); // Examine our children, and enqueue the appropriate ones for traversal. if traverse_children { @@ -535,6 +538,7 @@ where data, propagated_hint, child_cascade_requirement, + is_initial_style, note_child ); } @@ -550,8 +554,6 @@ where !element.has_animation_only_dirty_descendants(), "Should have cleared animation bits already"); clear_state_after_traversing(element, data, flags); - - context.thread_local.end_element(element); } fn clear_state_after_traversing( @@ -776,6 +778,7 @@ fn note_children( data: &ElementData, propagated_hint: RestyleHint, cascade_requirement: ChildCascadeRequirement, + is_initial_style: bool, mut note_child: F, ) where @@ -785,7 +788,6 @@ where { trace!("note_children: {:?}", element); let flags = context.shared.traversal_flags; - let is_initial_style = context.thread_local.is_initial_style(); // Loop over all the traversal children. for child_node in element.traversal_children() {