aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout_thread/lib.rs3
-rw-r--r--components/script/dom/cssstyledeclaration.rs10
-rw-r--r--components/style/properties/declaration_block.rs28
-rw-r--r--components/style/properties/gecko.mako.rs2
-rw-r--r--components/style/properties/properties.mako.rs22
-rw-r--r--components/style/stylesheets/keyframes_rule.rs4
-rw-r--r--components/style_traits/lib.rs14
-rw-r--r--ports/geckolib/error_reporter.rs3
-rw-r--r--tests/unit/style/stylesheets.rs29
9 files changed, 84 insertions, 31 deletions
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index fea91c164b7..b8436ce0bbf 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -133,7 +133,6 @@ use style::stylist::{ExtraStyleData, Stylist};
use style::thread_state;
use style::timer::Timer;
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
-use style::values::CompactCowStr;
/// Information needed by the layout thread.
pub struct LayoutThread {
@@ -714,7 +713,7 @@ impl LayoutThread {
Msg::RegisterPaint(name, mut properties, painter) => {
debug!("Registering the painter");
let properties = properties.drain(..)
- .filter_map(|name| PropertyId::parse(CompactCowStr::from(&*name)).ok().map(|id| (name.clone(), id)))
+ .filter_map(|name| PropertyId::parse(&*name).ok().map(|id| (name.clone(), id)))
.filter(|&(_, ref id)| id.as_shorthand().is_err())
.collect();
let registered_painter = RegisteredPainter {
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index 572550b2bc9..81dec4d3aa8 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -296,7 +296,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
fn GetPropertyValue(&self, property: DOMString) -> DOMString {
- let id = if let Ok(id) = PropertyId::parse(property.into()) {
+ let id = if let Ok(id) = PropertyId::parse(&property) {
id
} else {
// Unkwown property
@@ -307,7 +307,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
fn GetPropertyPriority(&self, property: DOMString) -> DOMString {
- let id = if let Ok(id) = PropertyId::parse(property.into()) {
+ let id = if let Ok(id) = PropertyId::parse(&property) {
id
} else {
// Unkwown property
@@ -331,7 +331,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
priority: DOMString)
-> ErrorResult {
// Step 3
- let id = if let Ok(id) = PropertyId::parse(property.into()) {
+ let id = if let Ok(id) = PropertyId::parse(&property) {
id
} else {
// Unknown property
@@ -348,7 +348,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
}
// Step 2 & 3
- let id = match PropertyId::parse(property.into()) {
+ let id = match PropertyId::parse(&property) {
Ok(id) => id,
Err(..) => return Ok(()), // Unkwown property
};
@@ -380,7 +380,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
return Err(Error::NoModificationAllowed);
}
- let id = if let Ok(id) = PropertyId::parse(property.into()) {
+ let id = if let Ok(id) = PropertyId::parse(&property) {
id
} else {
// Unkwown property, cannot be there to remove.
diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs
index a90627aae41..7afbdbdd518 100644
--- a/components/style/properties/declaration_block.rs
+++ b/components/style/properties/declaration_block.rs
@@ -8,7 +8,7 @@
use context::QuirksMode;
use cssparser::{DeclarationListParser, parse_important, ParserInput, CompactCowStr};
-use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter};
+use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError};
use error_reporting::{ParseErrorReporter, ContextualParseError};
use parser::{ParserContext, log_css_error};
use properties::animated_properties::AnimationValue;
@@ -935,13 +935,28 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Error = SelectorParseError<'i, StyleParseError<'i>>;
}
+/// Based on NonMozillaVendorIdentifier from Gecko's CSS parser.
+fn is_non_mozilla_vendor_identifier(name: &str) -> bool {
+ (name.starts_with("-") && !name.starts_with("-moz-")) ||
+ name.starts_with("_")
+}
+
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
type Declaration = Importance;
type Error = SelectorParseError<'i, StyleParseError<'i>>;
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<Importance, ParseError<'i>> {
- let id = PropertyId::parse(name)?;
+ let id = match PropertyId::parse(&name) {
+ Ok(id) => id,
+ Err(()) => {
+ return Err(if is_non_mozilla_vendor_identifier(&name) {
+ PropertyDeclarationParseError::UnknownVendorProperty
+ } else {
+ PropertyDeclarationParseError::UnknownProperty(name)
+ }.into());
+ }
+ };
input.parse_until_before(Delimiter::Bang, |input| {
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
.map_err(|e| e.into())
@@ -976,6 +991,15 @@ pub fn parse_property_declaration_list(context: &ParserContext,
}
Err(err) => {
iter.parser.declarations.clear();
+
+ // If the unrecognized property looks like a vendor-specific property,
+ // silently ignore it instead of polluting the error output.
+ if let CssParseError::Custom(SelectorParseError::Custom(
+ StyleParseError::PropertyDeclaration(
+ PropertyDeclarationParseError::UnknownVendorProperty))) = err.error {
+ continue;
+ }
+
let pos = err.span.start;
let error = ContextualParseError::UnsupportedPropertyDeclaration(
iter.input.slice(err.span), err.error);
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index d30b81ff7cb..13ca780ee9f 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -2871,7 +2871,7 @@ fn static_assert() {
Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr());
}
- if let Ok(prop_id) = PropertyId::parse(feature.0.to_string().into()) {
+ if let Ok(prop_id) = PropertyId::parse(&feature.0.to_string()) {
match prop_id.as_shorthand() {
Ok(shorthand) => {
for longhand in shorthand.longhands() {
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 9d710c1dcb3..9c6a017ced3 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -20,7 +20,7 @@ use stylearc::{Arc, UniqueArc};
use app_units::Au;
#[cfg(feature = "servo")] use cssparser::RGBA;
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
-use cssparser::{ParserInput, CompactCowStr};
+use cssparser::ParserInput;
#[cfg(feature = "servo")] use euclid::SideOffsets2D;
use computed_values;
use context::QuirksMode;
@@ -510,7 +510,7 @@ impl LonghandId {
% if not property.derived_from:
longhands::${property.ident}::parse_declared(context, input)
% else:
- Err(PropertyDeclarationParseError::UnknownProperty.into())
+ Err(PropertyDeclarationParseError::UnknownProperty("${property.ident}".into()).into())
% endif
}
% endfor
@@ -992,8 +992,8 @@ impl PropertyId {
/// Returns a given property from the string `s`.
///
/// Returns Err(()) for unknown non-custom properties
- pub fn parse<'i>(property_name: CompactCowStr<'i>) -> Result<Self, ParseError<'i>> {
- if let Ok(name) = ::custom_properties::parse_name(&property_name) {
+ pub fn parse(property_name: &str) -> Result<Self, ()> {
+ if let Ok(name) = ::custom_properties::parse_name(property_name) {
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
}
@@ -1014,10 +1014,10 @@ impl PropertyId {
% endfor
}
}
- match static_id(&property_name) {
+ match static_id(property_name) {
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(id)),
- None => Err(StyleParseError::UnknownProperty(property_name).into()),
+ None => Err(()),
}
}
@@ -1101,7 +1101,7 @@ impl PropertyId {
}
fn check_allowed_in(&self, rule_type: CssRuleType, stylesheet_origin: Origin)
- -> Result<(), PropertyDeclarationParseError> {
+ -> Result<(), PropertyDeclarationParseError<'static>> {
let id: NonCustomPropertyId;
match *self {
// Custom properties are allowed everywhere
@@ -1186,7 +1186,7 @@ impl PropertyId {
return Err(PropertyDeclarationParseError::ExperimentalProperty);
}
} else {
- return Err(PropertyDeclarationParseError::UnknownProperty);
+ return Err(PropertyDeclarationParseError::UnknownProperty(self.name().into()));
}
}
} else {
@@ -1462,9 +1462,9 @@ impl PropertyDeclaration {
/// This will not actually parse Importance values, and will always set things
/// to Importance::Normal. Parsing Importance values is the job of PropertyDeclarationParser,
/// we only set them here so that we don't have to reallocate
- pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
- id: PropertyId, context: &ParserContext, input: &mut Parser)
- -> Result<(), PropertyDeclarationParseError> {
+ pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
+ id: PropertyId, context: &ParserContext, input: &mut Parser<'i, 't>)
+ -> Result<(), PropertyDeclarationParseError<'i>> {
assert!(declarations.is_empty());
let rule_type = context.rule_type();
debug_assert!(rule_type == CssRuleType::Keyframe ||
diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs
index 356b675575f..af12629c289 100644
--- a/components/style/stylesheets/keyframes_rule.rs
+++ b/components/style/stylesheets/keyframes_rule.rs
@@ -17,6 +17,7 @@ use selectors::parser::SelectorParseError;
use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
use std::fmt;
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
+use style_traits::PropertyDeclarationParseError;
use stylearc::Arc;
use stylesheets::{CssRuleType, StylesheetContents};
use stylesheets::rule_parser::VendorPrefix;
@@ -532,7 +533,8 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for KeyframeDeclarationParser<'a, 'b> {
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
-> Result<(), ParseError<'i>> {
- let id = PropertyId::parse(name.into())?;
+ let id = PropertyId::parse(&name)
+ .map_err(|()| PropertyDeclarationParseError::UnknownProperty(name))?;
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
Ok(()) => {
// In case there is still unparsed text in the declaration, we should roll back.
diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs
index dc708f69d48..04e19f2c12d 100644
--- a/components/style_traits/lib.rs
+++ b/components/style_traits/lib.rs
@@ -91,7 +91,7 @@ pub enum StyleParseError<'i> {
/// Unexpected closing curly bracket in a DVB.
UnbalancedCloseCurlyBracketInDeclarationValueBlock,
/// A property declaration parsing error.
- PropertyDeclaration(PropertyDeclarationParseError),
+ PropertyDeclaration(PropertyDeclarationParseError<'i>),
/// A property declaration value had input remaining after successfully parsing.
PropertyDeclarationValueNotExhausted,
/// An unexpected dimension token was encountered.
@@ -112,15 +112,15 @@ pub enum StyleParseError<'i> {
UnspecifiedError,
/// An unexpected token was found within a namespace rule.
UnexpectedTokenWithinNamespace(Token<'i>),
- /// An unknown CSS property was encountered.
- UnknownProperty(CompactCowStr<'i>),
}
/// The result of parsing a property declaration.
#[derive(Eq, PartialEq, Clone, Debug)]
-pub enum PropertyDeclarationParseError {
+pub enum PropertyDeclarationParseError<'i> {
/// The property declaration was for an unknown property.
- UnknownProperty,
+ UnknownProperty(CompactCowStr<'i>),
+ /// An unknown vendor-specific identifier was encountered.
+ UnknownVendorProperty,
/// The property declaration was for a disabled experimental property.
ExperimentalProperty,
/// The property declaration contained an invalid value.
@@ -140,8 +140,8 @@ impl<'a> From<StyleParseError<'a>> for ParseError<'a> {
}
}
-impl<'a> From<PropertyDeclarationParseError> for ParseError<'a> {
- fn from(this: PropertyDeclarationParseError) -> Self {
+impl<'a> From<PropertyDeclarationParseError<'a>> for ParseError<'a> {
+ fn from(this: PropertyDeclarationParseError<'a>) -> Self {
cssparser::ParseError::Custom(SelectorParseError::Custom(StyleParseError::PropertyDeclaration(this)))
}
}
diff --git a/ports/geckolib/error_reporter.rs b/ports/geckolib/error_reporter.rs
index af92277c0dc..fcb2bbe1069 100644
--- a/ports/geckolib/error_reporter.rs
+++ b/ports/geckolib/error_reporter.rs
@@ -233,7 +233,8 @@ impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
ErrorString::Ident(namespace),
(_, CssParseError::Custom(SelectorParseError::Custom(
- StyleParseError::UnknownProperty(property)))) =>
+ StyleParseError::PropertyDeclaration(
+ PropertyDeclarationParseError::UnknownProperty(property))))) =>
ErrorString::Ident(property),
(_, CssParseError::Custom(SelectorParseError::Custom(
diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs
index 48a62fb7c18..51205b86427 100644
--- a/tests/unit/style/stylesheets.rs
+++ b/tests/unit/style/stylesheets.rs
@@ -316,7 +316,7 @@ fn test_report_error_stylesheet() {
let error = errors.pop().unwrap();
assert_eq!("Unsupported property declaration: 'invalid: true;', \
- Custom(UnknownProperty(\"invalid\"))", error.message);
+ Custom(PropertyDeclaration(UnknownProperty(\"invalid\")))", error.message);
assert_eq!(9, error.line);
assert_eq!(8, error.column);
@@ -329,3 +329,30 @@ fn test_report_error_stylesheet() {
// testing for the url
assert_eq!(url, error.url);
}
+
+#[test]
+fn test_no_report_unrecognized_vendor_properties() {
+ let css = r"
+ div {
+ -o-background-color: red;
+ _background-color: red;
+ -moz-background-color: red;
+ }
+ ";
+ let url = ServoUrl::parse("about::test").unwrap();
+ let error_reporter = CSSInvalidErrorReporterTest::new();
+
+ let errors = error_reporter.errors.clone();
+
+ let lock = SharedRwLock::new();
+ let media = Arc::new(lock.wrap(MediaList::empty()));
+ Stylesheet::from_str(css, url, Origin::UserAgent, media, lock,
+ None, &error_reporter, QuirksMode::NoQuirks, 0u64);
+
+ let mut errors = errors.lock().unwrap();
+ let error = errors.pop().unwrap();
+ assert_eq!("Unsupported property declaration: '-moz-background-color: red;', \
+ Custom(PropertyDeclaration(UnknownProperty(\"-moz-background-color\")))",
+ error.message);
+ assert!(errors.is_empty());
+}