diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index c8be4f560a6..90df36f2f1d 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -165,8 +165,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { } // Step 3 - // FIXME: give ownership on `property` here when parse_one_declaration can take &PropertyId - let id = if let Ok(id) = PropertyId::parse((&*property).into()) { + let id = if let Ok(id) = PropertyId::parse(property.into()) { id } else { // Unkwown property @@ -203,7 +202,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // Step 6 let window = window_from_node(&*self.owner); let declarations = - parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter(), + parse_one_declaration(id, &value, &window.get_url(), window.css_error_reporter(), ParserContextExtraData::default()); // Step 7 diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index 474e4c8b539..f458ae45f8e 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -6,7 +6,7 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule}; use parking_lot::RwLock; use parser::{ParserContext, ParserContextExtraData, log_css_error}; -use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; +use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId}; use properties::PropertyDeclarationParseResult; use properties::animated_properties::TransitionProperty; use std::fmt; @@ -343,8 +343,9 @@ impl<'a, 'b> DeclarationParser for KeyframeDeclarationParser<'a, 'b> { type Declaration = Vec; fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result, ()> { + let id = try!(PropertyId::parse(name.into())); let mut results = Vec::new(); - match PropertyDeclaration::parse(name, self.context, input, &mut results, true) { + match PropertyDeclaration::parse(id, self.context, input, &mut results, true) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {} _ => return Err(()) } diff --git a/components/style/lib.rs b/components/style/lib.rs index 21873f03e13..50725a52b00 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -38,7 +38,7 @@ //#![deny(unsafe_code)] #![allow(unused_unsafe)] -#![recursion_limit = "500"] // For match_ignore_ascii_case in PropertyDeclaration::parse +#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance extern crate app_units; #[allow(unused_extern_crates)] diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 6c6ec7348d9..de2d274280b 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -446,7 +446,7 @@ pub fn parse_style_attribute(input: &str, parse_property_declaration_list(&context, &mut Parser::new(input)) } -pub fn parse_one_declaration(name: &str, +pub fn parse_one_declaration(id: PropertyId, input: &str, base_url: &ServoUrl, error_reporter: StdBox, @@ -454,7 +454,7 @@ pub fn parse_one_declaration(name: &str, -> Result, ()> { let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data); let mut results = vec![]; - match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results, false) { + match PropertyDeclaration::parse(id, &context, &mut Parser::new(input), &mut results, false) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results), _ => Err(()) } @@ -477,9 +477,10 @@ impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> { fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(Vec, Importance), ()> { + let id = try!(PropertyId::parse(name.into())); let mut results = vec![]; try!(input.parse_until_before(Delimiter::Bang, |input| { - match PropertyDeclaration::parse(name, self.context, input, &mut results, false) { + match PropertyDeclaration::parse(id, self.context, input, &mut results, false) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(()), _ => Err(()) } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a001c846588..5dfb0d018d9 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -16,7 +16,6 @@ use std::collections::HashSet; use std::fmt::{self, Write}; use std::sync::Arc; -use Atom; use app_units::Au; #[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA}; use cssparser::{Parser, TokenSerializationType}; @@ -781,27 +780,28 @@ impl PropertyDeclaration { /// > The inside of accepts any CSS property /// > except those defined in this specification, /// > but does accept the `animation-play-state` property and interprets it specially. - pub fn parse(name: &str, context: &ParserContext, input: &mut Parser, + pub fn parse(id: PropertyId, context: &ParserContext, input: &mut Parser, result_list: &mut Vec, in_keyframe_block: bool) -> PropertyDeclarationParseResult { - if let Ok(name) = ::custom_properties::parse_name(name) { - let value = match input.try(|i| CSSWideKeyword::parse(context, i)) { - Ok(CSSWideKeyword::UnsetKeyword) | // Custom properties are alawys inherited - Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit, - Ok(CSSWideKeyword::InitialKeyword) => DeclaredValue::Initial, - Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) { - Ok(value) => DeclaredValue::Value(value), - Err(()) => return PropertyDeclarationParseResult::InvalidValue, - } - }; - result_list.push(PropertyDeclaration::Custom(Atom::from(name), value)); - return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration; - } - match_ignore_ascii_case! { name, + match id { + PropertyId::Custom(name) => { + let value = match input.try(|i| CSSWideKeyword::parse(context, i)) { + Ok(CSSWideKeyword::UnsetKeyword) | // Custom properties are alawys inherited + Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit, + Ok(CSSWideKeyword::InitialKeyword) => DeclaredValue::Initial, + Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) { + Ok(value) => DeclaredValue::Value(value), + Err(()) => return PropertyDeclarationParseResult::InvalidValue, + } + }; + result_list.push(PropertyDeclaration::Custom(name, value)); + return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration; + } + PropertyId::Longhand(id) => match id { % for property in data.longhands: - % if not property.derived_from: - "${property.name}" => { + LonghandId::${property.camel_case} => { + % if not property.derived_from: % if not property.allowed_in_keyframe_block: if in_keyframe_block { return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock @@ -825,13 +825,15 @@ impl PropertyDeclaration { }, Err(()) => PropertyDeclarationParseResult::InvalidValue, } - }, - % else: - "${property.name}" => PropertyDeclarationParseResult::UnknownProperty, - % endif + % else: + PropertyDeclarationParseResult::UnknownProperty + % endif + } % endfor + }, + PropertyId::Shorthand(id) => match id { % for shorthand in data.shorthands: - "${shorthand.name}" => { + ShorthandId::${shorthand.camel_case} => { % if not shorthand.allowed_in_keyframe_block: if in_keyframe_block { return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock @@ -878,14 +880,8 @@ impl PropertyDeclaration { Err(()) => PropertyDeclarationParseResult::InvalidValue, } } - }, - % endfor - - _ => { - if cfg!(all(debug_assertions, feature = "gecko")) && !name.starts_with('-') { - println!("stylo: Unimplemented property setter: {}", name); } - PropertyDeclarationParseResult::UnknownProperty + % endfor } } } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 95392a8fb26..d17acd9a35e 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -533,6 +533,11 @@ pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const principal: *mut ThreadSafePrincipalHolder) -> RawServoDeclarationBlockStrong { let name = unsafe { property.as_ref().unwrap().as_str_unchecked() }; + let id = if let Ok(id) = PropertyId::parse(name.into()) { + id + } else { + return RawServoDeclarationBlockStrong::null() + }; let value = unsafe { value.as_ref().unwrap().as_str_unchecked() }; let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() }; let base_url = ServoUrl::parse(base_str).unwrap(); @@ -547,7 +552,7 @@ pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const extra_data); let mut results = vec![]; - match PropertyDeclaration::parse(name, &context, &mut Parser::new(value), + match PropertyDeclaration::parse(id, &context, &mut Parser::new(value), &mut results, false) { PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {}, _ => return RawServoDeclarationBlockStrong::null(), @@ -674,7 +679,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetProperty(declarations: RawServoDecla // FIXME Needs real URL and ParserContextExtraData. let base_url = &*DUMMY_BASE_URL; let extra_data = ParserContextExtraData::default(); - if let Ok(decls) = parse_one_declaration(&property.to_css_string(), value, &base_url, + if let Ok(decls) = parse_one_declaration(property, value, &base_url, Box::new(StdoutErrorReporter), extra_data) { let mut declarations = RwLock::::as_arc(&declarations).write(); let importance = if is_important { Importance::Important } else { Importance::Normal }; @@ -698,12 +703,17 @@ pub extern "C" fn Servo_DeclarationBlock_RemoveProperty(declarations: RawServoDe #[no_mangle] pub extern "C" fn Servo_CSSSupports(property: *const nsACString, value: *const nsACString) -> bool { let property = unsafe { property.as_ref().unwrap().as_str_unchecked() }; + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + return false + }; let value = unsafe { value.as_ref().unwrap().as_str_unchecked() }; let base_url = &*DUMMY_BASE_URL; let extra_data = ParserContextExtraData::default(); - match parse_one_declaration(&property, &value, &base_url, Box::new(StdoutErrorReporter), extra_data) { + match parse_one_declaration(id, &value, &base_url, Box::new(StdoutErrorReporter), extra_data) { Ok(decls) => !decls.is_empty(), Err(()) => false, }