diff --git a/components/layout/context.rs b/components/layout/context.rs index 11cfed0d1b3..08237579626 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -25,15 +25,14 @@ use std::hash::BuildHasherDefault; use std::rc::Rc; use std::sync::{Arc, Mutex, RwLock}; use style::context::{LocalStyleContext, StyleContext}; -use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; -use style::properties::ServoComputedValues; use style::selector_impl::ServoSelectorImpl; use style::servo::SharedStyleContext; use url::Url; use util::opts; struct LocalLayoutContext { - style_context: LocalStyleContext, + style_context: LocalStyleContext, + font_context: RefCell, } @@ -64,11 +63,10 @@ fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) context } else { let font_cache_thread = shared_layout_context.font_cache_thread.lock().unwrap().clone(); + let local_style_data = shared_layout_context.style_context.local_context_creation_data.lock().unwrap(); + let context = Rc::new(LocalLayoutContext { - style_context: LocalStyleContext { - applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()), - style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()), - }, + style_context: LocalStyleContext::new(&local_style_data), font_context: RefCell::new(FontContext::new(font_cache_thread)), }); *r = Some(context.clone()); @@ -110,7 +108,7 @@ impl<'a> StyleContext<'a, ServoSelectorImpl> for LayoutContext<'a> { &self.shared.style_context } - fn local_context(&self) -> &LocalStyleContext { + fn local_context(&self) -> &LocalStyleContext { &self.cached_local_layout_context.style_context } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index b33a5c56eb1..8b147955569 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -108,7 +108,7 @@ use style::parallel::WorkQueueData; use style::properties::ComputedValues; use style::refcell::RefCell; use style::selector_matching::USER_OR_USER_AGENT_STYLESHEETS; -use style::servo::{Animation, SharedStyleContext, Stylesheet, Stylist}; +use style::servo::{Animation, LocalStyleContextCreationInfo, SharedStyleContext, Stylesheet, Stylist}; use style::stylesheets::CSSRuleIteratorExt; use url::Url; use util::geometry::MAX_RECT; @@ -488,6 +488,8 @@ impl LayoutThread { screen_size_changed: bool, goal: ReflowGoal) -> SharedLayoutContext { + let local_style_context_creation_data = LocalStyleContextCreationInfo::new(self.new_animations_sender.clone()); + SharedLayoutContext { style_context: SharedStyleContext { viewport_size: self.viewport_size.clone(), @@ -495,10 +497,10 @@ impl LayoutThread { stylist: rw_data.stylist.clone(), generation: self.generation, goal: goal, - new_animations_sender: Mutex::new(self.new_animations_sender.clone()), running_animations: self.running_animations.clone(), expired_animations: self.expired_animations.clone(), error_reporter: self.error_reporter.clone(), + local_context_creation_data: Mutex::new(local_style_context_creation_data), }, image_cache_thread: self.image_cache_thread.clone(), image_cache_sender: Mutex::new(self.image_cache_sender.clone()), diff --git a/components/style/animation.rs b/components/style/animation.rs index b2a64a5fa5e..29cd2bfa06d 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -19,8 +19,8 @@ use properties::style_struct_traits::Box; use properties::{self, ComputedValues}; use selector_impl::SelectorImplExt; use selectors::matching::DeclarationBlock; +use std::sync::Arc; use std::sync::mpsc::Sender; -use std::sync::{Arc, Mutex}; use string_cache::Atom; use time; use values::computed::Time; @@ -356,7 +356,7 @@ impl GetMod for Vec { // // TODO(emilio): Take rid of this mutex splitting SharedLayoutContex into a // cloneable part and a non-cloneable part.. -pub fn start_transitions_if_applicable(new_animations_sender: &Mutex>>, +pub fn start_transitions_if_applicable(new_animations_sender: &Sender>, node: OpaqueNode, old_style: &Impl::ComputedValues, new_style: &mut Arc) @@ -377,7 +377,6 @@ pub fn start_transitions_if_applicable(new_animations_sen let start_time = now + (box_style.transition_delay.0.get_mod(i).seconds() as f64); new_animations_sender - .lock().unwrap() .send(Animation::Transition(node, start_time, AnimationFrame { duration: box_style.transition_duration.0.get_mod(i).seconds() as f64, property_animation: property_animation, @@ -417,6 +416,7 @@ fn compute_style_for_animation_step(context: &SharedStyle } pub fn maybe_start_animations(context: &SharedStyleContext, + new_animations_sender: &Sender>, node: OpaqueNode, new_style: &Arc) -> bool { @@ -465,19 +465,18 @@ pub fn maybe_start_animations(context: &SharedStyleContex }; - context.new_animations_sender - .lock().unwrap() - .send(Animation::Keyframes(node, name.clone(), KeyframesAnimationState { - started_at: animation_start, - duration: duration as f64, - delay: delay as f64, - iteration_state: iteration_state, - running_state: running_state, - direction: animation_direction, - current_direction: initial_direction, - expired: false, - cascade_style: new_style.clone(), - })).unwrap(); + new_animations_sender + .send(Animation::Keyframes(node, name.clone(), KeyframesAnimationState { + started_at: animation_start, + duration: duration as f64, + delay: delay as f64, + iteration_state: iteration_state, + running_state: running_state, + direction: animation_direction, + current_direction: initial_direction, + expired: false, + cascade_style: new_style.clone(), + })).unwrap(); had_animations = true; } } diff --git a/components/style/context.rs b/components/style/context.rs index 041b52d2a17..bb8b179651c 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -10,7 +10,6 @@ use dom::OpaqueNode; use error_reporting::ParseErrorReporter; use euclid::Size2D; use matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; -use properties::ComputedValues; use selector_impl::SelectorImplExt; use selector_matching::Stylist; use std::cell::RefCell; @@ -18,6 +17,19 @@ use std::collections::HashMap; use std::sync::mpsc::Sender; use std::sync::{Arc, Mutex, RwLock}; +/// This structure is used to create a local style context from a shared one. +pub struct LocalStyleContextCreationInfo { + new_animations_sender: Sender>, +} + +impl LocalStyleContextCreationInfo { + pub fn new(animations_sender: Sender>) -> Self { + LocalStyleContextCreationInfo { + new_animations_sender: animations_sender, + } + } +} + pub struct SharedStyleContext { /// The current viewport size. pub viewport_size: Size2D, @@ -32,10 +44,6 @@ pub struct SharedStyleContext { /// This can be used to easily check for invalid stale data. pub generation: u32, - /// A channel on which new animations that have been triggered by style recalculation can be - /// sent. - pub new_animations_sender: Mutex>>, - /// Why is this reflow occurring pub goal: ReflowGoal, @@ -47,16 +55,32 @@ pub struct SharedStyleContext { ///The CSS error reporter for all CSS loaded in this layout thread pub error_reporter: Box, + + /// Data needed to create the local style context from the shared one. + pub local_context_creation_data: Mutex>, } -pub struct LocalStyleContext { - pub applicable_declarations_cache: RefCell>, - pub style_sharing_candidate_cache: RefCell>, +pub struct LocalStyleContext { + pub applicable_declarations_cache: RefCell>, + pub style_sharing_candidate_cache: RefCell>, + /// A channel on which new animations that have been triggered by style + /// recalculation can be sent. + pub new_animations_sender: Sender>, +} + +impl LocalStyleContext { + pub fn new(local_context_creation_data: &LocalStyleContextCreationInfo) -> Self { + LocalStyleContext { + applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()), + style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()), + new_animations_sender: local_context_creation_data.new_animations_sender.clone(), + } + } } pub trait StyleContext<'a, Impl: SelectorImplExt> { fn shared_context(&self) -> &'a SharedStyleContext; - fn local_context(&self) -> &LocalStyleContext; + fn local_context(&self) -> &LocalStyleContext; } /// Why we're doing reflow. diff --git a/components/style/matching.rs b/components/style/matching.rs index 1f85effdb33..5e0009c379b 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -7,7 +7,7 @@ #![allow(unsafe_code)] use animation::{self, Animation}; -use context::{SharedStyleContext, LocalStyleContext}; +use context::{StyleContext, SharedStyleContext}; use data::PrivateStyleData; use dom::{TElement, TNode, TRestyleDamage}; use properties::{ComputedValues, PropertyDeclaration, cascade}; @@ -371,19 +371,22 @@ trait PrivateMatchMethods: TNode /// /// Note that animations only apply to nodes or ::before or ::after /// pseudo-elements. - fn cascade_node_pseudo_element(&self, - context: &SharedStyleContext<::Impl>, - parent_style: Option<&Arc>, - applicable_declarations: &[DeclarationBlock], - mut style: Option<&mut Arc>, - applicable_declarations_cache: - &mut ApplicableDeclarationsCache, - shareable: bool, - animate_properties: bool) - -> (Self::ConcreteRestyleDamage, Arc) { + fn cascade_node_pseudo_element<'a, Ctx>(&self, + context: &Ctx, + parent_style: Option<&Arc>, + applicable_declarations: &[DeclarationBlock], + mut style: Option<&mut Arc>, + applicable_declarations_cache: + &mut ApplicableDeclarationsCache, + shareable: bool, + animate_properties: bool) + -> (Self::ConcreteRestyleDamage, Arc) + where Ctx: StyleContext<'a, ::Impl> { let mut cacheable = true; + let shared_context = context.shared_context(); if animate_properties { - cacheable = !self.update_animations_for_cascade(context, &mut style) && cacheable; + cacheable = !self.update_animations_for_cascade(shared_context, + &mut style) && cacheable; } let this_style; @@ -395,22 +398,22 @@ trait PrivateMatchMethods: TNode None => None, }; - let (the_style, is_cacheable) = cascade(context.viewport_size, + let (the_style, is_cacheable) = cascade(shared_context.viewport_size, applicable_declarations, shareable, Some(&***parent_style), cached_computed_values, - context.error_reporter.clone()); + shared_context.error_reporter.clone()); cacheable = cacheable && is_cacheable; this_style = the_style } None => { - let (the_style, is_cacheable) = cascade(context.viewport_size, + let (the_style, is_cacheable) = cascade(shared_context.viewport_size, applicable_declarations, shareable, None, None, - context.error_reporter.clone()); + shared_context.error_reporter.clone()); cacheable = cacheable && is_cacheable; this_style = the_style } @@ -419,10 +422,12 @@ trait PrivateMatchMethods: TNode let mut this_style = Arc::new(this_style); if animate_properties { + let new_animations_sender = &context.local_context().new_animations_sender; let this_opaque = self.opaque(); // Trigger any present animations if necessary. let mut animations_started = animation::maybe_start_animations::<::Impl>( - &context, + &shared_context, + new_animations_sender, this_opaque, &this_style); @@ -431,7 +436,7 @@ trait PrivateMatchMethods: TNode if let Some(ref style) = style { animations_started |= animation::start_transitions_if_applicable::<::Impl>( - &context.new_animations_sender, + new_animations_sender, this_opaque, &**style, &mut this_style); @@ -658,12 +663,13 @@ pub trait MatchMethods : TNode { } } - unsafe fn cascade_node(&self, - context: &SharedStyleContext<::Impl>, - local_context: &LocalStyleContext, - parent: Option, - applicable_declarations: &ApplicableDeclarations<::Impl>) - where ::Impl: SelectorImplExt + unsafe fn cascade_node<'a, Ctx>(&self, + context: &Ctx, + parent: Option, + applicable_declarations: + &ApplicableDeclarations<::Impl>) + where ::Impl: SelectorImplExt, + Ctx: StyleContext<'a, ::Impl> { // Get our parent's style. This must be unsafe so that we don't touch the parent's // borrow flags. @@ -679,7 +685,7 @@ pub trait MatchMethods : TNode { }; let mut applicable_declarations_cache = - local_context.applicable_declarations_cache.borrow_mut(); + context.local_context().applicable_declarations_cache.borrow_mut(); let damage; if self.is_text_node() { diff --git a/components/style/parallel.rs b/components/style/parallel.rs index 55f15f1d80f..d7cb95ecac2 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -45,7 +45,7 @@ pub fn traverse_dom(root: N, where N: TNode, C: DomTraversalContext { run_queue_with_custom_work_data_type(queue, |queue| { queue.push(WorkUnit { - fun: top_down_dom::, + fun: top_down_dom::, data: (Box::new(vec![root.to_unsafe()]), root.opaque()), }); }, queue_data); diff --git a/components/style/selector_impl.rs b/components/style/selector_impl.rs index 7f80cb2ea38..cf95f4a9048 100644 --- a/components/style/selector_impl.rs +++ b/components/style/selector_impl.rs @@ -65,7 +65,7 @@ pub trait ElementExt: Element { // NB: The `Clone` trait is here for convenience due to: // https://github.com/rust-lang/rust/issues/26925 -pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized { +pub trait SelectorImplExt : SelectorImpl + Clone + Debug + Sized + 'static { type ComputedValues: properties::ComputedValues; fn pseudo_element_cascade_type(pseudo: &Self::PseudoElement) -> PseudoElementCascadeType; diff --git a/components/style/servo.rs b/components/style/servo.rs index b592104832a..d5605a62832 100644 --- a/components/style/servo.rs +++ b/components/style/servo.rs @@ -15,4 +15,5 @@ pub type Stylesheet = stylesheets::Stylesheet; pub type PrivateStyleData = data::PrivateStyleData; pub type Stylist = selector_matching::Stylist; pub type SharedStyleContext = context::SharedStyleContext; +pub type LocalStyleContextCreationInfo = context::LocalStyleContextCreationInfo; pub type Animation = animation::Animation; diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 5e5b7d31948..f76b0b3f5da 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -218,8 +218,7 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C, // Perform the CSS cascade. unsafe { - node.cascade_node(&context.shared_context(), - &context.local_context(), + node.cascade_node(context, parent_opt, &applicable_declarations); } diff --git a/ports/geckolib/context.rs b/ports/geckolib/context.rs new file mode 100644 index 00000000000..ea95b00b4b7 --- /dev/null +++ b/ports/geckolib/context.rs @@ -0,0 +1,53 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use selector_impl::{GeckoSelectorImpl, SharedStyleContext}; +use std::cell::RefCell; +use std::rc::Rc; +use style::context::{LocalStyleContext, StyleContext}; + +thread_local!(static LOCAL_CONTEXT_KEY: + RefCell>>> = RefCell::new(None)); + +// Keep this implementation in sync with the one in components/layout/context.rs. +fn create_or_get_local_context(shared: &SharedStyleContext) + -> Rc> { + LOCAL_CONTEXT_KEY.with(|r| { + let mut r = r.borrow_mut(); + if let Some(context) = r.clone() { + if shared.screen_size_changed { + context.applicable_declarations_cache.borrow_mut().evict_all(); + } + context + } else { + let context = Rc::new(LocalStyleContext::new(&shared.local_context_creation_data.lock().unwrap())); + *r = Some(context.clone()); + context + } + }) +} + +pub struct StandaloneStyleContext<'a> { + pub shared: &'a SharedStyleContext, + cached_local_context: Rc>, +} + +impl<'a> StandaloneStyleContext<'a> { + pub fn new(shared: &'a SharedStyleContext) -> Self { + let local_context = create_or_get_local_context(shared); + StandaloneStyleContext { + shared: shared, + cached_local_context: local_context, + } + } +} + +impl<'a> StyleContext<'a, GeckoSelectorImpl> for StandaloneStyleContext<'a> { + fn shared_context(&self) -> &'a SharedStyleContext { + &self.shared + } + + fn local_context(&self) -> &LocalStyleContext { + &self.cached_local_context + } +} diff --git a/ports/geckolib/data.rs b/ports/geckolib/data.rs index 0f07ef83c57..9b2698409c9 100644 --- a/ports/geckolib/data.rs +++ b/ports/geckolib/data.rs @@ -6,7 +6,7 @@ use euclid::Size2D; use euclid::size::TypedSize2D; use gecko_bindings::bindings::RawServoStyleSet; use num_cpus; -use selector_impl::{GeckoSelectorImpl, Stylist, Stylesheet, SharedStyleContext}; +use selector_impl::{Animation, SharedStyleContext, Stylist, Stylesheet}; use std::cmp; use std::collections::HashMap; use std::sync::mpsc::{channel, Receiver, Sender}; @@ -18,8 +18,6 @@ use util::geometry::ViewportPx; use util::thread_state; use util::workqueue::WorkQueue; -pub type Animation = ::style::animation::Animation; - pub struct PerDocumentStyleData { /// Rule processor. pub stylist: Arc, diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 09503d76670..8f76407749c 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -22,7 +22,7 @@ use std::ptr; use std::slice; use std::str::from_utf8_unchecked; use std::sync::{Arc, Mutex}; -use style::context::ReflowGoal; +use style::context::{LocalStyleContextCreationInfo, ReflowGoal}; use style::dom::{TDocument, TElement, TNode}; use style::error_reporting::StdoutErrorReporter; use style::parallel; @@ -77,7 +77,7 @@ pub extern "C" fn Servo_Initialize() -> () { fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) { debug_assert!(node.is_element() || node.is_text_node()); - let data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) }; + let per_doc_data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) }; // Force the creation of our lazily-constructed initial computed values on // the main thread, since it's not safe to call elsewhere. @@ -88,24 +88,28 @@ fn restyle_subtree(node: GeckoNode, raw_data: *mut RawServoStyleSet) { // along in startup than the sensible place to call Servo_Initialize. GeckoComputedValues::initial_values(); - let _needs_dirtying = Arc::get_mut(&mut data.stylist).unwrap() - .update(&data.stylesheets, data.stylesheets_changed); - data.stylesheets_changed = false; + let _needs_dirtying = Arc::get_mut(&mut per_doc_data.stylist).unwrap() + .update(&per_doc_data.stylesheets, + per_doc_data.stylesheets_changed); + per_doc_data.stylesheets_changed = false; + + let local_context_data = + LocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone()); let shared_style_context = SharedStyleContext { viewport_size: Size2D::new(Au(0), Au(0)), screen_size_changed: false, generation: 0, goal: ReflowGoal::ForScriptQuery, - stylist: data.stylist.clone(), - new_animations_sender: Mutex::new(data.new_animations_sender.clone()), - running_animations: data.running_animations.clone(), - expired_animations: data.expired_animations.clone(), + stylist: per_doc_data.stylist.clone(), + running_animations: per_doc_data.running_animations.clone(), + expired_animations: per_doc_data.expired_animations.clone(), error_reporter: Box::new(StdoutErrorReporter), + local_context_creation_data: Mutex::new(local_context_data), }; if node.is_dirty() || node.has_dirty_descendants() { - parallel::traverse_dom::(node, &shared_style_context, &mut data.work_queue); + parallel::traverse_dom::(node, &shared_style_context, &mut per_doc_data.work_queue); } } diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index cedf344568f..c3c90da9cb3 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -24,6 +24,7 @@ extern crate style_traits; extern crate url; extern crate util; +mod context; mod data; #[allow(non_snake_case)] pub mod glue; diff --git a/ports/geckolib/selector_impl.rs b/ports/geckolib/selector_impl.rs index 5c5e1731b3b..c1284015414 100644 --- a/ports/geckolib/selector_impl.rs +++ b/ports/geckolib/selector_impl.rs @@ -12,6 +12,7 @@ pub type Stylist = style::selector_matching::Stylist; pub type Stylesheet = style::stylesheets::Stylesheet; pub type SharedStyleContext = style::context::SharedStyleContext; pub type PrivateStyleData = style::data::PrivateStyleData; +pub type Animation = style::animation::Animation; #[cfg(feature = "servo_features")] known_heap_size!(0, GeckoSelectorImpl, PseudoElement, NonTSPseudoClass); diff --git a/ports/geckolib/traversal.rs b/ports/geckolib/traversal.rs index f400377aeca..fc85963ba08 100644 --- a/ports/geckolib/traversal.rs +++ b/ports/geckolib/traversal.rs @@ -2,66 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use properties::GeckoComputedValues; -use selector_impl::{GeckoSelectorImpl, SharedStyleContext}; -use std::cell::RefCell; +use context::StandaloneStyleContext; +use selector_impl::SharedStyleContext; use std::mem; -use std::rc::Rc; -use style::context::{LocalStyleContext, StyleContext}; use style::dom::OpaqueNode; -use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache}; use style::traversal::{DomTraversalContext, recalc_style_at}; use wrapper::GeckoNode; -thread_local!(static LOCAL_CONTEXT_KEY: - RefCell>>> = RefCell::new(None)); - -// Keep this implementation in sync with the one in components/layout/context.rs. -fn create_or_get_local_context(shared: &SharedStyleContext) - -> Rc> { - LOCAL_CONTEXT_KEY.with(|r| { - let mut r = r.borrow_mut(); - if let Some(context) = r.clone() { - if shared.screen_size_changed { - context.applicable_declarations_cache.borrow_mut().evict_all(); - } - context - } else { - let context = Rc::new(LocalStyleContext { - applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()), - style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()), - }); - *r = Some(context.clone()); - context - } - }) -} - -pub struct StandaloneStyleContext<'a> { - pub shared: &'a SharedStyleContext, - cached_local_context: Rc>, -} - -impl<'a> StandaloneStyleContext<'a> { - pub fn new(shared: &'a SharedStyleContext) -> Self { - let local_context = create_or_get_local_context(shared); - StandaloneStyleContext { - shared: shared, - cached_local_context: local_context, - } - } -} - -impl<'a> StyleContext<'a, GeckoSelectorImpl> for StandaloneStyleContext<'a> { - fn shared_context(&self) -> &'a SharedStyleContext { - &self.shared - } - - fn local_context(&self) -> &LocalStyleContext { - &self.cached_local_context - } -} - pub struct RecalcStyleOnly<'lc> { context: StandaloneStyleContext<'lc>, root: OpaqueNode, @@ -73,7 +20,7 @@ impl<'lc, 'ln> DomTraversalContext> for RecalcStyleOnly<'lc> { fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self { // See the comment in RecalcStyleAndConstructFlows::new for an explanation of why this is // necessary. - let shared_lc: &'lc SharedStyleContext = unsafe { mem::transmute(shared) }; + let shared_lc: &'lc Self::SharedContext = unsafe { mem::transmute(shared) }; RecalcStyleOnly { context: StandaloneStyleContext::new(shared_lc), root: root, @@ -90,4 +37,3 @@ impl<'lc, 'ln> DomTraversalContext> for RecalcStyleOnly<'lc> { fn process_postorder(&self, _: GeckoNode<'ln>) {} } -