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
// 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

View file

@ -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<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();
match PropertyDeclaration::parse(name, self.context, input, &mut results, true) {
match PropertyDeclaration::parse(id, self.context, input, &mut results, true) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {}
_ => return Err(())
}

View file

@ -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)]

View file

@ -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<ParseErrorReporter + Send>,
@ -454,7 +454,7 @@ pub fn parse_one_declaration(name: &str,
-> Result<Vec<PropertyDeclaration>, ()> {
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<PropertyDeclaration>, 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(())
}

View file

@ -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,11 +780,12 @@ impl PropertyDeclaration {
/// > The <declaration-list> inside of <keyframe-block> 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<PropertyDeclaration>,
in_keyframe_block: bool)
-> 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)) {
Ok(CSSWideKeyword::UnsetKeyword) | // Custom properties are alawys inherited
Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit,
@ -795,13 +795,13 @@ impl PropertyDeclaration {
Err(()) => return PropertyDeclarationParseResult::InvalidValue,
}
};
result_list.push(PropertyDeclaration::Custom(Atom::from(name), value));
result_list.push(PropertyDeclaration::Custom(name, value));
return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration;
}
match_ignore_ascii_case! { name,
PropertyId::Longhand(id) => match id {
% for property in data.longhands:
LonghandId::${property.camel_case} => {
% if not property.derived_from:
"${property.name}" => {
% 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,
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
}
}
}

View file

@ -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::<PropertyDeclarationBlock>::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,
}