Thread ParseError return values through CSS parsing.

This commit is contained in:
Josh Matthews 2017-04-28 00:35:22 -04:00
parent 58e39bfffa
commit 27ae1ef2e7
121 changed files with 2133 additions and 1505 deletions

View file

@ -7,14 +7,15 @@
//! [custom]: https://drafts.csswg.org/css-variables/
use Atom;
use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType};
use parser::ParserContext;
use properties::{CSSWideKeyword, DeclaredValue};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::fmt;
use style_traits::{HasViewportPercentage, ToCss};
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
use stylearc::Arc;
/// A custom property name is just an `Atom`.
@ -131,7 +132,8 @@ impl ComputedValue {
impl SpecifiedValue {
/// Parse a custom property SpecifiedValue.
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Box<Self>, ()> {
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Box<Self>, ParseError<'i>> {
let mut references = Some(HashSet::new());
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
Ok(Box::new(SpecifiedValue {
@ -146,7 +148,7 @@ impl SpecifiedValue {
/// Parse the value of a non-custom property that contains `var()` references.
pub fn parse_non_custom_with_var<'i, 't>
(input: &mut Parser<'i, 't>)
-> Result<(TokenSerializationType, Cow<'i, str>), ()> {
-> Result<(TokenSerializationType, Cow<'i, str>), ParseError<'i>> {
let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None));
Ok((first_token_type, css))
}
@ -158,7 +160,7 @@ fn parse_self_contained_declaration_value<'i, 't>
TokenSerializationType,
Cow<'i, str>,
TokenSerializationType
), ()> {
), ParseError<'i>> {
let start_position = input.position();
let mut missing_closing_characters = String::new();
let (first, last) = try!(
@ -179,7 +181,7 @@ fn parse_declaration_value<'i, 't>
(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>,
missing_closing_characters: &mut String)
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
-> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> {
input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| {
// Need at least one token
let start_position = input.position();
@ -192,14 +194,16 @@ fn parse_declaration_value<'i, 't>
/// Like parse_declaration_value, but accept `!` and `;` since they are only
/// invalid at the top level
fn parse_declaration_value_block(input: &mut Parser,
fn parse_declaration_value_block<'i, 't>
(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>,
missing_closing_characters: &mut String)
-> Result<(TokenSerializationType, TokenSerializationType), ()> {
-> Result<(TokenSerializationType, TokenSerializationType),
ParseError<'i>> {
let mut token_start = input.position();
let mut token = match input.next_including_whitespace_and_comments() {
Ok(token) => token,
Err(()) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
Err(_) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing()))
};
let first_token_type = token.serialization_type();
loop {
@ -226,13 +230,16 @@ fn parse_declaration_value_block(input: &mut Parser,
}
token.serialization_type()
}
Token::BadUrl |
Token::BadString |
Token::CloseParenthesis |
Token::CloseSquareBracket |
Token::CloseCurlyBracket => {
return Err(())
}
Token::BadUrl =>
return Err(StyleParseError::BadUrlInDeclarationValueBlock.into()),
Token::BadString =>
return Err(StyleParseError::BadStringInDeclarationValueBlock.into()),
Token::CloseParenthesis =>
return Err(StyleParseError::UnbalancedCloseParenthesisInDeclarationValueBlock.into()),
Token::CloseSquareBracket =>
return Err(StyleParseError::UnbalancedCloseSquareBracketInDeclarationValueBlock.into()),
Token::CloseCurlyBracket =>
return Err(StyleParseError::UnbalancedCloseCurlyBracketInDeclarationValueBlock.into()),
Token::Function(ref name) => {
if name.eq_ignore_ascii_case("var") {
let position = input.position();
@ -303,9 +310,12 @@ fn parse_declaration_value_block(input: &mut Parser,
// If the var function is valid, return Ok((custom_property_name, fallback))
fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
references: &mut Option<HashSet<Name>>)
-> Result<(), ()> {
-> Result<(), ParseError<'i>> {
let name = try!(input.expect_ident());
let name = try!(parse_name(&name));
let name: Result<_, ParseError> =
parse_name(&name)
.map_err(|()| SelectorParseError::UnexpectedIdent(name.clone()).into());
let name = try!(name);
if input.try(|input| input.expect_comma()).is_ok() {
// Exclude `!` and `;` at the top level
// https://drafts.csswg.org/css-syntax/#typedef-declaration-value
@ -474,7 +484,8 @@ fn substitute_one(name: &Name,
}
let computed_value = if specified_value.references.map(|set| set.is_empty()) == Some(false) {
let mut partial_computed_value = ComputedValue::empty();
let mut input = Parser::new(&specified_value.css);
let mut input = ParserInput::new(&specified_value.css);
let mut input = Parser::new(&mut input);
let mut position = (input.position(), specified_value.first_token_type);
let result = substitute_block(
&mut input, &mut position, &mut partial_computed_value,
@ -525,11 +536,11 @@ fn substitute_one(name: &Name,
///
/// Return `Err(())` if `input` is invalid at computed-value time.
/// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise.
fn substitute_block<F>(input: &mut Parser,
position: &mut (SourcePosition, TokenSerializationType),
partial_computed_value: &mut ComputedValue,
substitute_one: &mut F)
-> Result<TokenSerializationType, ()>
fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>,
position: &mut (SourcePosition, TokenSerializationType),
partial_computed_value: &mut ComputedValue,
substitute_one: &mut F)
-> Result<TokenSerializationType, ParseError<'i>>
where F: FnMut(&Name, &mut ComputedValue) -> Result<TokenSerializationType, ()> {
let mut last_token_type = TokenSerializationType::nothing();
let mut set_position_at_next_iteration = false;
@ -539,7 +550,7 @@ fn substitute_block<F>(input: &mut Parser,
if set_position_at_next_iteration {
*position = (before_this_token, match next {
Ok(ref token) => token.serialization_type(),
Err(()) => TokenSerializationType::nothing(),
Err(_) => TokenSerializationType::nothing(),
});
set_position_at_next_iteration = false;
}
@ -605,11 +616,12 @@ fn substitute_block<F>(input: &mut Parser,
/// Replace `var()` functions for a non-custom property.
/// Return `Err(())` for invalid at computed time.
pub fn substitute(input: &str, first_token_type: TokenSerializationType,
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
-> Result<String, ()> {
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
-> Result<String, ParseError<'i>> {
let mut substituted = ComputedValue::empty();
let mut input = Parser::new(input);
let mut input = ParserInput::new(input);
let mut input = Parser::new(&mut input);
let mut position = (input.position(), first_token_type);
let last_token_type = try!(substitute_block(
&mut input, &mut position, &mut substituted, &mut |name, substituted| {