Auto merge of #13179 - servo:flatter-stylist, r=emilio

Remove one level of nesting in `Stylist`

<!-- Please describe your changes on the following line: -->

Since #13134, the "normal" and "important" parts of `Stylist` are identical, so we don’t need to store them twice.

r? @emilio

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13179)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-09-06 01:48:04 -05:00 committed by GitHub
commit 89126b44d7
10 changed files with 149 additions and 161 deletions

View file

@ -91,7 +91,7 @@ use style::properties::{DeclaredValue, Importance};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
use style::refcell::Ref; use style::refcell::Ref;
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl}; use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::selector_matching::DeclarationBlock; use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push; use style::sink::Push;
use style::values::CSSFloat; use style::values::CSSFloat;
use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage}; use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
@ -291,7 +291,7 @@ pub trait LayoutElementHelpers {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V) unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, &mut V)
where V: Push<DeclarationBlock>; where V: Push<ApplicableDeclarationBlock>;
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_colspan(self) -> u32; unsafe fn get_colspan(self) -> u32;
#[allow(unsafe_code)] #[allow(unsafe_code)]
@ -324,11 +324,11 @@ impl LayoutElementHelpers for LayoutJS<Element> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V) unsafe fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
where V: Push<DeclarationBlock> where V: Push<ApplicableDeclarationBlock>
{ {
#[inline] #[inline]
fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock { fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
DeclarationBlock::from_declarations( ApplicableDeclarationBlock::from_declarations(
Arc::new(PropertyDeclarationBlock { Arc::new(PropertyDeclarationBlock {
declarations: vec![(rule, Importance::Normal)], declarations: vec![(rule, Importance::Normal)],
important_count: 0, important_count: 0,

View file

@ -63,7 +63,7 @@ use style::element_state::*;
use style::properties::{ComputedValues, PropertyDeclarationBlock}; use style::properties::{ComputedValues, PropertyDeclarationBlock};
use style::refcell::{Ref, RefCell, RefMut}; use style::refcell::{Ref, RefCell, RefMut};
use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, PseudoElement, ServoSelectorImpl}; use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
use style::selector_matching::DeclarationBlock; use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push; use style::sink::Push;
use style::str::is_whitespace; use style::str::is_whitespace;
use url::Url; use url::Url;
@ -442,7 +442,7 @@ impl<'le> fmt::Debug for ServoLayoutElement<'le> {
impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> { impl<'le> PresentationalHintsSynthetizer for ServoLayoutElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V) fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
where V: Push<DeclarationBlock> where V: Push<ApplicableDeclarationBlock>
{ {
unsafe { unsafe {
self.element.synthesize_presentational_hints_for_legacy_attributes(hints); self.element.synthesize_presentational_hints_for_legacy_attributes(hints);
@ -1094,5 +1094,5 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> { impl<'le> PresentationalHintsSynthetizer for ServoThreadSafeLayoutElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V) fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
where V: Push<DeclarationBlock> {} where V: Push<ApplicableDeclarationBlock> {}
} }

View file

@ -16,7 +16,7 @@ use properties::longhands::animation_play_state::computed_value::AnimationPlaySt
use properties::longhands::transition_timing_function::computed_value::StartEnd; use properties::longhands::transition_timing_function::computed_value::StartEnd;
use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction; use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction;
use properties::{self, ComputedValues, Importance}; use properties::{self, ComputedValues, Importance};
use selector_matching::DeclarationBlock; use selector_matching::ApplicableDeclarationBlock;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use string_cache::Atom; use string_cache::Atom;
@ -384,7 +384,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
// an Arc in the below (more common case). // an Arc in the below (more common case).
KeyframesStepValue::ComputedValues => style_from_cascade.clone(), KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
KeyframesStepValue::Declarations(ref declarations) => { KeyframesStepValue::Declarations(ref declarations) => {
let declaration_block = DeclarationBlock { let declaration_block = ApplicableDeclarationBlock {
mixed_declarations: declarations.clone(), mixed_declarations: declarations.clone(),
importance: Importance::Normal, importance: Importance::Normal,
source_order: 0, source_order: 0,

View file

@ -13,7 +13,7 @@ use properties::{ComputedValues, PropertyDeclarationBlock};
use refcell::{Ref, RefMut}; use refcell::{Ref, RefMut};
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint}; use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use selector_impl::{ElementExt, PseudoElement}; use selector_impl::{ElementExt, PseudoElement};
use selector_matching::DeclarationBlock; use selector_matching::ApplicableDeclarationBlock;
use sink::Push; use sink::Push;
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::BitOr; use std::ops::BitOr;
@ -186,7 +186,7 @@ pub trait TDocument : Sized + Copy + Clone {
pub trait PresentationalHintsSynthetizer { pub trait PresentationalHintsSynthetizer {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V) fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, hints: &mut V)
where V: Push<DeclarationBlock>; where V: Push<ApplicableDeclarationBlock>;
} }
pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer { pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {

View file

@ -75,7 +75,7 @@ pub struct Keyframe {
/// `!important` is not allowed in keyframe declarations, /// `!important` is not allowed in keyframe declarations,
/// so the second value of these tuples is always `Importance::Normal`. /// so the second value of these tuples is always `Importance::Normal`.
/// But including them enables `compute_style_for_animation_step` to create a `DeclarationBlock` /// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock`
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`. /// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
pub block: Arc<PropertyDeclarationBlock>, pub block: Arc<PropertyDeclarationBlock>,
} }

View file

@ -16,7 +16,7 @@ use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
use properties::longhands::display::computed_value as display; use properties::longhands::display::computed_value as display;
use properties::{ComputedValues, cascade, PropertyDeclarationBlock}; use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
use selector_impl::{TheSelectorImpl, PseudoElement}; use selector_impl::{TheSelectorImpl, PseudoElement};
use selector_matching::{DeclarationBlock, Stylist}; use selector_matching::{ApplicableDeclarationBlock, Stylist};
use selectors::bloom::BloomFilter; use selectors::bloom::BloomFilter;
use selectors::matching::{MatchingReason, StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS}; use selectors::matching::{MatchingReason, StyleRelations, AFFECTED_BY_PSEUDO_ELEMENTS};
use selectors::{Element, MatchAttr}; use selectors::{Element, MatchAttr};
@ -51,9 +51,9 @@ fn create_common_style_affecting_attributes_from_element<E: TElement>(element: &
} }
pub struct ApplicableDeclarations { pub struct ApplicableDeclarations {
pub normal: SmallVec<[DeclarationBlock; 16]>, pub normal: SmallVec<[ApplicableDeclarationBlock; 16]>,
pub per_pseudo: HashMap<PseudoElement, pub per_pseudo: HashMap<PseudoElement,
Vec<DeclarationBlock>, Vec<ApplicableDeclarationBlock>,
BuildHasherDefault<::fnv::FnvHasher>>, BuildHasherDefault<::fnv::FnvHasher>>,
/// Whether the `normal` declarations are shareable with other nodes. /// Whether the `normal` declarations are shareable with other nodes.
@ -78,11 +78,11 @@ impl ApplicableDeclarations {
#[derive(Clone)] #[derive(Clone)]
pub struct ApplicableDeclarationsCacheEntry { pub struct ApplicableDeclarationsCacheEntry {
pub declarations: Vec<DeclarationBlock>, pub declarations: Vec<ApplicableDeclarationBlock>,
} }
impl ApplicableDeclarationsCacheEntry { impl ApplicableDeclarationsCacheEntry {
fn new(declarations: Vec<DeclarationBlock>) -> ApplicableDeclarationsCacheEntry { fn new(declarations: Vec<ApplicableDeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
ApplicableDeclarationsCacheEntry { ApplicableDeclarationsCacheEntry {
declarations: declarations, declarations: declarations,
} }
@ -105,11 +105,11 @@ impl Hash for ApplicableDeclarationsCacheEntry {
} }
struct ApplicableDeclarationsCacheQuery<'a> { struct ApplicableDeclarationsCacheQuery<'a> {
declarations: &'a [DeclarationBlock], declarations: &'a [ApplicableDeclarationBlock],
} }
impl<'a> ApplicableDeclarationsCacheQuery<'a> { impl<'a> ApplicableDeclarationsCacheQuery<'a> {
fn new(declarations: &'a [DeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> { fn new(declarations: &'a [ApplicableDeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
ApplicableDeclarationsCacheQuery { ApplicableDeclarationsCacheQuery {
declarations: declarations, declarations: declarations,
} }
@ -159,14 +159,14 @@ impl ApplicableDeclarationsCache {
} }
} }
pub fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> { pub fn find(&self, declarations: &[ApplicableDeclarationBlock]) -> Option<Arc<ComputedValues>> {
match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) { match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) {
None => None, None => None,
Some(ref values) => Some((*values).clone()), Some(ref values) => Some((*values).clone()),
} }
} }
pub fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) { pub fn insert(&mut self, declarations: Vec<ApplicableDeclarationBlock>, style: Arc<ComputedValues>) {
self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style) self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style)
} }
@ -493,7 +493,7 @@ trait PrivateMatchMethods: TNode {
fn cascade_node_pseudo_element<'a, Ctx>(&self, fn cascade_node_pseudo_element<'a, Ctx>(&self,
context: &Ctx, context: &Ctx,
parent_style: Option<&Arc<ComputedValues>>, parent_style: Option<&Arc<ComputedValues>>,
applicable_declarations: &[DeclarationBlock], applicable_declarations: &[ApplicableDeclarationBlock],
mut old_style: Option<&mut Arc<ComputedValues>>, mut old_style: Option<&mut Arc<ComputedValues>>,
applicable_declarations_cache: applicable_declarations_cache:
&mut ApplicableDeclarationsCache, &mut ApplicableDeclarationsCache,

View file

@ -29,7 +29,7 @@ use computed_values;
#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide}; #[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
use logical_geometry::WritingMode; use logical_geometry::WritingMode;
use parser::{ParserContext, ParserContextExtraData, log_css_error}; use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selector_matching::DeclarationBlock; use selector_matching::ApplicableDeclarationBlock;
use stylesheets::Origin; use stylesheets::Origin;
use values::LocalToCss; use values::LocalToCss;
use values::HasViewportPercentage; use values::HasViewportPercentage;
@ -1718,7 +1718,7 @@ mod lazy_static_module {
#[allow(unused_mut, unused_imports)] #[allow(unused_mut, unused_imports)]
fn cascade_with_cached_declarations( fn cascade_with_cached_declarations(
viewport_size: Size2D<Au>, viewport_size: Size2D<Au>,
applicable_declarations: &[DeclarationBlock], applicable_declarations: &[ApplicableDeclarationBlock],
shareable: bool, shareable: bool,
parent_style: &ComputedValues, parent_style: &ComputedValues,
cached_style: &ComputedValues, cached_style: &ComputedValues,
@ -1863,7 +1863,7 @@ static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
/// ///
/// Returns the computed values and a boolean indicating whether the result is cacheable. /// Returns the computed values and a boolean indicating whether the result is cacheable.
pub fn cascade(viewport_size: Size2D<Au>, pub fn cascade(viewport_size: Size2D<Au>,
applicable_declarations: &[DeclarationBlock], applicable_declarations: &[ApplicableDeclarationBlock],
shareable: bool, shareable: bool,
parent_style: Option<<&ComputedValues>, parent_style: Option<<&ComputedValues>,
cached_style: Option<<&ComputedValues>, cached_style: Option<<&ComputedValues>,

View file

@ -38,8 +38,7 @@ pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<::fnv::FnvHasher>>;
/// for a given document. The selectors are converted into `Rule`s /// for a given document. The selectors are converted into `Rule`s
/// (defined in rust-selectors), and introduced in a `SelectorMap` /// (defined in rust-selectors), and introduced in a `SelectorMap`
/// depending on the pseudo-element (see `PerPseudoElementSelectorMap`), /// depending on the pseudo-element (see `PerPseudoElementSelectorMap`),
/// stylesheet origin (see `PerOriginSelectorMap`), and priority /// and stylesheet origin (see the fields of `PerPseudoElementSelectorMap`).
/// (see the `normal` and `important` fields in `PerOriginSelectorMap`).
/// ///
/// This structure is effectively created once per pipeline, in the /// This structure is effectively created once per pipeline, in the
/// LayoutThread corresponding to that pipeline. /// LayoutThread corresponding to that pipeline.
@ -71,7 +70,7 @@ pub struct Stylist {
/// Applicable declarations for a given non-eagerly cascaded pseudo-element. /// Applicable declarations for a given non-eagerly cascaded pseudo-element.
/// These are eagerly computed once, and then used to resolve the new /// These are eagerly computed once, and then used to resolve the new
/// computed values on the fly on layout. /// computed values on the fly on layout.
precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<DeclarationBlock>>, precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<ApplicableDeclarationBlock>>,
rules_source_order: usize, rules_source_order: usize,
@ -162,11 +161,10 @@ impl Stylist {
} }
let mut rules_source_order = self.rules_source_order; let mut rules_source_order = self.rules_source_order;
// Take apart the StyleRule into individual Rules and insert for rule in stylesheet.effective_rules(&self.device) {
// them into the SelectorMap of that priority. match *rule {
macro_rules! append( CSSRule::Style(ref style_rule) => {
($style_rule: ident, $priority: ident, $importance: expr) => { for selector in &style_rule.selectors {
for selector in &$style_rule.selectors {
let map = if let Some(ref pseudo) = selector.pseudo_element { let map = if let Some(ref pseudo) = selector.pseudo_element {
self.pseudos_map self.pseudos_map
.entry(pseudo.clone()) .entry(pseudo.clone())
@ -176,24 +174,13 @@ impl Stylist {
self.element_map.borrow_for_origin(&stylesheet.origin) self.element_map.borrow_for_origin(&stylesheet.origin)
}; };
map.$priority.insert(Rule { map.insert(Rule {
selector: selector.complex_selector.clone(), selector: selector.complex_selector.clone(),
declarations: DeclarationBlock { declarations: style_rule.declarations.clone(),
specificity: selector.specificity, specificity: selector.specificity,
mixed_declarations: $style_rule.declarations.clone(),
importance: $importance,
source_order: rules_source_order, source_order: rules_source_order,
},
}); });
} }
};
);
for rule in stylesheet.effective_rules(&self.device) {
match *rule {
CSSRule::Style(ref style_rule) => {
append!(style_rule, normal, Importance::Normal);
append!(style_rule, important, Importance::Important);
rules_source_order += 1; rules_source_order += 1;
for selector in &style_rule.selectors { for selector in &style_rule.selectors {
@ -242,8 +229,7 @@ impl Stylist {
if let Some(map) = self.pseudos_map.remove(&pseudo) { if let Some(map) = self.pseudos_map.remove(&pseudo) {
let mut declarations = vec![]; let mut declarations = vec![];
map.user_agent.normal.get_universal_rules(&mut declarations); map.user_agent.get_universal_rules(&mut declarations);
map.user_agent.important.get_universal_rules(&mut declarations);
self.precomputed_pseudo_element_decls.insert(pseudo, declarations); self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
} }
@ -350,7 +336,7 @@ impl Stylist {
where E: Element<Impl=TheSelectorImpl> + where E: Element<Impl=TheSelectorImpl> +
fmt::Debug + fmt::Debug +
PresentationalHintsSynthetizer, PresentationalHintsSynthetizer,
V: Push<DeclarationBlock> + VecLike<DeclarationBlock> V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
{ {
assert!(!self.is_device_dirty); assert!(!self.is_device_dirty);
assert!(style_attribute.is_none() || pseudo_element.is_none(), assert!(style_attribute.is_none() || pseudo_element.is_none(),
@ -368,7 +354,7 @@ impl Stylist {
debug!("Determining if style is shareable: pseudo: {}", pseudo_element.is_some()); debug!("Determining if style is shareable: pseudo: {}", pseudo_element.is_some());
// Step 1: Normal user-agent rules. // Step 1: Normal user-agent rules.
map.user_agent.normal.get_all_matching_rules(element, map.user_agent.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
@ -386,14 +372,14 @@ impl Stylist {
debug!("preshints: {:?}", relations); debug!("preshints: {:?}", relations);
// Step 3: User and author normal rules. // Step 3: User and author normal rules.
map.user.normal.get_all_matching_rules(element, map.user.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
reason, reason,
Importance::Normal); Importance::Normal);
debug!("user normal: {:?}", relations); debug!("user normal: {:?}", relations);
map.author.normal.get_all_matching_rules(element, map.author.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
@ -407,14 +393,14 @@ impl Stylist {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE; relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push( Push::push(
applicable_declarations, applicable_declarations,
DeclarationBlock::from_declarations(sa.clone(), Importance::Normal)); ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
} }
} }
debug!("style attr: {:?}", relations); debug!("style attr: {:?}", relations);
// Step 5: Author-supplied `!important` rules. // Step 5: Author-supplied `!important` rules.
map.author.important.get_all_matching_rules(element, map.author.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
@ -429,14 +415,14 @@ impl Stylist {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE; relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push( Push::push(
applicable_declarations, applicable_declarations,
DeclarationBlock::from_declarations(sa.clone(), Importance::Important)); ApplicableDeclarationBlock::from_declarations(sa.clone(), Importance::Important));
} }
} }
debug!("style attr important: {:?}", relations); debug!("style attr important: {:?}", relations);
// Step 7: User and UA `!important` rules. // Step 7: User and UA `!important` rules.
map.user.important.get_all_matching_rules(element, map.user.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
@ -445,7 +431,7 @@ impl Stylist {
debug!("user important: {:?}", relations); debug!("user important: {:?}", relations);
map.user_agent.important.get_all_matching_rules(element, map.user_agent.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
&mut relations, &mut relations,
@ -549,51 +535,30 @@ impl Stylist {
} }
/// Map that contains the CSS rules for a given origin.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
struct PerOriginSelectorMap {
/// Rules that contains at least one property declaration with
/// normal importance.
normal: SelectorMap,
/// Rules that contains at least one property declaration with
/// !important.
important: SelectorMap,
}
impl PerOriginSelectorMap {
#[inline]
fn new() -> Self {
PerOriginSelectorMap {
normal: SelectorMap::new(),
important: SelectorMap::new(),
}
}
}
/// Map that contains the CSS rules for a specific PseudoElement /// Map that contains the CSS rules for a specific PseudoElement
/// (or lack of PseudoElement). /// (or lack of PseudoElement).
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
struct PerPseudoElementSelectorMap { struct PerPseudoElementSelectorMap {
/// Rules from user agent stylesheets /// Rules from user agent stylesheets
user_agent: PerOriginSelectorMap, user_agent: SelectorMap,
/// Rules from author stylesheets /// Rules from author stylesheets
author: PerOriginSelectorMap, author: SelectorMap,
/// Rules from user stylesheets /// Rules from user stylesheets
user: PerOriginSelectorMap, user: SelectorMap,
} }
impl PerPseudoElementSelectorMap { impl PerPseudoElementSelectorMap {
#[inline] #[inline]
fn new() -> Self { fn new() -> Self {
PerPseudoElementSelectorMap { PerPseudoElementSelectorMap {
user_agent: PerOriginSelectorMap::new(), user_agent: SelectorMap::new(),
author: PerOriginSelectorMap::new(), author: SelectorMap::new(),
user: PerOriginSelectorMap::new(), user: SelectorMap::new(),
} }
} }
#[inline] #[inline]
fn borrow_for_origin(&mut self, origin: &Origin) -> &mut PerOriginSelectorMap { fn borrow_for_origin(&mut self, origin: &Origin) -> &mut SelectorMap {
match *origin { match *origin {
Origin::UserAgent => &mut self.user_agent, Origin::UserAgent => &mut self.user_agent,
Origin::Author => &mut self.author, Origin::Author => &mut self.author,
@ -665,7 +630,7 @@ impl SelectorMap {
reason: MatchingReason, reason: MatchingReason,
importance: Importance) importance: Importance)
where E: Element<Impl=TheSelectorImpl>, where E: Element<Impl=TheSelectorImpl>,
V: VecLike<DeclarationBlock> V: VecLike<ApplicableDeclarationBlock>
{ {
if self.empty { if self.empty {
return return
@ -726,7 +691,7 @@ impl SelectorMap {
/// `self` sorted by specifity and source order. /// `self` sorted by specifity and source order.
pub fn get_universal_rules<V>(&self, pub fn get_universal_rules<V>(&self,
matching_rules_list: &mut V) matching_rules_list: &mut V)
where V: VecLike<DeclarationBlock> where V: VecLike<ApplicableDeclarationBlock>
{ {
if self.empty { if self.empty {
return return
@ -737,7 +702,14 @@ impl SelectorMap {
for rule in self.other_rules.iter() { for rule in self.other_rules.iter() {
if rule.selector.compound_selector.is_empty() && if rule.selector.compound_selector.is_empty() &&
rule.selector.next.is_none() { rule.selector.next.is_none() {
matching_rules_list.push(rule.declarations.clone()); if rule.declarations.any_normal() {
matching_rules_list.push(
rule.to_applicable_declaration_block(Importance::Normal));
}
if rule.declarations.any_important() {
matching_rules_list.push(
rule.to_applicable_declaration_block(Importance::Important));
}
} }
} }
@ -757,7 +729,7 @@ impl SelectorMap {
where E: Element<Impl=TheSelectorImpl>, where E: Element<Impl=TheSelectorImpl>,
Str: Borrow<BorrowedStr> + Eq + Hash, Str: Borrow<BorrowedStr> + Eq + Hash,
BorrowedStr: Eq + Hash, BorrowedStr: Eq + Hash,
Vector: VecLike<DeclarationBlock> Vector: VecLike<ApplicableDeclarationBlock>
{ {
if let Some(rules) = hash.get(key) { if let Some(rules) = hash.get(key) {
SelectorMap::get_matching_rules(element, SelectorMap::get_matching_rules(element,
@ -779,10 +751,10 @@ impl SelectorMap {
reason: MatchingReason, reason: MatchingReason,
importance: Importance) importance: Importance)
where E: Element<Impl=TheSelectorImpl>, where E: Element<Impl=TheSelectorImpl>,
V: VecLike<DeclarationBlock> V: VecLike<ApplicableDeclarationBlock>
{ {
for rule in rules.iter() { for rule in rules.iter() {
let block = &rule.declarations.mixed_declarations; let block = &rule.declarations;
let any_declaration_for_importance = if importance.important() { let any_declaration_for_importance = if importance.important() {
block.any_important() block.any_important()
} else { } else {
@ -791,7 +763,7 @@ impl SelectorMap {
if any_declaration_for_importance && if any_declaration_for_importance &&
matches_complex_selector(&*rule.selector, element, parent_bf, matches_complex_selector(&*rule.selector, element, parent_bf,
relations, reason) { relations, reason) {
matching_rules.push(rule.declarations.clone()); matching_rules.push(rule.to_applicable_declaration_block(importance));
} }
} }
} }
@ -868,28 +840,42 @@ pub struct Rule {
// that it matches. Selector contains an owned vector (through // that it matches. Selector contains an owned vector (through
// ComplexSelector) and we want to avoid the allocation. // ComplexSelector) and we want to avoid the allocation.
pub selector: Arc<ComplexSelector<TheSelectorImpl>>, pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
pub declarations: DeclarationBlock, pub declarations: Arc<PropertyDeclarationBlock>,
pub source_order: usize,
pub specificity: u32,
}
impl Rule {
fn to_applicable_declaration_block(&self, importance: Importance)
-> ApplicableDeclarationBlock {
ApplicableDeclarationBlock {
mixed_declarations: self.declarations.clone(),
importance: importance,
source_order: self.source_order,
specificity: self.specificity,
}
}
} }
/// A property declaration together with its precedence among rules of equal specificity so that /// A property declaration together with its precedence among rules of equal specificity so that
/// we can sort them. /// we can sort them.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DeclarationBlock { pub struct ApplicableDeclarationBlock {
/// Contains declarations of either importance, but only those of self.importance are relevant. /// Contains declarations of either importance, but only those of self.importance are relevant.
/// Use DeclarationBlock::iter /// Use ApplicableDeclarationBlock::iter
pub mixed_declarations: Arc<PropertyDeclarationBlock>, pub mixed_declarations: Arc<PropertyDeclarationBlock>,
pub importance: Importance, pub importance: Importance,
pub source_order: usize, pub source_order: usize,
pub specificity: u32, pub specificity: u32,
} }
impl DeclarationBlock { impl ApplicableDeclarationBlock {
#[inline] #[inline]
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>, pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
importance: Importance) importance: Importance)
-> Self { -> Self {
DeclarationBlock { ApplicableDeclarationBlock {
mixed_declarations: declarations, mixed_declarations: declarations,
importance: importance, importance: importance,
source_order: 0, source_order: 0,
@ -897,20 +883,20 @@ impl DeclarationBlock {
} }
} }
pub fn iter(&self) -> DeclarationBlockIter { pub fn iter(&self) -> ApplicableDeclarationBlockIter {
DeclarationBlockIter { ApplicableDeclarationBlockIter {
iter: self.mixed_declarations.declarations.iter(), iter: self.mixed_declarations.declarations.iter(),
importance: self.importance, importance: self.importance,
} }
} }
} }
pub struct DeclarationBlockIter<'a> { pub struct ApplicableDeclarationBlockIter<'a> {
iter: slice::Iter<'a, (PropertyDeclaration, Importance)>, iter: slice::Iter<'a, (PropertyDeclaration, Importance)>,
importance: Importance, importance: Importance,
} }
impl<'a> Iterator for DeclarationBlockIter<'a> { impl<'a> Iterator for ApplicableDeclarationBlockIter<'a> {
type Item = &'a PropertyDeclaration; type Item = &'a PropertyDeclaration;
#[inline] #[inline]
@ -924,7 +910,7 @@ impl<'a> Iterator for DeclarationBlockIter<'a> {
} }
} }
impl<'a> DoubleEndedIterator for DeclarationBlockIter<'a> { impl<'a> DoubleEndedIterator for ApplicableDeclarationBlockIter<'a> {
#[inline] #[inline]
fn next_back(&mut self) -> Option<Self::Item> { fn next_back(&mut self) -> Option<Self::Item> {
while let Some(&(ref declaration, importance)) = self.iter.next_back() { while let Some(&(ref declaration, importance)) = self.iter.next_back() {

View file

@ -51,7 +51,7 @@ use style::properties::PropertyDeclarationBlock;
use style::properties::{ComputedValues, parse_style_attribute}; use style::properties::{ComputedValues, parse_style_attribute};
use style::refcell::{Ref, RefCell, RefMut}; use style::refcell::{Ref, RefCell, RefMut};
use style::selector_impl::ElementExt; use style::selector_impl::ElementExt;
use style::selector_matching::DeclarationBlock; use style::selector_matching::ApplicableDeclarationBlock;
use style::sink::Push; use style::sink::Push;
use url::Url; use url::Url;
@ -484,7 +484,7 @@ impl<'le> PartialEq for GeckoElement<'le> {
impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> { impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V) fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
where V: Push<DeclarationBlock> where V: Push<ApplicableDeclarationBlock>
{ {
// FIXME(bholley) - Need to implement this. // FIXME(bholley) - Need to implement this.
} }

View file

@ -6,8 +6,9 @@ use cssparser::Parser;
use selectors::parser::{LocalName, ParserContext, parse_selector_list}; use selectors::parser::{LocalName, ParserContext, parse_selector_list};
use std::sync::Arc; use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use style::properties::{Importance, PropertyDeclarationBlock}; use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, DeclaredValue};
use style::selector_matching::{DeclarationBlock, Rule, SelectorMap}; use style::properties::{longhands, Importance};
use style::selector_matching::{Rule, SelectorMap};
/// Helper method to get some Rules from selector strings. /// Helper method to get some Rules from selector strings.
/// Each sublist of the result contains the Rules for one StyleRule. /// Each sublist of the result contains the Rules for one StyleRule.
@ -18,16 +19,17 @@ fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
.unwrap().into_iter().map(|s| { .unwrap().into_iter().map(|s| {
Rule { Rule {
selector: s.complex_selector.clone(), selector: s.complex_selector.clone(),
declarations: DeclarationBlock { declarations: Arc::new(PropertyDeclarationBlock {
mixed_declarations: Arc::new(PropertyDeclarationBlock { declarations: vec![
declarations: Vec::new(), (PropertyDeclaration::Display(DeclaredValue::Value(
longhands::display::SpecifiedValue::block)),
Importance::Normal),
],
important_count: 0, important_count: 0,
}), }),
importance: Importance::Normal,
specificity: s.specificity, specificity: s.specificity,
source_order: i, source_order: i,
} }
}
}).collect() }).collect()
}).collect() }).collect()
} }
@ -48,8 +50,8 @@ fn get_mock_map(selectors: &[&str]) -> SelectorMap {
#[test] #[test]
fn test_rule_ordering_same_specificity() { fn test_rule_ordering_same_specificity() {
let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]); let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]);
let a = &rules_list[0][0].declarations; let a = &rules_list[0][0];
let b = &rules_list[1][0].declarations; let b = &rules_list[1][0];
assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)), assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
"The rule that comes later should win."); "The rule that comes later should win.");
} }
@ -89,9 +91,9 @@ fn test_insert() {
let rules_list = get_mock_rules(&[".intro.foo", "#top"]); let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
let mut selector_map = SelectorMap::new(); let mut selector_map = SelectorMap::new();
selector_map.insert(rules_list[1][0].clone()); selector_map.insert(rules_list[1][0].clone());
assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].declarations.source_order); assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].source_order);
selector_map.insert(rules_list[0][0].clone()); selector_map.insert(rules_list[0][0].clone());
assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].declarations.source_order); assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].source_order);
assert!(selector_map.class_hash.get(&Atom::from("foo")).is_none()); assert!(selector_map.class_hash.get(&Atom::from("foo")).is_none());
} }