Skip to content

Commit

Permalink
Add an Importance enum replacing booleans to indicate !important.
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSapin committed Aug 20, 2016
1 parent 8218b46 commit 24fbb26
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 48 deletions.
15 changes: 8 additions & 7 deletions components/script/dom/cssstyledeclaration.rs
Expand Up @@ -10,15 +10,15 @@ use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::element::{Element, StylePriority};
use dom::element::Element;
use dom::node::{Node, NodeDamage, window_from_node};
use dom::window::Window;
use std::ascii::AsciiExt;
use std::cell::Ref;
use std::slice;
use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand};
use style::properties::{PropertyDeclaration, Shorthand, Importance};
use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute};
use style::selector_impl::PseudoElement;

Expand Down Expand Up @@ -160,7 +160,8 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
}

// TODO: important is hardcoded to false because method does not implement it yet
let serialized_value = shorthand.serialize_shorthand_value_to_string(Map(list.iter()), false);
let serialized_value = shorthand.serialize_shorthand_value_to_string(
Map(list.iter()), Importance::Normal);
return DOMString::from(serialized_value);
}

Expand Down Expand Up @@ -222,8 +223,8 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {

// Step 5
let priority = match &*priority {
"" => StylePriority::Normal,
p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
"" => Importance::Normal,
p if p.eq_ignore_ascii_case("important") => Importance::Important,
_ => return Ok(()),
};

Expand Down Expand Up @@ -265,8 +266,8 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {

// Step 4
let priority = match &*priority {
"" => StylePriority::Normal,
p if p.eq_ignore_ascii_case("important") => StylePriority::Important,
"" => Importance::Normal,
p if p.eq_ignore_ascii_case("important") => Importance::Important,
_ => return Ok(()),
};

Expand Down
24 changes: 9 additions & 15 deletions components/script/dom/element.rs
Expand Up @@ -87,8 +87,8 @@ use style::attr::{AttrValue, LengthOrPercentageOrAuto};
use style::element_state::*;
use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
use style::parser::ParserContextExtraData;
use style::properties::DeclaredValue;
use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{DeclaredValue, Importance};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl};
use style::sink::Push;
Expand Down Expand Up @@ -660,13 +660,6 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
}

#[derive(PartialEq, Eq, Copy, Clone, HeapSizeOf)]
pub enum StylePriority {
Important,
Normal,
}


