Bug 1351535 - Part 5.1: Move TraversalFlags into SharedStyleContext. r?bholley draft
authorCameron McCormack <cam@mcc.id.au>
Sat, 08 Apr 2017 16:36:09 +0800
changeset 558865 716619146c4e1a15b5c42ad0d24ba3f4f228a580
parent 558864 f30c0b04593311679e3d98fbdb7a3503634fa310
child 558866 f18318047e51375be45e6ea0a6473413918e7105
push id52975
push userbmo:cam@mcc.id.au
push dateSat, 08 Apr 2017 09:24:07 +0000
reviewersbholley
bugs1351535
milestone55.0a1
Bug 1351535 - Part 5.1: Move TraversalFlags into SharedStyleContext. r?bholley MozReview-Commit-ID: IfLzJ9h6vKT
servo/components/layout_thread/lib.rs
servo/components/style/context.rs
servo/components/style/matching.rs
servo/components/style/traversal.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -518,17 +518,17 @@ impl LayoutThread {
                 stylist: rw_data.stylist.clone(),
                 guards: guards,
                 running_animations: self.running_animations.clone(),
                 expired_animations: self.expired_animations.clone(),
                 error_reporter: Box::new(self.error_reporter.clone()),
                 local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
                 timer: self.timer.clone(),
                 quirks_mode: self.quirks_mode.unwrap(),
-                animation_only_restyle: false,
+                traversal_flags: TraversalFlags::empty(),
             },
             image_cache: self.image_cache.clone(),
             font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
             webrender_image_cache: self.webrender_image_cache.clone(),
             pending_images: if request_images { Some(Mutex::new(vec![])) } else { None },
         }
     }
 
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -24,17 +24,17 @@ use std::env;
 use std::fmt;
 use std::ops::Add;
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::Sender;
 use stylist::Stylist;
 use thread_state;
 use time;
 use timer::Timer;
