servo: Merge #17739 - Suppress CSS parser errors for vendor-prefixed properties (from jdm:no-vendor-prefixed-errors); r=emilio

This matches the behaviour of Gecko's CSS parser.

- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #17736
- [X] There are tests for these changes

Source-Repo: https://github.com/servo/servo
Source-Revision: 38f4ae80c4b456b89ee33543c8c6699501696c9c

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 1a1909fa1db0e97b0997462f48b23827f84394f0
This commit is contained in:
Josh Matthews 2017-07-17 07:10:11 -07:00
Родитель c2b9935278
Коммит 3e06aadbea
9 изменённых файлов: 84 добавлений и 31 удалений

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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.

Просмотреть файл

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

Просмотреть файл

@ -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() {

Просмотреть файл

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

Просмотреть файл

@ -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.

Просмотреть файл

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

Просмотреть файл

@ -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(

Просмотреть файл

@ -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());
}