mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Remove one level of nesting in Stylist
Since #13134, the "normal" and "important" parts of `Stylist` are identical, so we don’t need to store them twice.
This commit is contained in:
parent
3ce64fd269
commit
74eaf2ad6f
2 changed files with 104 additions and 116 deletions
|
@ -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.
|
||||||
|
@ -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: ApplicableDeclarationBlock {
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -414,7 +400,7 @@ impl Stylist {
|
||||||
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,
|
||||||
|
@ -436,7 +422,7 @@ impl Stylist {
|
||||||
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,
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +754,7 @@ impl SelectorMap {
|
||||||
V: VecLike<ApplicableDeclarationBlock>
|
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,7 +840,21 @@ 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: ApplicableDeclarationBlock,
|
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
|
||||||
|
|
|
@ -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::{ApplicableDeclarationBlock, 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: ApplicableDeclarationBlock {
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue