aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/selector_matching.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/selector_matching.rs')
-rw-r--r--components/style/selector_matching.rs120
1 files changed, 60 insertions, 60 deletions
diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs
index b97fcf9bb68..1a0a07b32e4 100644
--- a/components/style/selector_matching.rs
+++ b/components/style/selector_matching.rs
@@ -10,11 +10,12 @@ use element_state::*;
use error_reporting::StdoutErrorReporter;
use keyframes::KeyframesAnimation;
use media_queries::{Device, MediaType};
-use parking_lot::{RwLock, RwLockReadGuard};
+use parking_lot::RwLock;
use properties::{self, CascadeFlags, ComputedValues, INHERIT_ALL, Importance};
use properties::{PropertyDeclaration, PropertyDeclarationBlock};
use quickersort::sort_by;
use restyle_hints::{RestyleHint, DependencySet};
+use rule_tree::{RuleTree, StrongRuleNode, StyleSource};
use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement};
use selectors::Element;
use selectors::bloom::BloomFilter;
@@ -31,7 +32,7 @@ use std::hash::Hash;
use std::slice;
use std::sync::Arc;
use style_traits::viewport::ViewportConstraints;
-use stylesheets::{CSSRule, Origin, Stylesheet, UserAgentStylesheets};
+use stylesheets::{CSSRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets};
use viewport::{self, MaybeNew, ViewportRule};
pub type FnvHashMap<K, V> = HashMap<K, V, BuildHasherDefault<::fnv::FnvHasher>>;
@@ -62,6 +63,11 @@ pub struct Stylist {
/// rules against the current device.
element_map: PerPseudoElementSelectorMap,
+ /// The rule tree, that stores the results of selector matching.
+ ///
+ /// FIXME(emilio): Not `pub`!
+ pub rule_tree: RuleTree,
+
/// The selector maps corresponding to a given pseudo-element
/// (depending on the implementation)
pseudos_map: FnvHashMap<PseudoElement, PerPseudoElementSelectorMap>,
@@ -72,6 +78,8 @@ pub struct Stylist {
/// Applicable declarations for a given non-eagerly cascaded pseudo-element.
/// These are eagerly computed once, and then used to resolve the new
/// computed values on the fly on layout.
+ ///
+ /// FIXME(emilio): Use the rule tree!
precomputed_pseudo_element_decls: FnvHashMap<PseudoElement, Vec<ApplicableDeclarationBlock>>,
rules_source_order: usize,
@@ -103,6 +111,7 @@ impl Stylist {
animations: Default::default(),
precomputed_pseudo_element_decls: Default::default(),
rules_source_order: 0,
+ rule_tree: RuleTree::new(),
state_deps: DependencySet::new(),
// XXX remember resetting them!
@@ -179,8 +188,8 @@ impl Stylist {
stylesheet.effective_rules(&self.device, |rule| {
match *rule {
CSSRule::Style(ref style_rule) => {
- let style_rule = style_rule.read();
- for selector in &style_rule.selectors {
+ let guard = style_rule.read();
+ for selector in &guard.selectors {
let map = if let Some(ref pseudo) = selector.pseudo_element {
pseudos_map
.entry(pseudo.clone())
@@ -192,14 +201,14 @@ impl Stylist {
map.insert(Rule {
selector: selector.complex_selector.clone(),
- declarations: style_rule.block.clone(),
+ style_rule: style_rule.clone(),
specificity: selector.specificity,
source_order: *rules_source_order,
});
}
*rules_source_order += 1;
- for selector in &style_rule.selectors {
+ for selector in &guard.selectors {
state_deps.note_selector(&selector.complex_selector);
if selector.affects_siblings() {
sibling_affecting_selectors.push(selector.clone());
@@ -261,25 +270,30 @@ impl Stylist {
pseudo: &PseudoElement,
parent: Option<&Arc<ComputedValues>>,
inherit_all: bool)
- -> Option<Arc<ComputedValues>> {
+ -> Option<(Arc<ComputedValues>, StrongRuleNode)> {
debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_precomputed());
if let Some(declarations) = self.precomputed_pseudo_element_decls.get(pseudo) {
+ // FIXME(emilio): When we've taken rid of the cascade we can just
+ // use into_iter.
+ let rule_node =
+ self.rule_tree.insert_ordered_rules(
+ declarations.iter().map(|a| (a.source.clone(), a.importance)));
+
let mut flags = CascadeFlags::empty();
if inherit_all {
flags.insert(INHERIT_ALL)
}
- let (computed, _) =
+ let computed =
properties::cascade(self.device.au_viewport_size(),
- &declarations,
+ &rule_node,
parent.map(|p| &**p),
None,
- None,
Box::new(StdoutErrorReporter),
flags);
- Some(Arc::new(computed))
+ Some((Arc::new(computed), rule_node))
} else {
- parent.map(|p| p.clone())
+ parent.map(|p| (p.clone(), self.rule_tree.root()))
}
}
@@ -308,13 +322,14 @@ impl Stylist {
};
self.precomputed_values_for_pseudo(&pseudo, Some(parent_style), inherit_all)
.expect("style_for_anonymous_box(): No precomputed values for that pseudo!")
+ .0
}
pub fn lazily_compute_pseudo_element_style<E>(&self,
element: &E,
pseudo: &PseudoElement,
parent: &Arc<ComputedValues>)
- -> Option<Arc<ComputedValues>>
+ -> Option<(Arc<ComputedValues>, StrongRuleNode)>
where E: Element<Impl=TheSelectorImpl> +
fmt::Debug +
PresentationalHintsSynthetizer
@@ -326,8 +341,6 @@ impl Stylist {
let mut declarations = vec![];
- // NB: This being cached could be worth it, maybe allow an optional
- // ApplicableDeclarationsCache?.
self.push_applicable_declarations(element,
None,
None,
@@ -335,16 +348,18 @@ impl Stylist {
&mut declarations,
MatchingReason::ForStyling);
- let (computed, _) =
+ let rule_node =
+ self.rule_tree.insert_ordered_rules(declarations.into_iter().map(|a| (a.source.clone(), a.importance)));
+
+ let computed =
properties::cascade(self.device.au_viewport_size(),
- &declarations,
+ &rule_node,
Some(&**parent),
None,
- None,
Box::new(StdoutErrorReporter),
CascadeFlags::empty());
- Some(Arc::new(computed))
+ Some((Arc::new(computed), rule_node))
}
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
@@ -408,9 +423,9 @@ impl Stylist {
PresentationalHintsSynthetizer,
V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>
{
- assert!(!self.is_device_dirty);
- assert!(style_attribute.is_none() || pseudo_element.is_none(),
- "Style attributes do not apply to pseudo-elements");
+ debug_assert!(!self.is_device_dirty);
+ debug_assert!(style_attribute.is_none() || pseudo_element.is_none(),
+ "Style attributes do not apply to pseudo-elements");
debug_assert!(pseudo_element.is_none() ||
!TheSelectorImpl::pseudo_element_cascade_type(pseudo_element.as_ref().unwrap())
.is_precomputed());
@@ -557,6 +572,11 @@ impl Stylist {
true
}
+ #[inline]
+ pub fn rule_tree_root(&self) -> StrongRuleNode {
+ self.rule_tree.root()
+ }
+
pub fn match_same_sibling_affecting_rules<E>(&self,
element: &E,
candidate: &E) -> bool
@@ -754,7 +774,7 @@ impl SelectorMap {
// Sort only the rules we just added.
sort_by_key(&mut matching_rules_list[init_len..],
- |rule| (rule.specificity, rule.source_order));
+ |block| (block.specificity, block.source_order));
}
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
@@ -773,7 +793,8 @@ impl SelectorMap {
for rule in self.other_rules.iter() {
if rule.selector.compound_selector.is_empty() &&
rule.selector.next.is_none() {
- let block = rule.declarations.read();
+ let guard = rule.style_rule.read();
+ let block = guard.block.read();
if block.any_normal() {
matching_rules_list.push(
rule.to_applicable_declaration_block(Importance::Normal));
@@ -786,7 +807,7 @@ impl SelectorMap {
}
sort_by_key(&mut matching_rules_list[init_len..],
- |rule| (rule.specificity, rule.source_order));
+ |block| (block.specificity, block.source_order));
}
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector>(
@@ -827,7 +848,8 @@ impl SelectorMap {
V: VecLike<ApplicableDeclarationBlock>
{
for rule in rules.iter() {
- let block = rule.declarations.read();
+ let guard = rule.style_rule.read();
+ let block = guard.block.read();
let any_declaration_for_importance = if importance.important() {
block.any_important()
} else {
@@ -836,7 +858,8 @@ impl SelectorMap {
if any_declaration_for_importance &&
matches_complex_selector(&*rule.selector, element, parent_bf,
relations, reason) {
- matching_rules.push(rule.to_applicable_declaration_block(importance));
+ matching_rules.push(
+ rule.to_applicable_declaration_block(importance));
}
}
}
@@ -907,7 +930,7 @@ impl SelectorMap {
}
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct Rule {
// This is an Arc because Rule will essentially be cloned for every element
// that it matches. Selector contains an owned vector (through
@@ -915,16 +938,15 @@ pub struct Rule {
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
- pub declarations: Arc<RwLock<PropertyDeclarationBlock>>,
+ pub style_rule: Arc<RwLock<StyleRule>>,
pub source_order: usize,
pub specificity: u32,
}
impl Rule {
- fn to_applicable_declaration_block(&self, importance: Importance)
- -> ApplicableDeclarationBlock {
+ fn to_applicable_declaration_block(&self, importance: Importance) -> ApplicableDeclarationBlock {
ApplicableDeclarationBlock {
- mixed_declarations: self.declarations.clone(),
+ source: StyleSource::Style(self.style_rule.clone()),
importance: importance,
source_order: self.source_order,
specificity: self.specificity,
@@ -937,10 +959,8 @@ impl Rule {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug, Clone)]
pub struct ApplicableDeclarationBlock {
- /// Contains declarations of either importance, but only those of self.importance are relevant.
- /// Use ApplicableDeclarationBlock::iter
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
- pub mixed_declarations: Arc<RwLock<PropertyDeclarationBlock>>,
+ pub source: StyleSource,
pub importance: Importance,
pub source_order: usize,
pub specificity: u32,
@@ -952,32 +972,10 @@ impl ApplicableDeclarationBlock {
importance: Importance)
-> Self {
ApplicableDeclarationBlock {
- mixed_declarations: declarations,
- importance: importance,
+ source: StyleSource::Declarations(declarations),
source_order: 0,
specificity: 0,
- }
- }
-
- pub fn read(&self) -> ApplicableDeclarationBlockReadGuard {
- ApplicableDeclarationBlockReadGuard {
- guard: self.mixed_declarations.read(),
- importance: self.importance,
- }
- }
-
-}
-
-pub struct ApplicableDeclarationBlockReadGuard<'a> {
- guard: RwLockReadGuard<'a, PropertyDeclarationBlock>,
- importance: Importance,
-}
-
-impl<'a> ApplicableDeclarationBlockReadGuard<'a> {
- pub fn iter(&self) -> ApplicableDeclarationBlockIter {
- ApplicableDeclarationBlockIter {
- iter: self.guard.declarations.iter(),
- importance: self.importance,
+ importance: importance,
}
}
}
@@ -1013,6 +1011,8 @@ impl<'a> DoubleEndedIterator for ApplicableDeclarationBlockIter<'a> {
}
}
-fn find_push<Str: Eq + Hash>(map: &mut FnvHashMap<Str, Vec<Rule>>, key: Str, value: Rule) {
+#[inline]
+fn find_push<Str: Eq + Hash>(map: &mut FnvHashMap<Str, Vec<Rule>>, key: Str,
+ value: Rule) {
map.entry(key).or_insert_with(Vec::new).push(value)
}