impl Element {
pub fn html_element_in_html_document(&self) -> bool {
self.namespace == ns!(html) && self.upcast::<Node>().is_in_html_doc()
Expand Down Expand Up @@ -780,11 +773,12 @@ impl Element {

pub fn update_inline_style(&self,
declarations: Vec<PropertyDeclaration>,
style_priority: StylePriority) {
fn update(element: &Element, mut declarations: Vec<PropertyDeclaration>, style_priority: StylePriority) {
importance: Importance) {
fn update(element: &Element, mut declarations: Vec<PropertyDeclaration>,
importance: Importance) {
let mut inline_declarations = element.style_attribute().borrow_mut();
if let &mut Some(ref mut existing_declarations) = &mut *inline_declarations {
let existing_declarations = if style_priority == StylePriority::Important {
let existing_declarations = if importance.important() {
&mut existing_declarations.important
} else {
&mut existing_declarations.normal
Expand Down Expand Up @@ -813,7 +807,7 @@ impl Element {
return;
}

let (important, normal) = if style_priority == StylePriority::Important {
let (important, normal) = if importance.important() {
(declarations, vec![])
} else {
(vec![], declarations)
Expand All @@ -825,17 +819,17 @@ impl Element {
});
}

update(self, declarations, style_priority);
update(self, declarations, importance);
self.sync_property_with_attrs_style();
}

pub fn set_inline_style_property_priority(&self,
properties: &[&str],
style_priority: StylePriority) {
importance: Importance) {
{
let mut inline_declarations = self.style_attribute().borrow_mut();
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
let (from, to) = if style_priority == StylePriority::Important {
let (from, to) = if importance == Importance::Important {
(&mut declarations.normal, &mut declarations.important)
} else {
(&mut declarations.important, &mut declarations.normal)
Expand Down
73 changes: 47 additions & 26 deletions components/style/properties/properties.mako.rs
Expand Up @@ -14,6 +14,8 @@ use std::ascii::AsciiExt;
use std::boxed::Box as StdBox;
use std::collections::HashSet;
use std::fmt::{self, Write};
use std::iter::{Iterator, Chain, Zip, Rev, Repeat, repeat};
use std::slice;
use std::sync::Arc;

use app_units::Au;
Expand Down Expand Up @@ -261,11 +263,26 @@ mod property_bit_field {
% endif
% endfor

#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Importance {
/// Indicates a declaration without `!important`.
Normal,

use std::iter::{Iterator, Chain, Zip, Rev, Repeat, repeat};
use std::slice;
/// Overridden declarations are skipped.
/// Indicates a declaration with `!important`.
Important,
}

impl Importance {
pub fn important(self) -> bool {
match self {
Importance::Normal => false,
Importance::Important => true,
}
}
}

/// Overridden declarations are skipped.
// FIXME (https://github.com/servo/servo/issues/3426)
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
Expand All @@ -279,12 +296,12 @@ pub struct PropertyDeclarationBlock {
impl PropertyDeclarationBlock {
/// Provides an iterator of all declarations, with indication of !important value
pub fn declarations(&self) -> Chain<
Zip<Rev<slice::Iter<PropertyDeclaration>>, Repeat<bool>>,
Zip<Rev<slice::Iter<PropertyDeclaration>>, Repeat<bool>>
Zip<Rev<slice::Iter<PropertyDeclaration>>, Repeat<Importance>>,
Zip<Rev<slice::Iter<PropertyDeclaration>>, Repeat<Importance>>
> {
// Declarations are stored in reverse order.
let normal = self.normal.iter().rev().zip(repeat(false));
let important = self.important.iter().rev().zip(repeat(true));
let normal = self.normal.iter().rev().zip(repeat(Importance::Normal));
let important = self.important.iter().rev().zip(repeat(Importance::Important));
normal.chain(important)
}
}
Expand All @@ -300,7 +317,7 @@ impl ToCss for PropertyDeclarationBlock {
let mut already_serialized = Vec::new();

// Step 3
for (declaration, important) in self.declarations() {
for (declaration, importance) in self.declarations() {
// Step 3.1
let property = declaration.name();

Expand All @@ -326,11 +343,11 @@ impl ToCss for PropertyDeclarationBlock {
let mut current_longhands = Vec::new();
let mut important_count = 0;

for &(longhand, longhand_important) in longhands.iter() {
for &(longhand, longhand_importance) in longhands.iter() {
let longhand_name = longhand.name();
if properties.iter().any(|p| &longhand_name == *p) {
current_longhands.push(longhand);
if longhand_important {
if longhand_importance.important() {
important_count += 1;
}
}
Expand Down Expand Up @@ -396,7 +413,7 @@ impl ToCss for PropertyDeclarationBlock {
dest,
&property.to_string(),
AppendableValue::Declaration(declaration),
important,
importance,
&mut is_first_serialization));

// Step 3.3.8
Expand Down Expand Up @@ -430,7 +447,7 @@ fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool
fn append_declaration_value<'a, W, I>
(dest: &mut W,
appendable_value: AppendableValue<'a, I>,
is_important: bool)
importance: Importance)
-> fmt::Result
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {
match appendable_value {
Expand All @@ -445,7 +462,7 @@ fn append_declaration_value<'a, W, I>
}
}

if is_important {
if importance.important() {
try!(write!(dest, " !important"));
}

Expand All @@ -455,7 +472,7 @@ fn append_declaration_value<'a, W, I>
fn append_serialization<'a, W, I>(dest: &mut W,
property_name: &str,
appendable_value: AppendableValue<'a, I>,
is_important: bool,
importance: Importance,
is_first_serialization: &mut bool)
-> fmt::Result
where W: fmt::Write, I: Iterator<Item=&'a PropertyDeclaration> {
Expand All @@ -465,7 +482,7 @@ fn append_serialization<'a, W, I>(dest: &mut W,
// Overflow does not behave like a normal shorthand. When overflow-x and overflow-y are not of equal
// values, they no longer use the shared property name "overflow" and must be handled differently
if shorthands::is_overflow_shorthand(&appendable_value) {
return append_declaration_value(dest, appendable_value, is_important);
return append_declaration_value(dest, appendable_value, importance);
}

try!(write!(dest, "{}:", property_name));
Expand All @@ -484,7 +501,7 @@ fn append_serialization<'a, W, I>(dest: &mut W,
&AppendableValue::DeclarationsForShorthand(..) => try!(write!(dest, " "))
}

try!(append_declaration_value(dest, appendable_value, is_important));
try!(append_declaration_value(dest, appendable_value, importance));
write!(dest, ";")
}

Expand Down Expand Up @@ -514,23 +531,27 @@ struct PropertyDeclarationParser<'a, 'b: 'a> {
/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for PropertyDeclarationParser<'a, 'b> {
type Prelude = ();
type AtRule = (Vec<PropertyDeclaration>, bool);
type AtRule = (Vec<PropertyDeclaration>, Importance);
}


impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
type Declaration = (Vec<PropertyDeclaration>, bool);
type Declaration = (Vec<PropertyDeclaration>, Importance);

fn parse_value(&self, name: &str, input: &mut Parser) -> Result<(Vec<PropertyDeclaration>, bool), ()> {
fn parse_value(&self, name: &str, input: &mut Parser)
-> Result<(Vec<PropertyDeclaration>, Importance), ()> {
let mut results = vec![];
try!(input.parse_until_before(Delimiter::Bang, |input| {
match PropertyDeclaration::parse(name, self.context, input, &mut results) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(()),
_ => Err(())
}
}));
let important = input.try(parse_important).is_ok();
Ok((results, important))
let importance = match input.try(parse_important) {
Ok(()) => Importance::Important,
Err(()) => Importance::Normal,
};
Ok((results, importance))
}
}

Expand All @@ -545,8 +566,8 @@ pub fn parse_property_declaration_list(context: &ParserContext, input: &mut Pars
let mut iter = DeclarationListParser::new(input, parser);
while let Some(declaration) = iter.next() {
match declaration {
Ok((results, important)) => {
if important {
Ok((results, importance)) => {
if importance.important() {
important_declarations.extend(results);
} else {
normal_declarations.extend(results);
Expand Down Expand Up @@ -675,11 +696,11 @@ impl Shorthand {
}

/// Serializes possible shorthand value to String.
pub fn serialize_shorthand_value_to_string<'a, I>(self, declarations: I, is_important: bool) -> String
pub fn serialize_shorthand_value_to_string<'a, I>(self, declarations: I, importance: Importance) -> String
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
let appendable_value = self.get_shorthand_appendable_value(declarations).unwrap();
let mut result = String::new();
append_declaration_value(&mut result, appendable_value, is_important).unwrap();
append_declaration_value(&mut result, appendable_value, importance).unwrap();
result
}

Expand All @@ -700,7 +721,7 @@ impl Shorthand {
dest,
property_name,
appendable_value,
false,
Importance::Normal,
is_first_serialization
).and_then(|_| Ok(true))
}
Expand Down

0 comments on commit 24fbb26

Please sign in to comment.