diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index f036003f237f..db0bcdcd16c1 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1496,12 +1496,15 @@ mod property_bit_field { } } +pub enum PropertyDeclarationImportance { + Normal, + Important +} /// Declarations are stored in reverse order. /// Overridden declarations are skipped. pub struct PropertyDeclarationBlock { - pub important: Arc>, - pub normal: Arc>, + pub declarations: Arc> } @@ -1511,10 +1514,8 @@ pub fn parse_style_attribute(input: &str, base_url: &Url) -> PropertyDeclaration pub fn parse_property_declaration_list>(input: I, base_url: &Url) -> PropertyDeclarationBlock { - let mut important_declarations = vec!(); - let mut normal_declarations = vec!(); - let mut important_seen = PropertyBitField::new(); - let mut normal_seen = PropertyBitField::new(); + let mut property_declarations = vec!(); + let mut property_seen = PropertyBitField::new(); let items: Vec = ErrorLoggerIterator(parse_declaration_list(input)).collect(); for item in items.into_iter().rev() { @@ -1523,12 +1524,12 @@ pub fn parse_property_declaration_list>(input: I, base_url: &U rule.location, format!("Unsupported at-rule in declaration list: @{:s}", rule.name).as_slice()), Declaration_(Declaration{ location: l, name: n, value: v, important: i}) => { // TODO: only keep the last valid declaration for a given name. - let (list, seen) = if i { - (&mut important_declarations, &mut important_seen) - } else { - (&mut normal_declarations, &mut normal_seen) + let importance = match i { + true => Important, + false => Normal }; - match PropertyDeclaration::parse(n.as_slice(), v.as_slice(), list, base_url, seen) { + match PropertyDeclaration::parse(n.as_slice(), v.as_slice(), importance, + &mut property_declarations, base_url, &mut property_seen) { UnknownProperty => log_css_error(l, format!( "Unsupported property: {}:{}", n, v.iter().to_css()).as_slice()), ExperimentalProperty => log_css_error(l, format!( @@ -1543,8 +1544,7 @@ pub fn parse_property_declaration_list>(input: I, base_url: &U } } PropertyDeclarationBlock { - important: Arc::new(important_declarations), - normal: Arc::new(normal_declarations), + declarations: Arc::new(property_declarations) } } @@ -1597,7 +1597,8 @@ pub enum PropertyDeclarationParseResult { impl PropertyDeclaration { pub fn parse(name: &str, value: &[ComponentValue], - result_list: &mut Vec, + importance: PropertyDeclarationImportance, + result_list: &mut Vec<(PropertyDeclaration, PropertyDeclarationImportance)>, base_url: &Url, seen: &mut PropertyBitField) -> PropertyDeclarationParseResult { // FIXME: local variable to work around Rust #10683 @@ -1617,7 +1618,7 @@ impl PropertyDeclaration { match longhands::${property.ident}::parse_declared(value, base_url) { Ok(value) => { seen.set_${property.ident}(); - result_list.push(${property.camel_case}Declaration(value)); + result_list.push((${property.camel_case}Declaration(value), importance)); ValidOrIgnoredDeclaration }, Err(()) => InvalidValue, @@ -1639,7 +1640,7 @@ impl PropertyDeclaration { if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); result_list.push( - ${sub_property.camel_case}Declaration(Inherit)); + (${sub_property.camel_case}Declaration(Inherit), importance)); } % endfor ValidOrIgnoredDeclaration @@ -1649,7 +1650,7 @@ impl PropertyDeclaration { if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); result_list.push( - ${sub_property.camel_case}Declaration(Initial)); + (${sub_property.camel_case}Declaration(Initial), importance)); } % endfor ValidOrIgnoredDeclaration @@ -1658,9 +1659,9 @@ impl PropertyDeclaration { % for sub_property in shorthand.sub_properties: if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); - result_list.push(${sub_property.camel_case}Declaration( + result_list.push((${sub_property.camel_case}Declaration( ${"Inherit" if sub_property.style_struct.inherited else "Initial"} - )); + ), importance)); } % endfor ValidOrIgnoredDeclaration @@ -1670,12 +1671,12 @@ impl PropertyDeclaration { % for sub_property in shorthand.sub_properties: if !seen.get_${sub_property.ident}() { seen.set_${sub_property.ident}(); - result_list.push(${sub_property.camel_case}Declaration( + result_list.push((${sub_property.camel_case}Declaration( match result.${sub_property.ident} { Some(value) => SpecifiedValue(value), None => Initial, } - )); + ), importance)); } % endfor ValidOrIgnoredDeclaration @@ -1920,7 +1921,7 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock] % for style_struct in STYLE_STRUCTS: % for property in style_struct.longhands: % if property.derived_from is None: - ${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => { + (${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value), _) => { % if style_struct.inherited: if seen.get_${property.ident}() { continue @@ -1966,7 +1967,7 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock] % endif } % else: - ${property.camel_case}Declaration(_) => { + (${property.camel_case}Declaration(_), _) => { // Do not allow stylesheets to set derived properties. } % endif @@ -2052,7 +2053,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], // Declarations are stored in reverse source order, we want them in forward order here. for declaration in sub_list.declarations.iter().rev() { match *declaration { - FontSizeDeclaration(ref value) => { + (FontSizeDeclaration(ref value), _) => { context.font_size = match *value { SpecifiedValue(specified_value) => computed::compute_Au_with_font_size( specified_value, context.inherited_font_size), @@ -2060,27 +2061,27 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], Inherit => context.inherited_font_size, } } - ColorDeclaration(ref value) => { + (ColorDeclaration(ref value), _) => { context.color = get_specified!(get_color, color, value); } - DisplayDeclaration(ref value) => { + (DisplayDeclaration(ref value), _) => { context.display = get_specified!(get_box, display, value); } - PositionDeclaration(ref value) => { + (PositionDeclaration(ref value), _) => { context.positioned = match get_specified!(get_box, position, value) { longhands::position::absolute | longhands::position::fixed => true, _ => false, } } - FloatDeclaration(ref value) => { + (FloatDeclaration(ref value), _) => { context.floated = get_specified!(get_box, float, value) != longhands::float::none; } - TextDecorationDeclaration(ref value) => { + (TextDecorationDeclaration(ref value), _) => { context.text_decoration = get_specified!(get_text, text_decoration, value); } % for side in ["top", "right", "bottom", "left"]: - Border${side.capitalize()}StyleDeclaration(ref value) => { + (Border${side.capitalize()}StyleDeclaration(ref value), _) => { context.border_${side}_present = match get_specified!(get_border, border_${side}_style, value) { longhands::border_top_style::none | @@ -2126,7 +2127,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], % for style_struct in STYLE_STRUCTS: % for property in style_struct.longhands: % if property.derived_from is None: - ${property.camel_case}Declaration(ref declared_value) => { + (${property.camel_case}Declaration(ref declared_value), _) => { if seen.get_${property.ident}() { continue } @@ -2166,7 +2167,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], % endif } % else: - ${property.camel_case}Declaration(_) => { + (${property.camel_case}Declaration(_), _) => { // Do not allow stylesheets to set derived properties. } % endif diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 2a6d65f1be7a..db43cea8e30a 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -21,8 +21,8 @@ use string_cache::Atom; use legacy::{SizeIntegerAttribute, WidthLengthAttribute}; use media_queries::Device; use node::{TElement, TElementAttributes, TNode}; -use properties::{PropertyDeclaration, PropertyDeclarationBlock, SpecifiedValue, WidthDeclaration}; -use properties::{specified}; +use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationImportance, Normal}; +use properties::{specified, SpecifiedValue, WidthDeclaration}; use selectors::*; use stylesheets::{Stylesheet, iter_stylesheet_style_rules}; @@ -317,31 +317,25 @@ impl Stylist { // Take apart the StyleRule into individual Rules and insert // them into the SelectorMap of that priority. - macro_rules! append( - ($style_rule: ident, $priority: ident) => { - if $style_rule.declarations.$priority.len() > 0 { - for selector in $style_rule.selectors.iter() { - let map = match selector.pseudo_element { - None => &mut element_map, - Some(Before) => &mut before_map, - Some(After) => &mut after_map, - }; - map.$priority.insert(Rule { - selector: selector.compound_selectors.clone(), - declarations: DeclarationBlock { - specificity: selector.specificity, - declarations: $style_rule.declarations.$priority.clone(), - source_order: rules_source_order, - }, - }); - } + iter_stylesheet_style_rules(&stylesheet, device, |style_rule| { + if style_rule.declarations.declarations.len() > 0 { + for selector in style_rule.selectors.iter() { + let map = match selector.pseudo_element { + None => &mut element_map, + Some(Before) => &mut before_map, + Some(After) => &mut after_map, + }; + map.insert(Rule { + selector: selector.compound_selectors.clone(), + declarations: DeclarationBlock { + specificity: selector.specificity, + declarations: style_rule.declarations.declarations.clone(), + source_order: rules_source_order, + }, + }); } - }; - ); + } - iter_stylesheet_style_rules(&stylesheet, device, |style_rule| { - append!(style_rule, normal); - append!(style_rule, important); rules_source_order += 1; }); self.rules_source_order = rules_source_order; @@ -382,48 +376,35 @@ impl Stylist { &mut shareable); // Step 2: Normal rules. - map.user_agent.normal.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); - map.user.normal.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); - map.author.normal.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); + map.user_agent.get_all_matching_rules(element, + parent_bf, + applicable_declarations, + &mut shareable); + map.user.get_all_matching_rules(element, + parent_bf, + applicable_declarations, + &mut shareable); + map.author.get_all_matching_rules(element, + parent_bf, + applicable_declarations, + &mut shareable); // Step 3: Normal style attributes. style_attribute.map(|sa| { shareable = false; - applicable_declarations.vec_push(DeclarationBlock::from_declarations(sa.normal + applicable_declarations.vec_push(DeclarationBlock::from_declarations(sa.declarations .clone())) }); + // Step 4: Author-supplied `!important` rules. - map.author.important.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); + // Step 5: `!important` style attributes. - style_attribute.map(|sa| { - shareable = false; - applicable_declarations.vec_push(DeclarationBlock::from_declarations(sa.important - .clone())) - }); + // Step 6: User and UA `!important` rules. - map.user.important.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); - map.user_agent.important.get_all_matching_rules(element, - parent_bf, - applicable_declarations, - &mut shareable); + shareable } @@ -447,14 +428,14 @@ impl Stylist { AutoLpa => {} PercentageLpa(percentage) => { let width_value = specified::LPA_Percentage(percentage); - matching_rules_list.vec_push(DeclarationBlock::from_declaration( - WidthDeclaration(SpecifiedValue(width_value)))); + matching_rules_list.vec_push(DeclarationBlock::from_declaration(( + WidthDeclaration(SpecifiedValue(width_value)), Normal))); *shareable = false } LengthLpa(length) => { let width_value = specified::LPA_Length(specified::Au_(length)); - matching_rules_list.vec_push(DeclarationBlock::from_declaration( - WidthDeclaration(SpecifiedValue(width_value)))); + matching_rules_list.vec_push(DeclarationBlock::from_declaration(( + WidthDeclaration(SpecifiedValue(width_value)), Normal))); *shareable = false } }; @@ -472,9 +453,9 @@ impl Stylist { } _ => specified::Au_(Au::from_px(value as int)), }; - matching_rules_list.vec_push(DeclarationBlock::from_declaration( + matching_rules_list.vec_push(DeclarationBlock::from_declaration(( WidthDeclaration(SpecifiedValue(specified::LPA_Length( - value))))); + value))), Normal))); *shareable = false } Some(_) | None => {} @@ -485,34 +466,19 @@ impl Stylist { } } -struct PerOriginSelectorMap { - normal: SelectorMap, - important: SelectorMap, -} - -impl PerOriginSelectorMap { - #[inline] - fn new() -> PerOriginSelectorMap { - PerOriginSelectorMap { - normal: SelectorMap::new(), - important: SelectorMap::new(), - } - } -} - struct PerPseudoElementSelectorMap { - user_agent: PerOriginSelectorMap, - author: PerOriginSelectorMap, - user: PerOriginSelectorMap, + user_agent: SelectorMap, + author: SelectorMap, + user: SelectorMap, } impl PerPseudoElementSelectorMap { #[inline] fn new() -> PerPseudoElementSelectorMap { PerPseudoElementSelectorMap { - user_agent: PerOriginSelectorMap::new(), - author: PerOriginSelectorMap::new(), - user: PerOriginSelectorMap::new(), + user_agent: SelectorMap::new(), + author: SelectorMap::new(), + user: SelectorMap::new(), } } } @@ -530,14 +496,14 @@ struct Rule { /// we can sort them. #[deriving(Clone)] pub struct DeclarationBlock { - pub declarations: Arc>, + pub declarations: Arc>, source_order: uint, specificity: u32, } impl DeclarationBlock { #[inline] - pub fn from_declarations(declarations: Arc>) -> DeclarationBlock { + pub fn from_declarations(declarations: Arc>) -> DeclarationBlock { DeclarationBlock { declarations: declarations, source_order: 0, @@ -548,7 +514,7 @@ impl DeclarationBlock { /// A convenience function to create a declaration block from a single declaration. This is /// primarily used in `synthesize_rules_for_legacy_attributes`. #[inline] - pub fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock { + pub fn from_declaration(rule: (PropertyDeclaration, PropertyDeclarationImportance)) -> DeclarationBlock { DeclarationBlock::from_declarations(Arc::new(vec![rule])) } }