Handle importance when inserting into the rule tree.

This commit is contained in:
Bobby Holley 2017-05-10 17:05:52 +02:00
parent 48b5e5ebc4
commit e9d4110ad4
4 changed files with 141 additions and 143 deletions

View file

@ -327,10 +327,7 @@ impl Stylist {
SelectorImpl::each_precomputed_pseudo_element(|pseudo| {
if let Some(map) = self.pseudos_map.remove(&pseudo) {
let declarations =
map.user_agent.get_universal_rules(
guards.ua_or_user, CascadeLevel::UANormal, CascadeLevel::UAImportant
);
let declarations = map.user_agent.get_universal_rules(CascadeLevel::UANormal);
self.precomputed_pseudo_element_decls.insert(pseudo, declarations);
}
});
@ -376,7 +373,7 @@ impl Stylist {
self.num_declarations += style_rule.block.read_with(&guard).len();
for selector in &style_rule.selectors.0 {
self.num_selectors += 1;
self.add_rule_to_map(guard, selector, locked, stylesheet);
self.add_rule_to_map(selector, locked, stylesheet);
self.dependencies.note_selector(selector);
self.note_for_revalidation(selector);
}
@ -412,7 +409,6 @@ impl Stylist {
#[inline]
fn add_rule_to_map(&mut self,
guard: &SharedRwLockReadGuard,
selector: &Selector<SelectorImpl>,
rule: &Arc<Locked<StyleRule>>,
stylesheet: &Stylesheet)
@ -426,8 +422,7 @@ impl Stylist {
self.element_map.borrow_for_origin(&stylesheet.origin)
};
map.insert(Rule::new(guard,
selector.inner.clone(),
map.insert(Rule::new(selector.inner.clone(),
rule.clone(),
self.rules_source_order,
selector.specificity));
@ -460,8 +455,9 @@ impl Stylist {
Some(declarations) => {
// FIXME(emilio): When we've taken rid of the cascade we can just
// use into_iter.
self.rule_tree.insert_ordered_rules(
declarations.into_iter().map(|a| (a.source.clone(), a.level)))
self.rule_tree.insert_ordered_rules_with_important(
declarations.into_iter().map(|a| (a.source.clone(), a.level)),
guards)
}
None => self.rule_tree.root(),
};
@ -622,17 +618,21 @@ impl Stylist {
None,
AnimationRules(None, None),
Some(pseudo),
guards,
&mut declarations,
&mut set_selector_flags);
if declarations.is_empty() {
return None
}
let rule_node = self.rule_tree.insert_ordered_rules(declarations.into_iter().map(|a| {
(a.source, a.level)
}));
Some(rule_node)
let rule_node =
self.rule_tree.insert_ordered_rules_with_important(
declarations.into_iter().map(|a| (a.source, a.level)),
guards);
if rule_node == self.rule_tree.root() {
None
} else {
Some(rule_node)
}
}
/// Set a given device, which may change the styles that apply to the
@ -740,7 +740,6 @@ impl Stylist {
smil_override: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
animation_rules: AnimationRules,
pseudo_element: Option<&PseudoElement>,
guards: &StylesheetGuards,
applicable_declarations: &mut V,
flags_setter: &mut F)
-> StyleRelations
@ -810,13 +809,11 @@ impl Stylist {
// Step 4: Normal style attributes.
if let Some(sa) = style_attribute {
if sa.read_with(guards.author).any_normal() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(sa.clone(),
CascadeLevel::StyleAttributeNormal));
}
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(sa.clone(),
CascadeLevel::StyleAttributeNormal));
}
debug!("style attr: {:?}", relations);
@ -841,52 +838,14 @@ impl Stylist {
CascadeLevel::Animations));
}
debug!("animation: {:?}", relations);
// Step 7: Author-supplied `!important` rules.
map.author.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
flags_setter,
CascadeLevel::AuthorImportant);
debug!("author important: {:?}", relations);
// Step 8: `!important` style attributes.
if let Some(sa) = style_attribute {
if sa.read_with(guards.author).any_important() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(sa.clone(),
CascadeLevel::StyleAttributeImportant));
}
}
debug!("style attr important: {:?}", relations);
// Step 9: User `!important` rules.
map.user.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
flags_setter,
CascadeLevel::UserImportant);
debug!("user important: {:?}", relations);
} else {
debug!("skipping non-agent rules");
}
// Step 10: UA `!important` rules.
map.user_agent.get_all_matching_rules(element,
parent_bf,
applicable_declarations,
&mut relations,
flags_setter,
CascadeLevel::UAImportant);
debug!("UA important: {:?}", relations);
//
// Steps 7-10 correspond to !important rules, and are handled during
// rule tree insertion.
//
// Step 11: Transitions.
// The transitions sheet (CSS transitions that are tied to CSS markup)
@ -1256,45 +1215,24 @@ impl SelectorMap<Rule> {
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
/// `self` sorted by specificity and source order.
pub fn get_universal_rules(&self,
guard: &SharedRwLockReadGuard,
cascade_level: CascadeLevel,
important_cascade_level: CascadeLevel)
cascade_level: CascadeLevel)
-> Vec<ApplicableDeclarationBlock> {
debug_assert!(!cascade_level.is_important());
debug_assert!(important_cascade_level.is_important());
if self.is_empty() {
return vec![];
}
let mut matching_rules_list = vec![];
// We need to insert important rules _after_ normal rules for this to be
// correct, and also to not trigger rule tree assertions.
let mut important = vec![];
let mut rules_list = vec![];
for rule in self.other.iter() {
if rule.selector.complex.iter_raw().next().is_none() {
let style_rule = rule.style_rule.read_with(guard);
let block = style_rule.block.read_with(guard);
if block.any_normal() {
matching_rules_list.push(
rule.to_applicable_declaration_block(cascade_level));
}
if block.any_important() {
important.push(
rule.to_applicable_declaration_block(important_cascade_level));
}
rules_list.push(rule.to_applicable_declaration_block(cascade_level));
}
}
let normal_len = matching_rules_list.len();
matching_rules_list.extend(important.into_iter());
sort_by_key(&mut matching_rules_list[0..normal_len],
|block| (block.specificity, block.source_order));
sort_by_key(&mut matching_rules_list[normal_len..],
sort_by_key(&mut rules_list,
|block| (block.specificity, block.source_order));
matching_rules_list
rules_list
}
fn get_matching_rules_from_hash<E, Str, BorrowedStr: ?Sized, Vector, F>(
@ -1336,13 +1274,7 @@ impl SelectorMap<Rule> {
F: FnMut(&E, ElementSelectorFlags),
{
for rule in rules.iter() {
let any_declaration_for_importance = if cascade_level.is_important() {
rule.any_important_declarations()
} else {
rule.any_normal_declarations()
};
if any_declaration_for_importance &&
matches_selector(&rule.selector, element, parent_bf,
if matches_selector(&rule.selector, element, parent_bf,
relations, flags_setter) {
matching_rules.push(
rule.to_applicable_declaration_block(cascade_level));
@ -1556,10 +1488,11 @@ pub struct Rule {
pub style_rule: Arc<Locked<StyleRule>>,
/// The source order this style rule appears in.
pub source_order: usize,
/// Bottom 30 bits: The specificity of the rule this selector represents.
/// 31st bit: Whether the rule's declaration block has any important declarations.
/// 32nd bit: Whether the rule's declaration block has any normal declarations.
specificity_and_bits: u32,
/// The specificity of the rule this selector represents.
///
/// Note: The top two bits of this are unused, and could be used to store
/// flags.
specificity: u32,
}
impl Borrow<SelectorInner<SelectorImpl>> for Rule {
@ -1568,23 +1501,10 @@ impl Borrow<SelectorInner<SelectorImpl>> for Rule {
}
}
/// Masks for specificity_and_bits.
const SPECIFICITY_MASK: u32 = 0x3fffffff;
const ANY_IMPORTANT_DECLARATIONS_BIT: u32 = 1 << 30;
const ANY_NORMAL_DECLARATIONS_BIT: u32 = 1 << 31;
impl Rule {
/// Returns the specificity of the rule.
pub fn specificity(&self) -> u32 {
self.specificity_and_bits & SPECIFICITY_MASK
}
fn any_important_declarations(&self) -> bool {
(self.specificity_and_bits & ANY_IMPORTANT_DECLARATIONS_BIT) != 0
}
fn any_normal_declarations(&self) -> bool {
(self.specificity_and_bits & ANY_NORMAL_DECLARATIONS_BIT) != 0
self.specificity
}
fn to_applicable_declaration_block(&self, level: CascadeLevel) -> ApplicableDeclarationBlock {
@ -1597,31 +1517,17 @@ impl Rule {
}
/// Creates a new Rule.
pub fn new(guard: &SharedRwLockReadGuard,
selector: SelectorInner<SelectorImpl>,
pub fn new(selector: SelectorInner<SelectorImpl>,
style_rule: Arc<Locked<StyleRule>>,
source_order: usize,
specificity: u32)
-> Self
{
let (any_important, any_normal) = {
let block = style_rule.read_with(guard).block.read_with(guard);
(block.any_important(), block.any_normal())
};
debug_assert!(specificity & (ANY_IMPORTANT_DECLARATIONS_BIT | ANY_NORMAL_DECLARATIONS_BIT) == 0);
let mut specificity_and_bits = specificity;
if any_important {
specificity_and_bits |= ANY_IMPORTANT_DECLARATIONS_BIT;
}
if any_normal {
specificity_and_bits |= ANY_NORMAL_DECLARATIONS_BIT;
}
Rule {
selector: selector,
style_rule: style_rule,
source_order: source_order,
specificity_and_bits: specificity_and_bits,
specificity: specificity,
}
}
}