diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 180a356dd90..161c0d16b9f 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -192,7 +192,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration { if let Some(longhand_properties) = longhand_properties { // Step 2.1 & 2.2 & 2.3 if longhand_properties.iter() - .map(|longhand| self.GetPropertyPriority(longhand.clone())) + .map(|&longhand| self.GetPropertyPriority(longhand.to_owned())) .all(|priority| priority == "important") { return "important".to_owned(); @@ -274,34 +274,25 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration { return Err(Error::NoModificationAllowed); } - // Step 2 - let property = property.to_ascii_lowercase(); - - // Step 3 + // Step 2 & 3 if !is_supported_property(&property) { return Ok(()); } // Step 4 - let priority = priority.to_ascii_lowercase(); - if priority != "important" && !priority.is_empty() { - return Ok(()); - } + let priority = match &*priority { + "" => StylePriority::Normal, + p if p.eq_ignore_ascii_case("important") => StylePriority::Important, + _ => return Ok(()), + }; let owner = self.owner.root(); - let window = window_from_node(owner.r()); - let decl_block = parse_style_attribute(&property, &window.r().get_url()); let element = ElementCast::from_ref(owner.r()); - // Step 5 - for decl in decl_block.normal.iter() { - // Step 6 - let style_priority = if priority.is_empty() { - StylePriority::Normal - } else { - StylePriority::Important - }; - element.update_inline_style(decl.clone(), style_priority); + // Step 5 & 6 + match longhands_from_shorthand(&property) { + Some(properties) => element.set_inline_style_property_priority(properties, priority), + None => element.set_inline_style_property_priority(&[&*property], priority) } let document = document_from_node(element); @@ -328,21 +319,18 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration { // Step 3 let value = self.GetPropertyValue(property.clone()); - let longhand_properties = longhands_from_shorthand(&property); - match longhand_properties { + let owner = self.owner.root(); + let elem = ElementCast::from_ref(owner.r()); + + match longhands_from_shorthand(&property) { + // Step 4 Some(longhands) => { - // Step 4 for longhand in longhands.iter() { - try!(self.RemoveProperty(longhand.clone())); + elem.remove_inline_style_property(longhand) } } - - None => { - // Step 5 - let owner = self.owner.root(); - let elem = ElementCast::from_ref(owner.r()); - elem.remove_inline_style_property(property) - } + // Step 5 + None => elem.remove_inline_style_property(&property) } // Step 6 diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d8c0db97e60..03edf9a35e6 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -581,8 +581,9 @@ pub trait ElementHelpers<'a> { fn style_attribute(self) -> &'a DOMRefCell>; fn summarize(self) -> Vec; fn is_void(self) -> bool; - fn remove_inline_style_property(self, property: DOMString); + fn remove_inline_style_property(self, property: &str); fn update_inline_style(self, property_decl: PropertyDeclaration, style_priority: StylePriority); + fn set_inline_style_property_priority(self, properties: &[&str], style_priority: StylePriority); fn get_inline_style_declaration(self, property: &Atom) -> Option; fn get_important_inline_style_declaration(self, property: &Atom) -> Option; fn serialize(self, traversal_scope: TraversalScope) -> Fallible; @@ -652,7 +653,7 @@ impl<'a> ElementHelpers<'a> for &'a Element { } } - fn remove_inline_style_property(self, property: DOMString) { + fn remove_inline_style_property(self, property: &str) { let mut inline_declarations = self.style_attribute.borrow_mut(); if let &mut Some(ref mut declarations) = &mut *inline_declarations { let index = declarations.normal @@ -704,6 +705,28 @@ impl<'a> ElementHelpers<'a> for &'a Element { }); } + fn set_inline_style_property_priority(self, properties: &[&str], style_priority: StylePriority) { + 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 { + (&mut declarations.normal, &mut declarations.important) + } else { + (&mut declarations.normal, &mut declarations.important) + }; + let from = Arc::make_unique(from); + let to = Arc::make_unique(to); + let mut new_from = Vec::new(); + for declaration in from.drain(..) { + if properties.contains(&declaration.name()) { + to.push(declaration) + } else { + new_from.push(declaration) + } + } + mem::replace(from, new_from); + } + } + fn get_inline_style_declaration(self, property: &Atom) -> Option { let inline_declarations = self.style_attribute.borrow(); inline_declarations.as_ref().and_then(|declarations| { diff --git a/components/style/build.rs b/components/style/build.rs index e3a2784c3cf..87550d67c2b 100644 --- a/components/style/build.rs +++ b/components/style/build.rs @@ -28,7 +28,7 @@ import sys from mako.template import Template from mako import exceptions try: - print(Template(filename=os.environ['TEMPLATE']).render()) + print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render().encode('utf8')) except: sys.stderr.write(exceptions.text_error_template().render().encode('utf8')) sys.exit(1) diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 60041a5c1c4..e6531e41687 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -6543,11 +6543,12 @@ pub fn modify_style_for_inline_sides(style: &mut Arc, } pub fn is_supported_property(property: &str) -> bool { - match property { - % for property in SHORTHANDS + LONGHANDS: + match_ignore_ascii_case! { property, + % for property in SHORTHANDS + LONGHANDS[:-1]: "${property.name}" => true, % endfor - _ => false, + "${LONGHANDS[-1].name}" => true + _ => false } } @@ -6579,16 +6580,24 @@ macro_rules! longhand_properties_idents { } } -pub fn longhands_from_shorthand(shorthand: &str) -> Option> { - match shorthand { - % for property in SHORTHANDS: - "${property.name}" => Some(vec!( +// Extra space here because < seems to be removed by Mako when immediately followed by &. +// ↓ +pub fn longhands_from_shorthand(shorthand: &str) -> Option< &'static [&'static str]> { + % for property in SHORTHANDS: + static ${property.ident.upper()}: &'static [&'static str] = &[ % for sub in property.sub_properties: - "${sub.name}".to_owned(), + "${sub.name}", % endfor - )), + ]; + % endfor + match_ignore_ascii_case!{ shorthand, + % for property in SHORTHANDS[:-1]: + "${property.name}" => Some(${property.ident.upper()}), % endfor - _ => None, + % for property in SHORTHANDS[-1:]: + "${property.name}" => Some(${property.ident.upper()}) + % endfor + _ => None } }