-use traversal::DomTraversal;
+use traversal::{DomTraversal, TraversalFlags};
 
 /// This structure is used to create a local style context from a shared one.
 pub struct ThreadLocalStyleContextCreationInfo {
     new_animations_sender: Sender<Animation>,
 }
 
 impl ThreadLocalStyleContextCreationInfo {
     /// Trivially constructs a `ThreadLocalStyleContextCreationInfo`.
@@ -84,18 +84,18 @@ pub struct SharedStyleContext<'a> {
 
     /// The current timer for transitions and animations. This is needed to test
     /// them.
     pub timer: Timer,
 
     /// The QuirksMode state which the document needs to be rendered with
     pub quirks_mode: QuirksMode,
 
-    /// True if the traversal is processing only animation restyles.
-    pub animation_only_restyle: bool,
+    /// Flags controlling how we traverse the tree.
+    pub traversal_flags: TraversalFlags,
 }
 
 impl<'a> SharedStyleContext<'a> {
     /// Return a suitable viewport size in order to be used for viewport units.
     pub fn viewport_size(&self) -> Size2D<Au> {
         self.stylist.device.au_viewport_size()
     }
 }
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -1023,17 +1023,17 @@ pub trait MatchMethods : TElement {
                     rule_node_changed = true;
                 }
             };
 
             // RESTYLE_CSS_ANIMATIONS is processed prior to other restyle hints
             // in the name of animation-only traversal. Rest of restyle hints
             // will be processed in a subsequent normal traversal.
             if hint.contains(RESTYLE_CSS_ANIMATIONS) {
-                debug_assert!(context.shared.animation_only_restyle);
+                debug_assert!(context.shared.traversal_flags.for_animation_only());
 
                 let animation_rule = self.get_animation_rule(None);
                 replace_rule_node(CascadeLevel::Animations,
                                   animation_rule.as_ref(),
                                   primary_rules);
 
                 let pseudos = &mut element_styles.pseudos;
                 for pseudo in pseudos.keys().iter().filter(|p| p.is_before_or_after()) {
--- a/servo/components/style/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -160,31 +160,31 @@ pub trait DomTraversal<E: TElement> : Sy
         if let Some(mut data) = root.mutate_data() {
             if let Some(r) = data.get_restyle_mut() {
                 debug_assert!(root.next_sibling_element().is_none());
                 let _later_siblings = r.compute_final_hint(root, stylist);
             }
         }
 
         PreTraverseToken {
-            traverse: Self::node_needs_traversal(root.as_node(), traversal_flags.for_animation_only()),
+            traverse: Self::node_needs_traversal(root.as_node(), traversal_flags),
             unstyled_children_only: false,
         }
     }
 
     /// Returns true if traversal should visit a text node. The style system never
     /// processes text nodes, but Servo overrides this to visit them for flow
     /// construction when necessary.
     fn text_node_needs_traversal(node: E::ConcreteNode) -> bool {
         debug_assert!(node.is_text_node());
         false
     }
 
     /// Returns true if traversal is needed for the given node and subtree.
-    fn node_needs_traversal(node: E::ConcreteNode, animation_only: bool) -> bool {
+    fn node_needs_traversal(node: E::ConcreteNode, traversal_flags: TraversalFlags) -> bool {
         // Non-incremental layout visits every node.
         if cfg!(feature = "servo") && opts::get().nonincremental_layout {
             return true;
         }
 
         match node.as_element() {
             None => Self::text_node_needs_traversal(node),
             Some(el) => {
@@ -201,17 +201,17 @@ pub trait DomTraversal<E: TElement> : Sy
                             }
                         }
                     }
                 }
 
                 // In case of animation-only traversal we need to traverse
                 // the element if the element has animation only dirty
                 // descendants bit, animation-only restyle hint or recascade.
-                if animation_only {
+                if traversal_flags.for_animation_only() {
                     if el.has_animation_only_dirty_descendants() {
                         return true;
                     }
 
                     let data = match el.borrow_data() {
                         Some(d) => d,
                         None => return false,
                     };
@@ -326,17 +326,17 @@ pub trait DomTraversal<E: TElement> : Sy
             self.should_traverse_children(thread_local.borrow_mut(), parent,
                                           &parent.borrow_data().unwrap(), MayLog);
         thread_local.borrow_mut().end_element(parent);
         if !should_traverse {
             return;
         }
 
         for kid in parent.as_node().children() {
-            if Self::node_needs_traversal(kid, self.shared_context().animation_only_restyle) {
+            if Self::node_needs_traversal(kid, self.shared_context().traversal_flags) {
                 let el = kid.as_element();
                 if el.as_ref().and_then(|el| el.borrow_data())
                               .map_or(false, |d| d.has_styles())
                 {
                     unsafe { parent.set_dirty_descendants(); }
                 }
                 f(thread_local, kid);
             }
@@ -502,31 +502,32 @@ pub fn recalc_style_at<E, D>(traversal: 
         inherited_style_changed = true;
     }
 
     // Now that matching and cascading is done, clear the bits corresponding to
     // those operations and compute the propagated restyle hint.
     let propagated_hint = match data.get_restyle_mut() {
         None => StoredRestyleHint::empty(),
         Some(r) => {
-            debug_assert!(context.shared.animation_only_restyle ||
+            debug_assert!(context.shared.traversal_flags.for_animation_only() ||
                           !r.hint.has_animation_hint(),
                           "animation restyle hint should be handled during \
                            animation-only restyles");
             r.recascade = false;
             r.hint.propagate()
         },
     };
-    debug_assert!(data.has_current_styles() || context.shared.animation_only_restyle,
+    debug_assert!(data.has_current_styles() ||
+                  context.shared.traversal_flags.for_animation_only(),
                   "Should have computed style or haven't yet valid computed style in case of animation-only restyle");
     trace!("propagated_hint={:?}, inherited_style_changed={:?}",
            propagated_hint, inherited_style_changed);
 
     let has_dirty_descendants_for_this_restyle =
-        if context.shared.animation_only_restyle {
+        if context.shared.traversal_flags.for_animation_only() {
             element.has_animation_only_dirty_descendants()
         } else {
             element.has_dirty_descendants()
         };
 
     // Preprocess children, propagating restyle hints and handling sibling relationships.
     if traversal.should_traverse_children(&mut context.thread_local,
                                           element,
@@ -541,17 +542,17 @@ pub fn recalc_style_at<E, D>(traversal: 
 
         preprocess_children(traversal,
                             element,
                             propagated_hint,
                             damage_handled,
                             inherited_style_changed);
     }
 
-    if context.shared.animation_only_restyle {
+    if context.shared.traversal_flags.for_animation_only() {
         unsafe { element.unset_animation_only_dirty_descendants(); }
     }
 
     // Make sure the dirty descendants bit is not set for the root of a
     // display:none subtree, even if the style didn't change (since, if
     // the style did change, we'd have already cleared it above).
     //
     // This keeps the tree in a valid state without requiring the DOM to
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -136,32 +136,32 @@ pub extern "C" fn Servo_Shutdown() {
 }
 
 unsafe fn dummy_url_data() -> &'static RefPtr<URLExtraData> {
     RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
 }
 
 fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
                              per_doc_data: &PerDocumentStyleDataImpl,
-                             animation_only: bool) -> SharedStyleContext<'a> {
+                             traversal_flags: TraversalFlags) -> SharedStyleContext<'a> {
     let local_context_data =
         ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
 
     SharedStyleContext {
         stylist: per_doc_data.stylist.clone(),
         guards: StylesheetGuards::same(guard),
         running_animations: per_doc_data.running_animations.clone(),
         expired_animations: per_doc_data.expired_animations.clone(),
         // FIXME(emilio): Stop boxing here.
         error_reporter: Box::new(StdoutErrorReporter),
         local_context_creation_data: Mutex::new(local_context_data),
         timer: Timer::new(),
         // FIXME Find the real QuirksMode information for this document
         quirks_mode: QuirksMode::NoQuirks,
-        animation_only_restyle: animation_only,
+        traversal_flags: traversal_flags,
     }
 }
 
 fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
                     traversal_flags: TraversalFlags) {
     // When new content is inserted in a display:none subtree, we will call into
     // servo to try to style it. Detect that here and bail out.
     if let Some(parent) = element.parent_element() {
@@ -178,18 +178,17 @@ fn traverse_subtree(element: GeckoElemen
         return;
     }
 
     debug!("Traversing subtree:");
     debug!("{:?}", ShowSubtreeData(element.as_node()));
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
-    let shared_style_context = create_shared_context(&guard, &per_doc_data,
-                                                     traversal_flags.for_animation_only());
+    let shared_style_context = create_shared_context(&guard, &per_doc_data, traversal_flags);
 
     let traversal_driver = if global_style_data.style_thread_pool.is_none() {
         TraversalDriver::Sequential
     } else {
         TraversalDriver::Parallel
     };
 
     let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver);
@@ -393,17 +392,17 @@ pub extern "C" fn Servo_StyleSet_GetBase
                                                                  pseudo_tag: *mut nsIAtom)
                                                                  -> ServoComputedValuesStrong
 {
     use style::matching::MatchMethods;
 
     let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
-    let shared_context = &create_shared_context(&guard, &doc_data, false);
+    let shared_context = &create_shared_context(&guard, &doc_data, TraversalFlags::empty());
 
     let element = GeckoElement(element);
     let element_data = element.borrow_data().unwrap();
     let styles = element_data.styles();
 
     let pseudo = if pseudo_tag.is_null() {
         None
     } else {
@@ -1627,17 +1626,17 @@ pub extern "C" fn Servo_ResolveStyleLazi
     // up all the computation machinery.
     let mut result = element.mutate_data()
                             .and_then(|d| d.get_styles().map(&finish));
     if result.is_some() {
         return result.unwrap().into_strong();
     }
 
     // We don't have the style ready. Go ahead and compute it as necessary.
-    let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false);
+    let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), TraversalFlags::empty());
     let mut tlc = ThreadLocalStyleContext::new(&shared);
     let mut context = StyleContext {
         shared: &shared,
         thread_local: &mut tlc,
     };
     let ensure = |el: GeckoElement| { unsafe { el.ensure_data(); } };
     let clear = |el: GeckoElement| el.clear_data();
     resolve_style(&mut context, element, &ensure, &clear,