mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #17739 - jdm:no-vendor-prefixed-errors, r=emilio
Suppress CSS parser errors for vendor-prefixed properties. 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 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17739) <!-- Reviewable:end -->
This commit is contained in:
commit
38f4ae80c4
9 changed files with 84 additions and 31 deletions
|
@ -133,7 +133,6 @@ use style::stylist::{ExtraStyleData, Stylist};
|
||||||
use style::thread_state;
|
use style::thread_state;
|
||||||
use style::timer::Timer;
|
use style::timer::Timer;
|
||||||
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
|
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
|
||||||
use style::values::CompactCowStr;
|
|
||||||
|
|
||||||
/// Information needed by the layout thread.
|
/// Information needed by the layout thread.
|
||||||
pub struct LayoutThread {
|
pub struct LayoutThread {
|
||||||
|
@ -714,7 +713,7 @@ impl LayoutThread {
|
||||||
Msg::RegisterPaint(name, mut properties, painter) => {
|
Msg::RegisterPaint(name, mut properties, painter) => {
|
||||||
debug!("Registering the painter");
|
debug!("Registering the painter");
|
||||||
let properties = properties.drain(..)
|
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())
|
.filter(|&(_, ref id)| id.as_shorthand().is_err())
|
||||||
.collect();
|
.collect();
|
||||||
let registered_painter = RegisteredPainter {
|
let registered_painter = RegisteredPainter {
|
||||||
|
|
|
@ -296,7 +296,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
|
|
||||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
|
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
|
||||||
fn GetPropertyValue(&self, property: DOMString) -> DOMString {
|
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
|
id
|
||||||
} else {
|
} else {
|
||||||
// Unkwown property
|
// Unkwown property
|
||||||
|
@ -307,7 +307,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
|
|
||||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
|
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
|
||||||
fn GetPropertyPriority(&self, property: DOMString) -> DOMString {
|
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
|
id
|
||||||
} else {
|
} else {
|
||||||
// Unkwown property
|
// Unkwown property
|
||||||
|
@ -331,7 +331,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
priority: DOMString)
|
priority: DOMString)
|
||||||
-> ErrorResult {
|
-> ErrorResult {
|
||||||
// Step 3
|
// Step 3
|
||||||
let id = if let Ok(id) = PropertyId::parse(property.into()) {
|
let id = if let Ok(id) = PropertyId::parse(&property) {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
// Unknown property
|
// Unknown property
|
||||||
|
@ -348,7 +348,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2 & 3
|
// Step 2 & 3
|
||||||
let id = match PropertyId::parse(property.into()) {
|
let id = match PropertyId::parse(&property) {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
Err(..) => return Ok(()), // Unkwown property
|
Err(..) => return Ok(()), // Unkwown property
|
||||||
};
|
};
|
||||||
|
@ -380,7 +380,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
return Err(Error::NoModificationAllowed);
|
return Err(Error::NoModificationAllowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = if let Ok(id) = PropertyId::parse(property.into()) {
|
let id = if let Ok(id) = PropertyId::parse(&property) {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
// Unkwown property, cannot be there to remove.
|
// Unkwown property, cannot be there to remove.
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
use cssparser::{DeclarationListParser, parse_important, ParserInput, CompactCowStr};
|
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 error_reporting::{ParseErrorReporter, ContextualParseError};
|
||||||
use parser::{ParserContext, log_css_error};
|
use parser::{ParserContext, log_css_error};
|
||||||
use properties::animated_properties::AnimationValue;
|
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>>;
|
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> {
|
impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
|
||||||
type Declaration = Importance;
|
type Declaration = Importance;
|
||||||
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
type Error = SelectorParseError<'i, StyleParseError<'i>>;
|
||||||
|
|
||||||
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
|
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
|
||||||
-> Result<Importance, ParseError<'i>> {
|
-> 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| {
|
input.parse_until_before(Delimiter::Bang, |input| {
|
||||||
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
|
PropertyDeclaration::parse_into(self.declarations, id, self.context, input)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
|
@ -976,6 +991,15 @@ pub fn parse_property_declaration_list(context: &ParserContext,
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
iter.parser.declarations.clear();
|
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 pos = err.span.start;
|
||||||
let error = ContextualParseError::UnsupportedPropertyDeclaration(
|
let error = ContextualParseError::UnsupportedPropertyDeclaration(
|
||||||
iter.input.slice(err.span), err.error);
|
iter.input.slice(err.span), err.error);
|
||||||
|
|
|
@ -2871,7 +2871,7 @@ fn static_assert() {
|
||||||
Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr());
|
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() {
|
match prop_id.as_shorthand() {
|
||||||
Ok(shorthand) => {
|
Ok(shorthand) => {
|
||||||
for longhand in shorthand.longhands() {
|
for longhand in shorthand.longhands() {
|
||||||
|
|
|
@ -20,7 +20,7 @@ use stylearc::{Arc, UniqueArc};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
#[cfg(feature = "servo")] use cssparser::RGBA;
|
#[cfg(feature = "servo")] use cssparser::RGBA;
|
||||||
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
use cssparser::{Parser, TokenSerializationType, serialize_identifier};
|
||||||
use cssparser::{ParserInput, CompactCowStr};
|
use cssparser::ParserInput;
|
||||||
#[cfg(feature = "servo")] use euclid::SideOffsets2D;
|
#[cfg(feature = "servo")] use euclid::SideOffsets2D;
|
||||||
use computed_values;
|
use computed_values;
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
|
@ -510,7 +510,7 @@ impl LonghandId {
|
||||||
% if not property.derived_from:
|
% if not property.derived_from:
|
||||||
longhands::${property.ident}::parse_declared(context, input)
|
longhands::${property.ident}::parse_declared(context, input)
|
||||||
% else:
|
% else:
|
||||||
Err(PropertyDeclarationParseError::UnknownProperty.into())
|
Err(PropertyDeclarationParseError::UnknownProperty("${property.ident}".into()).into())
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -992,8 +992,8 @@ impl PropertyId {
|
||||||
/// Returns a given property from the string `s`.
|
/// Returns a given property from the string `s`.
|
||||||
///
|
///
|
||||||
/// Returns Err(()) for unknown non-custom properties
|
/// Returns Err(()) for unknown non-custom properties
|
||||||
pub fn parse<'i>(property_name: CompactCowStr<'i>) -> Result<Self, ParseError<'i>> {
|
pub fn parse(property_name: &str) -> Result<Self, ()> {
|
||||||
if let Ok(name) = ::custom_properties::parse_name(&property_name) {
|
if let Ok(name) = ::custom_properties::parse_name(property_name) {
|
||||||
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
return Ok(PropertyId::Custom(::custom_properties::Name::from(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1014,10 +1014,10 @@ impl PropertyId {
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match static_id(&property_name) {
|
match static_id(property_name) {
|
||||||
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
|
Some(&StaticId::Longhand(id)) => Ok(PropertyId::Longhand(id)),
|
||||||
Some(&StaticId::Shorthand(id)) => Ok(PropertyId::Shorthand(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)
|
fn check_allowed_in(&self, rule_type: CssRuleType, stylesheet_origin: Origin)
|
||||||
-> Result<(), PropertyDeclarationParseError> {
|
-> Result<(), PropertyDeclarationParseError<'static>> {
|
||||||
let id: NonCustomPropertyId;
|
let id: NonCustomPropertyId;
|
||||||
match *self {
|
match *self {
|
||||||
// Custom properties are allowed everywhere
|
// Custom properties are allowed everywhere
|
||||||
|
@ -1186,7 +1186,7 @@ impl PropertyId {
|
||||||
return Err(PropertyDeclarationParseError::ExperimentalProperty);
|
return Err(PropertyDeclarationParseError::ExperimentalProperty);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(PropertyDeclarationParseError::UnknownProperty);
|
return Err(PropertyDeclarationParseError::UnknownProperty(self.name().into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1462,9 +1462,9 @@ impl PropertyDeclaration {
|
||||||
/// This will not actually parse Importance values, and will always set things
|
/// This will not actually parse Importance values, and will always set things
|
||||||
/// to Importance::Normal. Parsing Importance values is the job of PropertyDeclarationParser,
|
/// to Importance::Normal. Parsing Importance values is the job of PropertyDeclarationParser,
|
||||||
/// we only set them here so that we don't have to reallocate
|
/// we only set them here so that we don't have to reallocate
|
||||||
pub fn parse_into(declarations: &mut SourcePropertyDeclaration,
|
pub fn parse_into<'i, 't>(declarations: &mut SourcePropertyDeclaration,
|
||||||
id: PropertyId, context: &ParserContext, input: &mut Parser)
|
id: PropertyId, context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(), PropertyDeclarationParseError> {
|
-> Result<(), PropertyDeclarationParseError<'i>> {
|
||||||
assert!(declarations.is_empty());
|
assert!(declarations.is_empty());
|
||||||
let rule_type = context.rule_type();
|
let rule_type = context.rule_type();
|
||||||
debug_assert!(rule_type == CssRuleType::Keyframe ||
|
debug_assert!(rule_type == CssRuleType::Keyframe ||
|
||||||
|
|
|
@ -17,6 +17,7 @@ use selectors::parser::SelectorParseError;
|
||||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
|
use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
|
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
|
||||||
|
use style_traits::PropertyDeclarationParseError;
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
use stylesheets::{CssRuleType, StylesheetContents};
|
use stylesheets::{CssRuleType, StylesheetContents};
|
||||||
use stylesheets::rule_parser::VendorPrefix;
|
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>)
|
fn parse_value<'t>(&mut self, name: CompactCowStr<'i>, input: &mut Parser<'i, 't>)
|
||||||
-> Result<(), ParseError<'i>> {
|
-> 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) {
|
match PropertyDeclaration::parse_into(self.declarations, id, self.context, input) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
// In case there is still unparsed text in the declaration, we should roll back.
|
// 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.
|
/// Unexpected closing curly bracket in a DVB.
|
||||||
UnbalancedCloseCurlyBracketInDeclarationValueBlock,
|
UnbalancedCloseCurlyBracketInDeclarationValueBlock,
|
||||||
/// A property declaration parsing error.
|
/// A property declaration parsing error.
|
||||||
PropertyDeclaration(PropertyDeclarationParseError),
|
PropertyDeclaration(PropertyDeclarationParseError<'i>),
|
||||||
/// A property declaration value had input remaining after successfully parsing.
|
/// A property declaration value had input remaining after successfully parsing.
|
||||||
PropertyDeclarationValueNotExhausted,
|
PropertyDeclarationValueNotExhausted,
|
||||||
/// An unexpected dimension token was encountered.
|
/// An unexpected dimension token was encountered.
|
||||||
|
@ -112,15 +112,15 @@ pub enum StyleParseError<'i> {
|
||||||
UnspecifiedError,
|
UnspecifiedError,
|
||||||
/// An unexpected token was found within a namespace rule.
|
/// An unexpected token was found within a namespace rule.
|
||||||
UnexpectedTokenWithinNamespace(Token<'i>),
|
UnexpectedTokenWithinNamespace(Token<'i>),
|
||||||
/// An unknown CSS property was encountered.
|
|
||||||
UnknownProperty(CompactCowStr<'i>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of parsing a property declaration.
|
/// The result of parsing a property declaration.
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub enum PropertyDeclarationParseError {
|
pub enum PropertyDeclarationParseError<'i> {
|
||||||
/// The property declaration was for an unknown property.
|
/// 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.
|
/// The property declaration was for a disabled experimental property.
|
||||||
ExperimentalProperty,
|
ExperimentalProperty,
|
||||||
/// The property declaration contained an invalid value.
|
/// 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> {
|
impl<'a> From<PropertyDeclarationParseError<'a>> for ParseError<'a> {
|
||||||
fn from(this: PropertyDeclarationParseError) -> Self {
|
fn from(this: PropertyDeclarationParseError<'a>) -> Self {
|
||||||
cssparser::ParseError::Custom(SelectorParseError::Custom(StyleParseError::PropertyDeclaration(this)))
|
cssparser::ParseError::Custom(SelectorParseError::Custom(StyleParseError::PropertyDeclaration(this)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,8 @@ impl<'a> ErrorHelpers<'a> for ContextualParseError<'a> {
|
||||||
ErrorString::Ident(namespace),
|
ErrorString::Ident(namespace),
|
||||||
|
|
||||||
(_, CssParseError::Custom(SelectorParseError::Custom(
|
(_, CssParseError::Custom(SelectorParseError::Custom(
|
||||||
StyleParseError::UnknownProperty(property)))) =>
|
StyleParseError::PropertyDeclaration(
|
||||||
|
PropertyDeclarationParseError::UnknownProperty(property))))) =>
|
||||||
ErrorString::Ident(property),
|
ErrorString::Ident(property),
|
||||||
|
|
||||||
(_, CssParseError::Custom(SelectorParseError::Custom(
|
(_, CssParseError::Custom(SelectorParseError::Custom(
|
||||||
|
|
|
@ -316,7 +316,7 @@ fn test_report_error_stylesheet() {
|
||||||
|
|
||||||
let error = errors.pop().unwrap();
|
let error = errors.pop().unwrap();
|
||||||
assert_eq!("Unsupported property declaration: 'invalid: true;', \
|
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!(9, error.line);
|
||||||
assert_eq!(8, error.column);
|
assert_eq!(8, error.column);
|
||||||
|
|
||||||
|
@ -329,3 +329,30 @@ fn test_report_error_stylesheet() {
|
||||||
// testing for the url
|
// testing for the url
|
||||||
assert_eq!(url, error.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());
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue