Match on PropertyId (not strings) to parse a declaration.

This commit is contained in:
Simon Sapin 2016-12-09 09:23:01 -10:00
parent 58d452fa4e
commit 433c33c4df
6 changed files with 49 additions and 42 deletions

View file

@ -165,8 +165,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
} }
// Step 3 // 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 id
} else { } else {
// Unkwown property // Unkwown property
@ -203,7 +202,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// Step 6 // Step 6
let window = window_from_node(&*self.owner); let window = window_from_node(&*self.owner);
let declarations = 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()); ParserContextExtraData::default());
// Step 7 // Step 7

View file

@ -6,7 +6,7 @@ use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule}; use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule};
use parking_lot::RwLock; use parking_lot::RwLock;
use parser::{ParserContext, ParserContextExtraData, log_css_error}; use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
use properties::PropertyDeclarationParseResult; use properties::PropertyDeclarationParseResult;
use properties::animated_properties::TransitionProperty; use properties::animated_properties::TransitionProperty;
use std::fmt; use std::fmt;
@ -343,8 +343,9 @@ impl<'a, 'b> DeclarationParser for KeyframeDeclarationParser<'a, 'b> {
type Declaration = Vec<PropertyDeclaration>; type Declaration = Vec<PropertyDeclaration>;
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Vec<PropertyDeclaration>, ()> { fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<Vec<PropertyDeclaration>, ()> {
let id = try!(PropertyId::parse(name.into()));
let mut results = Vec::new(); 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 => {} PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {}
_ => return Err(()) _ => return Err(())
} }

View file

@ -38,7 +38,7 @@
//#![deny(unsafe_code)] //#![deny(unsafe_code)]
#![allow(unused_unsafe)] #![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; extern crate app_units;
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]

View file

@ -446,7 +446,7 @@ pub fn parse_style_attribute(input: &str,
parse_property_declaration_list(&context, &mut Parser::new(input)) 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, input: &str,
base_url: &ServoUrl, base_url: &ServoUrl,
error_reporter: StdBox<ParseErrorReporter + Send>, error_reporter: StdBox<ParseErrorReporter + Send>,
@ -454,7 +454,7 @@ pub fn parse_one_declaration(name: &str,
-> Result<Vec<PropertyDeclaration>, ()> { -> Result<Vec<PropertyDeclaration>, ()> {
let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data); let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data);
let mut results = vec![]; 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), PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results),
_ => Err(()) _ => Err(())
} }
@ -477,9 +477,10 @@ impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> {
fn parse_value(&mut self, name: &str, input: &mut Parser) fn parse_value(&mut self, name: &str, input: &mut Parser)
-> Result<(Vec<PropertyDeclaration>, Importance), ()> { -> Result<(Vec<PropertyDeclaration>, Importance), ()> {
let id = try!(PropertyId::parse(name.into()));
let mut results = vec![]; let mut results = vec![];
try!(input.parse_until_before(Delimiter::Bang, |input| { 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(()), PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(()),
_ => Err(()) _ => Err(())
} }

View file

@ -16,7 +16,6 @@ use std::collections::HashSet;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::sync::Arc; use std::sync::Arc;
use Atom;
use app_units::Au; use app_units::Au;
#[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA}; #[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA};
use cssparser::{Parser, TokenSerializationType}; use cssparser::{Parser, TokenSerializationType};
@ -781,11 +780,12 @@ impl PropertyDeclaration {
/// > The <declaration-list> inside of <keyframe-block> accepts any CSS property /// > The <declaration-list> inside of <keyframe-block> accepts any CSS property
/// > except those defined in this specification, /// > except those defined in this specification,
/// > but does accept the `animation-play-state` property and interprets it specially. /// > 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<PropertyDeclaration>, result_list: &mut Vec<PropertyDeclaration>,
in_keyframe_block: bool) in_keyframe_block: bool)
-> PropertyDeclarationParseResult { -> PropertyDeclarationParseResult {
if let Ok(name) = ::custom_properties::parse_name(name) { match id {
PropertyId::Custom(name) => {
let value = match input.try(|i| CSSWideKeyword::parse(context, i)) { let value = match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(CSSWideKeyword::UnsetKeyword) | // Custom properties are alawys inherited Ok(CSSWideKeyword::UnsetKeyword) | // Custom properties are alawys inherited
Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit, Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit,
@ -795,13 +795,13 @@ impl PropertyDeclaration {
Err(()) => return PropertyDeclarationParseResult::InvalidValue, Err(()) => return PropertyDeclarationParseResult::InvalidValue,
} }
}; };
result_list.push(PropertyDeclaration::Custom(Atom::from(name), value)); result_list.push(PropertyDeclaration::Custom(name, value));
return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration; return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration;
} }
match_ignore_ascii_case! { name, PropertyId::Longhand(id) => match id {
% for property in data.longhands: % for property in data.longhands:
LonghandId::${property.camel_case} => {
% if not property.derived_from: % if not property.derived_from:
"${property.name}" => {
% if not property.allowed_in_keyframe_block: % if not property.allowed_in_keyframe_block:
if in_keyframe_block { if in_keyframe_block {
return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock
@ -825,13 +825,15 @@ impl PropertyDeclaration {
}, },
Err(()) => PropertyDeclarationParseResult::InvalidValue, Err(()) => PropertyDeclarationParseResult::InvalidValue,
} }
},
% else: % else:
"${property.name}" => PropertyDeclarationParseResult::UnknownProperty, PropertyDeclarationParseResult::UnknownProperty
% endif % endif
}
% endfor % endfor
},
PropertyId::Shorthand(id) => match id {
% for shorthand in data.shorthands: % for shorthand in data.shorthands:
"${shorthand.name}" => { ShorthandId::${shorthand.camel_case} => {
% if not shorthand.allowed_in_keyframe_block: % if not shorthand.allowed_in_keyframe_block:
if in_keyframe_block { if in_keyframe_block {
return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock return PropertyDeclarationParseResult::AnimationPropertyInKeyframeBlock
@ -878,14 +880,8 @@ impl PropertyDeclaration {
Err(()) => PropertyDeclarationParseResult::InvalidValue, Err(()) => PropertyDeclarationParseResult::InvalidValue,
} }
} }
},
% endfor
_ => {
if cfg!(all(debug_assertions, feature = "gecko")) && !name.starts_with('-') {
println!("stylo: Unimplemented property setter: {}", name);
} }
PropertyDeclarationParseResult::UnknownProperty % endfor
} }
} }
} }

View file

@ -533,6 +533,11 @@ pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const
principal: *mut ThreadSafePrincipalHolder) principal: *mut ThreadSafePrincipalHolder)
-> RawServoDeclarationBlockStrong { -> RawServoDeclarationBlockStrong {
let name = unsafe { property.as_ref().unwrap().as_str_unchecked() }; 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 value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
let base_str = unsafe { base_url.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(); 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); extra_data);
let mut results = vec![]; 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) { &mut results, false) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {}, PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {},
_ => return RawServoDeclarationBlockStrong::null(), _ => return RawServoDeclarationBlockStrong::null(),
@ -674,7 +679,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetProperty(declarations: RawServoDecla
// FIXME Needs real URL and ParserContextExtraData. // FIXME Needs real URL and ParserContextExtraData.
let base_url = &*DUMMY_BASE_URL; let base_url = &*DUMMY_BASE_URL;
let extra_data = ParserContextExtraData::default(); 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) { Box::new(StdoutErrorReporter), extra_data) {
let mut declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations).write(); let mut declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations).write();
let importance = if is_important { Importance::Important } else { Importance::Normal }; 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] #[no_mangle]
pub extern "C" fn Servo_CSSSupports(property: *const nsACString, value: *const nsACString) -> bool { pub extern "C" fn Servo_CSSSupports(property: *const nsACString, value: *const nsACString) -> bool {
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() }; 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 value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
let base_url = &*DUMMY_BASE_URL; let base_url = &*DUMMY_BASE_URL;
let extra_data = ParserContextExtraData::default(); 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(), Ok(decls) => !decls.is_empty(),
Err(()) => false, Err(()) => false,
} }