diff --git a/components/style/data.rs b/components/style/data.rs index 006f0593c76..430737c499e 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -17,7 +17,9 @@ use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage}; use servo_arc::Arc; use shared_lock::StylesheetGuards; use std::fmt; +use std::mem; use std::ops::{Deref, DerefMut}; +use style_resolver::{PrimaryStyle, ResolvedElementStyles, ResolvedStyle}; bitflags! { #[derive(Default)] @@ -264,6 +266,24 @@ impl ElementData { self.styles.primary.is_some() } + /// Returns this element's styles as resolved styles to use for sharing. + pub fn share_styles(&self) -> ResolvedElementStyles { + ResolvedElementStyles { + primary: self.share_primary_style(), + pseudos: self.styles.pseudos.clone(), + } + } + + /// Returns this element's primary style as a resolved style to use for sharing. + pub fn share_primary_style(&self) -> PrimaryStyle { + PrimaryStyle(ResolvedStyle::new(self.styles.primary().clone())) + } + + /// Sets a new set of styles, returning the old ones. + pub fn set_styles(&mut self, new_styles: ResolvedElementStyles) -> ElementStyles { + mem::replace(&mut self.styles, new_styles.into()) + } + /// Returns the kind of restyling that we're going to need to do on this /// element, based of the stored restyle hint. pub fn restyle_kind( diff --git a/components/style/matching.rs b/components/style/matching.rs index 1f140feeb8a..46b16f1c179 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -8,7 +8,7 @@ #![deny(missing_docs)] use context::{ElementCascadeInputs, SelectorFlagsMap, SharedStyleContext, StyleContext}; -use data::{ElementData, ElementStyles}; +use data::ElementData; use dom::TElement; use invalidation::element::restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS}; use invalidation::element::restyle_hints::{RESTYLE_SMIL, RESTYLE_STYLE_ATTRIBUTE}; @@ -18,6 +18,7 @@ use rule_tree::{CascadeLevel, StrongRuleNode}; use selector_parser::{PseudoElement, RestyleDamage}; use selectors::matching::ElementSelectorFlags; use servo_arc::{Arc, ArcBorrow}; +use style_resolver::ResolvedElementStyles; use traversal_flags; /// Represents the result of comparing an element's old and new style. @@ -156,7 +157,7 @@ trait PrivateMatchMethods: TElement { StyleResolverForElement::new(*self, context, RuleInclusion::All, PseudoElementResolution::IfApplicable) .cascade_style_and_visited_with_default_parents(inputs); - Some(style) + Some(style.into()) } #[cfg(feature = "gecko")] @@ -530,26 +531,23 @@ pub trait MatchMethods : TElement { &self, context: &mut StyleContext, data: &mut ElementData, - mut new_styles: ElementStyles, + mut new_styles: ResolvedElementStyles, important_rules_changed: bool, ) -> ChildCascadeRequirement { use app_units::Au; use dom::TNode; use std::cmp; - use std::mem; - - debug_assert!(new_styles.primary.is_some(), "How did that happen?"); self.process_animations( context, &mut data.styles.primary, - &mut new_styles.primary.as_mut().unwrap(), + &mut new_styles.primary.0.style, data.hint, important_rules_changed, ); // First of all, update the styles. - let old_styles = mem::replace(&mut data.styles, new_styles); + let old_styles = data.set_styles(new_styles); // Propagate the "can be fragmented" bit. It would be nice to // encapsulate this better. diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index 4d806f92de1..184f095c09e 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -49,12 +49,52 @@ struct MatchingResults { relevant_link_found: bool, } -/// The primary style of an element or an element-backed pseudo-element. -pub struct PrimaryStyle { - /// The style per se. +/// A style returned from the resolver machinery. +pub struct ResolvedStyle { + /// The style itself. pub style: Arc, } +/// The primary style of an element or an element-backed pseudo-element. +pub struct PrimaryStyle(pub ResolvedStyle); + +/// A set of style returned from the resolver machinery. +pub struct ResolvedElementStyles { + /// Primary style. + pub primary: PrimaryStyle, + /// Pseudo styles. + pub pseudos: EagerPseudoStyles, +} + +impl ResolvedStyle { + /// Creates a new ResolvedStyle. + pub fn new(style: Arc) -> Self { + ResolvedStyle { style } + } +} + +impl PrimaryStyle { + /// Convenience accessor for the style. + pub fn style(&self) -> &ComputedValues { + &*self.0.style + } +} + +impl From for Arc { + fn from(r: ResolvedStyle) -> Arc { + r.style + } +} + +impl From for ElementStyles { + fn from(r: ResolvedElementStyles) -> ElementStyles { + ElementStyles { + primary: Some(r.primary.0.into()), + pseudos: r.pseudos, + } + } +} + fn with_default_parent_styles(element: E, f: F) -> R where E: TElement, @@ -140,8 +180,8 @@ where None }; - PrimaryStyle { - style: self.cascade_style_and_visited( + PrimaryStyle( + self.cascade_style_and_visited( CascadeInputs { rules: Some(primary_results.rule_node), visited_rules, @@ -149,8 +189,8 @@ where parent_style, layout_parent_style, /* pseudo = */ None, - ), - } + ) + ) } /// Resolve the style of a given element, and all its eager pseudo-elements. @@ -158,7 +198,7 @@ where &mut self, parent_style: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, - ) -> ElementStyles { + ) -> ResolvedElementStyles { let primary_style = self.resolve_primary_style(parent_style, layout_parent_style); @@ -166,10 +206,10 @@ where if self.element.implemented_pseudo_element().is_none() { let layout_parent_style_for_pseudo = - if primary_style.style.is_display_contents() { + if primary_style.style().is_display_contents() { layout_parent_style } else { - Some(&*primary_style.style) + Some(primary_style.style()) }; SelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| { let pseudo_style = self.resolve_pseudo_style( @@ -188,16 +228,15 @@ where }) } - ElementStyles { - // FIXME(emilio): Remove the Option<>. - primary: Some(primary_style.style), + ResolvedElementStyles { + primary: primary_style, pseudos: pseudo_styles, } } /// Resolve an element's styles with the default inheritance parent/layout /// parents. - pub fn resolve_style_with_default_parents(&mut self) -> ElementStyles { + pub fn resolve_style_with_default_parents(&mut self) -> ResolvedElementStyles { with_default_parent_styles(self.element, |parent_style, layout_parent_style| { self.resolve_style(parent_style, layout_parent_style) }) @@ -207,7 +246,7 @@ where pub fn cascade_style_and_visited_with_default_parents( &mut self, inputs: CascadeInputs, - ) -> Arc { + ) -> ResolvedStyle { with_default_parent_styles(self.element, |parent_style, layout_parent_style| { self.cascade_style_and_visited( inputs, @@ -224,7 +263,7 @@ where parent_style: Option<&ComputedValues>, layout_parent_style: Option<&ComputedValues>, pseudo: Option<&PseudoElement>, - ) -> Arc { + ) -> ResolvedStyle { let mut style_if_visited = None; if parent_style.map_or(false, |s| s.get_visited_style().is_some()) || inputs.visited_rules.is_some() { @@ -237,38 +276,41 @@ where pseudo, )); } - self.cascade_style( - inputs.rules.as_ref(), - style_if_visited, - parent_style, - layout_parent_style, - CascadeVisitedMode::Unvisited, - pseudo, - ) + + ResolvedStyle { + style: self.cascade_style( + inputs.rules.as_ref(), + style_if_visited, + parent_style, + layout_parent_style, + CascadeVisitedMode::Unvisited, + pseudo, + ) + } } /// Cascade the element and pseudo-element styles with the default parents. pub fn cascade_styles_with_default_parents( &mut self, inputs: ElementCascadeInputs, - ) -> ElementStyles { + ) -> ResolvedElementStyles { with_default_parent_styles(self.element, move |parent_style, layout_parent_style| { - let primary_style = PrimaryStyle { - style: self.cascade_style_and_visited( + let primary_style = PrimaryStyle( + self.cascade_style_and_visited( inputs.primary, parent_style, layout_parent_style, /* pseudo = */ None, - ), - }; + ) + ); let mut pseudo_styles = EagerPseudoStyles::default(); if let Some(mut pseudo_array) = inputs.pseudos.into_array() { let layout_parent_style_for_pseudo = - if primary_style.style.is_display_contents() { + if primary_style.style().is_display_contents() { layout_parent_style } else { - Some(&*primary_style.style) + Some(primary_style.style()) }; for (i, inputs) in pseudo_array.iter_mut().enumerate() { @@ -278,23 +320,23 @@ where let style = self.cascade_style_and_visited( inputs, - Some(&*primary_style.style), + Some(&*primary_style.style()), layout_parent_style_for_pseudo, Some(&pseudo), ); if !matches!(self.pseudo_resolution, PseudoElementResolution::Force) && - eager_pseudo_is_definitely_not_generated(&pseudo, &style) { + eager_pseudo_is_definitely_not_generated(&pseudo, &style.style) { continue; } - pseudo_styles.set(&pseudo, style); + pseudo_styles.set(&pseudo, style.style); } } } - ElementStyles { - primary: Some(primary_style.style), + ResolvedElementStyles { + primary: primary_style, pseudos: pseudo_styles, } }) @@ -307,7 +349,7 @@ where layout_parent_style: Option<&ComputedValues>, ) -> Option> { let rules = self.match_pseudo( - &originating_element_style.style, + originating_element_style.style(), pseudo, VisitedHandlingMode::AllLinksUnvisited ); @@ -317,9 +359,9 @@ where }; let mut visited_rules = None; - if originating_element_style.style.get_visited_style().is_some() { + if originating_element_style.style().get_visited_style().is_some() { visited_rules = self.match_pseudo( - &originating_element_style.style, + originating_element_style.style(), pseudo, VisitedHandlingMode::RelevantLinkVisited, ); @@ -330,10 +372,10 @@ where rules: Some(rules), visited_rules }, - Some(&originating_element_style.style), + Some(originating_element_style.style()), layout_parent_style, Some(pseudo), - )) + ).style) } fn match_primary( diff --git a/components/style/traversal.rs b/components/style/traversal.rs index dc422f64cad..f7009f04abf 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -419,9 +419,9 @@ where layout_parent_style.as_ref().map(|s| &**s) ); - let is_display_contents = primary_style.style.is_display_contents(); + let is_display_contents = primary_style.style().is_display_contents(); - style = Some(primary_style.style); + style = Some(primary_style.0.into()); if !is_display_contents { layout_parent_style = style.clone(); } @@ -434,7 +434,7 @@ where .resolve_style( style.as_ref().map(|s| &**s), layout_parent_style.as_ref().map(|s| &**s) - ) + ).into() } /// Calculates the style for a single node. @@ -657,8 +657,7 @@ where match target.share_style_if_possible(context) { Some(shareable_element) => { context.thread_local.statistics.styles_shared += 1; - let shareable_data = shareable_element.borrow_data().unwrap(); - shareable_data.styles.clone() + shareable_element.borrow_data().unwrap().share_styles() } None => { context.thread_local.statistics.elements_matched += 1; @@ -679,7 +678,7 @@ where .sharing_cache .insert_if_possible( &element, - new_styles.primary(), + new_styles.primary.style(), &mut target, context.thread_local.bloom_filter.matching_depth(), ); diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 2667a46f4eb..ad1209dd287 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -727,9 +727,11 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe }; // Actually `PseudoElementResolution` doesn't matter. - StyleResolverForElement::new(element, &mut context, RuleInclusion::All, PseudoElementResolution::IfApplicable) + let style: Arc = + StyleResolverForElement::new(element, &mut context, RuleInclusion::All, PseudoElementResolution::IfApplicable) .cascade_style_and_visited_with_default_parents(inputs) - .into() + .into(); + style.into() } #[no_mangle]